root/ddb/db_sym.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ddb_init
  2. ddb_init
  3. db_add_symbol_table
  4. db_del_symbol_table
  5. db_qualify
  6. db_eqname
  7. db_value_of_name
  8. db_lookup
  9. db_sift
  10. db_sifting
  11. db_symbol_is_ambiguous
  12. db_search_symbol
  13. db_symbol_values
  14. db_printsym
  15. db_line_at_pc
  16. db_sym_numargs
  17. X_db_sym_init
  18. X_db_lookup
  19. X_db_search_symbol
  20. X_db_symbol_values
  21. X_db_line_at_pc
  22. X_db_sym_numargs
  23. X_db_forall

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

/* [<][>][^][v][top][bottom][index][help] */