db_sym.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /* $OpenBSD: db_sym.c,v 1.37 2015/03/14 03:38:46 jsg Exp $ */
  2. /* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */
  3. /*
  4. * Mach Operating System
  5. * Copyright (c) 1993,1992,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 "AS IS"
  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 Mellon
  26. * the rights to redistribute these changes.
  27. */
  28. #include <sys/param.h>
  29. #include <sys/systm.h>
  30. #include <machine/db_machdep.h>
  31. #include <ddb/db_lex.h>
  32. #include <ddb/db_sym.h>
  33. #include <ddb/db_output.h>
  34. #include <ddb/db_command.h>
  35. /*
  36. * Multiple symbol tables
  37. */
  38. #ifndef MAXLKMS
  39. #define MAXLKMS 20
  40. #endif
  41. #ifndef MAXNOSYMTABS
  42. #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */
  43. #endif
  44. db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
  45. db_symtab_t *db_last_symtab;
  46. static db_forall_func_t db_sift;
  47. extern char end[];
  48. /*
  49. * Put the most picky symbol table formats at the top!
  50. */
  51. const db_symformat_t *db_symformats[] = {
  52. &db_symformat_elf,
  53. NULL,
  54. };
  55. const db_symformat_t *db_symformat;
  56. boolean_t X_db_sym_init(int, void *, void *, const char *);
  57. db_sym_t X_db_lookup(db_symtab_t *, char *);
  58. db_sym_t X_db_search_symbol(db_symtab_t *, db_addr_t,
  59. db_strategy_t, db_expr_t *);
  60. void X_db_symbol_values(db_symtab_t *, db_sym_t, char **,
  61. db_expr_t *);
  62. boolean_t X_db_line_at_pc(db_symtab_t *, db_sym_t, char **,
  63. int *, db_expr_t);
  64. int X_db_sym_numargs(db_symtab_t *, db_sym_t, int *,
  65. char **);
  66. /*
  67. * Initialize the kernel debugger by initializing the master symbol
  68. * table. Note that if initializing the master symbol table fails,
  69. * no other symbol tables can be loaded.
  70. */
  71. #if 0
  72. void
  73. ddb_init(int symsize, void *vss, void *vse)
  74. {
  75. const db_symformat_t **symf;
  76. const char *name = "bsd";
  77. if (symsize <= 0) {
  78. printf(" [ no symbols available ]\n");
  79. return;
  80. }
  81. /*
  82. * Do this check now for the master symbol table to avoid printing
  83. * the message N times.
  84. */
  85. if (ALIGNED_POINTER(vss, long) == 0) {
  86. printf("[ %s symbol table has bad start address %p ]\n",
  87. name, vss);
  88. return;
  89. }
  90. for (symf = db_symformats; *symf != NULL; symf++) {
  91. db_symformat = *symf;
  92. if (X_db_sym_init(symsize, vss, vse, name) == TRUE)
  93. return;
  94. }
  95. db_symformat = NULL;
  96. printf("[ no symbol table formats found ]\n");
  97. }
  98. #else
  99. void
  100. ddb_init(void)
  101. {
  102. const db_symformat_t **symf;
  103. const char *name = "bsd";
  104. extern char *esym;
  105. #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
  106. extern char *ssym;
  107. #endif
  108. char *xssym, *xesym;
  109. xesym = esym;
  110. #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__)
  111. xssym = ssym;
  112. #else
  113. xssym = (char *)&end;
  114. #endif
  115. /*
  116. * Do this check now for the master symbol table to avoid printing
  117. * the message N times.
  118. */
  119. if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) {
  120. printf("[ %s symbol table has bad start address %p ]\n",
  121. name, xssym);
  122. return;
  123. }
  124. if (xesym != NULL && xesym != xssym)
  125. for (symf = db_symformats; *symf != NULL; symf++) {
  126. db_symformat = *symf;
  127. if (X_db_sym_init((vaddr_t)xesym - (vaddr_t)xssym,
  128. xssym, xesym, name) == TRUE)
  129. return;
  130. }
  131. db_symformat = NULL;
  132. printf("[ no symbol table formats found ]\n");
  133. }
  134. #endif
  135. /*
  136. * Add symbol table, with given name, to list of symbol tables.
  137. */
  138. int
  139. db_add_symbol_table(char *start, char *end, const char *name, char *ref)
  140. {
  141. int slot;
  142. for (slot = 0; slot < MAXNOSYMTABS; slot++) {
  143. if (db_symtabs[slot].name == NULL)
  144. break;
  145. }
  146. if (slot >= MAXNOSYMTABS) {
  147. db_printf("No slots left for %s symbol table", name);
  148. return(-1);
  149. }
  150. db_symtabs[slot].start = start;
  151. db_symtabs[slot].end = end;
  152. db_symtabs[slot].name = name;
  153. db_symtabs[slot].private = ref;
  154. return(slot);
  155. }
  156. /*
  157. * Delete a symbol table. Caller is responsible for freeing storage.
  158. */
  159. void
  160. db_del_symbol_table(char *name)
  161. {
  162. int slot;
  163. for (slot = 0; slot < MAXNOSYMTABS; slot++) {
  164. if (db_symtabs[slot].name &&
  165. ! strcmp(db_symtabs[slot].name, name))
  166. break;
  167. }
  168. if (slot >= MAXNOSYMTABS) {
  169. db_printf("Unable to find symbol table slot for %s.", name);
  170. return;
  171. }
  172. db_symtabs[slot].start = 0;
  173. db_symtabs[slot].end = 0;
  174. db_symtabs[slot].name = 0;
  175. db_symtabs[slot].private = 0;
  176. }
  177. /*
  178. * db_qualify("vm_map", "bsd") returns "bsd:vm_map".
  179. *
  180. * Note: return value points to static data whose content is
  181. * overwritten by each call... but in practice this seems okay.
  182. */
  183. char *
  184. db_qualify(db_sym_t sym, const char *symtabname)
  185. {
  186. char *symname;
  187. static char tmp[256];
  188. char *s;
  189. db_symbol_values(sym, &symname, 0);
  190. s = tmp;
  191. while ((*s++ = *symtabname++) != '\0')
  192. ;
  193. s[-1] = ':';
  194. while ((*s++ = *symname++) != '\0')
  195. ;
  196. return tmp;
  197. }
  198. boolean_t
  199. db_eqname(char *src, char *dst, int c)
  200. {
  201. if (!strcmp(src, dst))
  202. return (TRUE);
  203. if (src[0] == c)
  204. return (!strcmp(src+1,dst));
  205. return (FALSE);
  206. }
  207. boolean_t
  208. db_value_of_name(char *name, db_expr_t *valuep)
  209. {
  210. db_sym_t sym;
  211. sym = db_lookup(name);
  212. if (sym == DB_SYM_NULL)
  213. return (FALSE);
  214. db_symbol_values(sym, &name, valuep);
  215. return (TRUE);
  216. }
  217. /*
  218. * Lookup a symbol.
  219. * If the symbol has a qualifier (e.g., ux:vm_map),
  220. * then only the specified symbol table will be searched;
  221. * otherwise, all symbol tables will be searched.
  222. */
  223. db_sym_t
  224. db_lookup(char *symstr)
  225. {
  226. db_sym_t sp;
  227. int i;
  228. int symtab_start = 0;
  229. int symtab_end = MAXNOSYMTABS;
  230. char *cp;
  231. /*
  232. * Look for, remove, and remember any symbol table specifier.
  233. */
  234. for (cp = symstr; *cp; cp++) {
  235. if (*cp == ':') {
  236. *cp = '\0';
  237. for (i = 0; i < MAXNOSYMTABS; i++) {
  238. if (db_symtabs[i].name &&
  239. ! strcmp(symstr, db_symtabs[i].name)) {
  240. symtab_start = i;
  241. symtab_end = i + 1;
  242. break;
  243. }
  244. }
  245. *cp = ':';
  246. if (i == MAXNOSYMTABS) {
  247. db_error("invalid symbol table name");
  248. /*NOTREACHED*/
  249. }
  250. symstr = cp+1;
  251. }
  252. }
  253. /*
  254. * Look in the specified set of symbol tables.
  255. * Return on first match.
  256. */
  257. for (i = symtab_start; i < symtab_end; i++) {
  258. if (db_symtabs[i].name &&
  259. (sp = X_db_lookup(&db_symtabs[i], symstr))) {
  260. db_last_symtab = &db_symtabs[i];
  261. return sp;
  262. }
  263. }
  264. return 0;
  265. }
  266. /* Private structure for passing args to db_sift() from db_sifting(). */
  267. struct db_sift_args {
  268. char *symstr;
  269. int mode;
  270. };
  271. /*
  272. * Does the work of db_sifting(), called once for each
  273. * symbol via X_db_forall(), prints out symbols matching
  274. * criteria.
  275. */
  276. static void
  277. db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix,
  278. void *arg)
  279. {
  280. char c, sc;
  281. char *find, *p;
  282. size_t len;
  283. struct db_sift_args *dsa;
  284. dsa = (struct db_sift_args*)arg;
  285. find = dsa->symstr; /* String we're looking for. */
  286. p = name; /* String we're searching within. */
  287. /* Matching algorithm cribbed from strstr(), which is not
  288. in the kernel. */
  289. if ((c = *find++) != 0) {
  290. len = strlen(find);
  291. do {
  292. do {
  293. if ((sc = *p++) == 0)
  294. return;
  295. } while (sc != c);
  296. } while (strncmp(p, find, len) != 0);
  297. }
  298. if (dsa->mode=='F') /* ala ls -F */
  299. db_printf("%s%s ", name, suffix);
  300. else
  301. db_printf("%s ", name);
  302. }
  303. /*
  304. * "Sift" for a partial symbol.
  305. * Named for the Sun OpenPROM command ("sifting").
  306. * If the symbol has a qualifier (e.g., ux:vm_map),
  307. * then only the specified symbol table will be searched;
  308. * otherwise, all symbol tables will be searched..
  309. *
  310. * "mode" is how-to-display, set from modifiers.
  311. */
  312. void
  313. db_sifting(char *symstr, int mode)
  314. {
  315. char *cp;
  316. int i;
  317. int symtab_start = 0;
  318. int symtab_end = MAXNOSYMTABS;
  319. struct db_sift_args dsa;
  320. /*
  321. * Look for, remove, and remember any symbol table specifier.
  322. */
  323. for (cp = symstr; *cp; cp++) {
  324. if (*cp == ':') {
  325. *cp = '\0';
  326. for (i = 0; i < MAXNOSYMTABS; i++) {
  327. if (db_symtabs[i].name &&
  328. ! strcmp(symstr, db_symtabs[i].name)) {
  329. symtab_start = i;
  330. symtab_end = i + 1;
  331. break;
  332. }
  333. }
  334. *cp = ':';
  335. if (i == MAXNOSYMTABS) {
  336. db_error("invalid symbol table name");
  337. /*NOTREACHED*/
  338. }
  339. symstr = cp+1;
  340. }
  341. }
  342. /* Pass args to db_sift(). */
  343. dsa.symstr = symstr;
  344. dsa.mode = mode;
  345. /*
  346. * Look in the specified set of symbol tables.
  347. */
  348. for (i = symtab_start; i < symtab_end; i++)
  349. if (db_symtabs[i].name) {
  350. db_printf("Sifting table %s:\n", db_symtabs[i].name);
  351. X_db_forall(&db_symtabs[i], db_sift, &dsa);
  352. }
  353. return;
  354. }
  355. /*
  356. * Does this symbol name appear in more than one symbol table?
  357. * Used by db_symbol_values to decide whether to qualify a symbol.
  358. */
  359. boolean_t db_qualify_ambiguous_names = FALSE;
  360. boolean_t
  361. db_symbol_is_ambiguous(db_sym_t sym)
  362. {
  363. char *sym_name;
  364. int i;
  365. boolean_t found_once = FALSE;
  366. if (!db_qualify_ambiguous_names)
  367. return FALSE;
  368. db_symbol_values(sym, &sym_name, 0);
  369. for (i = 0; i < MAXNOSYMTABS; i++) {
  370. if (db_symtabs[i].name &&
  371. X_db_lookup(&db_symtabs[i], sym_name)) {
  372. if (found_once)
  373. return TRUE;
  374. found_once = TRUE;
  375. }
  376. }
  377. return FALSE;
  378. }
  379. /*
  380. * Find the closest symbol to val, and return its name
  381. * and the difference between val and the symbol found.
  382. */
  383. db_sym_t
  384. db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
  385. {
  386. unsigned int diff;
  387. db_expr_t newdiff;
  388. int i;
  389. db_sym_t ret = DB_SYM_NULL, sym;
  390. newdiff = diff = ~0;
  391. db_last_symtab = 0;
  392. for (i = 0; i < MAXNOSYMTABS; i++) {
  393. if (!db_symtabs[i].name)
  394. continue;
  395. sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
  396. if (newdiff < diff) {
  397. db_last_symtab = &db_symtabs[i];
  398. diff = newdiff;
  399. ret = sym;
  400. }
  401. }
  402. *offp = diff;
  403. return ret;
  404. }
  405. /*
  406. * Return name and value of a symbol
  407. */
  408. void
  409. db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep)
  410. {
  411. db_expr_t value;
  412. if (sym == DB_SYM_NULL) {
  413. *namep = 0;
  414. return;
  415. }
  416. X_db_symbol_values(db_last_symtab, sym, namep, &value);
  417. if (db_symbol_is_ambiguous(sym))
  418. *namep = db_qualify(sym, db_last_symtab->name);
  419. if (valuep)
  420. *valuep = value;
  421. }
  422. /*
  423. * Print a the closest symbol to value
  424. *
  425. * After matching the symbol according to the given strategy
  426. * we print it in the name+offset format, provided the symbol's
  427. * value is close enough (eg smaller than db_maxoff).
  428. * We also attempt to print [filename:linenum] when applicable
  429. * (eg for procedure names).
  430. *
  431. * If we could not find a reasonable name+offset representation,
  432. * then we just print the value in hex. Small values might get
  433. * bogus symbol associations, e.g. 3 might get some absolute
  434. * value like _INCLUDE_VERSION or something, therefore we do
  435. * not accept symbols whose value is zero (and use plain hex).
  436. * Also, avoid printing as "end+0x????" which is useless.
  437. * The variable db_lastsym is used instead of "end" in case we
  438. * add support for symbols in loadable driver modules.
  439. */
  440. unsigned long db_lastsym = (unsigned long)end;
  441. unsigned int db_maxoff = 0x10000000;
  442. void
  443. db_printsym(db_expr_t off, db_strategy_t strategy,
  444. int (*pr)(const char *, ...))
  445. {
  446. db_expr_t d;
  447. char *filename;
  448. char *name;
  449. db_expr_t value;
  450. int linenum;
  451. db_sym_t cursym;
  452. char buf[DB_FORMAT_BUF_SIZE];
  453. if (off <= db_lastsym) {
  454. cursym = db_search_symbol(off, strategy, &d);
  455. db_symbol_values(cursym, &name, &value);
  456. if (name && (d < db_maxoff) && value) {
  457. (*pr)("%s", name);
  458. if (d) {
  459. (*pr)("+%s", db_format(buf, sizeof(buf),
  460. d, DB_FORMAT_R, 1, 0));
  461. }
  462. if (strategy == DB_STGY_PROC) {
  463. if (db_line_at_pc(cursym, &filename, &linenum, off))
  464. (*pr)(" [%s:%d]", filename, linenum);
  465. }
  466. return;
  467. }
  468. }
  469. (*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0));
  470. return;
  471. }
  472. boolean_t
  473. db_line_at_pc(db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
  474. {
  475. return X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc);
  476. }
  477. int
  478. db_sym_numargs(db_sym_t sym, int *nargp, char **argnames)
  479. {
  480. return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames);
  481. }
  482. boolean_t
  483. X_db_sym_init(int symsize, void *vss, void *vse, const char *name)
  484. {
  485. if (db_symformat != NULL)
  486. return ((*db_symformat->sym_init)(symsize, vss, vse, name));
  487. return (FALSE);
  488. }
  489. db_sym_t
  490. X_db_lookup(db_symtab_t *stab, char *symstr)
  491. {
  492. if (db_symformat != NULL)
  493. return ((*db_symformat->sym_lookup)(stab, symstr));
  494. return ((db_sym_t)0);
  495. }
  496. db_sym_t
  497. X_db_search_symbol(db_symtab_t *stab, db_addr_t off, db_strategy_t strategy,
  498. db_expr_t *diffp)
  499. {
  500. if (db_symformat != NULL)
  501. return ((*db_symformat->sym_search)(stab, off, strategy,
  502. diffp));
  503. return ((db_sym_t)0);
  504. }
  505. void
  506. X_db_symbol_values(db_symtab_t *stab, db_sym_t sym, char **namep,
  507. db_expr_t *valuep)
  508. {
  509. if (db_symformat != NULL)
  510. (*db_symformat->sym_value)(stab, sym, namep, valuep);
  511. }
  512. boolean_t
  513. X_db_line_at_pc(db_symtab_t *stab, db_sym_t cursym, char **filename,
  514. int *linenum, db_expr_t off)
  515. {
  516. if (db_symformat != NULL)
  517. return ((*db_symformat->sym_line_at_pc)(stab, cursym,
  518. filename, linenum, off));
  519. return (FALSE);
  520. }
  521. boolean_t
  522. X_db_sym_numargs(db_symtab_t *stab, db_sym_t cursym, int *nargp,
  523. char **argnamep)
  524. {
  525. if (db_symformat != NULL)
  526. return ((*db_symformat->sym_numargs)(stab, cursym, nargp,
  527. argnamep));
  528. return (FALSE);
  529. }
  530. void
  531. X_db_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
  532. {
  533. if (db_symformat != NULL)
  534. (*db_symformat->sym_forall)(stab, db_forall_func, arg);
  535. }