]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
43866e37 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
43866e37 A |
8 | * This file contains Original Code and/or Modifications of Original Code |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
43866e37 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
1c79356b A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * @OSF_COPYRIGHT@ | |
27 | */ | |
de355530 A |
28 | /* |
29 | * HISTORY | |
30 | * | |
31 | * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez | |
32 | * Import of Mac OS X kernel (~semeria) | |
33 | * | |
34 | * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez | |
35 | * Import of OSF Mach kernel (~mburg) | |
36 | * | |
37 | * Revision 1.3.22.8 1996/07/31 09:07:24 paire | |
38 | * Merged with nmk20b7_shared (1.3.47.1) | |
39 | * [96/07/24 paire] | |
40 | * | |
41 | * Revision 1.3.47.1 1996/06/13 12:36:08 bernadat | |
42 | * Do not assume anymore that VM_MIN_KERNEL_ADDRESS | |
43 | * is greater or equal than VM_MAX_ADDRESS. | |
44 | * [96/05/23 bernadat] | |
45 | * | |
46 | * Revision 1.3.22.7 1996/01/09 19:16:15 devrcs | |
47 | * Added db_task_getlinenum() function. (steved) | |
48 | * Make db_maxval & db_minval long int's for Alpha. | |
49 | * Changed declarations of 'register foo' to 'register int foo'. | |
50 | * [1995/12/01 21:42:29 jfraser] | |
51 | * | |
52 | * Merged '64-bit safe' changes from DEC alpha port. | |
53 | * [1995/11/21 18:03:41 jfraser] | |
54 | * | |
55 | * Revision 1.3.22.6 1995/02/28 01:58:46 dwm | |
56 | * Merged with changes from 1.3.22.5 | |
57 | * [1995/02/28 01:53:47 dwm] | |
58 | * | |
59 | * mk6 CR1120 - Merge mk6pro_shared into cnmk_shared | |
60 | * remove a couple local protos, now in .h file (for better or worse) | |
61 | * [1995/02/28 01:12:51 dwm] | |
62 | * | |
63 | * Revision 1.3.22.5 1995/02/23 21:43:43 alanl | |
64 | * Move TR_INIT to model_dep.c (MACH_TR and MACH_KDB shouldn't | |
65 | * be bound). | |
66 | * [95/02/16 travos] | |
67 | * | |
68 | * Prepend a "db_" to qsort and qsort_limit_search | |
69 | * (collisions with the real qsort in stdlib.h) | |
70 | * [95/02/14 travos] | |
71 | * | |
72 | * Added X_db_init for object independent formats. | |
73 | * [95/01/24 sjs] | |
74 | * | |
75 | * Merge with DIPC2_SHARED. | |
76 | * [1995/01/05 13:32:53 alanl] | |
77 | * | |
78 | * Revision 1.3.30.2 1994/12/22 20:36:15 bolinger | |
79 | * Fix ri-osc CR881: enable freer use of symbol table of collocated | |
80 | * tasks. No point in requiring task to be named for symbols to be | |
81 | * usable. Also fixed glitch in use of symtab cloning. | |
82 | * [1994/12/22 20:34:55 bolinger] | |
83 | * | |
84 | * Revision 1.3.30.1 1994/11/04 09:53:14 dwm | |
85 | * mk6 CR668 - 1.3b26 merge | |
86 | * add arg to *_db_search_by_addr() from mk6 | |
87 | * * Revision 1.3.4.9 1994/05/13 15:57:14 tmt | |
88 | * Add hooks for catching calls to uninstalled symbol tables. | |
89 | * Add XXX_search_by_addr() vectors. | |
90 | * * Revision 1.3.4.8 1994/05/12 21:59:00 tmt | |
91 | * Fix numerous db_sym_t/char * mixups. | |
92 | * Fix and enable db_qualify_ambiguous_names. | |
93 | * Make dif and newdiff unsigned in symbol searches. | |
94 | * * Revision 1.3.4.7 1994/05/06 18:39:52 tmt | |
95 | * Merged osc1.3dec/shared with osc1.3b19 | |
96 | * Fix function prototype declarations. | |
97 | * Merge Alpha changes into osc1.312b source code. | |
98 | * String protos. | |
99 | * Handle multiple, coexisting symbol table types. | |
100 | * 64bit cleanup. | |
101 | * Revision 1.3.4.5 1993/10/20 18:58:55 gm | |
102 | * CR9704: Removed symbol load printf. | |
103 | * * End1.3merge | |
104 | * [1994/11/04 08:50:02 dwm] | |
105 | * | |
106 | * Revision 1.3.22.5 1995/02/23 21:43:43 alanl | |
107 | * Move TR_INIT to model_dep.c (MACH_TR and MACH_KDB shouldn't | |
108 | * be bound). | |
109 | * [95/02/16 travos] | |
110 | * | |
111 | * Prepend a "db_" to qsort and qsort_limit_search | |
112 | * (collisions with the real qsort in stdlib.h) | |
113 | * [95/02/14 travos] | |
114 | * | |
115 | * Added X_db_init for object independent formats. | |
116 | * [95/01/24 sjs] | |
117 | * | |
118 | * Merge with DIPC2_SHARED. | |
119 | * [1995/01/05 13:32:53 alanl] | |
120 | * | |
121 | * Revision 1.3.30.2 1994/12/22 20:36:15 bolinger | |
122 | * Fix ri-osc CR881: enable freer use of symbol table of collocated | |
123 | * tasks. No point in requiring task to be named for symbols to be | |
124 | * usable. Also fixed glitch in use of symtab cloning. | |
125 | * [1994/12/22 20:34:55 bolinger] | |
126 | * | |
127 | * Revision 1.3.30.1 1994/11/04 09:53:14 dwm | |
128 | * mk6 CR668 - 1.3b26 merge | |
129 | * add arg to *_db_search_by_addr() from mk6 | |
130 | * * Revision 1.3.4.9 1994/05/13 15:57:14 tmt | |
131 | * Add hooks for catching calls to uninstalled symbol tables. | |
132 | * Add XXX_search_by_addr() vectors. | |
133 | * * Revision 1.3.4.8 1994/05/12 21:59:00 tmt | |
134 | * Fix numerous db_sym_t/char * mixups. | |
135 | * Fix and enable db_qualify_ambiguous_names. | |
136 | * Make dif and newdiff unsigned in symbol searches. | |
137 | * * Revision 1.3.4.7 1994/05/06 18:39:52 tmt | |
138 | * Merged osc1.3dec/shared with osc1.3b19 | |
139 | * Fix function prototype declarations. | |
140 | * Merge Alpha changes into osc1.312b source code. | |
141 | * String protos. | |
142 | * Handle multiple, coexisting symbol table types. | |
143 | * 64bit cleanup. | |
144 | * Revision 1.3.4.5 1993/10/20 18:58:55 gm | |
145 | * CR9704: Removed symbol load printf. | |
146 | * * End1.3merge | |
147 | * [1994/11/04 08:50:02 dwm] | |
148 | * | |
149 | * Revision 1.3.22.3 1994/09/23 01:21:37 ezf | |
150 | * change marker to not FREE | |
151 | * [1994/09/22 21:10:58 ezf] | |
152 | * | |
153 | * Revision 1.3.22.2 1994/06/26 22:58:24 bolinger | |
154 | * Suppress symbol table range output when table is unsorted, since output | |
155 | * is meaningless in this case. | |
156 | * [1994/06/23 20:19:02 bolinger] | |
157 | * | |
158 | * Revision 1.3.22.1 1994/06/11 21:12:19 bolinger | |
159 | * Merge up to NMK17.2. | |
160 | * [1994/06/11 20:02:31 bolinger] | |
161 | * | |
162 | * Revision 1.3.17.1 1994/02/08 10:58:40 bernadat | |
163 | * Check result of X_db_line_at_pc() before | |
164 | * invoking db_shorten_filename(). | |
165 | * [93/11/30 bernadat] | |
166 | * | |
167 | * Installed ddb_init() routine in a symbol-independent file to call | |
168 | * symbol-dependent and machine-dependent initialization routines. | |
169 | * [93/08/27 paire] | |
170 | * | |
171 | * Fixed db_shorten_filename() to gobble the last slash. | |
172 | * Modified db_search_task_symbol_and_line() interface to return | |
173 | * the number of a function arguments. | |
174 | * [93/08/19 paire] | |
175 | * | |
176 | * Added new arguments to db_sym_print_completion() call. | |
177 | * [93/08/18 paire] | |
178 | * | |
179 | * Added db_lookup_incomplete(), db_sym_parse_and_lookup_incomplete(), | |
180 | * db_sym_print_completion() and db_completion_print() for support of | |
181 | * symbol completion. | |
182 | * [93/08/14 paire] | |
183 | * [94/02/07 bernadat] | |
184 | * | |
185 | * Revision 1.3.15.4 1994/06/08 19:11:23 dswartz | |
186 | * Preemption merge. | |
187 | * [1994/06/08 19:10:24 dswartz] | |
188 | * | |
189 | * Revision 1.3.20.2 1994/06/01 21:34:39 klj | |
190 | * Initial preemption code base merge | |
191 | * | |
192 | * Revision 1.3.15.3 1994/02/10 02:28:15 bolinger | |
193 | * Fix db_add_symbol_table() to increase db_maxval if highest-addressed | |
194 | * symbol in new symtab is greater than its current value. | |
195 | * [1994/02/09 21:42:12 bolinger] | |
196 | * | |
197 | * Revision 1.3.15.2 1994/02/03 21:44:23 bolinger | |
198 | * Update db_maxval when a symbol table is cloned for kernel-loaded | |
199 | * server. | |
200 | * [1994/02/03 20:47:22 bolinger] | |
201 | * | |
202 | * Revision 1.3.15.1 1994/02/03 02:41:58 dwm | |
203 | * Add short-term kludge to provide symbolic info on INKServer. | |
204 | * [1994/02/03 02:31:17 dwm] | |
205 | * | |
206 | * Revision 1.3.4.4 1993/08/11 20:38:11 elliston | |
207 | * Add ANSI Prototypes. CR #9523. | |
208 | * [1993/08/11 03:33:59 elliston] | |
209 | * | |
210 | * Revision 1.3.4.3 1993/07/27 18:28:09 elliston | |
211 | * Add ANSI prototypes. CR #9523. | |
212 | * [1993/07/27 18:12:57 elliston] | |
213 | * | |
214 | * Revision 1.3.4.2 1993/06/09 02:20:50 gm | |
215 | * CR9176 - ANSI C violations: trailing tokens on CPP | |
216 | * directives, extra semicolons after decl_ ..., asm keywords | |
217 | * [1993/06/07 18:57:31 jeffc] | |
218 | * | |
219 | * Added to OSF/1 R1.3 from NMK15.0. | |
220 | * [1993/06/02 20:57:10 jeffc] | |
221 | * | |
222 | * Revision 1.3 1993/04/19 16:03:09 devrcs | |
223 | * Protect db_line_at_pc() against null db_last_symtab. | |
224 | * [1993/02/11 15:37:16 barbou] | |
225 | * | |
226 | * Changes from MK78: | |
227 | * Upped MAXNOSYMTABS from 3 to 5. Now there is space for kernel, | |
228 | * bootstrap, server, and emulator symbols - plus one for future | |
229 | * expansion. | |
230 | * [92/03/21 danner] | |
231 | * Changed CHAR arg of db_eqname to UNSIGNED. | |
232 | * Made arg types proper for db_line_at_pc(). | |
233 | * [92/05/16 jfriedl] | |
234 | * [92/12/18 bruel] | |
235 | * | |
236 | * Sort large symbol tables to speedup lookup. | |
237 | * Improved symbol lookup (use of max_offset, dichotomic search) | |
238 | * [barbou@gr.osf.org] | |
239 | * | |
240 | * db_add_symbol_table now takes 3 additional arguments. Machine | |
241 | * dependant modules must provide them. [barbou@gr.osf.org] | |
242 | * [92/12/03 bernadat] | |
243 | * | |
244 | * Revision 1.2 1992/11/25 01:04:42 robert | |
245 | * integrate changes below for norma_14 | |
246 | * [1992/11/13 19:22:44 robert] | |
247 | * | |
248 | * Revision 1.1 1992/09/30 02:01:25 robert | |
249 | * Initial revision | |
250 | * | |
251 | * $EndLog$ | |
252 | */ | |
253 | /* CMU_HIST */ | |
254 | /* | |
255 | * Revision 2.10.4.1 92/02/18 18:38:53 jeffreyh | |
256 | * Added db_get_sym(). Simple interface to get symbol names | |
257 | * knowing the offset. | |
258 | * [91/12/20 bernadat] | |
259 | * | |
260 | * Do not look for symbol names if address | |
261 | * is to small or to large, otherwise get | |
262 | * random names like INCLUDE_VERSION+?? | |
263 | * [91/06/25 bernadat] | |
264 | * | |
265 | * Revision 2.10 91/10/09 16:02:30 af | |
266 | * Revision 2.9.2.1 91/10/05 13:07:27 jeffreyh | |
267 | * Changed symbol table name qualification syntax from "xxx:yyy" | |
268 | * to "xxx::yyy" to allow "file:func:line" in "yyy" part. | |
269 | * "db_sym_parse_and_lookup" is also added for "yyy" part parsing. | |
270 | * Replaced db_search_symbol with db_search_task_symbol, and moved | |
271 | * it to "db_sym.h" as a macro. | |
272 | * Added db_task_printsym, and changed db_printsym to call it. | |
273 | * Added include "db_task_thread.h". | |
274 | * Fixed infinite recursion of db_symbol_values. | |
275 | * [91/08/29 tak] | |
276 | * | |
277 | * Revision 2.9.2.1 91/10/05 13:07:27 jeffreyh | |
278 | * Changed symbol table name qualification syntax from "xxx:yyy" | |
279 | * to "xxx::yyy" to allow "file:func:line" in "yyy" part. | |
280 | * "db_sym_parse_and_lookup" is also added for "yyy" part parsing. | |
281 | * Replaced db_search_symbol with db_search_task_symbol, and moved | |
282 | * it to "db_sym.h" as a macro. | |
283 | * Added db_task_printsym, and changed db_printsym to call it. | |
284 | * Added include "db_task_thread.h". | |
285 | * Fixed infinite recursion of db_symbol_values. | |
286 | * [91/08/29 tak] | |
287 | * | |
288 | * Revision 2.9 91/07/31 17:31:14 dbg | |
289 | * Add task pointer and space for string storage to symbol table | |
290 | * descriptor. | |
291 | * [91/07/31 dbg] | |
292 | * | |
293 | * Revision 2.8 91/07/09 23:16:08 danner | |
294 | * Changed a printf. | |
295 | * [91/07/08 danner] | |
296 | * | |
297 | * Revision 2.7 91/05/14 15:35:54 mrt | |
298 | * Correcting copyright | |
299 | * | |
300 | * Revision 2.6 91/03/16 14:42:40 rpd | |
301 | * Changed the default db_maxoff to 4K. | |
302 | * [91/03/10 rpd] | |
303 | * | |
304 | * Revision 2.5 91/02/05 17:07:07 mrt | |
305 | * Changed to new Mach copyright | |
306 | * [91/01/31 16:19:17 mrt] | |
307 | * | |
308 | * Revision 2.4 90/10/25 14:44:05 rwd | |
309 | * Changed db_printsym to print unsigned. | |
310 | * [90/10/19 rpd] | |
311 | * | |
312 | * Revision 2.3 90/09/09 23:19:56 rpd | |
313 | * Avoid totally incorrect guesses of symbol names for small values. | |
314 | * [90/08/30 17:39:48 af] | |
315 | * | |
316 | * Revision 2.2 90/08/27 21:52:18 dbg | |
317 | * Removed nlist.h. Fixed some type declarations. | |
318 | * Qualifier character is ':'. | |
319 | * [90/08/20 dbg] | |
320 | * Modularized symtab info into a new db_symtab_t type. | |
321 | * Modified db_add_symbol_table and others accordingly. | |
322 | * Defined db_sym_t, a new (opaque) type used to represent | |
323 | * symbols. This should support all sort of future symtable | |
324 | * formats. Functions like db_qualify take a db_sym_t now. | |
325 | * New db_symbol_values() function to explode the content | |
326 | * of a db_sym_t. | |
327 | * db_search_symbol() replaces db_find_sym_and_offset(), which is | |
328 | * now a macro defined in our (new) header file. This new | |
329 | * function accepts more restrictive searches, which are | |
330 | * entirely delegated to the symtab-specific code. | |
331 | * Accordingly, db_printsym() accepts a strategy parameter. | |
332 | * New db_line_at_pc() function. | |
333 | * Renamed misleading db_eqsym into db_eqname. | |
334 | * [90/08/20 10:47:06 af] | |
335 | * | |
336 | * Created. | |
337 | * [90/07/25 dbg] | |
338 | * | |
339 | * Revision 2.1 90/07/26 16:43:52 dbg | |
340 | * Created. | |
341 | * | |
342 | */ | |
343 | /* CMU_ENDHIST */ | |
1c79356b A |
344 | /* |
345 | * Mach Operating System | |
346 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
347 | * All Rights Reserved. | |
348 | * | |
349 | * Permission to use, copy, modify and distribute this software and its | |
350 | * documentation is hereby granted, provided that both the copyright | |
351 | * notice and this permission notice appear in all copies of the | |
352 | * software, derivative works or modified versions, and any portions | |
353 | * thereof, and that both notices appear in supporting documentation. | |
354 | * | |
355 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
356 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
357 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
358 | * | |
359 | * Carnegie Mellon requests users of this software to return to | |
360 | * | |
361 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
362 | * School of Computer Science | |
363 | * Carnegie Mellon University | |
364 | * Pittsburgh PA 15213-3890 | |
365 | * | |
366 | * any improvements or extensions that they make and grant Carnegie Mellon | |
367 | * the rights to redistribute these changes. | |
368 | */ | |
369 | /* | |
370 | */ | |
371 | /* | |
372 | * Author: David B. Golub, Carnegie Mellon University | |
373 | * Date: 7/90 | |
374 | */ | |
375 | ||
376 | #include <machine/db_machdep.h> | |
377 | #include <string.h> /* For strcpy(), strcmp() */ | |
378 | #include <mach/std_types.h> | |
379 | #include <kern/misc_protos.h> /* For printf() */ | |
380 | #include <ddb/db_sym.h> | |
381 | #include <ddb/db_task_thread.h> | |
382 | #include <ddb/db_command.h> | |
383 | #include <ddb/db_output.h> /* For db_printf() */ | |
384 | ||
385 | #include <vm/vm_map.h> /* vm_map_t */ | |
386 | ||
387 | /* | |
388 | * Multiple symbol tables | |
389 | * | |
390 | * mach, bootstrap, name_server, default_pager, unix, 1 spare | |
391 | */ | |
392 | #define MAXNOSYMTABS 6 | |
393 | ||
394 | db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0}}; | |
395 | int db_nsymtab = 0; | |
396 | ||
397 | db_symtab_t *db_last_symtab; | |
398 | ||
399 | unsigned long db_maxoff = 0x4000; | |
400 | extern char end; | |
401 | unsigned long db_maxval = (unsigned long)&end; | |
402 | natural_t db_minval = 0x1000; | |
403 | ||
404 | /* Prototypes for functions local to this file. XXX -- should be static! | |
405 | */ | |
406 | static char *db_qualify( | |
407 | char *sym, | |
408 | register char *symtabname); | |
409 | ||
410 | boolean_t db_eqname( | |
411 | char *src, | |
412 | char *dst, | |
413 | unsigned c); | |
414 | ||
415 | boolean_t db_symbol_is_ambiguous(char *name); | |
416 | ||
417 | void db_shorten_filename(char **filenamep); | |
418 | ||
419 | void qsort_swap( | |
420 | register int *a, | |
421 | register int *b, | |
422 | register int size); | |
423 | ||
424 | void qsort_rotate( | |
425 | register int *a, | |
426 | register int *b, | |
427 | register int *c, | |
428 | register int size); | |
429 | ||
430 | void qsort_recur( | |
431 | char *left, | |
432 | char *right, | |
433 | int eltsize, | |
434 | int (*compfun)(char *, char *)); | |
435 | ||
436 | void qsort_checker( | |
437 | char *table, | |
438 | int nbelts, | |
439 | int eltsize, | |
440 | int (*compfun)(char *, char *)); | |
441 | ||
442 | void bubble_sort( | |
443 | char *table, | |
444 | int nbelts, | |
445 | int eltsize, | |
446 | int (*compfun)(char *, char *)); | |
447 | ||
448 | int no_print_completion( | |
449 | db_symtab_t *stab, | |
450 | char *symstr ); | |
451 | int no_lookup_incomplete( | |
452 | db_symtab_t *stab, | |
453 | char *symstr, | |
454 | char **name, | |
455 | int *len, | |
456 | int *toadd); | |
457 | ||
458 | /* | |
459 | * Initialization routine for ddb. | |
460 | */ | |
461 | void | |
462 | ddb_init(void) | |
463 | { | |
464 | X_db_init(); | |
465 | db_machdep_init(); | |
466 | } | |
467 | ||
468 | /* | |
469 | * Add symbol table, with given name, to list of symbol tables. | |
470 | */ | |
471 | boolean_t | |
472 | db_add_symbol_table( | |
473 | int type, | |
474 | char *start, | |
475 | char *end, | |
476 | char *name, | |
477 | char *ref, | |
478 | char *map_pointer, | |
479 | unsigned long minsym, | |
480 | unsigned long maxsym, | |
481 | boolean_t sorted) | |
482 | { | |
483 | register db_symtab_t *st; | |
484 | extern vm_map_t kernel_map; | |
485 | ||
486 | if (db_nsymtab >= MAXNOSYMTABS) | |
487 | return (FALSE); | |
488 | ||
489 | st = &db_symtabs[db_nsymtab]; | |
490 | st->type = type; | |
491 | st->start = start; | |
492 | st->end = end; | |
493 | st->private = ref; | |
494 | if (map_pointer == (char *)kernel_map || | |
495 | (VM_MAX_ADDRESS <= VM_MIN_KERNEL_ADDRESS && | |
496 | VM_MIN_KERNEL_ADDRESS <= minsym)) | |
497 | st->map_pointer = 0; | |
498 | else | |
499 | st->map_pointer = map_pointer; | |
500 | strcpy(st->name, name); | |
501 | st->minsym = minsym; | |
502 | st->maxsym = maxsym; | |
503 | if (maxsym == 0) | |
504 | st->sorted = FALSE; | |
505 | else { | |
506 | st->sorted = sorted; | |
507 | if (db_maxval < maxsym + db_maxoff) | |
508 | db_maxval = maxsym + db_maxoff; | |
509 | } | |
510 | db_nsymtab++; | |
511 | ||
512 | return (TRUE); | |
513 | } | |
514 | ||
515 | /* | |
516 | * db_qualify("vm_map", "ux") returns "ux::vm_map". | |
517 | * | |
518 | * Note: return value points to static data whose content is | |
519 | * overwritten by each call... but in practice this seems okay. | |
520 | */ | |
521 | static char * | |
522 | db_qualify( | |
523 | char *symname, | |
524 | register char *symtabname) | |
525 | { | |
526 | static char tmp[256]; | |
527 | register char *s; | |
528 | ||
529 | s = tmp; | |
530 | while (*s++ = *symtabname++) { | |
531 | } | |
532 | s[-1] = ':'; | |
533 | *s++ = ':'; | |
534 | while (*s++ = *symname++) { | |
535 | } | |
536 | return tmp; | |
537 | } | |
538 | ||
539 | ||
540 | boolean_t | |
541 | db_eqname( | |
542 | char *src, | |
543 | char *dst, | |
544 | unsigned c) | |
545 | { | |
546 | if (!strcmp(src, dst)) | |
547 | return (TRUE); | |
548 | if (src[0] == c) | |
549 | return (!strcmp(src+1,dst)); | |
550 | return (FALSE); | |
551 | } | |
552 | ||
553 | boolean_t | |
554 | db_value_of_name( | |
555 | char *name, | |
556 | db_expr_t *valuep) | |
557 | { | |
558 | db_sym_t sym; | |
559 | ||
560 | sym = db_lookup(name); | |
561 | if (sym == DB_SYM_NULL) | |
562 | return (FALSE); | |
563 | db_symbol_values(0, sym, &name, valuep); | |
564 | return (TRUE); | |
565 | } | |
566 | ||
567 | /* | |
568 | * Display list of possible completions for a symbol. | |
569 | */ | |
570 | void | |
571 | db_print_completion( | |
572 | char *symstr) | |
573 | { | |
574 | register int i; | |
575 | int symtab_start = 0; | |
576 | int symtab_end = db_nsymtab; | |
577 | register char *cp; | |
578 | int nsym = 0; | |
579 | char *name = (char *)0; | |
580 | int len; | |
581 | int toadd; | |
582 | ||
583 | /* | |
584 | * Look for, remove, and remember any symbol table specifier. | |
585 | */ | |
586 | for (cp = symstr; *cp; cp++) { | |
587 | if (*cp == ':' && cp[1] == ':') { | |
588 | *cp = '\0'; | |
589 | for (i = 0; i < db_nsymtab; i++) { | |
590 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
591 | symtab_start = i; | |
592 | symtab_end = i + 1; | |
593 | break; | |
594 | } | |
595 | } | |
596 | *cp = ':'; | |
597 | if (i == db_nsymtab) | |
598 | return; | |
599 | symstr = cp+2; | |
600 | } | |
601 | } | |
602 | ||
603 | /* | |
604 | * Look in the specified set of symbol tables. | |
605 | * Return on first match. | |
606 | */ | |
607 | for (i = symtab_start; i < symtab_end; i++) { | |
608 | if (X_db_print_completion(&db_symtabs[i], symstr)) | |
609 | break; | |
610 | } | |
611 | } | |
612 | ||
613 | /* | |
614 | * Lookup a (perhaps incomplete) symbol. | |
615 | * If the symbol has a qualifier (e.g., ux::vm_map), | |
616 | * then only the specified symbol table will be searched; | |
617 | * otherwise, all symbol tables will be searched. | |
618 | */ | |
619 | int | |
620 | db_lookup_incomplete( | |
621 | char *symstr, | |
622 | int symlen) | |
623 | { | |
624 | register int i; | |
625 | int symtab_start = 0; | |
626 | int symtab_end = db_nsymtab; | |
627 | register char *cp; | |
628 | int nsym = 0; | |
629 | char *name = (char *)0; | |
630 | int len; | |
631 | int toadd; | |
632 | ||
633 | /* | |
634 | * Look for, remove, and remember any symbol table specifier. | |
635 | */ | |
636 | for (cp = symstr; *cp; cp++) { | |
637 | if (*cp == ':' && cp[1] == ':') { | |
638 | *cp = '\0'; | |
639 | for (i = 0; i < db_nsymtab; i++) { | |
640 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
641 | symtab_start = i; | |
642 | symtab_end = i + 1; | |
643 | break; | |
644 | } | |
645 | } | |
646 | *cp = ':'; | |
647 | if (i == db_nsymtab) | |
648 | return 0; | |
649 | symstr = cp+2; | |
650 | } | |
651 | } | |
652 | ||
653 | /* | |
654 | * Look in the specified set of symbol tables. | |
655 | * Return on first match. | |
656 | */ | |
657 | for (i = symtab_start; i < symtab_end; i++) { | |
658 | nsym = X_db_lookup_incomplete(&db_symtabs[i], symstr, | |
659 | &name, &len, &toadd); | |
660 | if (nsym > 0) { | |
661 | if (toadd > 0) { | |
662 | len = strlen(symstr); | |
663 | if (len + toadd >= symlen) | |
664 | return 0; | |
665 | bcopy(&name[len], &symstr[len], toadd); | |
666 | symstr[len + toadd] = '\0'; | |
667 | } | |
668 | break; | |
669 | } | |
670 | } | |
671 | return nsym; | |
672 | } | |
673 | ||
674 | /* | |
675 | * Lookup a symbol. | |
676 | * If the symbol has a qualifier (e.g., ux::vm_map), | |
677 | * then only the specified symbol table will be searched; | |
678 | * otherwise, all symbol tables will be searched. | |
679 | */ | |
680 | db_sym_t | |
681 | db_lookup(char *symstr) | |
682 | { | |
683 | db_sym_t sp; | |
684 | register int i; | |
685 | int symtab_start = 0; | |
686 | int symtab_end = db_nsymtab; | |
687 | register char *cp; | |
688 | ||
689 | /* | |
690 | * Look for, remove, and remember any symbol table specifier. | |
691 | */ | |
692 | for (cp = symstr; *cp; cp++) { | |
693 | if (*cp == ':' && cp[1] == ':') { | |
694 | *cp = '\0'; | |
695 | for (i = 0; i < db_nsymtab; i++) { | |
696 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
697 | symtab_start = i; | |
698 | symtab_end = i + 1; | |
699 | break; | |
700 | } | |
701 | } | |
702 | *cp = ':'; | |
703 | if (i == db_nsymtab) | |
704 | db_error("Invalid symbol table name\n"); | |
705 | symstr = cp+2; | |
706 | } | |
707 | } | |
708 | ||
709 | /* | |
710 | * Look in the specified set of symbol tables. | |
711 | * Return on first match. | |
712 | */ | |
713 | for (i = symtab_start; i < symtab_end; i++) { | |
714 | if (sp = X_db_lookup(&db_symtabs[i], symstr)) { | |
715 | db_last_symtab = &db_symtabs[i]; | |
716 | return sp; | |
717 | } | |
718 | } | |
719 | return 0; | |
720 | } | |
721 | ||
722 | /* | |
723 | * Print a symbol completion | |
724 | */ | |
725 | void | |
726 | db_sym_print_completion( | |
727 | db_symtab_t *stab, | |
728 | char *name, | |
729 | int function, | |
730 | char *fname, | |
731 | int line) | |
732 | { | |
733 | if (stab != db_symtabs) | |
734 | db_printf("%s::", stab->name); | |
735 | db_printf(name); | |
736 | if (function) { | |
737 | db_putchar('('); | |
738 | db_putchar(')'); | |
739 | } | |
740 | if (fname) { | |
741 | db_printf(" [static from %s", fname); | |
742 | if (line > 0) | |
743 | db_printf(":%d", line); | |
744 | db_putchar(']'); | |
745 | } | |
746 | db_putchar('\n'); | |
747 | } | |
748 | ||
749 | /* | |
750 | * Common utility routine to parse a symbol string into a file | |
751 | * name, a (possibly incomplete) symbol name without line number. | |
752 | * This routine is called from aout_db_print_completion if the object | |
753 | * dependent handler supports qualified search with a file name. | |
754 | * It parses the symbol string, and call an object dependent routine | |
755 | * with parsed file name and symbol name. | |
756 | */ | |
757 | int | |
758 | db_sym_parse_and_print_completion( | |
759 | int (*func)(db_symtab_t *, | |
760 | char *), | |
761 | db_symtab_t *symtab, | |
762 | char *symstr) | |
763 | { | |
764 | register char *p; | |
765 | register int n; | |
766 | char *sym_name; | |
767 | char *component[2]; | |
768 | int nsym; | |
769 | ||
770 | /* | |
771 | * disassemble the symbol into components: [file_name:]symbol | |
772 | */ | |
773 | component[0] = symstr; | |
774 | component[1] = 0; | |
775 | for (p = symstr, n = 1; *p; p++) { | |
776 | if (*p == ':') { | |
777 | if (n == 2) | |
778 | break; | |
779 | *p = 0; | |
780 | component[n++] = p+1; | |
781 | } | |
782 | } | |
783 | if (*p == 0) { | |
784 | if (n == 1) { | |
785 | sym_name = component[0]; | |
786 | } else { | |
787 | sym_name = component[1]; | |
788 | } | |
789 | nsym = func(symtab, sym_name); | |
790 | } else | |
791 | nsym = 0; | |
792 | if (n == 2) | |
793 | component[1][-1] = ':'; | |
794 | return nsym; | |
795 | } | |
796 | ||
797 | /* | |
798 | * Common utility routine to parse a symbol string into a file | |
799 | * name, a (possibly incomplete) symbol name without line number. | |
800 | * This routine is called from X_db_lookup_incomplete if the object | |
801 | * dependent handler supports qualified search with a file name. | |
802 | * It parses the symbol string, and call an object dependent routine | |
803 | * with parsed file name and symbol name. | |
804 | */ | |
805 | int | |
806 | db_sym_parse_and_lookup_incomplete( | |
807 | int (*func)(db_symtab_t *, | |
808 | char *, | |
809 | char *, | |
810 | int, | |
811 | db_sym_t*, | |
812 | char **, | |
813 | int *), | |
814 | db_symtab_t *symtab, | |
815 | char *symstr, | |
816 | char **name, | |
817 | int *len, | |
818 | int *toadd) | |
819 | { | |
820 | register char *p; | |
821 | register int n; | |
822 | char *file_name = 0; | |
823 | char *sym_name = 0; | |
824 | char *component[2]; | |
825 | int nsym = 0; | |
826 | ||
827 | /* | |
828 | * disassemble the symbol into components: [file_name:]symbol | |
829 | */ | |
830 | component[0] = symstr; | |
831 | component[1] = 0; | |
832 | for (p = symstr, n = 1; *p; p++) { | |
833 | if (*p == ':') { | |
834 | if (n == 2) | |
835 | break; | |
836 | *p = 0; | |
837 | component[n++] = p+1; | |
838 | } | |
839 | } | |
840 | if (*p == 0) { | |
841 | if (n == 1) { | |
842 | file_name = 0; | |
843 | sym_name = component[0]; | |
844 | } else { | |
845 | file_name = component[0]; | |
846 | sym_name = component[1]; | |
847 | } | |
848 | nsym = func(symtab, file_name, sym_name, 0, (db_sym_t *)0, | |
849 | name, len); | |
850 | if (nsym > 0) | |
851 | *toadd = *len - strlen(sym_name); | |
852 | } | |
853 | if (n == 2) | |
854 | component[1][-1] = ':'; | |
855 | return(nsym); | |
856 | } | |
857 | ||
858 | /* | |
859 | * Common utility routine to parse a symbol string into a file | |
860 | * name, a symbol name and line number. | |
861 | * This routine is called from aout_db_lookup if the object dependent | |
862 | * handler supports qualified search with a file name or a line number. | |
863 | * It parses the symbol string, and call an object dependent routine | |
864 | * with parsed file name, symbol name and line number. | |
865 | */ | |
866 | db_sym_t | |
867 | db_sym_parse_and_lookup( | |
868 | int (*func)(db_symtab_t *, char *, char *, int, | |
869 | db_sym_t*, char **, int *), | |
870 | db_symtab_t *symtab, | |
871 | char *symstr) | |
872 | { | |
873 | register char *p; | |
874 | register int n; | |
875 | int n_name; | |
876 | int line_number; | |
877 | char *file_name = 0; | |
878 | char *sym_name = 0; | |
879 | char *component[3]; | |
880 | db_sym_t found = DB_SYM_NULL; | |
881 | ||
882 | /* | |
883 | * disassemble the symbol into components: | |
884 | * [file_name:]symbol[:line_nubmer] | |
885 | */ | |
886 | component[0] = symstr; | |
887 | component[1] = component[2] = 0; | |
888 | for (p = symstr, n = 1; *p; p++) { | |
889 | if (*p == ':') { | |
890 | if (n >= 3) | |
891 | break; | |
892 | *p = 0; | |
893 | component[n++] = p+1; | |
894 | } | |
895 | } | |
896 | if (*p != 0) | |
897 | goto out; | |
898 | line_number = 0; | |
899 | n_name = n; | |
900 | p = component[n-1]; | |
901 | if (*p >= '0' && *p <= '9') { | |
902 | if (n == 1) | |
903 | goto out; | |
904 | for (line_number = 0; *p; p++) { | |
905 | if (*p < '0' || *p > '9') | |
906 | goto out; | |
907 | line_number = line_number*10 + *p - '0'; | |
908 | } | |
909 | n_name--; | |
910 | } else if (n >= 3) | |
911 | goto out; | |
912 | if (n_name == 1) { | |
913 | for (p = component[0]; *p && *p != '.'; p++); | |
914 | if (*p == '.') { | |
915 | file_name = component[0]; | |
916 | sym_name = 0; | |
917 | } else { | |
918 | file_name = 0; | |
919 | sym_name = component[0]; | |
920 | } | |
921 | } else { | |
922 | file_name = component[0]; | |
923 | sym_name = component[1]; | |
924 | } | |
925 | (void) func(symtab, file_name, sym_name, line_number, &found, | |
926 | (char **)0, (int *)0); | |
927 | ||
928 | out: | |
929 | while (--n >= 1) | |
930 | component[n][-1] = ':'; | |
931 | return(found); | |
932 | } | |
933 | ||
934 | /* | |
935 | * Does this symbol name appear in more than one symbol table? | |
936 | * Used by db_symbol_values to decide whether to qualify a symbol. | |
937 | */ | |
938 | boolean_t db_qualify_ambiguous_names = TRUE; | |
939 | ||
940 | boolean_t | |
941 | db_symbol_is_ambiguous(char *name) | |
942 | { | |
943 | register int i; | |
944 | register | |
945 | boolean_t found_once = FALSE; | |
946 | ||
947 | if (!db_qualify_ambiguous_names) | |
948 | return FALSE; | |
949 | ||
950 | for (i = 0; i < db_nsymtab; i++) { | |
951 | if (X_db_lookup(&db_symtabs[i], name)) { | |
952 | if (found_once) | |
953 | return TRUE; | |
954 | found_once = TRUE; | |
955 | } | |
956 | } | |
957 | return FALSE; | |
958 | } | |
959 | ||
960 | /* | |
961 | * Find the closest symbol to val, and return its name | |
962 | * and the difference between val and the symbol found. | |
963 | */ | |
964 | unsigned int db_search_maxoff = 0x4000; | |
965 | db_sym_t | |
966 | db_search_task_symbol( | |
967 | register db_addr_t val, | |
968 | db_strategy_t strategy, | |
969 | db_addr_t *offp, /* better be unsigned */ | |
970 | task_t task) | |
971 | { | |
972 | unsigned long diff, newdiff; | |
973 | register int i; | |
974 | db_symtab_t *sp; | |
975 | db_sym_t ret = DB_SYM_NULL, sym; | |
976 | vm_map_t map_for_val; | |
977 | ||
978 | if (task == TASK_NULL) | |
979 | task = db_current_task(); | |
980 | map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map; | |
981 | again: | |
982 | newdiff = diff = ~0UL; | |
983 | db_last_symtab = 0; | |
984 | for (sp = &db_symtabs[0], i = 0; | |
985 | i < db_nsymtab; | |
986 | sp++, i++) { | |
987 | if (((vm_map_t)sp->map_pointer == VM_MAP_NULL || | |
988 | (vm_map_t)sp->map_pointer == map_for_val) && | |
989 | (sp->maxsym == 0 || | |
990 | ((unsigned long) val >= sp->minsym && | |
991 | (unsigned long) val <= sp->maxsym))) { | |
992 | sym = X_db_search_symbol(sp, val, strategy, | |
993 | (db_expr_t *)&newdiff); | |
994 | if (newdiff < diff) { | |
995 | db_last_symtab = sp; | |
996 | diff = newdiff; | |
997 | ret = sym; | |
998 | if (diff <= db_search_maxoff) | |
999 | break; | |
1000 | } | |
1001 | } | |
1002 | } | |
1003 | if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) { | |
1004 | map_for_val = VM_MAP_NULL; | |
1005 | goto again; | |
1006 | } | |
1007 | *offp = diff; | |
1008 | return ret; | |
1009 | } | |
1010 | ||
1011 | /* | |
1012 | * Find the closest symbol to val, and return its name | |
1013 | * and the difference between val and the symbol found. | |
1014 | * Also return the filename and linenumber if available. | |
1015 | */ | |
1016 | db_sym_t | |
1017 | db_search_task_symbol_and_line( | |
1018 | register db_addr_t val, | |
1019 | db_strategy_t strategy, | |
1020 | db_expr_t *offp, | |
1021 | char **filenamep, | |
1022 | int *linenump, | |
1023 | task_t task, | |
1024 | int *argsp) | |
1025 | { | |
1026 | unsigned long diff, newdiff; | |
1027 | register int i; | |
1028 | db_symtab_t *sp; | |
1029 | db_sym_t ret = DB_SYM_NULL, sym; | |
1030 | vm_map_t map_for_val; | |
1031 | char *func; | |
1032 | char *filename; | |
1033 | int linenum; | |
1034 | int args; | |
1035 | ||
1036 | if (task == TASK_NULL) | |
1037 | task = db_current_task(); | |
1038 | map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map; | |
1039 | *filenamep = (char *) 0; | |
1040 | *linenump = 0; | |
1041 | *argsp = -1; | |
1042 | again: | |
1043 | filename = (char *) 0; | |
1044 | linenum = 0; | |
1045 | newdiff = diff = ~0UL; | |
1046 | db_last_symtab = 0; | |
1047 | for (sp = &db_symtabs[0], i = 0; | |
1048 | i < db_nsymtab; | |
1049 | sp++, i++) { | |
1050 | if (((vm_map_t)sp->map_pointer == VM_MAP_NULL || | |
1051 | (vm_map_t)sp->map_pointer == map_for_val) && | |
1052 | (sp->maxsym == 0 || | |
1053 | ((unsigned long) val >= sp->minsym && | |
1054 | (unsigned long) val <= sp->maxsym))) { | |
1055 | sym = X_db_search_by_addr(sp, val, &filename, &func, | |
1056 | &linenum, (db_expr_t *)&newdiff, | |
1057 | &args); | |
1058 | if (sym && newdiff < diff) { | |
1059 | db_last_symtab = sp; | |
1060 | diff = newdiff; | |
1061 | ret = sym; | |
1062 | *filenamep = filename; | |
1063 | *linenump = linenum; | |
1064 | *argsp = args; | |
1065 | if (diff <= db_search_maxoff) | |
1066 | break; | |
1067 | } | |
1068 | } | |
1069 | } | |
1070 | if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) { | |
1071 | map_for_val = VM_MAP_NULL; | |
1072 | goto again; | |
1073 | } | |
1074 | *offp = diff; | |
1075 | if (*filenamep) | |
1076 | db_shorten_filename(filenamep); | |
1077 | return ret; | |
1078 | } | |
1079 | ||
1080 | /* | |
1081 | * Return name and value of a symbol | |
1082 | */ | |
1083 | void | |
1084 | db_symbol_values( | |
1085 | db_symtab_t *stab, | |
1086 | db_sym_t sym, | |
1087 | char **namep, | |
1088 | db_expr_t *valuep) | |
1089 | { | |
1090 | db_expr_t value; | |
1091 | char *name; | |
1092 | ||
1093 | if (sym == DB_SYM_NULL) { | |
1094 | *namep = 0; | |
1095 | return; | |
1096 | } | |
1097 | if (stab == 0) | |
1098 | stab = db_last_symtab; | |
1099 | ||
1100 | X_db_symbol_values(stab, sym, &name, &value); | |
1101 | ||
1102 | if (db_symbol_is_ambiguous(name)) { | |
1103 | *namep = db_qualify(name, db_last_symtab->name); | |
1104 | }else { | |
1105 | *namep = name; | |
1106 | } | |
1107 | if (valuep) | |
1108 | *valuep = value; | |
1109 | } | |
1110 | ||
1111 | ||
1112 | /* | |
1113 | * Print a the closest symbol to value | |
1114 | * | |
1115 | * After matching the symbol according to the given strategy | |
1116 | * we print it in the name+offset format, provided the symbol's | |
1117 | * value is close enough (eg smaller than db_maxoff). | |
1118 | * We also attempt to print [filename:linenum] when applicable | |
1119 | * (eg for procedure names). | |
1120 | * | |
1121 | * If we could not find a reasonable name+offset representation, | |
1122 | * then we just print the value in hex. Small values might get | |
1123 | * bogus symbol associations, e.g. 3 might get some absolute | |
1124 | * value like _INCLUDE_VERSION or something, therefore we do | |
1125 | * not accept symbols whose value is zero (and use plain hex). | |
1126 | */ | |
1127 | ||
1128 | void | |
1129 | db_task_printsym( | |
1130 | db_expr_t off, | |
1131 | db_strategy_t strategy, | |
1132 | task_t task) | |
1133 | { | |
1134 | db_addr_t d; | |
1135 | char *filename; | |
1136 | char *name; | |
1137 | db_expr_t value; | |
1138 | int linenum; | |
1139 | db_sym_t cursym; | |
1140 | ||
1141 | if (off >= db_maxval || off < db_minval) { | |
1142 | db_printf("%#n", off); | |
1143 | return; | |
1144 | } | |
1145 | cursym = db_search_task_symbol(off, strategy, &d, task); | |
1146 | ||
1147 | db_symbol_values(0, cursym, &name, &value); | |
1148 | if (name == 0 || d >= db_maxoff || value == 0) { | |
1149 | db_printf("%#n", off); | |
1150 | return; | |
1151 | } | |
1152 | db_printf("%s", name); | |
1153 | if (d) | |
1154 | db_printf("+0x%x", d); | |
1155 | if (strategy == DB_STGY_PROC) { | |
1156 | if (db_line_at_pc(cursym, &filename, &linenum, off)) { | |
1157 | db_printf(" [%s", filename); | |
1158 | if (linenum > 0) | |
1159 | db_printf(":%d", linenum); | |
1160 | db_printf("]"); | |
1161 | } | |
1162 | } | |
1163 | } | |
1164 | ||
1165 | /* | |
1166 | * Return symbol name for a given offset and | |
1167 | * change the offset to be relative to this symbol. | |
1168 | * Very usefull for xpr, when you want to log offsets | |
1169 | * in a user friendly way. | |
1170 | */ | |
1171 | ||
1172 | char null_sym[] = ""; | |
1173 | ||
1174 | char * | |
1175 | db_get_sym(db_expr_t *off) | |
1176 | { | |
1177 | db_sym_t cursym; | |
1178 | db_expr_t value; | |
1179 | char *name; | |
1180 | db_addr_t d; | |
1181 | ||
1182 | cursym = db_search_symbol(*off, DB_STGY_ANY, &d); | |
1183 | db_symbol_values(0, cursym, &name, &value); | |
1184 | if (name) | |
1185 | *off = d; | |
1186 | else | |
1187 | name = null_sym; | |
1188 | return(name); | |
1189 | } | |
1190 | ||
1191 | void | |
1192 | db_printsym( | |
1193 | db_expr_t off, | |
1194 | db_strategy_t strategy) | |
1195 | { | |
1196 | db_task_printsym(off, strategy, TASK_NULL); | |
1197 | } | |
1198 | ||
1199 | int db_short_filename = 1; | |
1200 | ||
1201 | void | |
1202 | db_shorten_filename(char **filenamep) | |
1203 | { | |
1204 | char *cp, *cp_slash; | |
1205 | ||
1206 | if (! *filenamep) | |
1207 | return; | |
1208 | for (cp = cp_slash = *filenamep; *cp; cp++) { | |
1209 | if (*cp == '/') | |
1210 | cp_slash = cp; | |
1211 | } | |
1212 | if (*cp_slash == '/') | |
1213 | *filenamep = cp_slash+1; | |
1214 | } | |
1215 | ||
1216 | int | |
1217 | db_task_getlinenum( | |
1218 | db_expr_t off, | |
1219 | task_t task) | |
1220 | { | |
1221 | db_addr_t d; | |
1222 | char *filename; | |
1223 | char *name; | |
1224 | db_expr_t value; | |
1225 | int linenum; | |
1226 | db_sym_t cursym; | |
1227 | db_strategy_t strategy = DB_STGY_PROC; | |
1228 | ||
1229 | if (off >= db_maxval || off < db_minval) { | |
1230 | db_printf("%#n", off); | |
1231 | return(-1); | |
1232 | } | |
1233 | cursym = db_search_task_symbol(off, strategy, &d, task); | |
1234 | ||
1235 | db_symbol_values(0, cursym, &name, &value); | |
1236 | if (name == 0 || d >= db_maxoff || value == 0) { | |
1237 | return(-1); | |
1238 | } | |
1239 | if (db_line_at_pc(cursym, &filename, &linenum, off)) | |
1240 | return(linenum); | |
1241 | else | |
1242 | return(-1); | |
1243 | } | |
1244 | ||
1245 | boolean_t | |
1246 | db_line_at_pc( | |
1247 | db_sym_t sym, | |
1248 | char **filename, | |
1249 | int *linenum, | |
1250 | db_expr_t pc) | |
1251 | { | |
1252 | boolean_t result; | |
1253 | ||
1254 | if (db_last_symtab == 0) | |
1255 | return FALSE; | |
1256 | if (X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc)) { | |
1257 | if (db_short_filename) | |
1258 | db_shorten_filename(filename); | |
1259 | result = TRUE; | |
1260 | } else | |
1261 | result = FALSE; | |
1262 | return(result); | |
1263 | } | |
1264 | ||
1265 | int qsort_check = 0; | |
1266 | ||
1267 | void | |
1268 | db_qsort( | |
1269 | char *table, | |
1270 | int nbelts, | |
1271 | int eltsize, | |
1272 | int (*compfun)(char *, char *)) | |
1273 | { | |
1274 | if (nbelts <= 0 || eltsize <= 0 || compfun == 0) { | |
1275 | printf("qsort: invalid parameters\n"); | |
1276 | return; | |
1277 | } | |
1278 | qsort_recur(table, table + nbelts * eltsize, eltsize, compfun); | |
1279 | ||
1280 | if (qsort_check) | |
1281 | qsort_checker(table, nbelts, eltsize, compfun); | |
1282 | } | |
1283 | ||
1284 | void | |
1285 | qsort_swap( | |
1286 | register int *a, | |
1287 | register int *b, | |
1288 | register int size) | |
1289 | { | |
1290 | register int temp; | |
1291 | char *aa, *bb; | |
1292 | char ctemp; | |
1293 | ||
1294 | for (; size >= sizeof (int); size -= sizeof (int), a++, b++) { | |
1295 | temp = *a; | |
1296 | *a = *b; | |
1297 | *b = temp; | |
1298 | } | |
1299 | aa = (char *)a; | |
1300 | bb = (char *)b; | |
1301 | for (; size > 0; size--, aa++, bb++) { | |
1302 | ctemp = *aa; | |
1303 | *aa = *bb; | |
1304 | *bb = ctemp; | |
1305 | } | |
1306 | } | |
1307 | ||
1308 | /* rotate the three elements to the left */ | |
1309 | void | |
1310 | qsort_rotate( | |
1311 | register int *a, | |
1312 | register int *b, | |
1313 | register int *c, | |
1314 | register int size) | |
1315 | { | |
1316 | register int temp; | |
1317 | char *aa, *bb, *cc; | |
1318 | char ctemp; | |
1319 | ||
1320 | for (; size >= sizeof (int); size -= sizeof (int), a++, b++, c++) { | |
1321 | temp = *a; | |
1322 | *a = *c; | |
1323 | *c = *b; | |
1324 | *b = temp; | |
1325 | } | |
1326 | aa = (char *)a; | |
1327 | bb = (char *)b; | |
1328 | cc = (char *)c; | |
1329 | for (; size > 0; size--, aa++, bb++, cc++) { | |
1330 | ctemp = *aa; | |
1331 | *aa = *cc; | |
1332 | *cc = *bb; | |
1333 | *bb = ctemp; | |
1334 | } | |
1335 | } | |
1336 | ||
1337 | void | |
1338 | qsort_recur( | |
1339 | char *left, | |
1340 | char *right, | |
1341 | int eltsize, | |
1342 | int (*compfun)(char *, char *)) | |
1343 | { | |
1344 | char *i, *j; | |
1345 | char *sameleft, *sameright; | |
1346 | ||
1347 | top: | |
1348 | if (left + eltsize - 1 >= right) { | |
1349 | return; | |
1350 | } | |
1351 | ||
1352 | /* partition element (reference for "same"ness */ | |
1353 | sameleft = left + (((right - left) / eltsize) / 2) * eltsize; | |
1354 | sameright = sameleft; | |
1355 | ||
1356 | i = left; | |
1357 | j = right - eltsize; | |
1358 | ||
1359 | again: | |
1360 | while (i < sameleft) { | |
1361 | int comp; | |
1362 | ||
1363 | comp = (*compfun)(i, sameleft); | |
1364 | if (comp == 0) { | |
1365 | /* | |
1366 | * Move to the "same" partition. | |
1367 | */ | |
1368 | /* | |
1369 | * Shift the left part of the "same" partition to | |
1370 | * the left, so that "same" elements stay in their | |
1371 | * original order. | |
1372 | */ | |
1373 | sameleft -= eltsize; | |
1374 | qsort_swap((int *) i, (int *) sameleft, eltsize); | |
1375 | } else if (comp < 0) { | |
1376 | /* | |
1377 | * Stay in the "left" partition. | |
1378 | */ | |
1379 | i += eltsize; | |
1380 | } else { | |
1381 | /* | |
1382 | * Should be moved to the "right" partition. | |
1383 | * Wait until the next loop finds an appropriate | |
1384 | * place to store this element. | |
1385 | */ | |
1386 | break; | |
1387 | } | |
1388 | } | |
1389 | ||
1390 | while (j > sameright) { | |
1391 | int comp; | |
1392 | ||
1393 | comp = (*compfun)(sameright, j); | |
1394 | if (comp == 0) { | |
1395 | /* | |
1396 | * Move to the right of the "same" partition. | |
1397 | */ | |
1398 | sameright += eltsize; | |
1399 | qsort_swap((int *) sameright, (int *) j, eltsize); | |
1400 | } else if (comp > 0) { | |
1401 | /* | |
1402 | * Move to the "left" partition. | |
1403 | */ | |
1404 | if (i == sameleft) { | |
1405 | /* | |
1406 | * Unfortunately, the "left" partition | |
1407 | * has already been fully processed, so | |
1408 | * we have to shift the "same" partition | |
1409 | * to the right to free a "left" element. | |
1410 | * This is done by moving the leftest same | |
1411 | * to the right of the "same" partition. | |
1412 | */ | |
1413 | sameright += eltsize; | |
1414 | qsort_rotate((int *) sameleft, (int*) sameright, | |
1415 | (int *) j, eltsize); | |
1416 | sameleft += eltsize; | |
1417 | i = sameleft; | |
1418 | } else { | |
1419 | /* | |
1420 | * Swap with the "left" partition element | |
1421 | * waiting to be moved to the "right" | |
1422 | * partition. | |
1423 | */ | |
1424 | qsort_swap((int *) i, (int *) j, eltsize); | |
1425 | j -= eltsize; | |
1426 | /* | |
1427 | * Go back to the 1st loop. | |
1428 | */ | |
1429 | i += eltsize; | |
1430 | goto again; | |
1431 | } | |
1432 | } else { | |
1433 | /* | |
1434 | * Stay in the "right" partition. | |
1435 | */ | |
1436 | j -= eltsize; | |
1437 | } | |
1438 | } | |
1439 | ||
1440 | if (i != sameleft) { | |
1441 | /* | |
1442 | * The second loop completed (the"right" partition is ok), | |
1443 | * but we have to go back to the first loop, and deal with | |
1444 | * the element waiting for a place in the "right" partition. | |
1445 | * Let's shift the "same" zone to the left. | |
1446 | */ | |
1447 | sameleft -= eltsize; | |
1448 | qsort_rotate((int *) sameright, (int *) sameleft, (int *) i, | |
1449 | eltsize); | |
1450 | sameright -= eltsize; | |
1451 | j = sameright; | |
1452 | /* | |
1453 | * Go back to 1st loop. | |
1454 | */ | |
1455 | goto again; | |
1456 | } | |
1457 | ||
1458 | /* | |
1459 | * The partitions are correct now. Recur on the smallest side only. | |
1460 | */ | |
1461 | if (sameleft - left >= right - (sameright + eltsize)) { | |
1462 | qsort_recur(sameright + eltsize, right, eltsize, compfun); | |
1463 | /* | |
1464 | * The "right" partition is now completely sorted. | |
1465 | * The "same" partition is OK, so... | |
1466 | * Ignore them, and start the loops again on the | |
1467 | * "left" partition. | |
1468 | */ | |
1469 | right = sameleft; | |
1470 | goto top; | |
1471 | } else { | |
1472 | qsort_recur(left, sameleft, eltsize, compfun); | |
1473 | /* | |
1474 | * The "left" partition is now completely sorted. | |
1475 | * The "same" partition is OK, so ... | |
1476 | * Ignore them, and start the loops again on the | |
1477 | * "right" partition. | |
1478 | */ | |
1479 | left = sameright + eltsize; | |
1480 | goto top; | |
1481 | } | |
1482 | } | |
1483 | ||
1484 | void | |
1485 | qsort_checker( | |
1486 | char *table, | |
1487 | int nbelts, | |
1488 | int eltsize, | |
1489 | int (*compfun)(char *, char *)) | |
1490 | { | |
1491 | char *curr, *prev, *last; | |
1492 | ||
1493 | prev = table; | |
1494 | curr = prev + eltsize; | |
1495 | last = table + (nbelts * eltsize); | |
1496 | ||
1497 | while (prev < last) { | |
1498 | if ((*compfun)(prev, curr) > 0) { | |
1499 | printf("**** qsort_checker: error between 0x%x and 0x%x!!!\n", prev, curr); | |
1500 | break; | |
1501 | } | |
1502 | prev = curr; | |
1503 | curr += eltsize; | |
1504 | } | |
1505 | printf("qsort_checker: OK\n"); | |
1506 | } | |
1507 | ||
1508 | int qsort_search_debug = 0; | |
1509 | ||
1510 | void | |
1511 | db_qsort_limit_search( | |
1512 | char *target, | |
1513 | char **start, | |
1514 | char **end, | |
1515 | int eltsize, | |
1516 | int (*compfun)(char *, char *)) | |
1517 | { | |
1518 | register char *left, *right; | |
1519 | char *oleft, *oright, *part; | |
1520 | int nbiter = 0; | |
1521 | int comp; | |
1522 | ||
1523 | oleft = left = *start; | |
1524 | oright = right = *end; | |
1525 | part = (char *) 0; | |
1526 | ||
1527 | while (left < right) { | |
1528 | nbiter++; | |
1529 | part = left + (((right - left) / eltsize) / 2) * eltsize; | |
1530 | comp = (*compfun)(target, part); | |
1531 | if (comp > 0) { | |
1532 | oleft = left; | |
1533 | oright = right; | |
1534 | left = part; | |
1535 | if (left == oleft) | |
1536 | break; | |
1537 | if (qsort_search_debug > 1) | |
1538 | printf(" [ Moved left from 0x%x to 0x%x]\n", | |
1539 | oleft, left); | |
1540 | } else if (comp < 0) { | |
1541 | oright = right; | |
1542 | oleft = left; | |
1543 | right = part; | |
1544 | if (qsort_search_debug > 1) | |
1545 | printf(" [ Moved right from 0x%x to 0x%x]\n", | |
1546 | oright, right); | |
1547 | } else { | |
1548 | if (qsort_search_debug > 1) | |
1549 | printf(" [ FOUND! left=0x%x right=0x%x]\n", | |
1550 | left, right); | |
1551 | for (left = part; | |
1552 | left > *start && (*compfun)(left, part) == 0; | |
1553 | left -= eltsize); | |
1554 | for (right = part + eltsize; | |
1555 | right < *end && (*compfun)(right, part) == 0; | |
1556 | right += eltsize); | |
1557 | oright = right; | |
1558 | oleft = left; | |
1559 | break; | |
1560 | } | |
1561 | } | |
1562 | ||
1563 | if (qsort_search_debug) | |
1564 | printf("[ Limited from %x-%x to %x-%x in %d iters ]\n", | |
1565 | *start, *end, oleft, oright, nbiter); | |
1566 | *start = oleft; | |
1567 | *end = oright; | |
1568 | } | |
1569 | ||
1570 | void | |
1571 | bubble_sort( | |
1572 | char *table, | |
1573 | int nbelts, | |
1574 | int eltsize, | |
1575 | int (*compfun)(char *, char *)) | |
1576 | { | |
1577 | boolean_t sorted; | |
1578 | char *end; | |
1579 | register char *p; | |
1580 | ||
1581 | end = table + ((nbelts-1) * eltsize); | |
1582 | do { | |
1583 | sorted = TRUE; | |
1584 | for (p = table; p < end; p += eltsize) { | |
1585 | if ((*compfun)(p, p + eltsize) > 0) { | |
1586 | qsort_swap((int *) p, (int *) (p + eltsize), | |
1587 | eltsize); | |
1588 | sorted = FALSE; | |
1589 | } | |
1590 | } | |
1591 | } while (sorted == FALSE); | |
1592 | ||
1593 | if (qsort_check) | |
1594 | qsort_checker(table, nbelts, eltsize, compfun); | |
1595 | } | |
1596 | ||
1597 | vm_offset_t vm_min_inks_addr = VM_MAX_KERNEL_ADDRESS; | |
1598 | ||
1599 | void | |
1600 | db_install_inks( | |
1601 | vm_offset_t base) | |
1602 | { | |
1603 | /* save addr to demarcate kernel/inks boundary (1st time only) */ | |
1604 | if (vm_min_inks_addr == VM_MAX_KERNEL_ADDRESS) { | |
1605 | vm_min_inks_addr = base; | |
1606 | db_qualify_ambiguous_names = TRUE; | |
1607 | } | |
1608 | } | |
1609 | ||
1610 | ||
1611 | void | |
1612 | db_clone_symtabXXX( | |
1613 | char *clonee, /* which symtab to clone */ | |
1614 | char *cloner, /* in-kernel-server name */ | |
1615 | vm_offset_t base) /* base address of cloner */ | |
1616 | { | |
1617 | db_symtab_t *st, *st_src; | |
1618 | char * memp; | |
1619 | vm_size_t size; | |
1620 | long offset; | |
1621 | extern vm_offset_t kalloc(vm_size_t); | |
1622 | extern void db_clone_offsetXXX(char *, long); | |
1623 | ||
1624 | if (db_nsymtab >= MAXNOSYMTABS) { | |
1625 | db_printf("db_clone_symtab: Too Many Symbol Tables\n"); | |
1626 | return; | |
1627 | } | |
1628 | ||
1629 | db_install_inks(base); | |
1630 | ||
1631 | st = &db_symtabs[db_nsymtab]; /* destination symtab */ | |
1632 | if ((st_src = db_symtab_cloneeXXX(clonee)) == 0) { | |
1633 | db_printf("db_clone_symtab: clonee (%s) not found\n", clonee); | |
1634 | return; | |
1635 | } | |
1636 | /* alloc new symbols */ | |
1637 | size = (vm_size_t)(st_src->end - st_src->private); | |
de355530 | 1638 | memp = (char *)kalloc( round_page(size) ); |
1c79356b A |
1639 | if (!memp) { |
1640 | db_printf("db_clone_symtab: no memory for symtab\n"); | |
1641 | return; | |
1642 | } | |
1643 | ||
1644 | *st = *st_src; /* bulk copy src -> dest */ | |
1645 | strcpy(st->name, cloner); /* new name */ | |
1646 | st->private = memp; /* copy symbols */ | |
1647 | bcopy((const char *)st_src->private, st->private, size); | |
1648 | st->start = memp + sizeof(int); /* fixup pointers to symtab */ | |
1649 | st->end = memp + *(int *)memp; | |
1650 | st->map_pointer = 0; /* no map because kernel-loaded */ | |
1651 | ||
1652 | /* Offset symbols, leaving strings pointing into st_src */ | |
1653 | offset = base - st_src->minsym; | |
1654 | st->minsym += offset; | |
1655 | st->maxsym += offset; | |
1656 | db_clone_offsetXXX(memp, offset); | |
1657 | db_nsymtab++; | |
1658 | ||
1659 | db_printf( "[ cloned symbol table for %s: range 0x%x to 0x%x %s]\n", | |
1660 | st->name, st->minsym, st->maxsym, | |
1661 | st->sorted ? "(sorted) " : ""); | |
1662 | db_maxval = (unsigned int)st->maxsym + db_maxoff; | |
1663 | } | |
1664 | ||
1665 | db_symtab_t * | |
1666 | db_symtab_cloneeXXX( | |
1667 | char *clonee) | |
1668 | { | |
1669 | db_symtab_t *st, *st_src; | |
1670 | ||
1671 | st = &db_symtabs[db_nsymtab]; /* destination symtab */ | |
1672 | for (st_src = &db_symtabs[0]; st_src < st; ++st_src) | |
1673 | if (!strcmp(clonee, st_src->name)) | |
1674 | break; | |
1675 | return ((st_src < st) ? st_src : 0); | |
1676 | } | |
1677 | ||
1678 | /* | |
1679 | * Switch into symbol-table specific routines | |
1680 | */ | |
1681 | ||
1682 | #if !defined(__alpha) && !defined(INTEL860) | |
1683 | #define DB_NO_COFF | |
1684 | #endif | |
1685 | ||
1686 | #ifndef DB_NO_AOUT | |
1687 | #include <ddb/db_aout.h> | |
1688 | #endif | |
1689 | ||
1690 | #ifndef DB_NO_COFF | |
1691 | #include <ddb/db_coff.h> | |
1692 | #endif | |
1693 | ||
1694 | static void no_init(void) | |
1695 | ||
1696 | { | |
1697 | db_printf("Non-existent code for ddb init\n"); | |
1698 | } | |
1699 | ||
1700 | static boolean_t no_sym_init( | |
1701 | char *start, | |
1702 | char *end, | |
1703 | char *name, | |
1704 | char *task_addr) | |
1705 | { | |
1706 | db_printf("Non-existent code for init of symtab %s\n", name); | |
1707 | return FALSE; | |
1708 | } | |
1709 | ||
1710 | static db_sym_t no_lookup( | |
1711 | db_symtab_t *stab, | |
1712 | char *symstr) | |
1713 | { | |
1714 | db_printf("Bogus lookup of symbol %s\n", symstr); | |
1715 | return DB_SYM_NULL; | |
1716 | } | |
1717 | ||
1718 | static db_sym_t no_search( | |
1719 | db_symtab_t *stab, | |
1720 | db_addr_t off, | |
1721 | db_strategy_t strategy, | |
1722 | db_expr_t *diffp) | |
1723 | { | |
1724 | db_printf("Bogus search for offset %#Xn", off); | |
1725 | return DB_SYM_NULL; | |
1726 | } | |
1727 | ||
1728 | static boolean_t no_line_at_pc( | |
1729 | db_symtab_t *stab, | |
1730 | db_sym_t sym, | |
1731 | char **file, | |
1732 | int *line, | |
1733 | db_expr_t pc) | |
1734 | { | |
1735 | db_printf("Bogus search for pc %#X\n", pc); | |
1736 | return FALSE; | |
1737 | } | |
1738 | ||
1739 | static void no_symbol_values( | |
1740 | db_sym_t sym, | |
1741 | char **namep, | |
1742 | db_expr_t *valuep) | |
1743 | { | |
1744 | db_printf("Bogus symbol value resolution\n"); | |
1745 | if (namep) *namep = NULL; | |
1746 | if (valuep) *valuep = 0; | |
1747 | } | |
1748 | ||
1749 | static db_sym_t no_search_by_addr( | |
1750 | db_symtab_t *stab, | |
1751 | db_addr_t off, | |
1752 | char **file, | |
1753 | char **func, | |
1754 | int *line, | |
1755 | db_expr_t *diffp, | |
1756 | int *args) | |
1757 | { | |
1758 | db_printf("Bogus search for address %#X\n", off); | |
1759 | return DB_SYM_NULL; | |
1760 | } | |
1761 | ||
1762 | int | |
1763 | no_print_completion( | |
1764 | db_symtab_t *stab, | |
1765 | char *symstr ) | |
1766 | { | |
1767 | db_printf("Bogus print completion: not supported\n"); | |
1768 | return 0; | |
1769 | } | |
1770 | ||
1771 | int | |
1772 | no_lookup_incomplete( | |
1773 | db_symtab_t *stab, | |
1774 | char *symstr, | |
1775 | char **name, | |
1776 | int *len, | |
1777 | int *toadd) | |
1778 | { | |
1779 | db_printf("Bogus lookup incomplete: not supported\n"); | |
1780 | return 0; | |
1781 | } | |
1782 | ||
1783 | #define NONE \ | |
1784 | { no_init, no_sym_init, no_lookup, no_search, \ | |
1785 | no_line_at_pc, no_symbol_values, no_search_by_addr, \ | |
1786 | no_print_completion, no_lookup_incomplete} | |
1787 | ||
1788 | struct db_sym_switch x_db[] = { | |
1789 | ||
1790 | /* BSD a.out format (really, sdb/dbx(1) symtabs) */ | |
1791 | #ifdef DB_NO_AOUT | |
1792 | NONE, | |
1793 | #else /* DB_NO_AOUT */ | |
1794 | { aout_db_init, aout_db_sym_init, aout_db_lookup, aout_db_search_symbol, | |
1795 | aout_db_line_at_pc, aout_db_symbol_values, aout_db_search_by_addr, | |
1796 | aout_db_print_completion, aout_db_lookup_incomplete}, | |
1797 | #endif /* DB_NO_AOUT */ | |
1798 | ||
1799 | #ifdef DB_NO_COFF | |
1800 | NONE, | |
1801 | #else /* DB_NO_COFF */ | |
1802 | { coff_db_init, coff_db_sym_init, coff_db_lookup, coff_db_search_symbol, | |
1803 | coff_db_line_at_pc, coff_db_symbol_values, coff_db_search_by_addr, | |
1804 | coff_db_print_completion, coff_db_lookup_incomplete }, | |
1805 | #endif /* DB_NO_COFF */ | |
1806 | ||
1807 | /* Machdep, not inited here */ | |
1808 | NONE | |
1809 | }; |