]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
91447636 | 2 | * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. |
1c79356b | 3 | * |
8ad349bb A |
4 | * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ |
5 | * | |
6 | * This file contains Original Code and/or Modifications of Original Code | |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the | |
10 | * License may not be used to create, or enable the creation or | |
11 | * redistribution of, unlawful or unlicensed copies of an Apple operating | |
12 | * system, or to circumvent, violate, or enable the circumvention or | |
13 | * violation of, any terms of an Apple operating system software license | |
14 | * agreement. | |
15 | * | |
16 | * Please obtain a copy of the License at | |
17 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
18 | * file. | |
19 | * | |
20 | * The Original Code and all software distributed under the License are | |
21 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
22 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
23 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
24 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
25 | * Please see the License for the specific language governing rights and | |
26 | * limitations under the License. | |
27 | * | |
28 | * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ | |
1c79356b A |
29 | */ |
30 | /* | |
31 | * @OSF_COPYRIGHT@ | |
32 | */ | |
1c79356b A |
33 | /* |
34 | * Mach Operating System | |
35 | * Copyright (c) 1991,1990 Carnegie Mellon University | |
36 | * All Rights Reserved. | |
37 | * | |
38 | * Permission to use, copy, modify and distribute this software and its | |
39 | * documentation is hereby granted, provided that both the copyright | |
40 | * notice and this permission notice appear in all copies of the | |
41 | * software, derivative works or modified versions, and any portions | |
42 | * thereof, and that both notices appear in supporting documentation. | |
43 | * | |
44 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
45 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
46 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
47 | * | |
48 | * Carnegie Mellon requests users of this software to return to | |
49 | * | |
50 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
51 | * School of Computer Science | |
52 | * Carnegie Mellon University | |
53 | * Pittsburgh PA 15213-3890 | |
54 | * | |
55 | * any improvements or extensions that they make and grant Carnegie Mellon | |
56 | * the rights to redistribute these changes. | |
57 | */ | |
58 | /* | |
59 | */ | |
60 | /* | |
61 | * Author: David B. Golub, Carnegie Mellon University | |
62 | * Date: 7/90 | |
63 | */ | |
64 | ||
65 | #include <machine/db_machdep.h> | |
66 | #include <string.h> /* For strcpy(), strcmp() */ | |
67 | #include <mach/std_types.h> | |
68 | #include <kern/misc_protos.h> /* For printf() */ | |
69 | #include <ddb/db_sym.h> | |
70 | #include <ddb/db_task_thread.h> | |
71 | #include <ddb/db_command.h> | |
72 | #include <ddb/db_output.h> /* For db_printf() */ | |
73 | ||
74 | #include <vm/vm_map.h> /* vm_map_t */ | |
75 | ||
76 | /* | |
77 | * Multiple symbol tables | |
78 | * | |
79 | * mach, bootstrap, name_server, default_pager, unix, 1 spare | |
80 | */ | |
81 | #define MAXNOSYMTABS 6 | |
82 | ||
83 | db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0}}; | |
84 | int db_nsymtab = 0; | |
85 | ||
86 | db_symtab_t *db_last_symtab; | |
87 | ||
88 | unsigned long db_maxoff = 0x4000; | |
89 | extern char end; | |
90 | unsigned long db_maxval = (unsigned long)&end; | |
91 | natural_t db_minval = 0x1000; | |
92 | ||
93 | /* Prototypes for functions local to this file. XXX -- should be static! | |
94 | */ | |
95 | static char *db_qualify( | |
96 | char *sym, | |
97 | register char *symtabname); | |
98 | ||
99 | boolean_t db_eqname( | |
100 | char *src, | |
101 | char *dst, | |
102 | unsigned c); | |
103 | ||
104 | boolean_t db_symbol_is_ambiguous(char *name); | |
105 | ||
106 | void db_shorten_filename(char **filenamep); | |
107 | ||
108 | void qsort_swap( | |
109 | register int *a, | |
110 | register int *b, | |
111 | register int size); | |
112 | ||
113 | void qsort_rotate( | |
114 | register int *a, | |
115 | register int *b, | |
116 | register int *c, | |
117 | register int size); | |
118 | ||
119 | void qsort_recur( | |
120 | char *left, | |
121 | char *right, | |
122 | int eltsize, | |
123 | int (*compfun)(char *, char *)); | |
124 | ||
125 | void qsort_checker( | |
126 | char *table, | |
127 | int nbelts, | |
128 | int eltsize, | |
129 | int (*compfun)(char *, char *)); | |
130 | ||
131 | void bubble_sort( | |
132 | char *table, | |
133 | int nbelts, | |
134 | int eltsize, | |
135 | int (*compfun)(char *, char *)); | |
136 | ||
137 | int no_print_completion( | |
138 | db_symtab_t *stab, | |
139 | char *symstr ); | |
140 | int no_lookup_incomplete( | |
141 | db_symtab_t *stab, | |
142 | char *symstr, | |
143 | char **name, | |
144 | int *len, | |
145 | int *toadd); | |
146 | ||
147 | /* | |
148 | * Initialization routine for ddb. | |
149 | */ | |
150 | void | |
151 | ddb_init(void) | |
152 | { | |
153 | X_db_init(); | |
154 | db_machdep_init(); | |
155 | } | |
156 | ||
157 | /* | |
158 | * Add symbol table, with given name, to list of symbol tables. | |
159 | */ | |
160 | boolean_t | |
161 | db_add_symbol_table( | |
162 | int type, | |
163 | char *start, | |
164 | char *end, | |
165 | char *name, | |
166 | char *ref, | |
167 | char *map_pointer, | |
168 | unsigned long minsym, | |
169 | unsigned long maxsym, | |
170 | boolean_t sorted) | |
171 | { | |
172 | register db_symtab_t *st; | |
173 | extern vm_map_t kernel_map; | |
174 | ||
175 | if (db_nsymtab >= MAXNOSYMTABS) | |
176 | return (FALSE); | |
177 | ||
178 | st = &db_symtabs[db_nsymtab]; | |
179 | st->type = type; | |
180 | st->start = start; | |
181 | st->end = end; | |
182 | st->private = ref; | |
183 | if (map_pointer == (char *)kernel_map || | |
184 | (VM_MAX_ADDRESS <= VM_MIN_KERNEL_ADDRESS && | |
185 | VM_MIN_KERNEL_ADDRESS <= minsym)) | |
186 | st->map_pointer = 0; | |
187 | else | |
188 | st->map_pointer = map_pointer; | |
189 | strcpy(st->name, name); | |
190 | st->minsym = minsym; | |
191 | st->maxsym = maxsym; | |
192 | if (maxsym == 0) | |
193 | st->sorted = FALSE; | |
194 | else { | |
195 | st->sorted = sorted; | |
196 | if (db_maxval < maxsym + db_maxoff) | |
197 | db_maxval = maxsym + db_maxoff; | |
198 | } | |
199 | db_nsymtab++; | |
200 | ||
201 | return (TRUE); | |
202 | } | |
203 | ||
204 | /* | |
205 | * db_qualify("vm_map", "ux") returns "ux::vm_map". | |
206 | * | |
207 | * Note: return value points to static data whose content is | |
208 | * overwritten by each call... but in practice this seems okay. | |
209 | */ | |
210 | static char * | |
211 | db_qualify( | |
212 | char *symname, | |
213 | register char *symtabname) | |
214 | { | |
215 | static char tmp[256]; | |
216 | register char *s; | |
217 | ||
218 | s = tmp; | |
219 | while (*s++ = *symtabname++) { | |
220 | } | |
221 | s[-1] = ':'; | |
222 | *s++ = ':'; | |
223 | while (*s++ = *symname++) { | |
224 | } | |
225 | return tmp; | |
226 | } | |
227 | ||
228 | ||
229 | boolean_t | |
230 | db_eqname( | |
231 | char *src, | |
232 | char *dst, | |
233 | unsigned c) | |
234 | { | |
235 | if (!strcmp(src, dst)) | |
236 | return (TRUE); | |
237 | if (src[0] == c) | |
238 | return (!strcmp(src+1,dst)); | |
239 | return (FALSE); | |
240 | } | |
241 | ||
242 | boolean_t | |
243 | db_value_of_name( | |
244 | char *name, | |
245 | db_expr_t *valuep) | |
246 | { | |
247 | db_sym_t sym; | |
248 | ||
249 | sym = db_lookup(name); | |
250 | if (sym == DB_SYM_NULL) | |
251 | return (FALSE); | |
252 | db_symbol_values(0, sym, &name, valuep); | |
253 | return (TRUE); | |
254 | } | |
255 | ||
256 | /* | |
257 | * Display list of possible completions for a symbol. | |
258 | */ | |
259 | void | |
260 | db_print_completion( | |
261 | char *symstr) | |
262 | { | |
263 | register int i; | |
264 | int symtab_start = 0; | |
265 | int symtab_end = db_nsymtab; | |
266 | register char *cp; | |
267 | int nsym = 0; | |
268 | char *name = (char *)0; | |
269 | int len; | |
270 | int toadd; | |
271 | ||
272 | /* | |
273 | * Look for, remove, and remember any symbol table specifier. | |
274 | */ | |
275 | for (cp = symstr; *cp; cp++) { | |
276 | if (*cp == ':' && cp[1] == ':') { | |
277 | *cp = '\0'; | |
278 | for (i = 0; i < db_nsymtab; i++) { | |
279 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
280 | symtab_start = i; | |
281 | symtab_end = i + 1; | |
282 | break; | |
283 | } | |
284 | } | |
285 | *cp = ':'; | |
286 | if (i == db_nsymtab) | |
287 | return; | |
288 | symstr = cp+2; | |
289 | } | |
290 | } | |
291 | ||
292 | /* | |
293 | * Look in the specified set of symbol tables. | |
294 | * Return on first match. | |
295 | */ | |
296 | for (i = symtab_start; i < symtab_end; i++) { | |
297 | if (X_db_print_completion(&db_symtabs[i], symstr)) | |
298 | break; | |
299 | } | |
300 | } | |
301 | ||
302 | /* | |
303 | * Lookup a (perhaps incomplete) symbol. | |
304 | * If the symbol has a qualifier (e.g., ux::vm_map), | |
305 | * then only the specified symbol table will be searched; | |
306 | * otherwise, all symbol tables will be searched. | |
307 | */ | |
308 | int | |
309 | db_lookup_incomplete( | |
310 | char *symstr, | |
311 | int symlen) | |
312 | { | |
313 | register int i; | |
314 | int symtab_start = 0; | |
315 | int symtab_end = db_nsymtab; | |
316 | register char *cp; | |
317 | int nsym = 0; | |
318 | char *name = (char *)0; | |
319 | int len; | |
320 | int toadd; | |
321 | ||
322 | /* | |
323 | * Look for, remove, and remember any symbol table specifier. | |
324 | */ | |
325 | for (cp = symstr; *cp; cp++) { | |
326 | if (*cp == ':' && cp[1] == ':') { | |
327 | *cp = '\0'; | |
328 | for (i = 0; i < db_nsymtab; i++) { | |
329 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
330 | symtab_start = i; | |
331 | symtab_end = i + 1; | |
332 | break; | |
333 | } | |
334 | } | |
335 | *cp = ':'; | |
336 | if (i == db_nsymtab) | |
337 | return 0; | |
338 | symstr = cp+2; | |
339 | } | |
340 | } | |
341 | ||
342 | /* | |
343 | * Look in the specified set of symbol tables. | |
344 | * Return on first match. | |
345 | */ | |
346 | for (i = symtab_start; i < symtab_end; i++) { | |
347 | nsym = X_db_lookup_incomplete(&db_symtabs[i], symstr, | |
348 | &name, &len, &toadd); | |
349 | if (nsym > 0) { | |
350 | if (toadd > 0) { | |
351 | len = strlen(symstr); | |
352 | if (len + toadd >= symlen) | |
353 | return 0; | |
354 | bcopy(&name[len], &symstr[len], toadd); | |
355 | symstr[len + toadd] = '\0'; | |
356 | } | |
357 | break; | |
358 | } | |
359 | } | |
360 | return nsym; | |
361 | } | |
362 | ||
363 | /* | |
364 | * Lookup a symbol. | |
365 | * If the symbol has a qualifier (e.g., ux::vm_map), | |
366 | * then only the specified symbol table will be searched; | |
367 | * otherwise, all symbol tables will be searched. | |
368 | */ | |
369 | db_sym_t | |
370 | db_lookup(char *symstr) | |
371 | { | |
372 | db_sym_t sp; | |
373 | register int i; | |
374 | int symtab_start = 0; | |
375 | int symtab_end = db_nsymtab; | |
376 | register char *cp; | |
377 | ||
378 | /* | |
379 | * Look for, remove, and remember any symbol table specifier. | |
380 | */ | |
381 | for (cp = symstr; *cp; cp++) { | |
382 | if (*cp == ':' && cp[1] == ':') { | |
383 | *cp = '\0'; | |
384 | for (i = 0; i < db_nsymtab; i++) { | |
385 | if (! strcmp(symstr, db_symtabs[i].name)) { | |
386 | symtab_start = i; | |
387 | symtab_end = i + 1; | |
388 | break; | |
389 | } | |
390 | } | |
391 | *cp = ':'; | |
392 | if (i == db_nsymtab) | |
393 | db_error("Invalid symbol table name\n"); | |
394 | symstr = cp+2; | |
395 | } | |
396 | } | |
397 | ||
398 | /* | |
399 | * Look in the specified set of symbol tables. | |
400 | * Return on first match. | |
401 | */ | |
402 | for (i = symtab_start; i < symtab_end; i++) { | |
403 | if (sp = X_db_lookup(&db_symtabs[i], symstr)) { | |
404 | db_last_symtab = &db_symtabs[i]; | |
405 | return sp; | |
406 | } | |
407 | } | |
408 | return 0; | |
409 | } | |
410 | ||
411 | /* | |
412 | * Print a symbol completion | |
413 | */ | |
414 | void | |
415 | db_sym_print_completion( | |
416 | db_symtab_t *stab, | |
417 | char *name, | |
418 | int function, | |
419 | char *fname, | |
420 | int line) | |
421 | { | |
422 | if (stab != db_symtabs) | |
423 | db_printf("%s::", stab->name); | |
424 | db_printf(name); | |
425 | if (function) { | |
426 | db_putchar('('); | |
427 | db_putchar(')'); | |
428 | } | |
429 | if (fname) { | |
430 | db_printf(" [static from %s", fname); | |
431 | if (line > 0) | |
432 | db_printf(":%d", line); | |
433 | db_putchar(']'); | |
434 | } | |
435 | db_putchar('\n'); | |
436 | } | |
437 | ||
438 | /* | |
439 | * Common utility routine to parse a symbol string into a file | |
440 | * name, a (possibly incomplete) symbol name without line number. | |
441 | * This routine is called from aout_db_print_completion if the object | |
442 | * dependent handler supports qualified search with a file name. | |
443 | * It parses the symbol string, and call an object dependent routine | |
444 | * with parsed file name and symbol name. | |
445 | */ | |
446 | int | |
447 | db_sym_parse_and_print_completion( | |
448 | int (*func)(db_symtab_t *, | |
449 | char *), | |
450 | db_symtab_t *symtab, | |
451 | char *symstr) | |
452 | { | |
453 | register char *p; | |
454 | register int n; | |
455 | char *sym_name; | |
456 | char *component[2]; | |
457 | int nsym; | |
458 | ||
459 | /* | |
460 | * disassemble the symbol into components: [file_name:]symbol | |
461 | */ | |
462 | component[0] = symstr; | |
463 | component[1] = 0; | |
464 | for (p = symstr, n = 1; *p; p++) { | |
465 | if (*p == ':') { | |
466 | if (n == 2) | |
467 | break; | |
468 | *p = 0; | |
469 | component[n++] = p+1; | |
470 | } | |
471 | } | |
472 | if (*p == 0) { | |
473 | if (n == 1) { | |
474 | sym_name = component[0]; | |
475 | } else { | |
476 | sym_name = component[1]; | |
477 | } | |
478 | nsym = func(symtab, sym_name); | |
479 | } else | |
480 | nsym = 0; | |
481 | if (n == 2) | |
482 | component[1][-1] = ':'; | |
483 | return nsym; | |
484 | } | |
485 | ||
486 | /* | |
487 | * Common utility routine to parse a symbol string into a file | |
488 | * name, a (possibly incomplete) symbol name without line number. | |
489 | * This routine is called from X_db_lookup_incomplete if the object | |
490 | * dependent handler supports qualified search with a file name. | |
491 | * It parses the symbol string, and call an object dependent routine | |
492 | * with parsed file name and symbol name. | |
493 | */ | |
494 | int | |
495 | db_sym_parse_and_lookup_incomplete( | |
496 | int (*func)(db_symtab_t *, | |
497 | char *, | |
498 | char *, | |
499 | int, | |
500 | db_sym_t*, | |
501 | char **, | |
502 | int *), | |
503 | db_symtab_t *symtab, | |
504 | char *symstr, | |
505 | char **name, | |
506 | int *len, | |
507 | int *toadd) | |
508 | { | |
509 | register char *p; | |
510 | register int n; | |
511 | char *file_name = 0; | |
512 | char *sym_name = 0; | |
513 | char *component[2]; | |
514 | int nsym = 0; | |
515 | ||
516 | /* | |
517 | * disassemble the symbol into components: [file_name:]symbol | |
518 | */ | |
519 | component[0] = symstr; | |
520 | component[1] = 0; | |
521 | for (p = symstr, n = 1; *p; p++) { | |
522 | if (*p == ':') { | |
523 | if (n == 2) | |
524 | break; | |
525 | *p = 0; | |
526 | component[n++] = p+1; | |
527 | } | |
528 | } | |
529 | if (*p == 0) { | |
530 | if (n == 1) { | |
531 | file_name = 0; | |
532 | sym_name = component[0]; | |
533 | } else { | |
534 | file_name = component[0]; | |
535 | sym_name = component[1]; | |
536 | } | |
537 | nsym = func(symtab, file_name, sym_name, 0, (db_sym_t *)0, | |
538 | name, len); | |
539 | if (nsym > 0) | |
540 | *toadd = *len - strlen(sym_name); | |
541 | } | |
542 | if (n == 2) | |
543 | component[1][-1] = ':'; | |
544 | return(nsym); | |
545 | } | |
546 | ||
547 | /* | |
548 | * Common utility routine to parse a symbol string into a file | |
549 | * name, a symbol name and line number. | |
550 | * This routine is called from aout_db_lookup if the object dependent | |
551 | * handler supports qualified search with a file name or a line number. | |
552 | * It parses the symbol string, and call an object dependent routine | |
553 | * with parsed file name, symbol name and line number. | |
554 | */ | |
555 | db_sym_t | |
556 | db_sym_parse_and_lookup( | |
557 | int (*func)(db_symtab_t *, char *, char *, int, | |
558 | db_sym_t*, char **, int *), | |
559 | db_symtab_t *symtab, | |
560 | char *symstr) | |
561 | { | |
562 | register char *p; | |
563 | register int n; | |
564 | int n_name; | |
565 | int line_number; | |
566 | char *file_name = 0; | |
567 | char *sym_name = 0; | |
568 | char *component[3]; | |
569 | db_sym_t found = DB_SYM_NULL; | |
570 | ||
571 | /* | |
572 | * disassemble the symbol into components: | |
573 | * [file_name:]symbol[:line_nubmer] | |
574 | */ | |
575 | component[0] = symstr; | |
576 | component[1] = component[2] = 0; | |
577 | for (p = symstr, n = 1; *p; p++) { | |
578 | if (*p == ':') { | |
579 | if (n >= 3) | |
580 | break; | |
581 | *p = 0; | |
582 | component[n++] = p+1; | |
583 | } | |
584 | } | |
585 | if (*p != 0) | |
586 | goto out; | |
587 | line_number = 0; | |
588 | n_name = n; | |
589 | p = component[n-1]; | |
590 | if (*p >= '0' && *p <= '9') { | |
591 | if (n == 1) | |
592 | goto out; | |
593 | for (line_number = 0; *p; p++) { | |
594 | if (*p < '0' || *p > '9') | |
595 | goto out; | |
596 | line_number = line_number*10 + *p - '0'; | |
597 | } | |
598 | n_name--; | |
599 | } else if (n >= 3) | |
600 | goto out; | |
601 | if (n_name == 1) { | |
602 | for (p = component[0]; *p && *p != '.'; p++); | |
603 | if (*p == '.') { | |
604 | file_name = component[0]; | |
605 | sym_name = 0; | |
606 | } else { | |
607 | file_name = 0; | |
608 | sym_name = component[0]; | |
609 | } | |
610 | } else { | |
611 | file_name = component[0]; | |
612 | sym_name = component[1]; | |
613 | } | |
614 | (void) func(symtab, file_name, sym_name, line_number, &found, | |
615 | (char **)0, (int *)0); | |
616 | ||
617 | out: | |
618 | while (--n >= 1) | |
619 | component[n][-1] = ':'; | |
620 | return(found); | |
621 | } | |
622 | ||
623 | /* | |
624 | * Does this symbol name appear in more than one symbol table? | |
625 | * Used by db_symbol_values to decide whether to qualify a symbol. | |
626 | */ | |
627 | boolean_t db_qualify_ambiguous_names = TRUE; | |
628 | ||
629 | boolean_t | |
630 | db_symbol_is_ambiguous(char *name) | |
631 | { | |
632 | register int i; | |
633 | register | |
634 | boolean_t found_once = FALSE; | |
635 | ||
636 | if (!db_qualify_ambiguous_names) | |
637 | return FALSE; | |
638 | ||
639 | for (i = 0; i < db_nsymtab; i++) { | |
640 | if (X_db_lookup(&db_symtabs[i], name)) { | |
641 | if (found_once) | |
642 | return TRUE; | |
643 | found_once = TRUE; | |
644 | } | |
645 | } | |
646 | return FALSE; | |
647 | } | |
648 | ||
649 | /* | |
650 | * Find the closest symbol to val, and return its name | |
651 | * and the difference between val and the symbol found. | |
652 | */ | |
653 | unsigned int db_search_maxoff = 0x4000; | |
654 | db_sym_t | |
655 | db_search_task_symbol( | |
656 | register db_addr_t val, | |
657 | db_strategy_t strategy, | |
658 | db_addr_t *offp, /* better be unsigned */ | |
659 | task_t task) | |
660 | { | |
91447636 | 661 | db_addr_t diff, newdiff; |
1c79356b A |
662 | register int i; |
663 | db_symtab_t *sp; | |
664 | db_sym_t ret = DB_SYM_NULL, sym; | |
665 | vm_map_t map_for_val; | |
666 | ||
667 | if (task == TASK_NULL) | |
668 | task = db_current_task(); | |
669 | map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map; | |
670 | again: | |
91447636 | 671 | newdiff = diff = -1; |
1c79356b A |
672 | db_last_symtab = 0; |
673 | for (sp = &db_symtabs[0], i = 0; | |
674 | i < db_nsymtab; | |
675 | sp++, i++) { | |
91447636 A |
676 | if ((((vm_map_t)sp->map_pointer == VM_MAP_NULL) || |
677 | ((vm_map_t)sp->map_pointer == map_for_val)) && | |
678 | ((sp->maxsym == 0) || | |
679 | ((val >= (db_addr_t)sp->minsym) && | |
680 | (val <= (db_addr_t)sp->maxsym)))) { | |
1c79356b A |
681 | sym = X_db_search_symbol(sp, val, strategy, |
682 | (db_expr_t *)&newdiff); | |
683 | if (newdiff < diff) { | |
684 | db_last_symtab = sp; | |
685 | diff = newdiff; | |
686 | ret = sym; | |
687 | if (diff <= db_search_maxoff) | |
688 | break; | |
689 | } | |
690 | } | |
691 | } | |
692 | if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) { | |
693 | map_for_val = VM_MAP_NULL; | |
694 | goto again; | |
695 | } | |
696 | *offp = diff; | |
697 | return ret; | |
698 | } | |
699 | ||
700 | /* | |
701 | * Find the closest symbol to val, and return its name | |
702 | * and the difference between val and the symbol found. | |
703 | * Also return the filename and linenumber if available. | |
704 | */ | |
705 | db_sym_t | |
706 | db_search_task_symbol_and_line( | |
707 | register db_addr_t val, | |
708 | db_strategy_t strategy, | |
709 | db_expr_t *offp, | |
710 | char **filenamep, | |
711 | int *linenump, | |
712 | task_t task, | |
713 | int *argsp) | |
714 | { | |
91447636 | 715 | db_addr_t diff, newdiff; |
1c79356b A |
716 | register int i; |
717 | db_symtab_t *sp; | |
718 | db_sym_t ret = DB_SYM_NULL, sym; | |
719 | vm_map_t map_for_val; | |
720 | char *func; | |
721 | char *filename; | |
722 | int linenum; | |
723 | int args; | |
724 | ||
725 | if (task == TASK_NULL) | |
726 | task = db_current_task(); | |
727 | map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map; | |
728 | *filenamep = (char *) 0; | |
729 | *linenump = 0; | |
730 | *argsp = -1; | |
731 | again: | |
732 | filename = (char *) 0; | |
733 | linenum = 0; | |
734 | newdiff = diff = ~0UL; | |
735 | db_last_symtab = 0; | |
736 | for (sp = &db_symtabs[0], i = 0; | |
737 | i < db_nsymtab; | |
738 | sp++, i++) { | |
91447636 A |
739 | if ((((vm_map_t)sp->map_pointer == VM_MAP_NULL) || |
740 | ((vm_map_t)sp->map_pointer == map_for_val)) && | |
741 | ((sp->maxsym == 0) || | |
742 | ((val >= (db_addr_t)sp->minsym) && | |
743 | (val <= (db_addr_t)sp->maxsym)))) { | |
744 | ||
745 | sym = X_db_search_by_addr(sp, val, &filename, &func, | |
746 | &linenum, (db_expr_t *)&newdiff, | |
747 | &args); | |
748 | if (sym && newdiff < diff) { | |
749 | db_last_symtab = sp; | |
750 | diff = newdiff; | |
751 | ret = sym; | |
752 | *filenamep = filename; | |
753 | *linenump = linenum; | |
754 | *argsp = args; | |
755 | if (diff <= db_search_maxoff) | |
756 | break; | |
757 | } | |
1c79356b A |
758 | } |
759 | } | |
760 | if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) { | |
761 | map_for_val = VM_MAP_NULL; | |
762 | goto again; | |
763 | } | |
764 | *offp = diff; | |
765 | if (*filenamep) | |
766 | db_shorten_filename(filenamep); | |
767 | return ret; | |
768 | } | |
769 | ||
770 | /* | |
771 | * Return name and value of a symbol | |
772 | */ | |
773 | void | |
774 | db_symbol_values( | |
775 | db_symtab_t *stab, | |
776 | db_sym_t sym, | |
777 | char **namep, | |
778 | db_expr_t *valuep) | |
779 | { | |
780 | db_expr_t value; | |
781 | char *name; | |
782 | ||
783 | if (sym == DB_SYM_NULL) { | |
784 | *namep = 0; | |
785 | return; | |
786 | } | |
787 | if (stab == 0) | |
788 | stab = db_last_symtab; | |
789 | ||
790 | X_db_symbol_values(stab, sym, &name, &value); | |
791 | ||
792 | if (db_symbol_is_ambiguous(name)) { | |
793 | *namep = db_qualify(name, db_last_symtab->name); | |
794 | }else { | |
795 | *namep = name; | |
796 | } | |
797 | if (valuep) | |
798 | *valuep = value; | |
799 | } | |
800 | ||
801 | ||
802 | /* | |
803 | * Print a the closest symbol to value | |
804 | * | |
805 | * After matching the symbol according to the given strategy | |
806 | * we print it in the name+offset format, provided the symbol's | |
807 | * value is close enough (eg smaller than db_maxoff). | |
808 | * We also attempt to print [filename:linenum] when applicable | |
809 | * (eg for procedure names). | |
810 | * | |
811 | * If we could not find a reasonable name+offset representation, | |
812 | * then we just print the value in hex. Small values might get | |
813 | * bogus symbol associations, e.g. 3 might get some absolute | |
814 | * value like _INCLUDE_VERSION or something, therefore we do | |
815 | * not accept symbols whose value is zero (and use plain hex). | |
816 | */ | |
817 | ||
818 | void | |
819 | db_task_printsym( | |
91447636 | 820 | db_addr_t off, |
1c79356b A |
821 | db_strategy_t strategy, |
822 | task_t task) | |
823 | { | |
91447636 | 824 | db_expr_t d; |
1c79356b A |
825 | char *filename; |
826 | char *name; | |
827 | db_expr_t value; | |
828 | int linenum; | |
829 | db_sym_t cursym; | |
830 | ||
831 | if (off >= db_maxval || off < db_minval) { | |
91447636 | 832 | db_printf("%#lln", (unsigned long long)off); |
1c79356b A |
833 | return; |
834 | } | |
835 | cursym = db_search_task_symbol(off, strategy, &d, task); | |
836 | ||
837 | db_symbol_values(0, cursym, &name, &value); | |
838 | if (name == 0 || d >= db_maxoff || value == 0) { | |
91447636 | 839 | db_printf("%#lln",(unsigned long long) off); |
1c79356b A |
840 | return; |
841 | } | |
842 | db_printf("%s", name); | |
843 | if (d) | |
91447636 | 844 | db_printf("+%llx", (unsigned long long)d); |
1c79356b A |
845 | if (strategy == DB_STGY_PROC) { |
846 | if (db_line_at_pc(cursym, &filename, &linenum, off)) { | |
847 | db_printf(" [%s", filename); | |
848 | if (linenum > 0) | |
849 | db_printf(":%d", linenum); | |
850 | db_printf("]"); | |
851 | } | |
852 | } | |
853 | } | |
854 | ||
855 | /* | |
856 | * Return symbol name for a given offset and | |
857 | * change the offset to be relative to this symbol. | |
858 | * Very usefull for xpr, when you want to log offsets | |
859 | * in a user friendly way. | |
860 | */ | |
861 | ||
862 | char null_sym[] = ""; | |
863 | ||
864 | char * | |
865 | db_get_sym(db_expr_t *off) | |
866 | { | |
867 | db_sym_t cursym; | |
868 | db_expr_t value; | |
869 | char *name; | |
870 | db_addr_t d; | |
871 | ||
872 | cursym = db_search_symbol(*off, DB_STGY_ANY, &d); | |
873 | db_symbol_values(0, cursym, &name, &value); | |
874 | if (name) | |
875 | *off = d; | |
876 | else | |
877 | name = null_sym; | |
878 | return(name); | |
879 | } | |
880 | ||
881 | void | |
882 | db_printsym( | |
883 | db_expr_t off, | |
884 | db_strategy_t strategy) | |
885 | { | |
886 | db_task_printsym(off, strategy, TASK_NULL); | |
887 | } | |
888 | ||
889 | int db_short_filename = 1; | |
890 | ||
891 | void | |
892 | db_shorten_filename(char **filenamep) | |
893 | { | |
894 | char *cp, *cp_slash; | |
895 | ||
896 | if (! *filenamep) | |
897 | return; | |
898 | for (cp = cp_slash = *filenamep; *cp; cp++) { | |
899 | if (*cp == '/') | |
900 | cp_slash = cp; | |
901 | } | |
902 | if (*cp_slash == '/') | |
903 | *filenamep = cp_slash+1; | |
904 | } | |
905 | ||
906 | int | |
907 | db_task_getlinenum( | |
908 | db_expr_t off, | |
909 | task_t task) | |
910 | { | |
911 | db_addr_t d; | |
912 | char *filename; | |
913 | char *name; | |
914 | db_expr_t value; | |
915 | int linenum; | |
916 | db_sym_t cursym; | |
917 | db_strategy_t strategy = DB_STGY_PROC; | |
918 | ||
919 | if (off >= db_maxval || off < db_minval) { | |
91447636 | 920 | db_printf("%#lln", (unsigned long long)off); |
1c79356b A |
921 | return(-1); |
922 | } | |
923 | cursym = db_search_task_symbol(off, strategy, &d, task); | |
924 | ||
925 | db_symbol_values(0, cursym, &name, &value); | |
926 | if (name == 0 || d >= db_maxoff || value == 0) { | |
927 | return(-1); | |
928 | } | |
929 | if (db_line_at_pc(cursym, &filename, &linenum, off)) | |
930 | return(linenum); | |
931 | else | |
932 | return(-1); | |
933 | } | |
934 | ||
935 | boolean_t | |
936 | db_line_at_pc( | |
937 | db_sym_t sym, | |
938 | char **filename, | |
939 | int *linenum, | |
940 | db_expr_t pc) | |
941 | { | |
942 | boolean_t result; | |
943 | ||
944 | if (db_last_symtab == 0) | |
945 | return FALSE; | |
946 | if (X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc)) { | |
947 | if (db_short_filename) | |
948 | db_shorten_filename(filename); | |
949 | result = TRUE; | |
950 | } else | |
951 | result = FALSE; | |
952 | return(result); | |
953 | } | |
954 | ||
955 | int qsort_check = 0; | |
956 | ||
957 | void | |
958 | db_qsort( | |
959 | char *table, | |
960 | int nbelts, | |
961 | int eltsize, | |
962 | int (*compfun)(char *, char *)) | |
963 | { | |
964 | if (nbelts <= 0 || eltsize <= 0 || compfun == 0) { | |
965 | printf("qsort: invalid parameters\n"); | |
966 | return; | |
967 | } | |
968 | qsort_recur(table, table + nbelts * eltsize, eltsize, compfun); | |
969 | ||
970 | if (qsort_check) | |
971 | qsort_checker(table, nbelts, eltsize, compfun); | |
972 | } | |
973 | ||
974 | void | |
975 | qsort_swap( | |
976 | register int *a, | |
977 | register int *b, | |
978 | register int size) | |
979 | { | |
980 | register int temp; | |
981 | char *aa, *bb; | |
982 | char ctemp; | |
983 | ||
984 | for (; size >= sizeof (int); size -= sizeof (int), a++, b++) { | |
985 | temp = *a; | |
986 | *a = *b; | |
987 | *b = temp; | |
988 | } | |
989 | aa = (char *)a; | |
990 | bb = (char *)b; | |
991 | for (; size > 0; size--, aa++, bb++) { | |
992 | ctemp = *aa; | |
993 | *aa = *bb; | |
994 | *bb = ctemp; | |
995 | } | |
996 | } | |
997 | ||
998 | /* rotate the three elements to the left */ | |
999 | void | |
1000 | qsort_rotate( | |
1001 | register int *a, | |
1002 | register int *b, | |
1003 | register int *c, | |
1004 | register int size) | |
1005 | { | |
1006 | register int temp; | |
1007 | char *aa, *bb, *cc; | |
1008 | char ctemp; | |
1009 | ||
1010 | for (; size >= sizeof (int); size -= sizeof (int), a++, b++, c++) { | |
1011 | temp = *a; | |
1012 | *a = *c; | |
1013 | *c = *b; | |
1014 | *b = temp; | |
1015 | } | |
1016 | aa = (char *)a; | |
1017 | bb = (char *)b; | |
1018 | cc = (char *)c; | |
1019 | for (; size > 0; size--, aa++, bb++, cc++) { | |
1020 | ctemp = *aa; | |
1021 | *aa = *cc; | |
1022 | *cc = *bb; | |
1023 | *bb = ctemp; | |
1024 | } | |
1025 | } | |
1026 | ||
1027 | void | |
1028 | qsort_recur( | |
1029 | char *left, | |
1030 | char *right, | |
1031 | int eltsize, | |
1032 | int (*compfun)(char *, char *)) | |
1033 | { | |
1034 | char *i, *j; | |
1035 | char *sameleft, *sameright; | |
1036 | ||
1037 | top: | |
1038 | if (left + eltsize - 1 >= right) { | |
1039 | return; | |
1040 | } | |
1041 | ||
1042 | /* partition element (reference for "same"ness */ | |
1043 | sameleft = left + (((right - left) / eltsize) / 2) * eltsize; | |
1044 | sameright = sameleft; | |
1045 | ||
1046 | i = left; | |
1047 | j = right - eltsize; | |
1048 | ||
1049 | again: | |
1050 | while (i < sameleft) { | |
1051 | int comp; | |
1052 | ||
1053 | comp = (*compfun)(i, sameleft); | |
1054 | if (comp == 0) { | |
1055 | /* | |
1056 | * Move to the "same" partition. | |
1057 | */ | |
1058 | /* | |
1059 | * Shift the left part of the "same" partition to | |
1060 | * the left, so that "same" elements stay in their | |
1061 | * original order. | |
1062 | */ | |
1063 | sameleft -= eltsize; | |
1064 | qsort_swap((int *) i, (int *) sameleft, eltsize); | |
1065 | } else if (comp < 0) { | |
1066 | /* | |
1067 | * Stay in the "left" partition. | |
1068 | */ | |
1069 | i += eltsize; | |
1070 | } else { | |
1071 | /* | |
1072 | * Should be moved to the "right" partition. | |
1073 | * Wait until the next loop finds an appropriate | |
1074 | * place to store this element. | |
1075 | */ | |
1076 | break; | |
1077 | } | |
1078 | } | |
1079 | ||
1080 | while (j > sameright) { | |
1081 | int comp; | |
1082 | ||
1083 | comp = (*compfun)(sameright, j); | |
1084 | if (comp == 0) { | |
1085 | /* | |
1086 | * Move to the right of the "same" partition. | |
1087 | */ | |
1088 | sameright += eltsize; | |
1089 | qsort_swap((int *) sameright, (int *) j, eltsize); | |
1090 | } else if (comp > 0) { | |
1091 | /* | |
1092 | * Move to the "left" partition. | |
1093 | */ | |
1094 | if (i == sameleft) { | |
1095 | /* | |
1096 | * Unfortunately, the "left" partition | |
1097 | * has already been fully processed, so | |
1098 | * we have to shift the "same" partition | |
1099 | * to the right to free a "left" element. | |
1100 | * This is done by moving the leftest same | |
1101 | * to the right of the "same" partition. | |
1102 | */ | |
1103 | sameright += eltsize; | |
1104 | qsort_rotate((int *) sameleft, (int*) sameright, | |
1105 | (int *) j, eltsize); | |
1106 | sameleft += eltsize; | |
1107 | i = sameleft; | |
1108 | } else { | |
1109 | /* | |
1110 | * Swap with the "left" partition element | |
1111 | * waiting to be moved to the "right" | |
1112 | * partition. | |
1113 | */ | |
1114 | qsort_swap((int *) i, (int *) j, eltsize); | |
1115 | j -= eltsize; | |
1116 | /* | |
1117 | * Go back to the 1st loop. | |
1118 | */ | |
1119 | i += eltsize; | |
1120 | goto again; | |
1121 | } | |
1122 | } else { | |
1123 | /* | |
1124 | * Stay in the "right" partition. | |
1125 | */ | |
1126 | j -= eltsize; | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | if (i != sameleft) { | |
1131 | /* | |
1132 | * The second loop completed (the"right" partition is ok), | |
1133 | * but we have to go back to the first loop, and deal with | |
1134 | * the element waiting for a place in the "right" partition. | |
1135 | * Let's shift the "same" zone to the left. | |
1136 | */ | |
1137 | sameleft -= eltsize; | |
1138 | qsort_rotate((int *) sameright, (int *) sameleft, (int *) i, | |
1139 | eltsize); | |
1140 | sameright -= eltsize; | |
1141 | j = sameright; | |
1142 | /* | |
1143 | * Go back to 1st loop. | |
1144 | */ | |
1145 | goto again; | |
1146 | } | |
1147 | ||
1148 | /* | |
1149 | * The partitions are correct now. Recur on the smallest side only. | |
1150 | */ | |
1151 | if (sameleft - left >= right - (sameright + eltsize)) { | |
1152 | qsort_recur(sameright + eltsize, right, eltsize, compfun); | |
1153 | /* | |
1154 | * The "right" partition is now completely sorted. | |
1155 | * The "same" partition is OK, so... | |
1156 | * Ignore them, and start the loops again on the | |
1157 | * "left" partition. | |
1158 | */ | |
1159 | right = sameleft; | |
1160 | goto top; | |
1161 | } else { | |
1162 | qsort_recur(left, sameleft, eltsize, compfun); | |
1163 | /* | |
1164 | * The "left" partition is now completely sorted. | |
1165 | * The "same" partition is OK, so ... | |
1166 | * Ignore them, and start the loops again on the | |
1167 | * "right" partition. | |
1168 | */ | |
1169 | left = sameright + eltsize; | |
1170 | goto top; | |
1171 | } | |
1172 | } | |
1173 | ||
1174 | void | |
1175 | qsort_checker( | |
1176 | char *table, | |
1177 | int nbelts, | |
1178 | int eltsize, | |
1179 | int (*compfun)(char *, char *)) | |
1180 | { | |
1181 | char *curr, *prev, *last; | |
1182 | ||
1183 | prev = table; | |
1184 | curr = prev + eltsize; | |
1185 | last = table + (nbelts * eltsize); | |
1186 | ||
1187 | while (prev < last) { | |
1188 | if ((*compfun)(prev, curr) > 0) { | |
1189 | printf("**** qsort_checker: error between 0x%x and 0x%x!!!\n", prev, curr); | |
1190 | break; | |
1191 | } | |
1192 | prev = curr; | |
1193 | curr += eltsize; | |
1194 | } | |
1195 | printf("qsort_checker: OK\n"); | |
1196 | } | |
1197 | ||
1198 | int qsort_search_debug = 0; | |
1199 | ||
1200 | void | |
1201 | db_qsort_limit_search( | |
1202 | char *target, | |
1203 | char **start, | |
1204 | char **end, | |
1205 | int eltsize, | |
1206 | int (*compfun)(char *, char *)) | |
1207 | { | |
1208 | register char *left, *right; | |
1209 | char *oleft, *oright, *part; | |
1210 | int nbiter = 0; | |
1211 | int comp; | |
1212 | ||
1213 | oleft = left = *start; | |
1214 | oright = right = *end; | |
1215 | part = (char *) 0; | |
1216 | ||
1217 | while (left < right) { | |
1218 | nbiter++; | |
1219 | part = left + (((right - left) / eltsize) / 2) * eltsize; | |
1220 | comp = (*compfun)(target, part); | |
1221 | if (comp > 0) { | |
1222 | oleft = left; | |
1223 | oright = right; | |
1224 | left = part; | |
1225 | if (left == oleft) | |
1226 | break; | |
1227 | if (qsort_search_debug > 1) | |
1228 | printf(" [ Moved left from 0x%x to 0x%x]\n", | |
1229 | oleft, left); | |
1230 | } else if (comp < 0) { | |
1231 | oright = right; | |
1232 | oleft = left; | |
1233 | right = part; | |
1234 | if (qsort_search_debug > 1) | |
1235 | printf(" [ Moved right from 0x%x to 0x%x]\n", | |
1236 | oright, right); | |
1237 | } else { | |
1238 | if (qsort_search_debug > 1) | |
1239 | printf(" [ FOUND! left=0x%x right=0x%x]\n", | |
1240 | left, right); | |
1241 | for (left = part; | |
1242 | left > *start && (*compfun)(left, part) == 0; | |
1243 | left -= eltsize); | |
1244 | for (right = part + eltsize; | |
1245 | right < *end && (*compfun)(right, part) == 0; | |
1246 | right += eltsize); | |
1247 | oright = right; | |
1248 | oleft = left; | |
1249 | break; | |
1250 | } | |
1251 | } | |
1252 | ||
1253 | if (qsort_search_debug) | |
1254 | printf("[ Limited from %x-%x to %x-%x in %d iters ]\n", | |
1255 | *start, *end, oleft, oright, nbiter); | |
1256 | *start = oleft; | |
1257 | *end = oright; | |
1258 | } | |
1259 | ||
1260 | void | |
1261 | bubble_sort( | |
1262 | char *table, | |
1263 | int nbelts, | |
1264 | int eltsize, | |
1265 | int (*compfun)(char *, char *)) | |
1266 | { | |
1267 | boolean_t sorted; | |
1268 | char *end; | |
1269 | register char *p; | |
1270 | ||
1271 | end = table + ((nbelts-1) * eltsize); | |
1272 | do { | |
1273 | sorted = TRUE; | |
1274 | for (p = table; p < end; p += eltsize) { | |
1275 | if ((*compfun)(p, p + eltsize) > 0) { | |
1276 | qsort_swap((int *) p, (int *) (p + eltsize), | |
1277 | eltsize); | |
1278 | sorted = FALSE; | |
1279 | } | |
1280 | } | |
1281 | } while (sorted == FALSE); | |
1282 | ||
1283 | if (qsort_check) | |
1284 | qsort_checker(table, nbelts, eltsize, compfun); | |
1285 | } | |
1286 | ||
1287 | vm_offset_t vm_min_inks_addr = VM_MAX_KERNEL_ADDRESS; | |
1288 | ||
1289 | void | |
1290 | db_install_inks( | |
1291 | vm_offset_t base) | |
1292 | { | |
1293 | /* save addr to demarcate kernel/inks boundary (1st time only) */ | |
1294 | if (vm_min_inks_addr == VM_MAX_KERNEL_ADDRESS) { | |
1295 | vm_min_inks_addr = base; | |
1296 | db_qualify_ambiguous_names = TRUE; | |
1297 | } | |
1298 | } | |
1299 | ||
1300 | ||
1301 | void | |
1302 | db_clone_symtabXXX( | |
1303 | char *clonee, /* which symtab to clone */ | |
1304 | char *cloner, /* in-kernel-server name */ | |
1305 | vm_offset_t base) /* base address of cloner */ | |
1306 | { | |
1307 | db_symtab_t *st, *st_src; | |
1308 | char * memp; | |
1309 | vm_size_t size; | |
1310 | long offset; | |
1c79356b A |
1311 | extern void db_clone_offsetXXX(char *, long); |
1312 | ||
1313 | if (db_nsymtab >= MAXNOSYMTABS) { | |
1314 | db_printf("db_clone_symtab: Too Many Symbol Tables\n"); | |
1315 | return; | |
1316 | } | |
1317 | ||
1318 | db_install_inks(base); | |
1319 | ||
1320 | st = &db_symtabs[db_nsymtab]; /* destination symtab */ | |
1321 | if ((st_src = db_symtab_cloneeXXX(clonee)) == 0) { | |
1322 | db_printf("db_clone_symtab: clonee (%s) not found\n", clonee); | |
1323 | return; | |
1324 | } | |
1325 | /* alloc new symbols */ | |
1326 | size = (vm_size_t)(st_src->end - st_src->private); | |
91447636 | 1327 | memp = (char *)kalloc( round_page(size) ); |
1c79356b A |
1328 | if (!memp) { |
1329 | db_printf("db_clone_symtab: no memory for symtab\n"); | |
1330 | return; | |
1331 | } | |
1332 | ||
1333 | *st = *st_src; /* bulk copy src -> dest */ | |
1334 | strcpy(st->name, cloner); /* new name */ | |
1335 | st->private = memp; /* copy symbols */ | |
1336 | bcopy((const char *)st_src->private, st->private, size); | |
1337 | st->start = memp + sizeof(int); /* fixup pointers to symtab */ | |
1338 | st->end = memp + *(int *)memp; | |
1339 | st->map_pointer = 0; /* no map because kernel-loaded */ | |
1340 | ||
1341 | /* Offset symbols, leaving strings pointing into st_src */ | |
1342 | offset = base - st_src->minsym; | |
1343 | st->minsym += offset; | |
1344 | st->maxsym += offset; | |
1345 | db_clone_offsetXXX(memp, offset); | |
1346 | db_nsymtab++; | |
1347 | ||
1348 | db_printf( "[ cloned symbol table for %s: range 0x%x to 0x%x %s]\n", | |
1349 | st->name, st->minsym, st->maxsym, | |
1350 | st->sorted ? "(sorted) " : ""); | |
1351 | db_maxval = (unsigned int)st->maxsym + db_maxoff; | |
1352 | } | |
1353 | ||
1354 | db_symtab_t * | |
1355 | db_symtab_cloneeXXX( | |
1356 | char *clonee) | |
1357 | { | |
1358 | db_symtab_t *st, *st_src; | |
1359 | ||
1360 | st = &db_symtabs[db_nsymtab]; /* destination symtab */ | |
1361 | for (st_src = &db_symtabs[0]; st_src < st; ++st_src) | |
1362 | if (!strcmp(clonee, st_src->name)) | |
1363 | break; | |
1364 | return ((st_src < st) ? st_src : 0); | |
1365 | } | |
1366 | ||
1367 | /* | |
1368 | * Switch into symbol-table specific routines | |
1369 | */ | |
1370 | ||
1371 | #if !defined(__alpha) && !defined(INTEL860) | |
1372 | #define DB_NO_COFF | |
1373 | #endif | |
1374 | ||
1375 | #ifndef DB_NO_AOUT | |
1376 | #include <ddb/db_aout.h> | |
1377 | #endif | |
1378 | ||
1379 | #ifndef DB_NO_COFF | |
1380 | #include <ddb/db_coff.h> | |
1381 | #endif | |
1382 | ||
1383 | static void no_init(void) | |
1384 | ||
1385 | { | |
1386 | db_printf("Non-existent code for ddb init\n"); | |
1387 | } | |
1388 | ||
1389 | static boolean_t no_sym_init( | |
1390 | char *start, | |
1391 | char *end, | |
1392 | char *name, | |
1393 | char *task_addr) | |
1394 | { | |
1395 | db_printf("Non-existent code for init of symtab %s\n", name); | |
1396 | return FALSE; | |
1397 | } | |
1398 | ||
1399 | static db_sym_t no_lookup( | |
1400 | db_symtab_t *stab, | |
1401 | char *symstr) | |
1402 | { | |
1403 | db_printf("Bogus lookup of symbol %s\n", symstr); | |
1404 | return DB_SYM_NULL; | |
1405 | } | |
1406 | ||
1407 | static db_sym_t no_search( | |
1408 | db_symtab_t *stab, | |
1409 | db_addr_t off, | |
1410 | db_strategy_t strategy, | |
1411 | db_expr_t *diffp) | |
1412 | { | |
91447636 | 1413 | db_printf("Bogus search for offset %#llXn", (unsigned long long)off); |
1c79356b A |
1414 | return DB_SYM_NULL; |
1415 | } | |
1416 | ||
1417 | static boolean_t no_line_at_pc( | |
1418 | db_symtab_t *stab, | |
1419 | db_sym_t sym, | |
1420 | char **file, | |
1421 | int *line, | |
1422 | db_expr_t pc) | |
1423 | { | |
91447636 | 1424 | db_printf("Bogus search for pc %#llX\n", (unsigned long long)pc); |
1c79356b A |
1425 | return FALSE; |
1426 | } | |
1427 | ||
1428 | static void no_symbol_values( | |
1429 | db_sym_t sym, | |
1430 | char **namep, | |
1431 | db_expr_t *valuep) | |
1432 | { | |
1433 | db_printf("Bogus symbol value resolution\n"); | |
1434 | if (namep) *namep = NULL; | |
1435 | if (valuep) *valuep = 0; | |
1436 | } | |
1437 | ||
1438 | static db_sym_t no_search_by_addr( | |
1439 | db_symtab_t *stab, | |
1440 | db_addr_t off, | |
1441 | char **file, | |
1442 | char **func, | |
1443 | int *line, | |
1444 | db_expr_t *diffp, | |
1445 | int *args) | |
1446 | { | |
91447636 | 1447 | db_printf("Bogus search for address %#llX\n", (unsigned long long)off); |
1c79356b A |
1448 | return DB_SYM_NULL; |
1449 | } | |
1450 | ||
1451 | int | |
1452 | no_print_completion( | |
1453 | db_symtab_t *stab, | |
1454 | char *symstr ) | |
1455 | { | |
1456 | db_printf("Bogus print completion: not supported\n"); | |
1457 | return 0; | |
1458 | } | |
1459 | ||
1460 | int | |
1461 | no_lookup_incomplete( | |
1462 | db_symtab_t *stab, | |
1463 | char *symstr, | |
1464 | char **name, | |
1465 | int *len, | |
1466 | int *toadd) | |
1467 | { | |
1468 | db_printf("Bogus lookup incomplete: not supported\n"); | |
1469 | return 0; | |
1470 | } | |
1471 | ||
1472 | #define NONE \ | |
1473 | { no_init, no_sym_init, no_lookup, no_search, \ | |
1474 | no_line_at_pc, no_symbol_values, no_search_by_addr, \ | |
1475 | no_print_completion, no_lookup_incomplete} | |
1476 | ||
1477 | struct db_sym_switch x_db[] = { | |
1478 | ||
1479 | /* BSD a.out format (really, sdb/dbx(1) symtabs) */ | |
1480 | #ifdef DB_NO_AOUT | |
1481 | NONE, | |
1482 | #else /* DB_NO_AOUT */ | |
1483 | { aout_db_init, aout_db_sym_init, aout_db_lookup, aout_db_search_symbol, | |
1484 | aout_db_line_at_pc, aout_db_symbol_values, aout_db_search_by_addr, | |
1485 | aout_db_print_completion, aout_db_lookup_incomplete}, | |
1486 | #endif /* DB_NO_AOUT */ | |
1487 | ||
1488 | #ifdef DB_NO_COFF | |
1489 | NONE, | |
1490 | #else /* DB_NO_COFF */ | |
1491 | { coff_db_init, coff_db_sym_init, coff_db_lookup, coff_db_search_symbol, | |
1492 | coff_db_line_at_pc, coff_db_symbol_values, coff_db_search_by_addr, | |
1493 | coff_db_print_completion, coff_db_lookup_incomplete }, | |
1494 | #endif /* DB_NO_COFF */ | |
1495 | ||
1496 | /* Machdep, not inited here */ | |
1497 | NONE | |
1498 | }; |