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