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