|
|
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.