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