0
|
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 };
|