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