svc_agent_dbx.hpp 6.2 KB
Newer Older
D
duke 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
/*
 * Copyright 2000-2001 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

#include "shell_imp.h"
#include "IOBuf.hpp"
#include <sys/time.h>
#include <thread_db.h>

typedef td_err_e td_init_fn_t();
typedef td_err_e td_ta_new_fn_t(struct ps_prochandle *, td_thragent_t **);
typedef td_err_e td_ta_delete_fn_t(td_thragent_t *);
typedef td_err_e td_ta_map_id2thr_fn_t(const td_thragent_t *, thread_t,  td_thrhandle_t *);
typedef td_err_e td_thr_getgregs_fn_t(const td_thrhandle_t *, prgregset_t);

class ServiceabilityAgentDbxModule {
public:
  ServiceabilityAgentDbxModule(int major, int minor,
                               shell_imp_interp_t interp, int argc, char *argv[]);
  ~ServiceabilityAgentDbxModule();

  bool install();
  bool uninstall();

  /* This is invoked through the dbx command interpreter. It listens
     on a socket for commands and does not return until it receives an
     "exit" command. At that point control is returned to dbx's main
     loop, at which point if the user sends an exit command to dbx's
     shell the dbx process will exit. Returns true if completed
     successfully, false if an error occurred while running (for
     example, unable to bind listening socket). */
  bool run();

private:

  // This must be shared between the Java and C layers
  static const int PORT = 21928;

  // Command handlers
  bool handleAddressSize(char* data);
  bool handlePeekFailFast(char* data);
  bool handlePeek(char* data);
  bool handlePoke(char* data);
  bool handleMapped(char* data);
  bool handleLookup(char* data);
  bool handleThrGRegs(char* data);

  // Input routines

  // May mutate addr argument even if result is false
  bool scanAddress(char** data, psaddr_t* addr);
  // May mutate num argument even if result is false
  bool scanUnsignedInt(char** data, unsigned int* num);
  // Returns NULL if error occurred while scanning. Otherwise, returns
  // newly-allocated character array which must be freed with delete[].
  char* scanSymbol(char** data);
  // Helper routine: converts ASCII to 4-bit integer. Returns true if
  // character is in range, false otherwise.
  bool charToNibble(char ascii, int* value);

  // Output routines

  // Writes an int with no leading or trailing spaces
  bool writeInt(int val, int fd);
  // Writes an address in hex format with no leading or trailing
  // spaces
  bool writeAddress(psaddr_t addr, int fd);
  // Writes a register in hex format with no leading or trailing
  // spaces (addresses and registers might be of different size)
  bool writeRegister(prgreg_t reg, int fd);
  // Writes a space to given file descriptor
  bool writeSpace(int fd);
  // Writes carriage return to given file descriptor
  bool writeCR(int fd);
  // Writes a bool as [0|1]
  bool writeBoolAsInt(bool val, int fd);
  // Helper routine: converts low 4 bits to ASCII [0..9][A..F]
  char nibbleToChar(unsigned char nibble);

  // Base routine called by most of the above
  bool writeString(const char* str, int fd);

  // Writes a binary character
  bool writeBinChar(char val, int fd);
  // Writes a binary unsigned int in network (big-endian) byte order
  bool writeBinUnsignedInt(unsigned int val, int fd);
  // Writes a binary buffer
  bool writeBinBuf(char* buf, int size, int fd);

  // Routine to flush the socket
  bool flush(int client_socket);

  void cleanup(int client_socket);

  // The shell interpreter on which we can invoke commands (?)
  shell_imp_interp_t _interp;

  // The "command line" arguments passed to us by dbx (?)
  int _argc;
  char **_argv;

  // The installed command in the dbx shell
  shell_imp_command_t _command;

  // Access to libthread_db (dlsym'ed to be able to pick up the
  // version loaded by dbx)
  td_init_fn_t*          td_init_fn;
  td_ta_new_fn_t*        td_ta_new_fn;
  td_ta_delete_fn_t*     td_ta_delete_fn;
  td_ta_map_id2thr_fn_t* td_ta_map_id2thr_fn;
  td_thr_getgregs_fn_t*  td_thr_getgregs_fn;

  // Our "thread agent" -- access to libthread_db
  td_thragent_t* _tdb_agent;

  // Path to libthread.so in target process; free with delete[]
  char* libThreadName;

  // Handle to dlopen'ed libthread_db.so
  void* libThreadDB;

  // Helper callback for finding libthread_db.so
  friend int findLibThreadCB(const rd_loadobj_t* lo, void* data);

  // Support for reading C strings out of the target process (so we
  // can find the correct libthread_db). Returns newly-allocated char*
  // which must be freed with delete[], or null if the read failed.
  char* readCStringFromProcess(psaddr_t addr);

  IOBuf myComm;

  // Output buffer support (used by writeString, writeChar, flush)
  char* output_buffer;
  int output_buffer_size;
  int output_buffer_pos;

  // "Fail fast" flag
  bool peek_fail_fast;

  // Commands
  static const char* CMD_ADDRESS_SIZE;
  static const char* CMD_PEEK_FAIL_FAST;
  static const char* CMD_PEEK;
  static const char* CMD_POKE;
  static const char* CMD_MAPPED;
  static const char* CMD_LOOKUP;
  static const char* CMD_THR_GREGS;
  static const char* CMD_EXIT;
};

// For profiling. Times reported are in milliseconds.
class Timer {
public:
  Timer();
  ~Timer();

  void start();
  void stop();
  long total();
  long average();
  void reset();

private:
  struct timeval startTime;
  long long totalMicroseconds; // stored internally in microseconds
  int counter;
  long long timevalDiff(struct timeval* startTime, struct timeval* endTime);
};