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