1 /* $NetBSD: db_sym.c,v 1.8 1994/10/09 08:56:27 mycroft 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 36 /* 37 * We import from the symbol-table dependent routines: 38 */ 39 extern db_sym_t X_db_lookup(); 40 extern db_sym_t X_db_search_symbol(); 41 extern boolean_t X_db_line_at_pc(); 42 extern void X_db_symbol_values(); 43 44 /* 45 * Multiple symbol tables 46 */ 47 #ifndef MAXLKMS 48 #define MAXLKMS 20 49 #endif 50 51 #ifndef MAXNOSYMTABS 52 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */ 53 #endif 54 55 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; 56 57 db_symtab_t *db_last_symtab; 58 59 db_sym_t db_lookup(); /* forward */ 60 61 /* 62 * Add symbol table, with given name, to list of symbol tables. 63 */ 64 int 65 db_add_symbol_table(start, end, name, ref) 66 char *start; 67 char *end; 68 char *name; 69 char *ref; 70 { 71 int slot; 72 73 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 74 if (db_symtabs[slot].name == NULL) 75 break; 76 } 77 if (slot >= MAXNOSYMTABS) { 78 printf ("No slots left for %s symbol table", name); 79 return(-1); 80 } 81 82 db_symtabs[slot].start = start; 83 db_symtabs[slot].end = end; 84 db_symtabs[slot].name = name; 85 db_symtabs[slot].private = ref; 86 87 return(slot); 88 } 89 90 /* 91 * Delete a symbol table. Caller is responsible for freeing storage. 92 */ 93 void 94 db_del_symbol_table(name) 95 char *name; 96 { 97 int slot; 98 99 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 100 if (db_symtabs[slot].name && 101 ! strcmp(db_symtabs[slot].name, name)) 102 break; 103 } 104 if (slot >= MAXNOSYMTABS) { 105 printf ("Unable to find symbol table slot for %s.", name); 106 return; 107 } 108 109 db_symtabs[slot].start = 0; 110 db_symtabs[slot].end = 0; 111 db_symtabs[slot].name = 0; 112 db_symtabs[slot].private = 0; 113 } 114 115 /* 116 * db_qualify("vm_map", "netbsd") returns "netbsd:vm_map". 117 * 118 * Note: return value points to static data whose content is 119 * overwritten by each call... but in practice this seems okay. 120 */ 121 static char * 122 db_qualify(sym, symtabname) 123 db_sym_t sym; 124 register char *symtabname; 125 { 126 char *symname; 127 static char tmp[256]; 128 register char *s; 129 130 db_symbol_values(sym, &symname, 0); 131 s = tmp; 132 while (*s++ = *symtabname++) { 133 } 134 s[-1] = ':'; 135 while (*s++ = *symname++) { 136 } 137 return tmp; 138 } 139 140 141 boolean_t 142 db_eqname(src, dst, c) 143 char *src; 144 char *dst; 145 char c; 146 { 147 if (!strcmp(src, dst)) 148 return (TRUE); 149 if (src[0] == c) 150 return (!strcmp(src+1,dst)); 151 return (FALSE); 152 } 153 154 boolean_t 155 db_value_of_name(name, valuep) 156 char *name; 157 db_expr_t *valuep; 158 { 159 db_sym_t sym; 160 161 sym = db_lookup(name); 162 if (sym == DB_SYM_NULL) 163 return (FALSE); 164 db_symbol_values(sym, &name, valuep); 165 return (TRUE); 166 } 167 168 169 /* 170 * Lookup a symbol. 171 * If the symbol has a qualifier (e.g., ux:vm_map), 172 * then only the specified symbol table will be searched; 173 * otherwise, all symbol tables will be searched. 174 */ 175 db_sym_t 176 db_lookup(symstr) 177 char *symstr; 178 { 179 db_sym_t sp; 180 register int i; 181 int symtab_start = 0; 182 int symtab_end = MAXNOSYMTABS; 183 register char *cp; 184 185 /* 186 * Look for, remove, and remember any symbol table specifier. 187 */ 188 for (cp = symstr; *cp; cp++) { 189 if (*cp == ':') { 190 *cp = '\0'; 191 for (i = 0; i < MAXNOSYMTABS; i++) { 192 if (db_symtabs[i].name && 193 ! strcmp(symstr, db_symtabs[i].name)) { 194 symtab_start = i; 195 symtab_end = i + 1; 196 break; 197 } 198 } 199 *cp = ':'; 200 if (i == MAXNOSYMTABS) { 201 db_error("invalid symbol table name"); 202 /*NOTREACHED*/ 203 } 204 symstr = cp+1; 205 } 206 } 207 208 /* 209 * Look in the specified set of symbol tables. 210 * Return on first match. 211 */ 212 for (i = symtab_start; i < symtab_end; i++) { 213 if (db_symtabs[i].name && 214 (sp = X_db_lookup(&db_symtabs[i], symstr))) { 215 db_last_symtab = &db_symtabs[i]; 216 return sp; 217 } 218 } 219 return 0; 220 } 221 222 /* 223 * Does this symbol name appear in more than one symbol table? 224 * Used by db_symbol_values to decide whether to qualify a symbol. 225 */ 226 boolean_t db_qualify_ambiguous_names = FALSE; 227 228 boolean_t 229 db_symbol_is_ambiguous(sym) 230 db_sym_t sym; 231 { 232 char *sym_name; 233 register int i; 234 register 235 boolean_t found_once = FALSE; 236 237 if (!db_qualify_ambiguous_names) 238 return FALSE; 239 240 db_symbol_values(sym, &sym_name, 0); 241 for (i = 0; i < MAXNOSYMTABS; i++) { 242 if (db_symtabs[i].name && 243 X_db_lookup(&db_symtabs[i], sym_name)) { 244 if (found_once) 245 return TRUE; 246 found_once = TRUE; 247 } 248 } 249 return FALSE; 250 } 251 252 /* 253 * Find the closest symbol to val, and return its name 254 * and the difference between val and the symbol found. 255 */ 256 db_sym_t 257 db_search_symbol( val, strategy, offp) 258 register db_addr_t val; 259 db_strategy_t strategy; 260 db_expr_t *offp; 261 { 262 register 263 unsigned int diff; 264 unsigned int newdiff; 265 register int i; 266 db_sym_t ret = DB_SYM_NULL, sym; 267 268 newdiff = diff = ~0; 269 db_last_symtab = 0; 270 for (i = 0; i < MAXNOSYMTABS; i++) { 271 if (!db_symtabs[i].name) 272 continue; 273 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); 274 if (newdiff < diff) { 275 db_last_symtab = &db_symtabs[i]; 276 diff = newdiff; 277 ret = sym; 278 } 279 } 280 *offp = diff; 281 return ret; 282 } 283 284 /* 285 * Return name and value of a symbol 286 */ 287 void 288 db_symbol_values(sym, namep, valuep) 289 db_sym_t sym; 290 char **namep; 291 db_expr_t *valuep; 292 { 293 db_expr_t value; 294 295 if (sym == DB_SYM_NULL) { 296 *namep = 0; 297 return; 298 } 299 300 X_db_symbol_values(sym, namep, &value); 301 302 if (db_symbol_is_ambiguous(sym)) 303 *namep = db_qualify(sym, db_last_symtab->name); 304 if (valuep) 305 *valuep = value; 306 } 307 308 309 /* 310 * Print a the closest symbol to value 311 * 312 * After matching the symbol according to the given strategy 313 * we print it in the name+offset format, provided the symbol's 314 * value is close enough (eg smaller than db_maxoff). 315 * We also attempt to print [filename:linenum] when applicable 316 * (eg for procedure names). 317 * 318 * If we could not find a reasonable name+offset representation, 319 * then we just print the value in hex. Small values might get 320 * bogus symbol associations, e.g. 3 might get some absolute 321 * value like _INCLUDE_VERSION or something, therefore we do 322 * not accept symbols whose value is zero (and use plain hex). 323 */ 324 325 unsigned int db_maxoff = 0x10000000; 326 327 void 328 db_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 cursym = db_search_symbol(off, strategy, &d); 340 db_symbol_values(cursym, &name, &value); 341 if (name == 0 || d >= db_maxoff || value == 0) { 342 db_printf("%#n", off); 343 return; 344 } 345 db_printf("%s", name); 346 if (d) 347 db_printf("+%#r", d); 348 if (strategy == DB_STGY_PROC) { 349 if (db_line_at_pc(cursym, &filename, &linenum, off)) 350 db_printf(" [%s:%d]", filename, linenum); 351 } 352 } 353 354 355 boolean_t 356 db_line_at_pc( sym, filename, linenum, pc) 357 db_sym_t sym; 358 char **filename; 359 int *linenum; 360 db_expr_t pc; 361 { 362 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc); 363 } 364 365 int 366 db_sym_numargs(sym, nargp, argnames) 367 db_sym_t sym; 368 int *nargp; 369 char **argnames; 370 { 371 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames); 372 } 373