1 /*
   2  * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "shell_imp.h"
  26 #include "IOBuf.hpp"
  27 #include <sys/time.h>
  28 #include <thread_db.h>
  29 
  30 typedef td_err_e td_init_fn_t();
  31 typedef td_err_e td_ta_new_fn_t(struct ps_prochandle *, td_thragent_t **);
  32 typedef td_err_e td_ta_delete_fn_t(td_thragent_t *);
  33 typedef td_err_e td_ta_map_id2thr_fn_t(const td_thragent_t *, thread_t,  td_thrhandle_t *);
  34 typedef td_err_e td_thr_getgregs_fn_t(const td_thrhandle_t *, prgregset_t);
  35 
  36 class ServiceabilityAgentDbxModule {
  37 public:
  38   ServiceabilityAgentDbxModule(int major, int minor,
  39                                shell_imp_interp_t interp, int argc, char *argv[]);
  40   ~ServiceabilityAgentDbxModule();
  41 
  42   bool install();
  43   bool uninstall();
  44 
  45   /* This is invoked through the dbx command interpreter. It listens
  46      on a socket for commands and does not return until it receives an
  47      "exit" command. At that point control is returned to dbx's main
  48      loop, at which point if the user sends an exit command to dbx's
  49      shell the dbx process will exit. Returns true if completed
  50      successfully, false if an error occurred while running (for
  51      example, unable to bind listening socket). */
  52   bool run();
  53 
  54 private:
  55 
  56   // This must be shared between the Java and C layers
  57   static const int PORT = 21928;
  58 
  59   // Command handlers
  60   bool handleAddressSize(char* data);
  61   bool handlePeekFailFast(char* data);
  62   bool handlePeek(char* data);
  63   bool handlePoke(char* data);
  64   bool handleMapped(char* data);
  65   bool handleLookup(char* data);
  66   bool handleThrGRegs(char* data);
  67 
  68   // Input routines
  69 
  70   // May mutate addr argument even if result is false
  71   bool scanAddress(char** data, psaddr_t* addr);
  72   // May mutate num argument even if result is false
  73   bool scanUnsignedInt(char** data, unsigned int* num);
  74   // Returns NULL if error occurred while scanning. Otherwise, returns
  75   // newly-allocated character array which must be freed with delete[].
  76   char* scanSymbol(char** data);
  77   // Helper routine: converts ASCII to 4-bit integer. Returns true if
  78   // character is in range, false otherwise.
  79   bool charToNibble(char ascii, int* value);
  80 
  81   // Output routines
  82 
  83   // Writes an int with no leading or trailing spaces
  84   bool writeInt(int val, int fd);
  85   // Writes an address in hex format with no leading or trailing
  86   // spaces
  87   bool writeAddress(psaddr_t addr, int fd);
  88   // Writes a register in hex format with no leading or trailing
  89   // spaces (addresses and registers might be of different size)
  90   bool writeRegister(prgreg_t reg, int fd);
  91   // Writes a space to given file descriptor
  92   bool writeSpace(int fd);
  93   // Writes carriage return to given file descriptor
  94   bool writeCR(int fd);
  95   // Writes a bool as [0|1]
  96   bool writeBoolAsInt(bool val, int fd);
  97   // Helper routine: converts low 4 bits to ASCII [0..9][A..F]
  98   char nibbleToChar(unsigned char nibble);
  99 
 100   // Base routine called by most of the above
 101   bool writeString(const char* str, int fd);
 102 
 103   // Writes a binary character
 104   bool writeBinChar(char val, int fd);
 105   // Writes a binary unsigned int in network (big-endian) byte order
 106   bool writeBinUnsignedInt(unsigned int val, int fd);
 107   // Writes a binary buffer
 108   bool writeBinBuf(char* buf, int size, int fd);
 109 
 110   // Routine to flush the socket
 111   bool flush(int client_socket);
 112 
 113   void cleanup(int client_socket);
 114 
 115   // The shell interpreter on which we can invoke commands (?)
 116   shell_imp_interp_t _interp;
 117 
 118   // The "command line" arguments passed to us by dbx (?)
 119   int _argc;
 120   char **_argv;
 121 
 122   // The installed command in the dbx shell
 123   shell_imp_command_t _command;
 124 
 125   // Access to libthread_db (dlsym'ed to be able to pick up the
 126   // version loaded by dbx)
 127   td_init_fn_t*          td_init_fn;
 128   td_ta_new_fn_t*        td_ta_new_fn;
 129   td_ta_delete_fn_t*     td_ta_delete_fn;
 130   td_ta_map_id2thr_fn_t* td_ta_map_id2thr_fn;
 131   td_thr_getgregs_fn_t*  td_thr_getgregs_fn;
 132 
 133   // Our "thread agent" -- access to libthread_db
 134   td_thragent_t* _tdb_agent;
 135 
 136   // Path to libthread.so in target process; free with delete[]
 137   char* libThreadName;
 138 
 139   // Handle to dlopen'ed libthread_db.so
 140   void* libThreadDB;
 141 
 142   // Helper callback for finding libthread_db.so
 143   friend int findLibThreadCB(const rd_loadobj_t* lo, void* data);
 144 
 145   // Support for reading C strings out of the target process (so we
 146   // can find the correct libthread_db). Returns newly-allocated char*
 147   // which must be freed with delete[], or null if the read failed.
 148   char* readCStringFromProcess(psaddr_t addr);
 149 
 150   IOBuf myComm;
 151 
 152   // Output buffer support (used by writeString, writeChar, flush)
 153   char* output_buffer;
 154   int output_buffer_size;
 155   int output_buffer_pos;
 156 
 157   // "Fail fast" flag
 158   bool peek_fail_fast;
 159 
 160   // Commands
 161   static const char* CMD_ADDRESS_SIZE;
 162   static const char* CMD_PEEK_FAIL_FAST;
 163   static const char* CMD_PEEK;
 164   static const char* CMD_POKE;
 165   static const char* CMD_MAPPED;
 166   static const char* CMD_LOOKUP;
 167   static const char* CMD_THR_GREGS;
 168   static const char* CMD_EXIT;
 169 };
 170 
 171 // For profiling. Times reported are in milliseconds.
 172 class Timer {
 173 public:
 174   Timer();
 175   ~Timer();
 176 
 177   void start();
 178   void stop();
 179   long total();
 180   long average();
 181   void reset();
 182 
 183 private:
 184   struct timeval startTime;
 185   long long totalMicroseconds; // stored internally in microseconds
 186   int counter;
 187   long long timevalDiff(struct timeval* startTime, struct timeval* endTime);
 188 };