|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * HISTORY
27: *
28: * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
29: * Import of Mac OS X kernel (~semeria)
30: *
31: * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
32: * Import of OSF Mach kernel (~mburg)
33: *
34: * Revision 1.3.22.8 1996/07/31 09:07:24 paire
35: * Merged with nmk20b7_shared (1.3.47.1)
36: * [96/07/24 paire]
37: *
38: * Revision 1.3.47.1 1996/06/13 12:36:08 bernadat
39: * Do not assume anymore that VM_MIN_KERNEL_ADDRESS
40: * is greater or equal than VM_MAX_ADDRESS.
41: * [96/05/23 bernadat]
42: *
43: * Revision 1.3.22.7 1996/01/09 19:16:15 devrcs
44: * Added db_task_getlinenum() function. (steved)
45: * Make db_maxval & db_minval long int's for Alpha.
46: * Changed declarations of 'register foo' to 'register int foo'.
47: * [1995/12/01 21:42:29 jfraser]
48: *
49: * Merged '64-bit safe' changes from DEC alpha port.
50: * [1995/11/21 18:03:41 jfraser]
51: *
52: * Revision 1.3.22.6 1995/02/28 01:58:46 dwm
53: * Merged with changes from 1.3.22.5
54: * [1995/02/28 01:53:47 dwm]
55: *
56: * mk6 CR1120 - Merge mk6pro_shared into cnmk_shared
57: * remove a couple local protos, now in .h file (for better or worse)
58: * [1995/02/28 01:12:51 dwm]
59: *
60: * Revision 1.3.22.5 1995/02/23 21:43:43 alanl
61: * Move TR_INIT to model_dep.c (MACH_TR and MACH_KDB shouldn't
62: * be bound).
63: * [95/02/16 travos]
64: *
65: * Prepend a "db_" to qsort and qsort_limit_search
66: * (collisions with the real qsort in stdlib.h)
67: * [95/02/14 travos]
68: *
69: * Added X_db_init for object independent formats.
70: * [95/01/24 sjs]
71: *
72: * Merge with DIPC2_SHARED.
73: * [1995/01/05 13:32:53 alanl]
74: *
75: * Revision 1.3.30.2 1994/12/22 20:36:15 bolinger
76: * Fix ri-osc CR881: enable freer use of symbol table of collocated
77: * tasks. No point in requiring task to be named for symbols to be
78: * usable. Also fixed glitch in use of symtab cloning.
79: * [1994/12/22 20:34:55 bolinger]
80: *
81: * Revision 1.3.30.1 1994/11/04 09:53:14 dwm
82: * mk6 CR668 - 1.3b26 merge
83: * add arg to *_db_search_by_addr() from mk6
84: * * Revision 1.3.4.9 1994/05/13 15:57:14 tmt
85: * Add hooks for catching calls to uninstalled symbol tables.
86: * Add XXX_search_by_addr() vectors.
87: * * Revision 1.3.4.8 1994/05/12 21:59:00 tmt
88: * Fix numerous db_sym_t/char * mixups.
89: * Fix and enable db_qualify_ambiguous_names.
90: * Make dif and newdiff unsigned in symbol searches.
91: * * Revision 1.3.4.7 1994/05/06 18:39:52 tmt
92: * Merged osc1.3dec/shared with osc1.3b19
93: * Fix function prototype declarations.
94: * Merge Alpha changes into osc1.312b source code.
95: * String protos.
96: * Handle multiple, coexisting symbol table types.
97: * 64bit cleanup.
98: * Revision 1.3.4.5 1993/10/20 18:58:55 gm
99: * CR9704: Removed symbol load printf.
100: * * End1.3merge
101: * [1994/11/04 08:50:02 dwm]
102: *
103: * Revision 1.3.22.5 1995/02/23 21:43:43 alanl
104: * Move TR_INIT to model_dep.c (MACH_TR and MACH_KDB shouldn't
105: * be bound).
106: * [95/02/16 travos]
107: *
108: * Prepend a "db_" to qsort and qsort_limit_search
109: * (collisions with the real qsort in stdlib.h)
110: * [95/02/14 travos]
111: *
112: * Added X_db_init for object independent formats.
113: * [95/01/24 sjs]
114: *
115: * Merge with DIPC2_SHARED.
116: * [1995/01/05 13:32:53 alanl]
117: *
118: * Revision 1.3.30.2 1994/12/22 20:36:15 bolinger
119: * Fix ri-osc CR881: enable freer use of symbol table of collocated
120: * tasks. No point in requiring task to be named for symbols to be
121: * usable. Also fixed glitch in use of symtab cloning.
122: * [1994/12/22 20:34:55 bolinger]
123: *
124: * Revision 1.3.30.1 1994/11/04 09:53:14 dwm
125: * mk6 CR668 - 1.3b26 merge
126: * add arg to *_db_search_by_addr() from mk6
127: * * Revision 1.3.4.9 1994/05/13 15:57:14 tmt
128: * Add hooks for catching calls to uninstalled symbol tables.
129: * Add XXX_search_by_addr() vectors.
130: * * Revision 1.3.4.8 1994/05/12 21:59:00 tmt
131: * Fix numerous db_sym_t/char * mixups.
132: * Fix and enable db_qualify_ambiguous_names.
133: * Make dif and newdiff unsigned in symbol searches.
134: * * Revision 1.3.4.7 1994/05/06 18:39:52 tmt
135: * Merged osc1.3dec/shared with osc1.3b19
136: * Fix function prototype declarations.
137: * Merge Alpha changes into osc1.312b source code.
138: * String protos.
139: * Handle multiple, coexisting symbol table types.
140: * 64bit cleanup.
141: * Revision 1.3.4.5 1993/10/20 18:58:55 gm
142: * CR9704: Removed symbol load printf.
143: * * End1.3merge
144: * [1994/11/04 08:50:02 dwm]
145: *
146: * Revision 1.3.22.3 1994/09/23 01:21:37 ezf
147: * change marker to not FREE
148: * [1994/09/22 21:10:58 ezf]
149: *
150: * Revision 1.3.22.2 1994/06/26 22:58:24 bolinger
151: * Suppress symbol table range output when table is unsorted, since output
152: * is meaningless in this case.
153: * [1994/06/23 20:19:02 bolinger]
154: *
155: * Revision 1.3.22.1 1994/06/11 21:12:19 bolinger
156: * Merge up to NMK17.2.
157: * [1994/06/11 20:02:31 bolinger]
158: *
159: * Revision 1.3.17.1 1994/02/08 10:58:40 bernadat
160: * Check result of X_db_line_at_pc() before
161: * invoking db_shorten_filename().
162: * [93/11/30 bernadat]
163: *
164: * Installed ddb_init() routine in a symbol-independent file to call
165: * symbol-dependent and machine-dependent initialization routines.
166: * [93/08/27 paire]
167: *
168: * Fixed db_shorten_filename() to gobble the last slash.
169: * Modified db_search_task_symbol_and_line() interface to return
170: * the number of a function arguments.
171: * [93/08/19 paire]
172: *
173: * Added new arguments to db_sym_print_completion() call.
174: * [93/08/18 paire]
175: *
176: * Added db_lookup_incomplete(), db_sym_parse_and_lookup_incomplete(),
177: * db_sym_print_completion() and db_completion_print() for support of
178: * symbol completion.
179: * [93/08/14 paire]
180: * [94/02/07 bernadat]
181: *
182: * Revision 1.3.15.4 1994/06/08 19:11:23 dswartz
183: * Preemption merge.
184: * [1994/06/08 19:10:24 dswartz]
185: *
186: * Revision 1.3.20.2 1994/06/01 21:34:39 klj
187: * Initial preemption code base merge
188: *
189: * Revision 1.3.15.3 1994/02/10 02:28:15 bolinger
190: * Fix db_add_symbol_table() to increase db_maxval if highest-addressed
191: * symbol in new symtab is greater than its current value.
192: * [1994/02/09 21:42:12 bolinger]
193: *
194: * Revision 1.3.15.2 1994/02/03 21:44:23 bolinger
195: * Update db_maxval when a symbol table is cloned for kernel-loaded
196: * server.
197: * [1994/02/03 20:47:22 bolinger]
198: *
199: * Revision 1.3.15.1 1994/02/03 02:41:58 dwm
200: * Add short-term kludge to provide symbolic info on INKServer.
201: * [1994/02/03 02:31:17 dwm]
202: *
203: * Revision 1.3.4.4 1993/08/11 20:38:11 elliston
204: * Add ANSI Prototypes. CR #9523.
205: * [1993/08/11 03:33:59 elliston]
206: *
207: * Revision 1.3.4.3 1993/07/27 18:28:09 elliston
208: * Add ANSI prototypes. CR #9523.
209: * [1993/07/27 18:12:57 elliston]
210: *
211: * Revision 1.3.4.2 1993/06/09 02:20:50 gm
212: * CR9176 - ANSI C violations: trailing tokens on CPP
213: * directives, extra semicolons after decl_ ..., asm keywords
214: * [1993/06/07 18:57:31 jeffc]
215: *
216: * Added to OSF/1 R1.3 from NMK15.0.
217: * [1993/06/02 20:57:10 jeffc]
218: *
219: * Revision 1.3 1993/04/19 16:03:09 devrcs
220: * Protect db_line_at_pc() against null db_last_symtab.
221: * [1993/02/11 15:37:16 barbou]
222: *
223: * Changes from MK78:
224: * Upped MAXNOSYMTABS from 3 to 5. Now there is space for kernel,
225: * bootstrap, server, and emulator symbols - plus one for future
226: * expansion.
227: * [92/03/21 danner]
228: * Changed CHAR arg of db_eqname to UNSIGNED.
229: * Made arg types proper for db_line_at_pc().
230: * [92/05/16 jfriedl]
231: * [92/12/18 bruel]
232: *
233: * Sort large symbol tables to speedup lookup.
234: * Improved symbol lookup (use of max_offset, dichotomic search)
235: * [[email protected]]
236: *
237: * db_add_symbol_table now takes 3 additional arguments. Machine
238: * dependant modules must provide them. [[email protected]]
239: * [92/12/03 bernadat]
240: *
241: * Revision 1.2 1992/11/25 01:04:42 robert
242: * integrate changes below for norma_14
243: * [1992/11/13 19:22:44 robert]
244: *
245: * Revision 1.1 1992/09/30 02:01:25 robert
246: * Initial revision
247: *
248: * $EndLog$
249: */
250: /* CMU_HIST */
251: /*
252: * Revision 2.10.4.1 92/02/18 18:38:53 jeffreyh
253: * Added db_get_sym(). Simple interface to get symbol names
254: * knowing the offset.
255: * [91/12/20 bernadat]
256: *
257: * Do not look for symbol names if address
258: * is to small or to large, otherwise get
259: * random names like INCLUDE_VERSION+??
260: * [91/06/25 bernadat]
261: *
262: * Revision 2.10 91/10/09 16:02:30 af
263: * Revision 2.9.2.1 91/10/05 13:07:27 jeffreyh
264: * Changed symbol table name qualification syntax from "xxx:yyy"
265: * to "xxx::yyy" to allow "file:func:line" in "yyy" part.
266: * "db_sym_parse_and_lookup" is also added for "yyy" part parsing.
267: * Replaced db_search_symbol with db_search_task_symbol, and moved
268: * it to "db_sym.h" as a macro.
269: * Added db_task_printsym, and changed db_printsym to call it.
270: * Added include "db_task_thread.h".
271: * Fixed infinite recursion of db_symbol_values.
272: * [91/08/29 tak]
273: *
274: * Revision 2.9.2.1 91/10/05 13:07:27 jeffreyh
275: * Changed symbol table name qualification syntax from "xxx:yyy"
276: * to "xxx::yyy" to allow "file:func:line" in "yyy" part.
277: * "db_sym_parse_and_lookup" is also added for "yyy" part parsing.
278: * Replaced db_search_symbol with db_search_task_symbol, and moved
279: * it to "db_sym.h" as a macro.
280: * Added db_task_printsym, and changed db_printsym to call it.
281: * Added include "db_task_thread.h".
282: * Fixed infinite recursion of db_symbol_values.
283: * [91/08/29 tak]
284: *
285: * Revision 2.9 91/07/31 17:31:14 dbg
286: * Add task pointer and space for string storage to symbol table
287: * descriptor.
288: * [91/07/31 dbg]
289: *
290: * Revision 2.8 91/07/09 23:16:08 danner
291: * Changed a printf.
292: * [91/07/08 danner]
293: *
294: * Revision 2.7 91/05/14 15:35:54 mrt
295: * Correcting copyright
296: *
297: * Revision 2.6 91/03/16 14:42:40 rpd
298: * Changed the default db_maxoff to 4K.
299: * [91/03/10 rpd]
300: *
301: * Revision 2.5 91/02/05 17:07:07 mrt
302: * Changed to new Mach copyright
303: * [91/01/31 16:19:17 mrt]
304: *
305: * Revision 2.4 90/10/25 14:44:05 rwd
306: * Changed db_printsym to print unsigned.
307: * [90/10/19 rpd]
308: *
309: * Revision 2.3 90/09/09 23:19:56 rpd
310: * Avoid totally incorrect guesses of symbol names for small values.
311: * [90/08/30 17:39:48 af]
312: *
313: * Revision 2.2 90/08/27 21:52:18 dbg
314: * Removed nlist.h. Fixed some type declarations.
315: * Qualifier character is ':'.
316: * [90/08/20 dbg]
317: * Modularized symtab info into a new db_symtab_t type.
318: * Modified db_add_symbol_table and others accordingly.
319: * Defined db_sym_t, a new (opaque) type used to represent
320: * symbols. This should support all sort of future symtable
321: * formats. Functions like db_qualify take a db_sym_t now.
322: * New db_symbol_values() function to explode the content
323: * of a db_sym_t.
324: * db_search_symbol() replaces db_find_sym_and_offset(), which is
325: * now a macro defined in our (new) header file. This new
326: * function accepts more restrictive searches, which are
327: * entirely delegated to the symtab-specific code.
328: * Accordingly, db_printsym() accepts a strategy parameter.
329: * New db_line_at_pc() function.
330: * Renamed misleading db_eqsym into db_eqname.
331: * [90/08/20 10:47:06 af]
332: *
333: * Created.
334: * [90/07/25 dbg]
335: *
336: * Revision 2.1 90/07/26 16:43:52 dbg
337: * Created.
338: *
339: */
340: /* CMU_ENDHIST */
341: /*
342: * Mach Operating System
343: * Copyright (c) 1991,1990 Carnegie Mellon University
344: * All Rights Reserved.
345: *
346: * Permission to use, copy, modify and distribute this software and its
347: * documentation is hereby granted, provided that both the copyright
348: * notice and this permission notice appear in all copies of the
349: * software, derivative works or modified versions, and any portions
350: * thereof, and that both notices appear in supporting documentation.
351: *
352: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
353: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
354: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
355: *
356: * Carnegie Mellon requests users of this software to return to
357: *
358: * Software Distribution Coordinator or [email protected]
359: * School of Computer Science
360: * Carnegie Mellon University
361: * Pittsburgh PA 15213-3890
362: *
363: * any improvements or extensions that they make and grant Carnegie Mellon
364: * the rights to redistribute these changes.
365: */
366: /*
367: */
368: /*
369: * Author: David B. Golub, Carnegie Mellon University
370: * Date: 7/90
371: */
372:
373: #include <machine/db_machdep.h>
374: #include <string.h> /* For strcpy(), strcmp() */
375: #include <mach/std_types.h>
376: #include <kern/misc_protos.h> /* For printf() */
377: #include <ddb/db_sym.h>
378: #include <ddb/db_task_thread.h>
379: #include <ddb/db_command.h>
380: #include <ddb/db_output.h> /* For db_printf() */
381:
382: #include <vm/vm_map.h> /* vm_map_t */
383:
384: /*
385: * Multiple symbol tables
386: *
387: * mach, bootstrap, name_server, default_pager, unix, 1 spare
388: */
389: #define MAXNOSYMTABS 6
390:
391: db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0}};
392: int db_nsymtab = 0;
393:
394: db_symtab_t *db_last_symtab;
395:
396: unsigned long db_maxoff = 0x4000;
397: extern char end;
398: unsigned long db_maxval = (unsigned long)&end;
399: natural_t db_minval = 0x1000;
400:
401: /* Prototypes for functions local to this file. XXX -- should be static!
402: */
403: static char *db_qualify(
404: char *sym,
405: register char *symtabname);
406:
407: boolean_t db_eqname(
408: char *src,
409: char *dst,
410: unsigned c);
411:
412: boolean_t db_symbol_is_ambiguous(char *name);
413:
414: void db_shorten_filename(char **filenamep);
415:
416: void qsort_swap(
417: register int *a,
418: register int *b,
419: register int size);
420:
421: void qsort_rotate(
422: register int *a,
423: register int *b,
424: register int *c,
425: register int size);
426:
427: void qsort_recur(
428: char *left,
429: char *right,
430: int eltsize,
431: int (*compfun)(char *, char *));
432:
433: void qsort_checker(
434: char *table,
435: int nbelts,
436: int eltsize,
437: int (*compfun)(char *, char *));
438:
439: void bubble_sort(
440: char *table,
441: int nbelts,
442: int eltsize,
443: int (*compfun)(char *, char *));
444:
445: int no_print_completion(
446: db_symtab_t *stab,
447: char *symstr );
448: int no_lookup_incomplete(
449: db_symtab_t *stab,
450: char *symstr,
451: char **name,
452: int *len,
453: int *toadd);
454:
455: /*
456: * Initialization routine for ddb.
457: */
458: void
459: ddb_init(void)
460: {
461: X_db_init();
462: db_machdep_init();
463: }
464:
465: /*
466: * Add symbol table, with given name, to list of symbol tables.
467: */
468: boolean_t
469: db_add_symbol_table(
470: int type,
471: char *start,
472: char *end,
473: char *name,
474: char *ref,
475: char *map_pointer,
476: unsigned long minsym,
477: unsigned long maxsym,
478: boolean_t sorted)
479: {
480: register db_symtab_t *st;
481: extern vm_map_t kernel_map;
482:
483: if (db_nsymtab >= MAXNOSYMTABS)
484: return (FALSE);
485:
486: st = &db_symtabs[db_nsymtab];
487: st->type = type;
488: st->start = start;
489: st->end = end;
490: st->private = ref;
491: if (map_pointer == (char *)kernel_map ||
492: (VM_MAX_ADDRESS <= VM_MIN_KERNEL_ADDRESS &&
493: VM_MIN_KERNEL_ADDRESS <= minsym))
494: st->map_pointer = 0;
495: else
496: st->map_pointer = map_pointer;
497: strcpy(st->name, name);
498: st->minsym = minsym;
499: st->maxsym = maxsym;
500: if (maxsym == 0)
501: st->sorted = FALSE;
502: else {
503: st->sorted = sorted;
504: if (db_maxval < maxsym + db_maxoff)
505: db_maxval = maxsym + db_maxoff;
506: }
507: db_nsymtab++;
508:
509: return (TRUE);
510: }
511:
512: /*
513: * db_qualify("vm_map", "ux") returns "ux::vm_map".
514: *
515: * Note: return value points to static data whose content is
516: * overwritten by each call... but in practice this seems okay.
517: */
518: static char *
519: db_qualify(
520: char *symname,
521: register char *symtabname)
522: {
523: static char tmp[256];
524: register char *s;
525:
526: s = tmp;
527: while (*s++ = *symtabname++) {
528: }
529: s[-1] = ':';
530: *s++ = ':';
531: while (*s++ = *symname++) {
532: }
533: return tmp;
534: }
535:
536:
537: boolean_t
538: db_eqname(
539: char *src,
540: char *dst,
541: unsigned c)
542: {
543: if (!strcmp(src, dst))
544: return (TRUE);
545: if (src[0] == c)
546: return (!strcmp(src+1,dst));
547: return (FALSE);
548: }
549:
550: boolean_t
551: db_value_of_name(
552: char *name,
553: db_expr_t *valuep)
554: {
555: db_sym_t sym;
556:
557: sym = db_lookup(name);
558: if (sym == DB_SYM_NULL)
559: return (FALSE);
560: db_symbol_values(0, sym, &name, valuep);
561: return (TRUE);
562: }
563:
564: /*
565: * Display list of possible completions for a symbol.
566: */
567: void
568: db_print_completion(
569: char *symstr)
570: {
571: register int i;
572: int symtab_start = 0;
573: int symtab_end = db_nsymtab;
574: register char *cp;
575: int nsym = 0;
576: char *name = (char *)0;
577: int len;
578: int toadd;
579:
580: /*
581: * Look for, remove, and remember any symbol table specifier.
582: */
583: for (cp = symstr; *cp; cp++) {
584: if (*cp == ':' && cp[1] == ':') {
585: *cp = '\0';
586: for (i = 0; i < db_nsymtab; i++) {
587: if (! strcmp(symstr, db_symtabs[i].name)) {
588: symtab_start = i;
589: symtab_end = i + 1;
590: break;
591: }
592: }
593: *cp = ':';
594: if (i == db_nsymtab)
595: return;
596: symstr = cp+2;
597: }
598: }
599:
600: /*
601: * Look in the specified set of symbol tables.
602: * Return on first match.
603: */
604: for (i = symtab_start; i < symtab_end; i++) {
605: if (X_db_print_completion(&db_symtabs[i], symstr))
606: break;
607: }
608: }
609:
610: /*
611: * Lookup a (perhaps incomplete) symbol.
612: * If the symbol has a qualifier (e.g., ux::vm_map),
613: * then only the specified symbol table will be searched;
614: * otherwise, all symbol tables will be searched.
615: */
616: int
617: db_lookup_incomplete(
618: char *symstr,
619: int symlen)
620: {
621: register int i;
622: int symtab_start = 0;
623: int symtab_end = db_nsymtab;
624: register char *cp;
625: int nsym = 0;
626: char *name = (char *)0;
627: int len;
628: int toadd;
629:
630: /*
631: * Look for, remove, and remember any symbol table specifier.
632: */
633: for (cp = symstr; *cp; cp++) {
634: if (*cp == ':' && cp[1] == ':') {
635: *cp = '\0';
636: for (i = 0; i < db_nsymtab; i++) {
637: if (! strcmp(symstr, db_symtabs[i].name)) {
638: symtab_start = i;
639: symtab_end = i + 1;
640: break;
641: }
642: }
643: *cp = ':';
644: if (i == db_nsymtab)
645: return 0;
646: symstr = cp+2;
647: }
648: }
649:
650: /*
651: * Look in the specified set of symbol tables.
652: * Return on first match.
653: */
654: for (i = symtab_start; i < symtab_end; i++) {
655: nsym = X_db_lookup_incomplete(&db_symtabs[i], symstr,
656: &name, &len, &toadd);
657: if (nsym > 0) {
658: if (toadd > 0) {
659: len = strlen(symstr);
660: if (len + toadd >= symlen)
661: return 0;
662: bcopy(&name[len], &symstr[len], toadd);
663: symstr[len + toadd] = '\0';
664: }
665: break;
666: }
667: }
668: return nsym;
669: }
670:
671: /*
672: * Lookup a symbol.
673: * If the symbol has a qualifier (e.g., ux::vm_map),
674: * then only the specified symbol table will be searched;
675: * otherwise, all symbol tables will be searched.
676: */
677: db_sym_t
678: db_lookup(char *symstr)
679: {
680: db_sym_t sp;
681: register int i;
682: int symtab_start = 0;
683: int symtab_end = db_nsymtab;
684: register char *cp;
685:
686: /*
687: * Look for, remove, and remember any symbol table specifier.
688: */
689: for (cp = symstr; *cp; cp++) {
690: if (*cp == ':' && cp[1] == ':') {
691: *cp = '\0';
692: for (i = 0; i < db_nsymtab; i++) {
693: if (! strcmp(symstr, db_symtabs[i].name)) {
694: symtab_start = i;
695: symtab_end = i + 1;
696: break;
697: }
698: }
699: *cp = ':';
700: if (i == db_nsymtab)
701: db_error("Invalid symbol table name\n");
702: symstr = cp+2;
703: }
704: }
705:
706: /*
707: * Look in the specified set of symbol tables.
708: * Return on first match.
709: */
710: for (i = symtab_start; i < symtab_end; i++) {
711: if (sp = X_db_lookup(&db_symtabs[i], symstr)) {
712: db_last_symtab = &db_symtabs[i];
713: return sp;
714: }
715: }
716: return 0;
717: }
718:
719: /*
720: * Print a symbol completion
721: */
722: void
723: db_sym_print_completion(
724: db_symtab_t *stab,
725: char *name,
726: int function,
727: char *fname,
728: int line)
729: {
730: if (stab != db_symtabs)
731: db_printf("%s::", stab->name);
732: db_printf(name);
733: if (function) {
734: db_putchar('(');
735: db_putchar(')');
736: }
737: if (fname) {
738: db_printf(" [static from %s", fname);
739: if (line > 0)
740: db_printf(":%d", line);
741: db_putchar(']');
742: }
743: db_putchar('\n');
744: }
745:
746: /*
747: * Common utility routine to parse a symbol string into a file
748: * name, a (possibly incomplete) symbol name without line number.
749: * This routine is called from aout_db_print_completion if the object
750: * dependent handler supports qualified search with a file name.
751: * It parses the symbol string, and call an object dependent routine
752: * with parsed file name and symbol name.
753: */
754: int
755: db_sym_parse_and_print_completion(
756: int (*func)(db_symtab_t *,
757: char *),
758: db_symtab_t *symtab,
759: char *symstr)
760: {
761: register char *p;
762: register int n;
763: char *sym_name;
764: char *component[2];
765: int nsym;
766:
767: /*
768: * disassemble the symbol into components: [file_name:]symbol
769: */
770: component[0] = symstr;
771: component[1] = 0;
772: for (p = symstr, n = 1; *p; p++) {
773: if (*p == ':') {
774: if (n == 2)
775: break;
776: *p = 0;
777: component[n++] = p+1;
778: }
779: }
780: if (*p == 0) {
781: if (n == 1) {
782: sym_name = component[0];
783: } else {
784: sym_name = component[1];
785: }
786: nsym = func(symtab, sym_name);
787: } else
788: nsym = 0;
789: if (n == 2)
790: component[1][-1] = ':';
791: return nsym;
792: }
793:
794: /*
795: * Common utility routine to parse a symbol string into a file
796: * name, a (possibly incomplete) symbol name without line number.
797: * This routine is called from X_db_lookup_incomplete if the object
798: * dependent handler supports qualified search with a file name.
799: * It parses the symbol string, and call an object dependent routine
800: * with parsed file name and symbol name.
801: */
802: int
803: db_sym_parse_and_lookup_incomplete(
804: int (*func)(db_symtab_t *,
805: char *,
806: char *,
807: int,
808: db_sym_t*,
809: char **,
810: int *),
811: db_symtab_t *symtab,
812: char *symstr,
813: char **name,
814: int *len,
815: int *toadd)
816: {
817: register char *p;
818: register int n;
819: char *file_name = 0;
820: char *sym_name = 0;
821: char *component[2];
822: int nsym = 0;
823:
824: /*
825: * disassemble the symbol into components: [file_name:]symbol
826: */
827: component[0] = symstr;
828: component[1] = 0;
829: for (p = symstr, n = 1; *p; p++) {
830: if (*p == ':') {
831: if (n == 2)
832: break;
833: *p = 0;
834: component[n++] = p+1;
835: }
836: }
837: if (*p == 0) {
838: if (n == 1) {
839: file_name = 0;
840: sym_name = component[0];
841: } else {
842: file_name = component[0];
843: sym_name = component[1];
844: }
845: nsym = func(symtab, file_name, sym_name, 0, (db_sym_t *)0,
846: name, len);
847: if (nsym > 0)
848: *toadd = *len - strlen(sym_name);
849: }
850: if (n == 2)
851: component[1][-1] = ':';
852: return(nsym);
853: }
854:
855: /*
856: * Common utility routine to parse a symbol string into a file
857: * name, a symbol name and line number.
858: * This routine is called from aout_db_lookup if the object dependent
859: * handler supports qualified search with a file name or a line number.
860: * It parses the symbol string, and call an object dependent routine
861: * with parsed file name, symbol name and line number.
862: */
863: db_sym_t
864: db_sym_parse_and_lookup(
865: int (*func)(db_symtab_t *, char *, char *, int,
866: db_sym_t*, char **, int *),
867: db_symtab_t *symtab,
868: char *symstr)
869: {
870: register char *p;
871: register int n;
872: int n_name;
873: int line_number;
874: char *file_name = 0;
875: char *sym_name = 0;
876: char *component[3];
877: db_sym_t found = DB_SYM_NULL;
878:
879: /*
880: * disassemble the symbol into components:
881: * [file_name:]symbol[:line_nubmer]
882: */
883: component[0] = symstr;
884: component[1] = component[2] = 0;
885: for (p = symstr, n = 1; *p; p++) {
886: if (*p == ':') {
887: if (n >= 3)
888: break;
889: *p = 0;
890: component[n++] = p+1;
891: }
892: }
893: if (*p != 0)
894: goto out;
895: line_number = 0;
896: n_name = n;
897: p = component[n-1];
898: if (*p >= '0' && *p <= '9') {
899: if (n == 1)
900: goto out;
901: for (line_number = 0; *p; p++) {
902: if (*p < '0' || *p > '9')
903: goto out;
904: line_number = line_number*10 + *p - '0';
905: }
906: n_name--;
907: } else if (n >= 3)
908: goto out;
909: if (n_name == 1) {
910: for (p = component[0]; *p && *p != '.'; p++);
911: if (*p == '.') {
912: file_name = component[0];
913: sym_name = 0;
914: } else {
915: file_name = 0;
916: sym_name = component[0];
917: }
918: } else {
919: file_name = component[0];
920: sym_name = component[1];
921: }
922: (void) func(symtab, file_name, sym_name, line_number, &found,
923: (char **)0, (int *)0);
924:
925: out:
926: while (--n >= 1)
927: component[n][-1] = ':';
928: return(found);
929: }
930:
931: /*
932: * Does this symbol name appear in more than one symbol table?
933: * Used by db_symbol_values to decide whether to qualify a symbol.
934: */
935: boolean_t db_qualify_ambiguous_names = TRUE;
936:
937: boolean_t
938: db_symbol_is_ambiguous(char *name)
939: {
940: register int i;
941: register
942: boolean_t found_once = FALSE;
943:
944: if (!db_qualify_ambiguous_names)
945: return FALSE;
946:
947: for (i = 0; i < db_nsymtab; i++) {
948: if (X_db_lookup(&db_symtabs[i], name)) {
949: if (found_once)
950: return TRUE;
951: found_once = TRUE;
952: }
953: }
954: return FALSE;
955: }
956:
957: /*
958: * Find the closest symbol to val, and return its name
959: * and the difference between val and the symbol found.
960: */
961: unsigned int db_search_maxoff = 0x4000;
962: db_sym_t
963: db_search_task_symbol(
964: register db_addr_t val,
965: db_strategy_t strategy,
966: db_addr_t *offp, /* better be unsigned */
967: task_t task)
968: {
969: unsigned long diff, newdiff;
970: register int i;
971: db_symtab_t *sp;
972: db_sym_t ret = DB_SYM_NULL, sym;
973: vm_map_t map_for_val;
974:
975: if (task == TASK_NULL)
976: task = db_current_task();
977: map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
978: again:
979: newdiff = diff = ~0UL;
980: db_last_symtab = 0;
981: for (sp = &db_symtabs[0], i = 0;
982: i < db_nsymtab;
983: sp++, i++) {
984: if (((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
985: (vm_map_t)sp->map_pointer == map_for_val) &&
986: (sp->maxsym == 0 ||
987: ((unsigned long) val >= sp->minsym &&
988: (unsigned long) val <= sp->maxsym))) {
989: sym = X_db_search_symbol(sp, val, strategy,
990: (db_expr_t *)&newdiff);
991: if (newdiff < diff) {
992: db_last_symtab = sp;
993: diff = newdiff;
994: ret = sym;
995: if (diff <= db_search_maxoff)
996: break;
997: }
998: }
999: }
1000: if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) {
1001: map_for_val = VM_MAP_NULL;
1002: goto again;
1003: }
1004: *offp = diff;
1005: return ret;
1006: }
1007:
1008: /*
1009: * Find the closest symbol to val, and return its name
1010: * and the difference between val and the symbol found.
1011: * Also return the filename and linenumber if available.
1012: */
1013: db_sym_t
1014: db_search_task_symbol_and_line(
1015: register db_addr_t val,
1016: db_strategy_t strategy,
1017: db_expr_t *offp,
1018: char **filenamep,
1019: int *linenump,
1020: task_t task,
1021: int *argsp)
1022: {
1023: unsigned long diff, newdiff;
1024: register int i;
1025: db_symtab_t *sp;
1026: db_sym_t ret = DB_SYM_NULL, sym;
1027: vm_map_t map_for_val;
1028: char *func;
1029: char *filename;
1030: int linenum;
1031: int args;
1032:
1033: if (task == TASK_NULL)
1034: task = db_current_task();
1035: map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
1036: *filenamep = (char *) 0;
1037: *linenump = 0;
1038: *argsp = -1;
1039: again:
1040: filename = (char *) 0;
1041: linenum = 0;
1042: newdiff = diff = ~0UL;
1043: db_last_symtab = 0;
1044: for (sp = &db_symtabs[0], i = 0;
1045: i < db_nsymtab;
1046: sp++, i++) {
1047: if (((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
1048: (vm_map_t)sp->map_pointer == map_for_val) &&
1049: (sp->maxsym == 0 ||
1050: ((unsigned long) val >= sp->minsym &&
1051: (unsigned long) val <= sp->maxsym))) {
1052: sym = X_db_search_by_addr(sp, val, &filename, &func,
1053: &linenum, (db_expr_t *)&newdiff,
1054: &args);
1055: if (sym && newdiff < diff) {
1056: db_last_symtab = sp;
1057: diff = newdiff;
1058: ret = sym;
1059: *filenamep = filename;
1060: *linenump = linenum;
1061: *argsp = args;
1062: if (diff <= db_search_maxoff)
1063: break;
1064: }
1065: }
1066: }
1067: if (ret == DB_SYM_NULL && map_for_val != VM_MAP_NULL) {
1068: map_for_val = VM_MAP_NULL;
1069: goto again;
1070: }
1071: *offp = diff;
1072: if (*filenamep)
1073: db_shorten_filename(filenamep);
1074: return ret;
1075: }
1076:
1077: /*
1078: * Return name and value of a symbol
1079: */
1080: void
1081: db_symbol_values(
1082: db_symtab_t *stab,
1083: db_sym_t sym,
1084: char **namep,
1085: db_expr_t *valuep)
1086: {
1087: db_expr_t value;
1088: char *name;
1089:
1090: if (sym == DB_SYM_NULL) {
1091: *namep = 0;
1092: return;
1093: }
1094: if (stab == 0)
1095: stab = db_last_symtab;
1096:
1097: X_db_symbol_values(stab, sym, &name, &value);
1098:
1099: if (db_symbol_is_ambiguous(name)) {
1100: *namep = db_qualify(name, db_last_symtab->name);
1101: }else {
1102: *namep = name;
1103: }
1104: if (valuep)
1105: *valuep = value;
1106: }
1107:
1108:
1109: /*
1110: * Print a the closest symbol to value
1111: *
1112: * After matching the symbol according to the given strategy
1113: * we print it in the name+offset format, provided the symbol's
1114: * value is close enough (eg smaller than db_maxoff).
1115: * We also attempt to print [filename:linenum] when applicable
1116: * (eg for procedure names).
1117: *
1118: * If we could not find a reasonable name+offset representation,
1119: * then we just print the value in hex. Small values might get
1120: * bogus symbol associations, e.g. 3 might get some absolute
1121: * value like _INCLUDE_VERSION or something, therefore we do
1122: * not accept symbols whose value is zero (and use plain hex).
1123: */
1124:
1125: void
1126: db_task_printsym(
1127: db_expr_t off,
1128: db_strategy_t strategy,
1129: task_t task)
1130: {
1131: db_addr_t d;
1132: char *filename;
1133: char *name;
1134: db_expr_t value;
1135: int linenum;
1136: db_sym_t cursym;
1137:
1138: if (off >= db_maxval || off < db_minval) {
1139: db_printf("%#n", off);
1140: return;
1141: }
1142: cursym = db_search_task_symbol(off, strategy, &d, task);
1143:
1144: db_symbol_values(0, cursym, &name, &value);
1145: if (name == 0 || d >= db_maxoff || value == 0) {
1146: db_printf("%#n", off);
1147: return;
1148: }
1149: db_printf("%s", name);
1150: if (d)
1151: db_printf("+0x%x", d);
1152: if (strategy == DB_STGY_PROC) {
1153: if (db_line_at_pc(cursym, &filename, &linenum, off)) {
1154: db_printf(" [%s", filename);
1155: if (linenum > 0)
1156: db_printf(":%d", linenum);
1157: db_printf("]");
1158: }
1159: }
1160: }
1161:
1162: /*
1163: * Return symbol name for a given offset and
1164: * change the offset to be relative to this symbol.
1165: * Very usefull for xpr, when you want to log offsets
1166: * in a user friendly way.
1167: */
1168:
1169: char null_sym[] = "";
1170:
1171: char *
1172: db_get_sym(db_expr_t *off)
1173: {
1174: db_sym_t cursym;
1175: db_expr_t value;
1176: char *name;
1177: db_addr_t d;
1178:
1179: cursym = db_search_symbol(*off, DB_STGY_ANY, &d);
1180: db_symbol_values(0, cursym, &name, &value);
1181: if (name)
1182: *off = d;
1183: else
1184: name = null_sym;
1185: return(name);
1186: }
1187:
1188: void
1189: db_printsym(
1190: db_expr_t off,
1191: db_strategy_t strategy)
1192: {
1193: db_task_printsym(off, strategy, TASK_NULL);
1194: }
1195:
1196: int db_short_filename = 1;
1197:
1198: void
1199: db_shorten_filename(char **filenamep)
1200: {
1201: char *cp, *cp_slash;
1202:
1203: if (! *filenamep)
1204: return;
1205: for (cp = cp_slash = *filenamep; *cp; cp++) {
1206: if (*cp == '/')
1207: cp_slash = cp;
1208: }
1209: if (*cp_slash == '/')
1210: *filenamep = cp_slash+1;
1211: }
1212:
1213: int
1214: db_task_getlinenum(
1215: db_expr_t off,
1216: task_t task)
1217: {
1218: db_addr_t d;
1219: char *filename;
1220: char *name;
1221: db_expr_t value;
1222: int linenum;
1223: db_sym_t cursym;
1224: db_strategy_t strategy = DB_STGY_PROC;
1225:
1226: if (off >= db_maxval || off < db_minval) {
1227: db_printf("%#n", off);
1228: return(-1);
1229: }
1230: cursym = db_search_task_symbol(off, strategy, &d, task);
1231:
1232: db_symbol_values(0, cursym, &name, &value);
1233: if (name == 0 || d >= db_maxoff || value == 0) {
1234: return(-1);
1235: }
1236: if (db_line_at_pc(cursym, &filename, &linenum, off))
1237: return(linenum);
1238: else
1239: return(-1);
1240: }
1241:
1242: boolean_t
1243: db_line_at_pc(
1244: db_sym_t sym,
1245: char **filename,
1246: int *linenum,
1247: db_expr_t pc)
1248: {
1249: boolean_t result;
1250:
1251: if (db_last_symtab == 0)
1252: return FALSE;
1253: if (X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc)) {
1254: if (db_short_filename)
1255: db_shorten_filename(filename);
1256: result = TRUE;
1257: } else
1258: result = FALSE;
1259: return(result);
1260: }
1261:
1262: int qsort_check = 0;
1263:
1264: void
1265: db_qsort(
1266: char *table,
1267: int nbelts,
1268: int eltsize,
1269: int (*compfun)(char *, char *))
1270: {
1271: if (nbelts <= 0 || eltsize <= 0 || compfun == 0) {
1272: printf("qsort: invalid parameters\n");
1273: return;
1274: }
1275: qsort_recur(table, table + nbelts * eltsize, eltsize, compfun);
1276:
1277: if (qsort_check)
1278: qsort_checker(table, nbelts, eltsize, compfun);
1279: }
1280:
1281: void
1282: qsort_swap(
1283: register int *a,
1284: register int *b,
1285: register int size)
1286: {
1287: register int temp;
1288: char *aa, *bb;
1289: char ctemp;
1290:
1291: for (; size >= sizeof (int); size -= sizeof (int), a++, b++) {
1292: temp = *a;
1293: *a = *b;
1294: *b = temp;
1295: }
1296: aa = (char *)a;
1297: bb = (char *)b;
1298: for (; size > 0; size--, aa++, bb++) {
1299: ctemp = *aa;
1300: *aa = *bb;
1301: *bb = ctemp;
1302: }
1303: }
1304:
1305: /* rotate the three elements to the left */
1306: void
1307: qsort_rotate(
1308: register int *a,
1309: register int *b,
1310: register int *c,
1311: register int size)
1312: {
1313: register int temp;
1314: char *aa, *bb, *cc;
1315: char ctemp;
1316:
1317: for (; size >= sizeof (int); size -= sizeof (int), a++, b++, c++) {
1318: temp = *a;
1319: *a = *c;
1320: *c = *b;
1321: *b = temp;
1322: }
1323: aa = (char *)a;
1324: bb = (char *)b;
1325: cc = (char *)c;
1326: for (; size > 0; size--, aa++, bb++, cc++) {
1327: ctemp = *aa;
1328: *aa = *cc;
1329: *cc = *bb;
1330: *bb = ctemp;
1331: }
1332: }
1333:
1334: void
1335: qsort_recur(
1336: char *left,
1337: char *right,
1338: int eltsize,
1339: int (*compfun)(char *, char *))
1340: {
1341: char *i, *j;
1342: char *sameleft, *sameright;
1343:
1344: top:
1345: if (left + eltsize - 1 >= right) {
1346: return;
1347: }
1348:
1349: /* partition element (reference for "same"ness */
1350: sameleft = left + (((right - left) / eltsize) / 2) * eltsize;
1351: sameright = sameleft;
1352:
1353: i = left;
1354: j = right - eltsize;
1355:
1356: again:
1357: while (i < sameleft) {
1358: int comp;
1359:
1360: comp = (*compfun)(i, sameleft);
1361: if (comp == 0) {
1362: /*
1363: * Move to the "same" partition.
1364: */
1365: /*
1366: * Shift the left part of the "same" partition to
1367: * the left, so that "same" elements stay in their
1368: * original order.
1369: */
1370: sameleft -= eltsize;
1371: qsort_swap((int *) i, (int *) sameleft, eltsize);
1372: } else if (comp < 0) {
1373: /*
1374: * Stay in the "left" partition.
1375: */
1376: i += eltsize;
1377: } else {
1378: /*
1379: * Should be moved to the "right" partition.
1380: * Wait until the next loop finds an appropriate
1381: * place to store this element.
1382: */
1383: break;
1384: }
1385: }
1386:
1387: while (j > sameright) {
1388: int comp;
1389:
1390: comp = (*compfun)(sameright, j);
1391: if (comp == 0) {
1392: /*
1393: * Move to the right of the "same" partition.
1394: */
1395: sameright += eltsize;
1396: qsort_swap((int *) sameright, (int *) j, eltsize);
1397: } else if (comp > 0) {
1398: /*
1399: * Move to the "left" partition.
1400: */
1401: if (i == sameleft) {
1402: /*
1403: * Unfortunately, the "left" partition
1404: * has already been fully processed, so
1405: * we have to shift the "same" partition
1406: * to the right to free a "left" element.
1407: * This is done by moving the leftest same
1408: * to the right of the "same" partition.
1409: */
1410: sameright += eltsize;
1411: qsort_rotate((int *) sameleft, (int*) sameright,
1412: (int *) j, eltsize);
1413: sameleft += eltsize;
1414: i = sameleft;
1415: } else {
1416: /*
1417: * Swap with the "left" partition element
1418: * waiting to be moved to the "right"
1419: * partition.
1420: */
1421: qsort_swap((int *) i, (int *) j, eltsize);
1422: j -= eltsize;
1423: /*
1424: * Go back to the 1st loop.
1425: */
1426: i += eltsize;
1427: goto again;
1428: }
1429: } else {
1430: /*
1431: * Stay in the "right" partition.
1432: */
1433: j -= eltsize;
1434: }
1435: }
1436:
1437: if (i != sameleft) {
1438: /*
1439: * The second loop completed (the"right" partition is ok),
1440: * but we have to go back to the first loop, and deal with
1441: * the element waiting for a place in the "right" partition.
1442: * Let's shift the "same" zone to the left.
1443: */
1444: sameleft -= eltsize;
1445: qsort_rotate((int *) sameright, (int *) sameleft, (int *) i,
1446: eltsize);
1447: sameright -= eltsize;
1448: j = sameright;
1449: /*
1450: * Go back to 1st loop.
1451: */
1452: goto again;
1453: }
1454:
1455: /*
1456: * The partitions are correct now. Recur on the smallest side only.
1457: */
1458: if (sameleft - left >= right - (sameright + eltsize)) {
1459: qsort_recur(sameright + eltsize, right, eltsize, compfun);
1460: /*
1461: * The "right" partition is now completely sorted.
1462: * The "same" partition is OK, so...
1463: * Ignore them, and start the loops again on the
1464: * "left" partition.
1465: */
1466: right = sameleft;
1467: goto top;
1468: } else {
1469: qsort_recur(left, sameleft, eltsize, compfun);
1470: /*
1471: * The "left" partition is now completely sorted.
1472: * The "same" partition is OK, so ...
1473: * Ignore them, and start the loops again on the
1474: * "right" partition.
1475: */
1476: left = sameright + eltsize;
1477: goto top;
1478: }
1479: }
1480:
1481: void
1482: qsort_checker(
1483: char *table,
1484: int nbelts,
1485: int eltsize,
1486: int (*compfun)(char *, char *))
1487: {
1488: char *curr, *prev, *last;
1489:
1490: prev = table;
1491: curr = prev + eltsize;
1492: last = table + (nbelts * eltsize);
1493:
1494: while (prev < last) {
1495: if ((*compfun)(prev, curr) > 0) {
1496: printf("**** qsort_checker: error between 0x%x and 0x%x!!!\n", prev, curr);
1497: break;
1498: }
1499: prev = curr;
1500: curr += eltsize;
1501: }
1502: printf("qsort_checker: OK\n");
1503: }
1504:
1505: int qsort_search_debug = 0;
1506:
1507: void
1508: db_qsort_limit_search(
1509: char *target,
1510: char **start,
1511: char **end,
1512: int eltsize,
1513: int (*compfun)(char *, char *))
1514: {
1515: register char *left, *right;
1516: char *oleft, *oright, *part;
1517: int nbiter = 0;
1518: int comp;
1519:
1520: oleft = left = *start;
1521: oright = right = *end;
1522: part = (char *) 0;
1523:
1524: while (left < right) {
1525: nbiter++;
1526: part = left + (((right - left) / eltsize) / 2) * eltsize;
1527: comp = (*compfun)(target, part);
1528: if (comp > 0) {
1529: oleft = left;
1530: oright = right;
1531: left = part;
1532: if (left == oleft)
1533: break;
1534: if (qsort_search_debug > 1)
1535: printf(" [ Moved left from 0x%x to 0x%x]\n",
1536: oleft, left);
1537: } else if (comp < 0) {
1538: oright = right;
1539: oleft = left;
1540: right = part;
1541: if (qsort_search_debug > 1)
1542: printf(" [ Moved right from 0x%x to 0x%x]\n",
1543: oright, right);
1544: } else {
1545: if (qsort_search_debug > 1)
1546: printf(" [ FOUND! left=0x%x right=0x%x]\n",
1547: left, right);
1548: for (left = part;
1549: left > *start && (*compfun)(left, part) == 0;
1550: left -= eltsize);
1551: for (right = part + eltsize;
1552: right < *end && (*compfun)(right, part) == 0;
1553: right += eltsize);
1554: oright = right;
1555: oleft = left;
1556: break;
1557: }
1558: }
1559:
1560: if (qsort_search_debug)
1561: printf("[ Limited from %x-%x to %x-%x in %d iters ]\n",
1562: *start, *end, oleft, oright, nbiter);
1563: *start = oleft;
1564: *end = oright;
1565: }
1566:
1567: void
1568: bubble_sort(
1569: char *table,
1570: int nbelts,
1571: int eltsize,
1572: int (*compfun)(char *, char *))
1573: {
1574: boolean_t sorted;
1575: char *end;
1576: register char *p;
1577:
1578: end = table + ((nbelts-1) * eltsize);
1579: do {
1580: sorted = TRUE;
1581: for (p = table; p < end; p += eltsize) {
1582: if ((*compfun)(p, p + eltsize) > 0) {
1583: qsort_swap((int *) p, (int *) (p + eltsize),
1584: eltsize);
1585: sorted = FALSE;
1586: }
1587: }
1588: } while (sorted == FALSE);
1589:
1590: if (qsort_check)
1591: qsort_checker(table, nbelts, eltsize, compfun);
1592: }
1593:
1594: vm_offset_t vm_min_inks_addr = VM_MAX_KERNEL_ADDRESS;
1595:
1596: void
1597: db_install_inks(
1598: vm_offset_t base)
1599: {
1600: /* save addr to demarcate kernel/inks boundary (1st time only) */
1601: if (vm_min_inks_addr == VM_MAX_KERNEL_ADDRESS) {
1602: vm_min_inks_addr = base;
1603: db_qualify_ambiguous_names = TRUE;
1604: }
1605: }
1606:
1607:
1608: void
1609: db_clone_symtabXXX(
1610: char *clonee, /* which symtab to clone */
1611: char *cloner, /* in-kernel-server name */
1612: vm_offset_t base) /* base address of cloner */
1613: {
1614: db_symtab_t *st, *st_src;
1615: char * memp;
1616: vm_size_t size;
1617: long offset;
1618: extern vm_offset_t kalloc(vm_size_t);
1619: extern void db_clone_offsetXXX(char *, long);
1620:
1621: if (db_nsymtab >= MAXNOSYMTABS) {
1622: db_printf("db_clone_symtab: Too Many Symbol Tables\n");
1623: return;
1624: }
1625:
1626: db_install_inks(base);
1627:
1628: st = &db_symtabs[db_nsymtab]; /* destination symtab */
1629: if ((st_src = db_symtab_cloneeXXX(clonee)) == 0) {
1630: db_printf("db_clone_symtab: clonee (%s) not found\n", clonee);
1631: return;
1632: }
1633: /* alloc new symbols */
1634: size = (vm_size_t)(st_src->end - st_src->private);
1635: memp = (char *)kalloc( round_page(size) );
1636: if (!memp) {
1637: db_printf("db_clone_symtab: no memory for symtab\n");
1638: return;
1639: }
1640:
1641: *st = *st_src; /* bulk copy src -> dest */
1642: strcpy(st->name, cloner); /* new name */
1643: st->private = memp; /* copy symbols */
1644: bcopy((const char *)st_src->private, st->private, size);
1645: st->start = memp + sizeof(int); /* fixup pointers to symtab */
1646: st->end = memp + *(int *)memp;
1647: st->map_pointer = 0; /* no map because kernel-loaded */
1648:
1649: /* Offset symbols, leaving strings pointing into st_src */
1650: offset = base - st_src->minsym;
1651: st->minsym += offset;
1652: st->maxsym += offset;
1653: db_clone_offsetXXX(memp, offset);
1654: db_nsymtab++;
1655:
1656: db_printf( "[ cloned symbol table for %s: range 0x%x to 0x%x %s]\n",
1657: st->name, st->minsym, st->maxsym,
1658: st->sorted ? "(sorted) " : "");
1659: db_maxval = (unsigned int)st->maxsym + db_maxoff;
1660: }
1661:
1662: db_symtab_t *
1663: db_symtab_cloneeXXX(
1664: char *clonee)
1665: {
1666: db_symtab_t *st, *st_src;
1667:
1668: st = &db_symtabs[db_nsymtab]; /* destination symtab */
1669: for (st_src = &db_symtabs[0]; st_src < st; ++st_src)
1670: if (!strcmp(clonee, st_src->name))
1671: break;
1672: return ((st_src < st) ? st_src : 0);
1673: }
1674:
1675: /*
1676: * Switch into symbol-table specific routines
1677: */
1678:
1679: #if !defined(__alpha) && !defined(INTEL860)
1680: #define DB_NO_COFF
1681: #endif
1682:
1683: #ifndef DB_NO_AOUT
1684: #include <ddb/db_aout.h>
1685: #endif
1686:
1687: #ifndef DB_NO_COFF
1688: #include <ddb/db_coff.h>
1689: #endif
1690:
1691: static void no_init(void)
1692:
1693: {
1694: db_printf("Non-existent code for ddb init\n");
1695: }
1696:
1697: static boolean_t no_sym_init(
1698: char *start,
1699: char *end,
1700: char *name,
1701: char *task_addr)
1702: {
1703: db_printf("Non-existent code for init of symtab %s\n", name);
1704: return FALSE;
1705: }
1706:
1707: static db_sym_t no_lookup(
1708: db_symtab_t *stab,
1709: char *symstr)
1710: {
1711: db_printf("Bogus lookup of symbol %s\n", symstr);
1712: return DB_SYM_NULL;
1713: }
1714:
1715: static db_sym_t no_search(
1716: db_symtab_t *stab,
1717: db_addr_t off,
1718: db_strategy_t strategy,
1719: db_expr_t *diffp)
1720: {
1721: db_printf("Bogus search for offset %#Xn", off);
1722: return DB_SYM_NULL;
1723: }
1724:
1725: static boolean_t no_line_at_pc(
1726: db_symtab_t *stab,
1727: db_sym_t sym,
1728: char **file,
1729: int *line,
1730: db_expr_t pc)
1731: {
1732: db_printf("Bogus search for pc %#X\n", pc);
1733: return FALSE;
1734: }
1735:
1736: static void no_symbol_values(
1737: db_sym_t sym,
1738: char **namep,
1739: db_expr_t *valuep)
1740: {
1741: db_printf("Bogus symbol value resolution\n");
1742: if (namep) *namep = NULL;
1743: if (valuep) *valuep = 0;
1744: }
1745:
1746: static db_sym_t no_search_by_addr(
1747: db_symtab_t *stab,
1748: db_addr_t off,
1749: char **file,
1750: char **func,
1751: int *line,
1752: db_expr_t *diffp,
1753: int *args)
1754: {
1755: db_printf("Bogus search for address %#X\n", off);
1756: return DB_SYM_NULL;
1757: }
1758:
1759: int
1760: no_print_completion(
1761: db_symtab_t *stab,
1762: char *symstr )
1763: {
1764: db_printf("Bogus print completion: not supported\n");
1765: return 0;
1766: }
1767:
1768: int
1769: no_lookup_incomplete(
1770: db_symtab_t *stab,
1771: char *symstr,
1772: char **name,
1773: int *len,
1774: int *toadd)
1775: {
1776: db_printf("Bogus lookup incomplete: not supported\n");
1777: return 0;
1778: }
1779:
1780: #define NONE \
1781: { no_init, no_sym_init, no_lookup, no_search, \
1782: no_line_at_pc, no_symbol_values, no_search_by_addr, \
1783: no_print_completion, no_lookup_incomplete}
1784:
1785: struct db_sym_switch x_db[] = {
1786:
1787: /* BSD a.out format (really, sdb/dbx(1) symtabs) */
1788: #ifdef DB_NO_AOUT
1789: NONE,
1790: #else /* DB_NO_AOUT */
1791: { aout_db_init, aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
1792: aout_db_line_at_pc, aout_db_symbol_values, aout_db_search_by_addr,
1793: aout_db_print_completion, aout_db_lookup_incomplete},
1794: #endif /* DB_NO_AOUT */
1795:
1796: #ifdef DB_NO_COFF
1797: NONE,
1798: #else /* DB_NO_COFF */
1799: { coff_db_init, coff_db_sym_init, coff_db_lookup, coff_db_search_symbol,
1800: coff_db_line_at_pc, coff_db_symbol_values, coff_db_search_by_addr,
1801: coff_db_print_completion, coff_db_lookup_incomplete },
1802: #endif /* DB_NO_COFF */
1803:
1804: /* Machdep, not inited here */
1805: NONE
1806: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.