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