]>
Commit | Line | Data |
---|---|---|
cd10c7e3 SG |
1 | #include "defs.h" |
2 | #include "gdbcmd.h" | |
3 | #include "symtab.h" | |
4 | #include "value.h" | |
5 | #include <ctype.h> | |
6 | #include <string.h> | |
7 | #ifdef DYNAMIC_COMMAND_SUPPORT | |
8 | #include <dlfcn.h> | |
9 | #endif | |
10 | ||
11 | typedef unsigned long ulong; | |
12 | ||
13 | #ifdef DYNAMIC_COMMAND_SUPPORT | |
14 | static void | |
15 | dlopen_command PARAMS ((char *, int)); | |
16 | #endif | |
17 | ||
18 | #ifdef DYNAMIC_COMMAND_SUPPORT | |
19 | /* ARGSUSED */ | |
20 | static void | |
21 | dlopen_command (arg, from_tty) | |
22 | char *arg; | |
23 | int from_tty; | |
24 | { | |
25 | char *p; | |
26 | void *hdl; | |
27 | void (*sym)(); | |
28 | ||
29 | if (arg == 0) { | |
30 | error ("No arguments specified."); | |
31 | return; | |
32 | } | |
33 | p = arg; | |
34 | while(*p != ' ' && *p != '\0') | |
35 | p++; | |
36 | if (*p != ' ') { | |
37 | error ("Not enough arguments."); | |
38 | return; | |
39 | } | |
40 | *p++ = '\0'; | |
41 | ||
42 | hdl = dlopen(arg, RTLD_NOW); | |
43 | if (hdl == NULL) { | |
44 | fprintf(stderr, "%s: %s\n", arg, dlerror()); | |
45 | return; | |
46 | } | |
47 | sym = dlsym(hdl, p); | |
48 | ||
49 | if (sym == NULL) { | |
50 | fprintf(stderr, "%s: %s\n", p, dlerror()); | |
51 | return; | |
52 | } | |
53 | ||
54 | sym(); | |
55 | } | |
56 | #endif | |
57 | ||
58 | static void | |
59 | local_shell_escape (char *arg) | |
60 | { | |
61 | #ifdef CANT_FORK | |
62 | /* FIXME: what about errors (I don't know how GO32 system() handles | |
63 | them)? */ | |
64 | system (arg); | |
65 | #else /* Can fork. */ | |
66 | int rc, status, pid; | |
67 | char *p, *user_shell; | |
68 | ||
69 | if ((user_shell = (char *) getenv ("SHELL")) == NULL) | |
70 | user_shell = "/bin/sh"; | |
71 | ||
72 | /* Get the name of the shell for arg0 */ | |
73 | if ((p = strrchr (user_shell, '/')) == NULL) | |
74 | p = user_shell; | |
75 | else | |
76 | p++; /* Get past '/' */ | |
77 | ||
78 | if ((pid = fork()) == 0) | |
79 | { | |
80 | if (!arg) | |
81 | execl (user_shell, p, 0); | |
82 | else | |
83 | execl (user_shell, p, "-c", arg, 0); | |
84 | ||
85 | fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell, | |
86 | safe_strerror (errno)); | |
87 | gdb_flush (gdb_stderr); | |
88 | _exit (0177); | |
89 | } | |
90 | ||
91 | if (pid != -1) | |
92 | while ((rc = wait (&status)) != pid && rc != -1) | |
93 | ; | |
94 | else | |
95 | error ("Fork failed"); | |
96 | #endif /* Can fork. */ | |
97 | } | |
98 | ||
99 | static void | |
100 | GetClassName(long objectID, char* name) | |
101 | { | |
102 | register value_ptr val; | |
103 | register struct symbol *sym; | |
104 | struct minimal_symbol *msymbol; | |
105 | struct type *type; | |
106 | value_ptr blocklen; | |
107 | LONGEST maddr; | |
108 | ||
109 | /* Find the address of RemoteGetClassName in the inferior. */ | |
110 | ||
111 | sym = lookup_symbol ("RemoteGetClassName", 0, VAR_NAMESPACE, 0, NULL); | |
112 | if (sym != NULL) | |
113 | { | |
114 | if (SYMBOL_CLASS (sym) != LOC_BLOCK) | |
115 | { | |
116 | error ("\"RemoteGetClassName\" exists in this program but is not a function."); | |
117 | } | |
118 | val = value_of_variable (sym, NULL); | |
119 | } | |
120 | else | |
121 | { | |
122 | msymbol = lookup_minimal_symbol ("RemoteGetClassName", "", (struct objfile *) NULL); | |
123 | if (msymbol != NULL) | |
124 | { | |
125 | type = lookup_pointer_type (builtin_type_char); | |
126 | type = lookup_function_type (type); | |
127 | type = lookup_pointer_type (type); | |
128 | maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol); | |
129 | val = value_from_longest (type, maddr); | |
130 | } | |
131 | else | |
132 | { | |
133 | error ("evaluation of this expression requires the program to have a function \"RemoteGetClassName\"."); | |
134 | } | |
135 | } | |
136 | ||
137 | blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID); | |
138 | val = call_function_by_hand (val, 1, &blocklen); | |
139 | if (value_logical_not (val)) | |
140 | { | |
141 | error ("Could not get class name."); | |
142 | } | |
143 | read_memory(value_as_pointer(val), name, 32); | |
144 | ||
145 | } | |
146 | ||
147 | static CORE_ADDR | |
148 | GetBasePtr(long objectID) | |
149 | { | |
150 | register value_ptr val; | |
151 | register struct symbol *sym; | |
152 | struct minimal_symbol *msymbol; | |
153 | struct type *type; | |
154 | value_ptr blocklen; | |
155 | LONGEST maddr; | |
156 | ||
157 | /* Find the address of RemoteGetBasePtr in the inferior. */ | |
158 | ||
159 | sym = lookup_symbol ("RemoteGetBasePtr", 0, VAR_NAMESPACE, 0, NULL); | |
160 | if (sym != NULL) | |
161 | { | |
162 | if (SYMBOL_CLASS (sym) != LOC_BLOCK) | |
163 | { | |
164 | error ("\"RemoteGetBasePtr\" exists in this program but is not a function."); | |
165 | } | |
166 | val = value_of_variable (sym, NULL); | |
167 | } | |
168 | else | |
169 | { | |
170 | msymbol = lookup_minimal_symbol ("RemoteGetBasePtr", "", (struct objfile *) NULL); | |
171 | if (msymbol != NULL) | |
172 | { | |
173 | type = lookup_pointer_type (builtin_type_char); | |
174 | type = lookup_function_type (type); | |
175 | type = lookup_pointer_type (type); | |
176 | maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol); | |
177 | val = value_from_longest (type, maddr); | |
178 | } | |
179 | else | |
180 | { | |
181 | error ("evaluation of this expression requires the program to have a function \"RemoteGetBasePtr\"."); | |
182 | } | |
183 | } | |
184 | ||
185 | blocklen = value_from_longest (builtin_type_int, (LONGEST) objectID); | |
186 | val = call_function_by_hand (val, 1, &blocklen); | |
187 | if (value_logical_not (val)) | |
188 | { | |
189 | error ("Could not get base pointer to object."); | |
190 | } | |
191 | return value_as_pointer(val); | |
192 | } | |
193 | ||
194 | static void | |
195 | dump_extra_data(CORE_ADDR addr, ulong length) | |
196 | { | |
197 | ulong buf[5], chunk, i; | |
198 | char *p; | |
199 | ||
200 | while (length > 3) { | |
201 | chunk = (length > 16) ? 16 : length; | |
202 | ||
203 | memset(buf, 0, 5*sizeof(long)); | |
204 | read_memory(addr, &buf, chunk); | |
205 | fprintf(gdb_stdout, "%08lx %08lx %08lx %08lx | ", buf[0], | |
206 | buf[1], buf[2], buf[3]); | |
207 | for (i = 0, p = (char*)buf; i < chunk; i++, p++) { | |
208 | if (!isprint(*p)) | |
209 | *p = '.'; | |
210 | } | |
211 | fprintf(gdb_stdout, "%s |\n", buf); | |
212 | addr += chunk; | |
213 | length -= chunk; | |
214 | } | |
215 | } | |
216 | ||
217 | struct type *type_of_object(CORE_ADDR object) | |
218 | { | |
219 | char className[32], classAllFieldsName[128]; | |
220 | struct type *type = NULL; | |
221 | GetClassName(object, className); | |
222 | sprintf(classAllFieldsName, "%s_AllFields", className); | |
223 | ||
224 | type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0); | |
225 | return lookup_pointer_type(type); | |
226 | } | |
227 | ||
228 | CORE_ADDR baseptr_of_object(ulong object) | |
229 | { | |
230 | return GetBasePtr(object) + 12; | |
231 | } | |
232 | ||
233 | /* ARGSUSED */ | |
234 | static void | |
235 | print_object (arg, dump) | |
236 | char *arg; | |
237 | int dump; | |
238 | { | |
239 | CORE_ADDR addr; | |
240 | ulong object, objectLength, typeLength = 0; | |
241 | char className[32], classAllFieldsName[128]; | |
242 | struct type* type = NULL; | |
243 | ||
244 | object = parse_and_eval_address(arg); | |
245 | ||
246 | GetClassName(object, className); | |
247 | sprintf(classAllFieldsName, "%s_AllFields", className); | |
248 | ||
249 | type = lookup_typename(classAllFieldsName, (struct block *)NULL, 0); | |
250 | typeLength = TYPE_LENGTH(type); | |
251 | addr = GetBasePtr(object); | |
252 | read_memory(addr, &objectLength, 4); | |
253 | objectLength -= 12; | |
254 | addr += 12; | |
255 | if (TYPE_CODE(type) != TYPE_CODE_UNDEF && !(TYPE_FLAGS(type)&TYPE_FLAG_STUB)) { | |
256 | if (dump) { | |
257 | value_ptr valptr = value_at_lazy(type, addr); | |
258 | int histindex = record_latest_value(valptr); | |
259 | printf_filtered("Object 0x%08lx at address 0x%08lx of class %s\n", | |
260 | object, addr, className); | |
261 | if (histindex >= 0) printf_filtered ("$%d = ", histindex); | |
262 | value_print(valptr, gdb_stdout, 0, Val_prettyprint); | |
263 | objectLength -= typeLength; | |
264 | addr += typeLength; | |
265 | printf_filtered("\n"); | |
266 | dump_extra_data(addr, objectLength); | |
267 | printf_filtered("\n"); | |
268 | } else { | |
269 | value_ptr valptr = value_from_longest(lookup_pointer_type(type), addr); | |
270 | int histindex = record_latest_value(valptr); | |
271 | if (histindex >= 0) printf_filtered ("$%d = ", histindex); | |
272 | value_print(valptr, gdb_stdout, 0, Val_prettyprint); | |
273 | printf_filtered("\n"); | |
274 | } | |
275 | } | |
276 | } | |
277 | ||
278 | /* ARGSUSED */ | |
279 | static void | |
280 | dobj_command (arg, from_tty) | |
281 | char *arg; | |
282 | int from_tty; | |
283 | { | |
284 | print_object(arg, 1); | |
285 | } | |
286 | ||
287 | /* ARGSUSED */ | |
288 | static void | |
289 | pobj_command (arg, from_tty) | |
290 | char *arg; | |
291 | int from_tty; | |
292 | { | |
293 | print_object(arg, 0); | |
294 | } | |
295 | ||
296 | /* ARGSUSED */ | |
297 | static void | |
298 | getint_command (arg, from_tty) | |
299 | char *arg; | |
300 | int from_tty; | |
301 | { | |
302 | char shellCommand[128]; | |
303 | ||
304 | sprintf(shellCommand, "getint %s", arg); | |
305 | local_shell_escape(shellCommand); | |
306 | } | |
307 | ||
308 | /* ARGSUSED */ | |
309 | static void | |
310 | getindexical_command (arg, from_tty) | |
311 | char *arg; | |
312 | int from_tty; | |
313 | { | |
314 | char shellCommand[128]; | |
315 | ||
316 | sprintf(shellCommand, "getindexical %s", arg); | |
317 | local_shell_escape(shellCommand); | |
318 | } | |
319 | ||
320 | /* ARGSUSED */ | |
321 | static void | |
322 | exc_command (arg, from_tty) | |
323 | char *arg; | |
324 | int from_tty; | |
325 | { | |
326 | char shellCommand[128]; | |
327 | ulong exception; | |
328 | ||
329 | sprintf(shellCommand, "getexc %s", arg); | |
330 | local_shell_escape(shellCommand); | |
331 | } | |
332 | ||
333 | static CORE_ADDR dispatch_method_addr = -1, dispatch_inherited_addr = -1, dispatch_delegated_addr = -1, dispatch_intrinsic_addr = -1; | |
334 | CORE_ADDR do_dispatch_method_addr = -1, do_dispatch_intrinsic_addr = -1; | |
335 | ||
336 | static CORE_ADDR | |
337 | lookup_address(const char *name) | |
338 | { | |
339 | struct symbol *sym = lookup_symbol(name, NULL, VAR_NAMESPACE, NULL, NULL); | |
340 | if (sym) | |
341 | return BLOCK_START(SYMBOL_BLOCK_VALUE(sym)); | |
342 | else | |
343 | { | |
344 | /* printf("Couldn't find %s!\n", name); */ | |
345 | return -1; | |
346 | } | |
347 | } | |
348 | ||
349 | void | |
350 | init_magic() | |
351 | { | |
352 | dispatch_method_addr = lookup_address("__DispatchMethod"); | |
353 | dispatch_inherited_addr = lookup_address("__DispatchInherited"); | |
354 | dispatch_delegated_addr = lookup_address("__DispatchDelegated"); | |
355 | dispatch_intrinsic_addr = lookup_address("__DispatchIntrinsic"); | |
356 | do_dispatch_method_addr = lookup_address("__DoTheDispatch"); | |
357 | do_dispatch_intrinsic_addr = lookup_address("__DoDispatchIntrinsic"); | |
358 | } | |
359 | ||
360 | int | |
361 | is_dispatch(CORE_ADDR pc) | |
362 | { | |
363 | return (pc == dispatch_method_addr) || (pc == dispatch_inherited_addr) || (pc == dispatch_delegated_addr); | |
364 | } | |
365 | ||
366 | int | |
367 | is_dispatch_intrinsic(CORE_ADDR pc) | |
368 | { | |
369 | return pc == dispatch_intrinsic_addr; | |
370 | } | |
371 | ||
372 | /* If we are stopped at one of the entry points to the dispatcher, we want to continue until just | |
373 | before we jump to the implementation. If we are at that point, we want to continue until we | |
374 | actually get to the implementation. Likewise for the intrinsic dispatcher | |
375 | */ | |
376 | CORE_ADDR | |
377 | deal_with_dispatch(CORE_ADDR stop_pc) | |
378 | { | |
379 | if (is_dispatch(stop_pc)) | |
380 | return do_dispatch_method_addr; | |
381 | else if (is_dispatch_intrinsic(stop_pc)) | |
382 | return do_dispatch_intrinsic_addr; | |
383 | else if (stop_pc == do_dispatch_method_addr) | |
384 | /* This assumes that we branch through t6 */ | |
385 | return read_register(14); | |
386 | else if (stop_pc == do_dispatch_intrinsic_addr) | |
387 | /* This assumes that we branch through t0 */ | |
388 | return read_register(8); | |
389 | else | |
390 | return 0; | |
391 | } | |
392 | ||
393 | void | |
394 | magic_create_inferior_hook() | |
395 | { | |
396 | struct symbol *sym = lookup_symbol("gHandleError", NULL, VAR_NAMESPACE, NULL, NULL); | |
397 | if (sym) | |
398 | { | |
399 | CORE_ADDR addr = SYMBOL_VALUE(sym); | |
400 | unsigned long errorDebugger = 2; | |
401 | target_write_memory(addr, &errorDebugger, 4); | |
402 | } | |
403 | ||
404 | init_magic (); | |
405 | } | |
406 | ||
407 | ||
408 | _initialize_magic () | |
409 | { | |
410 | add_com ("dobj", class_support, dobj_command, "Display Object Contents"); | |
411 | add_com ("pobj", class_support, pobj_command, "Print object base pointer"); | |
412 | add_com ("getint", class_support, getint_command, "Convert intrinsic name to number or vice versa."); | |
413 | add_com ("getindexical", class_support, getindexical_command, "Convert indexical name to number or vice versa."); | |
414 | add_com ("exc", class_support, exc_command, "Convert exception name to number or vice versa."); | |
415 | ||
416 | #ifdef DYNAMIC_COMMAND_SUPPORT | |
417 | add_com ("dlopen", class_support, dlopen_command, | |
418 | "Load the dynamic library specified and execute the specified symbol"); | |
419 | #endif | |
420 | } |