db_sym.c revision 1.14
1/* $NetBSD: db_sym.c,v 1.14 1997/06/26 01:19:07 thorpej Exp $ */ 2 3/* 4 * Mach Operating System 5 * Copyright (c) 1991,1990 Carnegie Mellon University 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify and distribute this software and its 9 * documentation is hereby granted, provided that both the copyright 10 * notice and this permission notice appear in all copies of the 11 * software, derivative works or modified versions, and any portions 12 * thereof, and that both notices appear in supporting documentation. 13 * 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 17 * 18 * Carnegie Mellon requests users of this software to return to 19 * 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 21 * School of Computer Science 22 * Carnegie Mellon University 23 * Pittsburgh PA 15213-3890 24 * 25 * any improvements or extensions that they make and grant Carnegie the 26 * rights to redistribute these changes. 27 */ 28 29#include <sys/param.h> 30#include <sys/proc.h> 31 32#include <machine/db_machdep.h> 33 34#include <ddb/db_sym.h> 35#include <ddb/db_output.h> 36#include <ddb/db_extern.h> 37#include <ddb/db_command.h> 38 39/* 40 * Multiple symbol tables 41 */ 42#ifndef MAXLKMS 43#define MAXLKMS 20 44#endif 45 46#ifndef MAXNOSYMTABS 47#define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */ 48#endif 49 50db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; 51 52db_symtab_t *db_last_symtab; 53 54static char *db_qualify __P((db_sym_t, char *)); 55 56/* 57 * Add symbol table, with given name, to list of symbol tables. 58 */ 59int 60db_add_symbol_table(start, end, name, ref) 61 char *start; 62 char *end; 63 char *name; 64 char *ref; 65{ 66 int slot; 67 68 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 69 if (db_symtabs[slot].name == NULL) 70 break; 71 } 72 if (slot >= MAXNOSYMTABS) { 73 db_printf("No slots left for %s symbol table", name); 74 return(-1); 75 } 76 77 db_symtabs[slot].start = start; 78 db_symtabs[slot].end = end; 79 db_symtabs[slot].name = name; 80 db_symtabs[slot].private = ref; 81 82 return(slot); 83} 84 85/* 86 * Delete a symbol table. Caller is responsible for freeing storage. 87 */ 88void 89db_del_symbol_table(name) 90 char *name; 91{ 92 int slot; 93 94 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 95 if (db_symtabs[slot].name && 96 ! strcmp(db_symtabs[slot].name, name)) 97 break; 98 } 99 if (slot >= MAXNOSYMTABS) { 100 db_printf("Unable to find symbol table slot for %s.", name); 101 return; 102 } 103 104 db_symtabs[slot].start = 0; 105 db_symtabs[slot].end = 0; 106 db_symtabs[slot].name = 0; 107 db_symtabs[slot].private = 0; 108} 109 110/* 111 * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map". 112 * 113 * Note: return value points to static data whose content is 114 * overwritten by each call... but in practice this seems okay. 115 */ 116static char * 117db_qualify(sym, symtabname) 118 db_sym_t sym; 119 register char *symtabname; 120{ 121 char *symname; 122 static char tmp[256]; 123 register char *s; 124 125 db_symbol_values(sym, &symname, 0); 126 s = tmp; 127 while ((*s++ = *symtabname++) != '\0') 128 ; 129 s[-1] = ':'; 130 while ((*s++ = *symname++) != '\0') 131 ; 132 return tmp; 133} 134 135 136boolean_t 137db_eqname(src, dst, c) 138 char *src; 139 char *dst; 140 int c; 141{ 142 if (!strcmp(src, dst)) 143 return (TRUE); 144 if (src[0] == c) 145 return (!strcmp(src+1,dst)); 146 return (FALSE); 147} 148 149boolean_t 150db_value_of_name(name, valuep) 151 char *name; 152 db_expr_t *valuep; 153{ 154 db_sym_t sym; 155 156 sym = db_lookup(name); 157 if (sym == DB_SYM_NULL) 158 return (FALSE); 159 db_symbol_values(sym, &name, valuep); 160 return (TRUE); 161} 162 163 164/* 165 * Lookup a symbol. 166 * If the symbol has a qualifier (e.g., ux:vm_map), 167 * then only the specified symbol table will be searched; 168 * otherwise, all symbol tables will be searched. 169 */ 170db_sym_t 171db_lookup(symstr) 172 char *symstr; 173{ 174 db_sym_t sp; 175 register int i; 176 int symtab_start = 0; 177 int symtab_end = MAXNOSYMTABS; 178 register char *cp; 179 180 /* 181 * Look for, remove, and remember any symbol table specifier. 182 */ 183 for (cp = symstr; *cp; cp++) { 184 if (*cp == ':') { 185 *cp = '\0'; 186 for (i = 0; i < MAXNOSYMTABS; i++) { 187 if (db_symtabs[i].name && 188 ! strcmp(symstr, db_symtabs[i].name)) { 189 symtab_start = i; 190 symtab_end = i + 1; 191 break; 192 } 193 } 194 *cp = ':'; 195 if (i == MAXNOSYMTABS) { 196 db_error("invalid symbol table name"); 197 /*NOTREACHED*/ 198 } 199 symstr = cp+1; 200 } 201 } 202 203 /* 204 * Look in the specified set of symbol tables. 205 * Return on first match. 206 */ 207 for (i = symtab_start; i < symtab_end; i++) { 208 if (db_symtabs[i].name && 209 (sp = X_db_lookup(&db_symtabs[i], symstr))) { 210 db_last_symtab = &db_symtabs[i]; 211 return sp; 212 } 213 } 214 return 0; 215} 216 217/* 218 * Does this symbol name appear in more than one symbol table? 219 * Used by db_symbol_values to decide whether to qualify a symbol. 220 */ 221boolean_t db_qualify_ambiguous_names = FALSE; 222 223boolean_t 224db_symbol_is_ambiguous(sym) 225 db_sym_t sym; 226{ 227 char *sym_name; 228 register int i; 229 register 230 boolean_t found_once = FALSE; 231 232 if (!db_qualify_ambiguous_names) 233 return FALSE; 234 235 db_symbol_values(sym, &sym_name, 0); 236 for (i = 0; i < MAXNOSYMTABS; i++) { 237 if (db_symtabs[i].name && 238 X_db_lookup(&db_symtabs[i], sym_name)) { 239 if (found_once) 240 return TRUE; 241 found_once = TRUE; 242 } 243 } 244 return FALSE; 245} 246 247/* 248 * Find the closest symbol to val, and return its name 249 * and the difference between val and the symbol found. 250 */ 251db_sym_t 252db_search_symbol( val, strategy, offp) 253 register db_addr_t val; 254 db_strategy_t strategy; 255 db_expr_t *offp; 256{ 257 register 258 unsigned int diff; 259 db_expr_t newdiff; 260 register int i; 261 db_sym_t ret = DB_SYM_NULL, sym; 262 263 newdiff = diff = ~0; 264 db_last_symtab = 0; 265 for (i = 0; i < MAXNOSYMTABS; i++) { 266 if (!db_symtabs[i].name) 267 continue; 268 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); 269 if (newdiff < diff) { 270 db_last_symtab = &db_symtabs[i]; 271 diff = newdiff; 272 ret = sym; 273 } 274 } 275 *offp = diff; 276 return ret; 277} 278 279/* 280 * Return name and value of a symbol 281 */ 282void 283db_symbol_values(sym, namep, valuep) 284 db_sym_t sym; 285 char **namep; 286 db_expr_t *valuep; 287{ 288 db_expr_t value; 289 290 if (sym == DB_SYM_NULL) { 291 *namep = 0; 292 return; 293 } 294 295 X_db_symbol_values(db_last_symtab, sym, namep, &value); 296 297 if (db_symbol_is_ambiguous(sym)) 298 *namep = db_qualify(sym, db_last_symtab->name); 299 if (valuep) 300 *valuep = value; 301} 302 303 304/* 305 * Print a the closest symbol to value 306 * 307 * After matching the symbol according to the given strategy 308 * we print it in the name+offset format, provided the symbol's 309 * value is close enough (eg smaller than db_maxoff). 310 * We also attempt to print [filename:linenum] when applicable 311 * (eg for procedure names). 312 * 313 * If we could not find a reasonable name+offset representation, 314 * then we just print the value in hex. Small values might get 315 * bogus symbol associations, e.g. 3 might get some absolute 316 * value like _INCLUDE_VERSION or something, therefore we do 317 * not accept symbols whose value is zero (and use plain hex). 318 * Also, avoid printing as "end+0x????" which is useless. 319 * The variable db_lastsym is used instead of "end" in case we 320 * add support for symbols in loadable driver modules. 321 */ 322extern char end[]; 323unsigned long db_lastsym = (unsigned long)end; 324unsigned int db_maxoff = 0x10000000; 325 326 327void 328db_printsym(off, strategy) 329 db_expr_t off; 330 db_strategy_t strategy; 331{ 332 db_expr_t d; 333 char *filename; 334 char *name; 335 db_expr_t value; 336 int linenum; 337 db_sym_t cursym; 338 339 if (off <= db_lastsym) { 340 cursym = db_search_symbol(off, strategy, &d); 341 db_symbol_values(cursym, &name, &value); 342 if (name && (d < db_maxoff) && value) { 343 db_printf("%s", name); 344 if (d) 345 db_printf("+%#lr", d); 346 if (strategy == DB_STGY_PROC) { 347 if (db_line_at_pc(cursym, &filename, &linenum, off)) 348 db_printf(" [%s:%d]", filename, linenum); 349 } 350 return; 351 } 352 } 353 db_printf("%#ln", off); 354 return; 355} 356 357 358boolean_t 359db_line_at_pc( sym, filename, linenum, pc) 360 db_sym_t sym; 361 char **filename; 362 int *linenum; 363 db_expr_t pc; 364{ 365 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc); 366} 367 368int 369db_sym_numargs(sym, nargp, argnames) 370 db_sym_t sym; 371 int *nargp; 372 char **argnames; 373{ 374 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames); 375} 376