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 /* 27 * $Id: db_sym.c,v 1.2 1993/05/20 03:39:31 cgd Exp $ 28 * 29 * HISTORY 30 * $Log: db_sym.c,v $ 31 * Revision 1.2 1993/05/20 03:39:31 cgd 32 * add explicit rcs id 33 * 34 * Revision 1.1.1.1 1993/03/21 09:46:27 cgd 35 * initial import of 386bsd-0.1 sources 36 * 37 * Revision 1.1 1992/03/25 21:45:27 pace 38 * Initial revision 39 * 40 * Revision 2.5 91/02/05 17:07:07 mrt 41 * Changed to new Mach copyright 42 * [91/01/31 16:19:17 mrt] 43 * 44 * Revision 2.4 90/10/25 14:44:05 rwd 45 * Changed db_printsym to print unsigned. 46 * [90/10/19 rpd] 47 * 48 * Revision 2.3 90/09/09 23:19:56 rpd 49 * Avoid totally incorrect guesses of symbol names for small values. 50 * [90/08/30 17:39:48 af] 51 * 52 * Revision 2.2 90/08/27 21:52:18 dbg 53 * Removed nlist.h. Fixed some type declarations. 54 * Qualifier character is ':'. 55 * [90/08/20 dbg] 56 * Modularized symtab info into a new db_symtab_t type. 57 * Modified db_add_symbol_table and others accordingly. 58 * Defined db_sym_t, a new (opaque) type used to represent 59 * symbols. This should support all sort of future symtable 60 * formats. Functions like db_qualify take a db_sym_t now. 61 * New db_symbol_values() function to explode the content 62 * of a db_sym_t. 63 * db_search_symbol() replaces db_find_sym_and_offset(), which is 64 * now a macro defined in our (new) header file. This new 65 * function accepts more restrictive searches, which are 66 * entirely delegated to the symtab-specific code. 67 * Accordingly, db_printsym() accepts a strategy parameter. 68 * New db_line_at_pc() function. 69 * Renamed misleading db_eqsym into db_eqname. 70 * [90/08/20 10:47:06 af] 71 * 72 * Created. 73 * [90/07/25 dbg] 74 * 75 * Revision 2.1 90/07/26 16:43:52 dbg 76 * Created. 77 * 78 */ 79 /* 80 * Author: David B. Golub, Carnegie Mellon University 81 * Date: 7/90 82 */ 83 #include "param.h" 84 #include "proc.h" 85 #include <machine/db_machdep.h> 86 #include <ddb/db_sym.h> 87 88 /* 89 * We import from the symbol-table dependent routines: 90 */ 91 extern db_sym_t X_db_lookup(); 92 extern db_sym_t X_db_search_symbol(); 93 extern boolean_t X_db_line_at_pc(); 94 extern void X_db_symbol_values(); 95 96 /* 97 * Multiple symbol tables 98 */ 99 #define MAXNOSYMTABS 3 /* mach, ux, emulator */ 100 101 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; 102 int db_nsymtab = 0; 103 104 db_symtab_t *db_last_symtab; 105 106 db_sym_t db_lookup(); /* forward */ 107 108 /* 109 * Add symbol table, with given name, to list of symbol tables. 110 */ 111 void 112 db_add_symbol_table(start, end, name, ref) 113 char *start; 114 char *end; 115 char *name; 116 char *ref; 117 { 118 if (db_nsymtab >= MAXNOSYMTABS) { 119 printf ("No slots left for %s symbol table", name); 120 panic ("db_sym.c: db_add_symbol_table"); 121 } 122 123 db_symtabs[db_nsymtab].start = start; 124 db_symtabs[db_nsymtab].end = end; 125 db_symtabs[db_nsymtab].name = name; 126 db_symtabs[db_nsymtab].private = ref; 127 db_nsymtab++; 128 } 129 130 /* 131 * db_qualify("vm_map", "ux") returns "unix:vm_map". 132 * 133 * Note: return value points to static data whose content is 134 * overwritten by each call... but in practice this seems okay. 135 */ 136 static char * 137 db_qualify(sym, symtabname) 138 db_sym_t sym; 139 register char *symtabname; 140 { 141 char *symname; 142 static char tmp[256]; 143 register char *s; 144 145 db_symbol_values(sym, &symname, 0); 146 s = tmp; 147 while (*s++ = *symtabname++) { 148 } 149 s[-1] = ':'; 150 while (*s++ = *symname++) { 151 } 152 return tmp; 153 } 154 155 156 boolean_t 157 db_eqname(src, dst, c) 158 char *src; 159 char *dst; 160 char c; 161 { 162 if (!strcmp(src, dst)) 163 return (TRUE); 164 if (src[0] == c) 165 return (!strcmp(src+1,dst)); 166 return (FALSE); 167 } 168 169 boolean_t 170 db_value_of_name(name, valuep) 171 char *name; 172 db_expr_t *valuep; 173 { 174 db_sym_t sym; 175 176 sym = db_lookup(name); 177 if (sym == DB_SYM_NULL) 178 return (FALSE); 179 db_symbol_values(sym, &name, valuep); 180 return (TRUE); 181 } 182 183 184 /* 185 * Lookup a symbol. 186 * If the symbol has a qualifier (e.g., ux:vm_map), 187 * then only the specified symbol table will be searched; 188 * otherwise, all symbol tables will be searched. 189 */ 190 db_sym_t 191 db_lookup(symstr) 192 char *symstr; 193 { 194 db_sym_t sp; 195 register int i; 196 int symtab_start = 0; 197 int symtab_end = db_nsymtab; 198 register char *cp; 199 200 /* 201 * Look for, remove, and remember any symbol table specifier. 202 */ 203 for (cp = symstr; *cp; cp++) { 204 if (*cp == ':') { 205 *cp = '\0'; 206 for (i = 0; i < db_nsymtab; i++) { 207 if (! strcmp(symstr, db_symtabs[i].name)) { 208 symtab_start = i; 209 symtab_end = i + 1; 210 break; 211 } 212 } 213 *cp = ':'; 214 if (i == db_nsymtab) { 215 db_error("invalid symbol table name"); 216 } 217 symstr = cp+1; 218 } 219 } 220 221 /* 222 * Look in the specified set of symbol tables. 223 * Return on first match. 224 */ 225 for (i = symtab_start; i < symtab_end; i++) { 226 if (sp = X_db_lookup(&db_symtabs[i], symstr)) { 227 db_last_symtab = &db_symtabs[i]; 228 return sp; 229 } 230 } 231 return 0; 232 } 233 234 /* 235 * Does this symbol name appear in more than one symbol table? 236 * Used by db_symbol_values to decide whether to qualify a symbol. 237 */ 238 boolean_t db_qualify_ambiguous_names = FALSE; 239 240 boolean_t 241 db_symbol_is_ambiguous(sym) 242 db_sym_t sym; 243 { 244 char *sym_name; 245 register int i; 246 register 247 boolean_t found_once = FALSE; 248 249 if (!db_qualify_ambiguous_names) 250 return FALSE; 251 252 db_symbol_values(sym, &sym_name, 0); 253 for (i = 0; i < db_nsymtab; i++) { 254 if (X_db_lookup(&db_symtabs[i], sym_name)) { 255 if (found_once) 256 return TRUE; 257 found_once = TRUE; 258 } 259 } 260 return FALSE; 261 } 262 263 /* 264 * Find the closest symbol to val, and return its name 265 * and the difference between val and the symbol found. 266 */ 267 db_sym_t 268 db_search_symbol( val, strategy, offp) 269 register db_addr_t val; 270 db_strategy_t strategy; 271 db_expr_t *offp; 272 { 273 register 274 unsigned int diff; 275 unsigned int newdiff; 276 register int i; 277 db_sym_t ret = DB_SYM_NULL, sym; 278 279 newdiff = diff = ~0; 280 db_last_symtab = 0; 281 for (i = 0; i < db_nsymtab; i++) { 282 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); 283 if (newdiff < diff) { 284 db_last_symtab = &db_symtabs[i]; 285 diff = newdiff; 286 ret = sym; 287 } 288 } 289 *offp = diff; 290 return ret; 291 } 292 293 /* 294 * Return name and value of a symbol 295 */ 296 void 297 db_symbol_values(sym, namep, valuep) 298 db_sym_t sym; 299 char **namep; 300 db_expr_t *valuep; 301 { 302 db_expr_t value; 303 304 if (sym == DB_SYM_NULL) { 305 *namep = 0; 306 return; 307 } 308 309 X_db_symbol_values(sym, namep, &value); 310 311 if (db_symbol_is_ambiguous(sym)) 312 *namep = db_qualify(sym, db_last_symtab->name); 313 if (valuep) 314 *valuep = value; 315 } 316 317 318 /* 319 * Print a the closest symbol to value 320 * 321 * After matching the symbol according to the given strategy 322 * we print it in the name+offset format, provided the symbol's 323 * value is close enough (eg smaller than db_maxoff). 324 * We also attempt to print [filename:linenum] when applicable 325 * (eg for procedure names). 326 * 327 * If we could not find a reasonable name+offset representation, 328 * then we just print the value in hex. Small values might get 329 * bogus symbol associations, e.g. 3 might get some absolute 330 * value like _INCLUDE_VERSION or something, therefore we do 331 * not accept symbols whose value is zero (and use plain hex). 332 */ 333 334 unsigned int db_maxoff = 0x10000000; 335 336 void 337 db_printsym(off, strategy) 338 db_expr_t off; 339 db_strategy_t strategy; 340 { 341 db_expr_t d; 342 char *filename; 343 char *name; 344 db_expr_t value; 345 int linenum; 346 db_sym_t cursym; 347 348 cursym = db_search_symbol(off, strategy, &d); 349 db_symbol_values(cursym, &name, &value); 350 if (name == 0 || d >= db_maxoff || value == 0) { 351 db_printf("%#n", off); 352 return; 353 } 354 db_printf("%s", name); 355 if (d) 356 db_printf("+%#r", d); 357 if (strategy == DB_STGY_PROC) { 358 if (db_line_at_pc(cursym, &filename, &linenum, off)) 359 db_printf(" [%s:%d]", filename, linenum); 360 } 361 } 362 363 364 boolean_t 365 db_line_at_pc( sym, filename, linenum, pc) 366 { 367 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc); 368 } 369