]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_sym.c
8e3b5be68b13a9329d10e4c776f7a2d165067031
[apple/xnu.git] / osfmk / ddb / db_sym.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
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@
29 */
30 /*
31 * @OSF_COPYRIGHT@
32 */
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 {
661 db_addr_t diff, newdiff;
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:
671 newdiff = diff = -1;
672 db_last_symtab = 0;
673 for (sp = &db_symtabs[0], i = 0;
674 i < db_nsymtab;
675 sp++, i++) {
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)))) {
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 {
715 db_addr_t diff, newdiff;
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++) {
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 }
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(
820 db_addr_t off,
821 db_strategy_t strategy,
822 task_t task)
823 {
824 db_expr_t d;
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) {
832 db_printf("%#lln", (unsigned long long)off);
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) {
839 db_printf("%#lln",(unsigned long long) off);
840 return;
841 }
842 db_printf("%s", name);
843 if (d)
844 db_printf("+%llx", (unsigned long long)d);
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) {
920 db_printf("%#lln", (unsigned long long)off);
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;
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);
1327 memp = (char *)kalloc( round_page(size) );
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 {
1413 db_printf("Bogus search for offset %#llXn", (unsigned long long)off);
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 {
1424 db_printf("Bogus search for pc %#llX\n", (unsigned long long)pc);
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 {
1447 db_printf("Bogus search for address %#llX\n", (unsigned long long)off);
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 };