bool db_value_of_name(const char *name, db_expr_t *valuep) { char symbol[128]; char *mod, *sym; #ifdef _KERNEL unsigned long uval; long val; #endif #ifndef _KERNEL if (!use_ksyms) { db_sym_t ssym; /* * Cannot load symtabs in a.out kernels, so the ':' * style of selecting modules is irrelevant. */ ssym = (*db_symformat->sym_lookup)(NULL, name); if (ssym == DB_SYM_NULL) return (false); db_symbol_values(ssym, &name, valuep); return (true); } #endif (void)strlcpy(symbol, name, sizeof(symbol)); db_symsplit(symbol, &mod, &sym); #ifdef _KERNEL if (ksyms_getval_unlocked(mod, sym, &uval, KSYMS_EXTERN) == 0) { val = (long) uval; *valuep = (db_expr_t)val; return true; } if (ksyms_getval_unlocked(mod, sym, &uval, KSYMS_ANY) == 0) { val = (long) uval; *valuep = (db_expr_t)val; return true; } #endif return false; }
/* * Find the closest symbol to val, and return its name * and the difference between val and the symbol found. */ db_sym_t db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp) { unsigned int diff; db_sym_t ret = DB_SYM_NULL; #ifdef _KERNEL unsigned long naddr; const char *mod; const char *sym; #endif #ifndef _KERNEL if (!use_ksyms) { db_expr_t newdiff; db_sym_t ssym; newdiff = diff = ~0; ssym = (*db_symformat->sym_search) (NULL, val, strategy, &newdiff); if ((unsigned int) newdiff < diff) { diff = newdiff; ret = ssym; } *offp = diff; return ret; } #endif #ifdef _KERNEL if (ksyms_getname(&mod, &sym, (vaddr_t)val, strategy) == 0) { (void)ksyms_getval_unlocked(mod, sym, &naddr, KSYMS_ANY); diff = val - (db_addr_t)naddr; ret = (db_sym_t)naddr; } else #endif diff = 0; *offp = diff; return ret; }
/* * kobj_checksyms: * * Scan symbol table for duplicates or resolve references to * exernal symbols. */ static int kobj_checksyms(kobj_t ko, bool undefined) { unsigned long rval; Elf_Sym *sym, *ms; const char *name; int error; error = 0; for (ms = (sym = ko->ko_symtab) + ko->ko_symcnt; sym < ms; sym++) { /* Check validity of the symbol. */ if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL || sym->st_name == 0) continue; if (undefined != (sym->st_shndx == SHN_UNDEF)) { continue; } /* * Look it up. Don't need to lock, as it is known that * the symbol tables aren't going to change (we hold * module_lock). */ name = ko->ko_strtab + sym->st_name; if (ksyms_getval_unlocked(NULL, name, &rval, KSYMS_EXTERN) != 0) { if (undefined) { kobj_error(__func__, __LINE__, ko, "symbol `%s' not found", name); error = ENOEXEC; } continue; } /* Save values of undefined globals. */ if (undefined) { sym->st_value = (Elf_Addr)rval; continue; } /* Check (and complain) about differing values. */ if (sym->st_value == rval) { continue; } if (strcmp(name, "_bss_start") == 0 || strcmp(name, "__bss_start") == 0 || strcmp(name, "_bss_end__") == 0 || strcmp(name, "__bss_end__") == 0 || strcmp(name, "_edata") == 0 || strcmp(name, "_end") == 0 || strcmp(name, "__end") == 0 || strcmp(name, "__end__") == 0 || strncmp(name, "__start_link_set_", 17) == 0 || strncmp(name, "__stop_link_set_", 16)) { continue; } kobj_error(__func__, __LINE__, ko, "global symbol `%s' redefined", name); error = ENOEXEC; } return error; }
void db_printsym(db_expr_t off, db_strategy_t strategy, void (*pr)(const char *, ...)) { const char *name; #ifdef _KERNEL const char *mod; unsigned long uval; long val; #endif #ifdef notyet char *filename; int linenum; #endif #ifndef _KERNEL if (!use_ksyms) { db_expr_t d; char *filename; db_expr_t value; int linenum; db_sym_t cursym; cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); if (name != NULL && ((unsigned int)d < db_maxoff) && value != 0) { (*pr)("%s", name); if (d) { char tbuf[24]; db_format_radix(tbuf, 24, d, true); (*pr)("+%s", tbuf); } if (strategy == DB_STGY_PROC) { if ((*db_symformat->sym_line_at_pc) (NULL, cursym, &filename, &linenum, off)) (*pr)(" [%s:%d]", filename, linenum); } return; } (*pr)("%s", db_num_to_str(off)); return; } #endif #ifdef _KERNEL if (ksyms_getname(&mod, &name, (vaddr_t)off, strategy|KSYMS_CLOSEST) == 0) { (void)ksyms_getval_unlocked(mod, name, &uval, KSYMS_ANY); val = (long) uval; if (((off - val) < db_maxoff) && val) { (*pr)("%s:%s", mod, name); if (off - val) { char tbuf[24]; db_format_radix(tbuf, 24, off - val, true); (*pr)("+%s", tbuf); } #ifdef notyet if (strategy & KSYMS_PROC) { if (ksyms_fmaddr(off, &filename, &linenum) == 0) (*pr)(" [%s:%d]", filename, linenum); } #endif return; } } #endif (*pr)("%s", db_num_to_str(off)); return; }
void db_symstr(char *buf, size_t buflen, db_expr_t off, db_strategy_t strategy) { const char *name; #ifdef _KERNEL const char *mod; unsigned long val; #endif #ifndef _KERNEL if (!use_ksyms) { db_expr_t d; char *filename; db_expr_t value; int linenum; db_sym_t cursym; cursym = db_search_symbol(off, strategy, &d); db_symbol_values(cursym, &name, &value); if (name != NULL && ((unsigned int)d < db_maxoff) && value != 0) { strlcpy(buf, name, buflen); if (d) { strlcat(buf, "+", buflen); db_format_radix(buf + strlen(buf), 24, d, true); } if (strategy == DB_STGY_PROC) { if ((*db_symformat->sym_line_at_pc) (NULL, cursym, &filename, &linenum, off)) { size_t len = strlen(buf); snprintf(buf + len, buflen - len, " [%s:%d]", filename, linenum); } } return; } strlcpy(buf, db_num_to_str(off), buflen); return; } #endif #ifdef _KERNEL if (ksyms_getname(&mod, &name, (vaddr_t)off, strategy|KSYMS_CLOSEST) == 0) { (void)ksyms_getval_unlocked(mod, name, &val, KSYMS_ANY); if (((off - val) < db_maxoff) && val) { snprintf(buf, buflen, "%s:%s", mod, name); if (off - val) { strlcat(buf, "+", buflen); db_format_radix(buf+strlen(buf), 24, off - val, true); } #ifdef notyet if (strategy & KSYMS_PROC) { if (ksyms_fmaddr(off, &filename, &linenum) == 0) snprintf(buf + strlen(buf), buflen - strlen(buf), " [%s:%d]", filename, linenum); } #endif return; } } strlcpy(buf, db_num_to_str(off), buflen); #endif }