]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/ddb/db_sym.c
xnu-344.34.tar.gz
[apple/xnu.git] / osfmk / ddb / db_sym.c
... / ...
CommitLineData
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 * [barbou@gr.osf.org]
236 *
237 * db_add_symbol_table now takes 3 additional arguments. Machine
238 * dependant modules must provide them. [barbou@gr.osf.org]
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 Software.Distribution@CS.CMU.EDU
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
391db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0}};
392int db_nsymtab = 0;
393
394db_symtab_t *db_last_symtab;
395
396unsigned long db_maxoff = 0x4000;
397extern char end;
398unsigned long db_maxval = (unsigned long)&end;
399natural_t db_minval = 0x1000;
400
401/* Prototypes for functions local to this file. XXX -- should be static!
402 */
403static char *db_qualify(
404 char *sym,
405 register char *symtabname);
406
407boolean_t db_eqname(
408 char *src,
409 char *dst,
410 unsigned c);
411
412boolean_t db_symbol_is_ambiguous(char *name);
413
414void db_shorten_filename(char **filenamep);
415
416void qsort_swap(
417 register int *a,
418 register int *b,
419 register int size);
420
421void qsort_rotate(
422 register int *a,
423 register int *b,
424 register int *c,
425 register int size);
426
427void qsort_recur(
428 char *left,
429 char *right,
430 int eltsize,
431 int (*compfun)(char *, char *));
432
433void qsort_checker(
434 char *table,
435 int nbelts,
436 int eltsize,
437 int (*compfun)(char *, char *));
438
439void bubble_sort(
440 char *table,
441 int nbelts,
442 int eltsize,
443 int (*compfun)(char *, char *));
444
445int no_print_completion(
446 db_symtab_t *stab,
447 char *symstr );
448int 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 */
458void
459ddb_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 */
468boolean_t
469db_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 */
518static char *
519db_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
537boolean_t
538db_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
550boolean_t
551db_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 */
567void
568db_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 */
616int
617db_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 */
677db_sym_t
678db_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 */
722void
723db_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 */
754int
755db_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 */
802int
803db_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 */
863db_sym_t
864db_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
925out:
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 */
935boolean_t db_qualify_ambiguous_names = TRUE;
936
937boolean_t
938db_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 */
961unsigned int db_search_maxoff = 0x4000;
962db_sym_t
963db_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;
978again:
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 */
1013db_sym_t
1014db_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 */
1080void
1081db_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
1125void
1126db_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
1169char null_sym[] = "";
1170
1171char *
1172db_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
1188void
1189db_printsym(
1190 db_expr_t off,
1191 db_strategy_t strategy)
1192{
1193 db_task_printsym(off, strategy, TASK_NULL);
1194}
1195
1196int db_short_filename = 1;
1197
1198void
1199db_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
1213int
1214db_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
1242boolean_t
1243db_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
1262int qsort_check = 0;
1263
1264void
1265db_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
1281void
1282qsort_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 */
1306void
1307qsort_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
1334void
1335qsort_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
1481void
1482qsort_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
1505int qsort_search_debug = 0;
1506
1507void
1508db_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
1567void
1568bubble_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
1594vm_offset_t vm_min_inks_addr = VM_MAX_KERNEL_ADDRESS;
1595
1596void
1597db_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
1608void
1609db_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
1662db_symtab_t *
1663db_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
1691static void no_init(void)
1692
1693{
1694 db_printf("Non-existent code for ddb init\n");
1695}
1696
1697static 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
1707static 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
1715static 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
1725static 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
1736static 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
1746static 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
1759int
1760no_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
1768int
1769no_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
1785struct 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};