1 /* 2 * Copyright 2000-2001 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any 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 };