]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ddb/db_sym.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / osfmk / ddb / db_sym.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
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.
e5568f75 11 *
37839358
A
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,
37839358
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{
91447636 653 db_addr_t diff, newdiff;
1c79356b
A
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:
91447636 663 newdiff = diff = -1;
1c79356b
A
664 db_last_symtab = 0;
665 for (sp = &db_symtabs[0], i = 0;
666 i < db_nsymtab;
667 sp++, i++) {
91447636
A
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 ((val >= (db_addr_t)sp->minsym) &&
672 (val <= (db_addr_t)sp->maxsym)))) {
1c79356b
A
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{
91447636 707 db_addr_t diff, newdiff;
1c79356b
A
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++) {
91447636
A
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 ((val >= (db_addr_t)sp->minsym) &&
735 (val <= (db_addr_t)sp->maxsym)))) {
736
737 sym = X_db_search_by_addr(sp, val, &filename, &func,
738 &linenum, (db_expr_t *)&newdiff,
739 &args);
740 if (sym && newdiff < diff) {
741 db_last_symtab = sp;
742 diff = newdiff;
743 ret = sym;
744 *filenamep = filename;
745 *linenump = linenum;
746 *argsp = args;
747 if (diff <= db_search_maxoff)
748 break;
749 }
1c79356b
A
750 }
751 }
752 if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) {
753 map_for_val = VM_MAP_NULL;
754 goto again;
755 }
756 *offp = diff;
757 if (*filenamep)
758 db_shorten_filename(filenamep);
759 return ret;
760}
761
762/*
763 * Return name and value of a symbol
764 */
765void
766db_symbol_values(
767 db_symtab_t *stab,
768 db_sym_t sym,
769 char **namep,
770 db_expr_t *valuep)
771{
772 db_expr_t value;
773 char *name;
774
775 if (sym == DB_SYM_NULL) {
776 *namep = 0;
777 return;
778 }
779 if (stab == 0)
780 stab = db_last_symtab;
781
782 X_db_symbol_values(stab, sym, &name, &value);
783
784 if (db_symbol_is_ambiguous(name)) {
785 *namep = db_qualify(name, db_last_symtab->name);
786 }else {
787 *namep = name;
788 }
789 if (valuep)
790 *valuep = value;
791}
792
793
794/*
795 * Print a the closest symbol to value
796 *
797 * After matching the symbol according to the given strategy
798 * we print it in the name+offset format, provided the symbol's
799 * value is close enough (eg smaller than db_maxoff).
800 * We also attempt to print [filename:linenum] when applicable
801 * (eg for procedure names).
802 *
803 * If we could not find a reasonable name+offset representation,
804 * then we just print the value in hex. Small values might get
805 * bogus symbol associations, e.g. 3 might get some absolute
806 * value like _INCLUDE_VERSION or something, therefore we do
807 * not accept symbols whose value is zero (and use plain hex).
808 */
809
810void
811db_task_printsym(
91447636 812 db_addr_t off,
1c79356b
A
813 db_strategy_t strategy,
814 task_t task)
815{
91447636 816 db_expr_t d;
1c79356b
A
817 char *filename;
818 char *name;
819 db_expr_t value;
820 int linenum;
821 db_sym_t cursym;
822
823 if (off >= db_maxval || off < db_minval) {
91447636 824 db_printf("%#lln", (unsigned long long)off);
1c79356b
A
825 return;
826 }
827 cursym = db_search_task_symbol(off, strategy, &d, task);
828
829 db_symbol_values(0, cursym, &name, &value);
830 if (name == 0 || d >= db_maxoff || value == 0) {
91447636 831 db_printf("%#lln",(unsigned long long) off);
1c79356b
A
832 return;
833 }
834 db_printf("%s", name);
835 if (d)
91447636 836 db_printf("+%llx", (unsigned long long)d);
1c79356b
A
837 if (strategy == DB_STGY_PROC) {
838 if (db_line_at_pc(cursym, &filename, &linenum, off)) {
839 db_printf(" [%s", filename);
840 if (linenum > 0)
841 db_printf(":%d", linenum);
842 db_printf("]");
843 }
844 }
845}
846
847/*
848 * Return symbol name for a given offset and
849 * change the offset to be relative to this symbol.
850 * Very usefull for xpr, when you want to log offsets
851 * in a user friendly way.
852 */
853
854char null_sym[] = "";
855
856char *
857db_get_sym(db_expr_t *off)
858{
859 db_sym_t cursym;
860 db_expr_t value;
861 char *name;
862 db_addr_t d;
863
864 cursym = db_search_symbol(*off, DB_STGY_ANY, &d);
865 db_symbol_values(0, cursym, &name, &value);
866 if (name)
867 *off = d;
868 else
869 name = null_sym;
870 return(name);
871}
872
873void
874db_printsym(
875 db_expr_t off,
876 db_strategy_t strategy)
877{
878 db_task_printsym(off, strategy, TASK_NULL);
879}
880
881int db_short_filename = 1;
882
883void
884db_shorten_filename(char **filenamep)
885{
886 char *cp, *cp_slash;
887
888 if (! *filenamep)
889 return;
890 for (cp = cp_slash = *filenamep; *cp; cp++) {
891 if (*cp == '/')
892 cp_slash = cp;
893 }
894 if (*cp_slash == '/')
895 *filenamep = cp_slash+1;
896}
897
898int
899db_task_getlinenum(
900 db_expr_t off,
901 task_t task)
902{
903 db_addr_t d;
904 char *filename;
905 char *name;
906 db_expr_t value;
907 int linenum;
908 db_sym_t cursym;
909 db_strategy_t strategy = DB_STGY_PROC;
910
911 if (off >= db_maxval || off < db_minval) {
91447636 912 db_printf("%#lln", (unsigned long long)off);
1c79356b
A
913 return(-1);
914 }
915 cursym = db_search_task_symbol(off, strategy, &d, task);
916
917 db_symbol_values(0, cursym, &name, &value);
918 if (name == 0 || d >= db_maxoff || value == 0) {
919 return(-1);
920 }
921 if (db_line_at_pc(cursym, &filename, &linenum, off))
922 return(linenum);
923 else
924 return(-1);
925}
926
927boolean_t
928db_line_at_pc(
929 db_sym_t sym,
930 char **filename,
931 int *linenum,
932 db_expr_t pc)
933{
934 boolean_t result;
935
936 if (db_last_symtab == 0)
937 return FALSE;
938 if (X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc)) {
939 if (db_short_filename)
940 db_shorten_filename(filename);
941 result = TRUE;
942 } else
943 result = FALSE;
944 return(result);
945}
946
947int qsort_check = 0;
948
949void
950db_qsort(
951 char *table,
952 int nbelts,
953 int eltsize,
954 int (*compfun)(char *, char *))
955{
956 if (nbelts <= 0 || eltsize <= 0 || compfun == 0) {
957 printf("qsort: invalid parameters\n");
958 return;
959 }
960 qsort_recur(table, table + nbelts * eltsize, eltsize, compfun);
961
962 if (qsort_check)
963 qsort_checker(table, nbelts, eltsize, compfun);
964}
965
966void
967qsort_swap(
968 register int *a,
969 register int *b,
970 register int size)
971{
972 register int temp;
973 char *aa, *bb;
974 char ctemp;
975
976 for (; size >= sizeof (int); size -= sizeof (int), a++, b++) {
977 temp = *a;
978 *a = *b;
979 *b = temp;
980 }
981 aa = (char *)a;
982 bb = (char *)b;
983 for (; size > 0; size--, aa++, bb++) {
984 ctemp = *aa;
985 *aa = *bb;
986 *bb = ctemp;
987 }
988}
989
990/* rotate the three elements to the left */
991void
992qsort_rotate(
993 register int *a,
994 register int *b,
995 register int *c,
996 register int size)
997{
998 register int temp;
999 char *aa, *bb, *cc;
1000 char ctemp;
1001
1002 for (; size >= sizeof (int); size -= sizeof (int), a++, b++, c++) {
1003 temp = *a;
1004 *a = *c;
1005 *c = *b;
1006 *b = temp;
1007 }
1008 aa = (char *)a;
1009 bb = (char *)b;
1010 cc = (char *)c;
1011 for (; size > 0; size--, aa++, bb++, cc++) {
1012 ctemp = *aa;
1013 *aa = *cc;
1014 *cc = *bb;
1015 *bb = ctemp;
1016 }
1017}
1018
1019void
1020qsort_recur(
1021 char *left,
1022 char *right,
1023 int eltsize,
1024 int (*compfun)(char *, char *))
1025{
1026 char *i, *j;
1027 char *sameleft, *sameright;
1028
1029 top:
1030 if (left + eltsize - 1 >= right) {
1031 return;
1032 }
1033
1034 /* partition element (reference for "same"ness */
1035 sameleft = left + (((right - left) / eltsize) / 2) * eltsize;
1036 sameright = sameleft;
1037
1038 i = left;
1039 j = right - eltsize;
1040
1041 again:
1042 while (i < sameleft) {
1043 int comp;
1044
1045 comp = (*compfun)(i, sameleft);
1046 if (comp == 0) {
1047 /*
1048 * Move to the "same" partition.
1049 */
1050 /*
1051 * Shift the left part of the "same" partition to
1052 * the left, so that "same" elements stay in their
1053 * original order.
1054 */
1055 sameleft -= eltsize;
1056 qsort_swap((int *) i, (int *) sameleft, eltsize);
1057 } else if (comp < 0) {
1058 /*
1059 * Stay in the "left" partition.
1060 */
1061 i += eltsize;
1062 } else {
1063 /*
1064 * Should be moved to the "right" partition.
1065 * Wait until the next loop finds an appropriate
1066 * place to store this element.
1067 */
1068 break;
1069 }
1070 }
1071
1072 while (j > sameright) {
1073 int comp;
1074
1075 comp = (*compfun)(sameright, j);
1076 if (comp == 0) {
1077 /*
1078 * Move to the right of the "same" partition.
1079 */
1080 sameright += eltsize;
1081 qsort_swap((int *) sameright, (int *) j, eltsize);
1082 } else if (comp > 0) {
1083 /*
1084 * Move to the "left" partition.
1085 */
1086 if (i == sameleft) {
1087 /*
1088 * Unfortunately, the "left" partition
1089 * has already been fully processed, so
1090 * we have to shift the "same" partition
1091 * to the right to free a "left" element.
1092 * This is done by moving the leftest same
1093 * to the right of the "same" partition.
1094 */
1095 sameright += eltsize;
1096 qsort_rotate((int *) sameleft, (int*) sameright,
1097 (int *) j, eltsize);
1098 sameleft += eltsize;
1099 i = sameleft;
1100 } else {
1101 /*
1102 * Swap with the "left" partition element
1103 * waiting to be moved to the "right"
1104 * partition.
1105 */
1106 qsort_swap((int *) i, (int *) j, eltsize);
1107 j -= eltsize;
1108 /*
1109 * Go back to the 1st loop.
1110 */
1111 i += eltsize;
1112 goto again;
1113 }
1114 } else {
1115 /*
1116 * Stay in the "right" partition.
1117 */
1118 j -= eltsize;
1119 }
1120 }
1121
1122 if (i != sameleft) {
1123 /*
1124 * The second loop completed (the"right" partition is ok),
1125 * but we have to go back to the first loop, and deal with
1126 * the element waiting for a place in the "right" partition.
1127 * Let's shift the "same" zone to the left.
1128 */
1129 sameleft -= eltsize;
1130 qsort_rotate((int *) sameright, (int *) sameleft, (int *) i,
1131 eltsize);
1132 sameright -= eltsize;
1133 j = sameright;
1134 /*
1135 * Go back to 1st loop.
1136 */
1137 goto again;
1138 }
1139
1140 /*
1141 * The partitions are correct now. Recur on the smallest side only.
1142 */
1143 if (sameleft - left >= right - (sameright + eltsize)) {
1144 qsort_recur(sameright + eltsize, right, eltsize, compfun);
1145 /*
1146 * The "right" partition is now completely sorted.
1147 * The "same" partition is OK, so...
1148 * Ignore them, and start the loops again on the
1149 * "left" partition.
1150 */
1151 right = sameleft;
1152 goto top;
1153 } else {
1154 qsort_recur(left, sameleft, eltsize, compfun);
1155 /*
1156 * The "left" partition is now completely sorted.
1157 * The "same" partition is OK, so ...
1158 * Ignore them, and start the loops again on the
1159 * "right" partition.
1160 */
1161 left = sameright + eltsize;
1162 goto top;
1163 }
1164}
1165
1166void
1167qsort_checker(
1168 char *table,
1169 int nbelts,
1170 int eltsize,
1171 int (*compfun)(char *, char *))
1172{
1173 char *curr, *prev, *last;
1174
1175 prev = table;
1176 curr = prev + eltsize;
1177 last = table + (nbelts * eltsize);
1178
1179 while (prev < last) {
1180 if ((*compfun)(prev, curr) > 0) {
1181 printf("**** qsort_checker: error between 0x%x and 0x%x!!!\n", prev, curr);
1182 break;
1183 }
1184 prev = curr;
1185 curr += eltsize;
1186 }
1187 printf("qsort_checker: OK\n");
1188}
1189
1190int qsort_search_debug = 0;
1191
1192void
1193db_qsort_limit_search(
1194 char *target,
1195 char **start,
1196 char **end,
1197 int eltsize,
1198 int (*compfun)(char *, char *))
1199{
1200 register char *left, *right;
1201 char *oleft, *oright, *part;
1202 int nbiter = 0;
1203 int comp;
1204
1205 oleft = left = *start;
1206 oright = right = *end;
1207 part = (char *) 0;
1208
1209 while (left < right) {
1210 nbiter++;
1211 part = left + (((right - left) / eltsize) / 2) * eltsize;
1212 comp = (*compfun)(target, part);
1213 if (comp > 0) {
1214 oleft = left;
1215 oright = right;
1216 left = part;
1217 if (left == oleft)
1218 break;
1219 if (qsort_search_debug > 1)
1220 printf(" [ Moved left from 0x%x to 0x%x]\n",
1221 oleft, left);
1222 } else if (comp < 0) {
1223 oright = right;
1224 oleft = left;
1225 right = part;
1226 if (qsort_search_debug > 1)
1227 printf(" [ Moved right from 0x%x to 0x%x]\n",
1228 oright, right);
1229 } else {
1230 if (qsort_search_debug > 1)
1231 printf(" [ FOUND! left=0x%x right=0x%x]\n",
1232 left, right);
1233 for (left = part;
1234 left > *start && (*compfun)(left, part) == 0;
1235 left -= eltsize);
1236 for (right = part + eltsize;
1237 right < *end && (*compfun)(right, part) == 0;
1238 right += eltsize);
1239 oright = right;
1240 oleft = left;
1241 break;
1242 }
1243 }
1244
1245 if (qsort_search_debug)
1246 printf("[ Limited from %x-%x to %x-%x in %d iters ]\n",
1247 *start, *end, oleft, oright, nbiter);
1248 *start = oleft;
1249 *end = oright;
1250}
1251
1252void
1253bubble_sort(
1254 char *table,
1255 int nbelts,
1256 int eltsize,
1257 int (*compfun)(char *, char *))
1258{
1259 boolean_t sorted;
1260 char *end;
1261 register char *p;
1262
1263 end = table + ((nbelts-1) * eltsize);
1264 do {
1265 sorted = TRUE;
1266 for (p = table; p < end; p += eltsize) {
1267 if ((*compfun)(p, p + eltsize) > 0) {
1268 qsort_swap((int *) p, (int *) (p + eltsize),
1269 eltsize);
1270 sorted = FALSE;
1271 }
1272 }
1273 } while (sorted == FALSE);
1274
1275 if (qsort_check)
1276 qsort_checker(table, nbelts, eltsize, compfun);
1277}
1278
1279vm_offset_t vm_min_inks_addr = VM_MAX_KERNEL_ADDRESS;
1280
1281void
1282db_install_inks(
1283 vm_offset_t base)
1284{
1285 /* save addr to demarcate kernel/inks boundary (1st time only) */
1286 if (vm_min_inks_addr == VM_MAX_KERNEL_ADDRESS) {
1287 vm_min_inks_addr = base;
1288 db_qualify_ambiguous_names = TRUE;
1289 }
1290}
1291
1292
1293void
1294db_clone_symtabXXX(
1295 char *clonee, /* which symtab to clone */
1296 char *cloner, /* in-kernel-server name */
1297 vm_offset_t base) /* base address of cloner */
1298{
1299 db_symtab_t *st, *st_src;
1300 char * memp;
1301 vm_size_t size;
1302 long offset;
1c79356b
A
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);
91447636 1319 memp = (char *)kalloc( round_page(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{
91447636 1405 db_printf("Bogus search for offset %#llXn", (unsigned long long)off);
1c79356b
A
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{
91447636 1416 db_printf("Bogus search for pc %#llX\n", (unsigned long long)pc);
1c79356b
A
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{
91447636 1439 db_printf("Bogus search for address %#llX\n", (unsigned long long)off);
1c79356b
A
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};