The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_sym.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: db_sym.c,v 1.49 2005/02/26 23:04:17 perry Exp $        */
    2 
    3 /*
    4  * Mach Operating System
    5  * Copyright (c) 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 the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: db_sym.c,v 1.49 2005/02/26 23:04:17 perry Exp $");
   31 
   32 #include "opt_ddbparam.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/proc.h>
   36 #include <sys/systm.h>
   37 #include <sys/ksyms.h>
   38 
   39 #include <machine/db_machdep.h>
   40 
   41 #include <ddb/db_lex.h>
   42 #include <ddb/db_sym.h>
   43 #include <ddb/db_output.h>
   44 #include <ddb/db_extern.h>
   45 #include <ddb/db_command.h>
   46 
   47 static void             db_symsplit(char *, char **, char **);
   48 
   49 
   50 #ifdef DB_AOUT_SYMBOLS
   51 #define TBLNAME "netbsd"
   52 
   53 static int using_aout_symtab;
   54 const db_symformat_t *db_symformat;
   55 static db_forall_func_t db_sift;
   56 extern db_symformat_t db_symformat_aout;
   57 #endif
   58 
   59 
   60 /*
   61  * Initialize the kernel debugger by initializing the master symbol
   62  * table.  Note that if initializing the master symbol table fails,
   63  * no other symbol tables can be loaded.
   64  */
   65 void
   66 ddb_init(int symsize, void *vss, void *vse)
   67 {
   68 #ifdef DB_AOUT_SYMBOLS
   69         db_symformat = &db_symformat_aout;
   70         if ((*db_symformat->sym_init)(symsize, vss, vse, TBLNAME) == TRUE) {
   71                 using_aout_symtab = TRUE;
   72                 return;
   73         }
   74 #endif
   75         ksyms_init(symsize, vss, vse);  /* Will complain if necessary */
   76 }
   77 
   78 boolean_t
   79 db_eqname(char *src, char *dst, int c)
   80 {
   81 
   82         if (!strcmp(src, dst))
   83                 return (TRUE);
   84         if (src[0] == c)
   85                 return (!strcmp(src+1,dst));
   86         return (FALSE);
   87 }
   88 
   89 boolean_t
   90 db_value_of_name(char *name, db_expr_t *valuep)
   91 {
   92         char *mod, *sym;
   93         unsigned long uval;
   94         long val;
   95 
   96 #ifdef DB_AOUT_SYMBOLS
   97         db_sym_t        ssym;
   98 
   99         if (using_aout_symtab) {
  100                 /*
  101                  * Cannot load symtabs in a.out kernels, so the ':'
  102                  * style of selecting modules is irrelevant.
  103                  */
  104                 ssym = (*db_symformat->sym_lookup)(NULL, name);
  105                 if (ssym == DB_SYM_NULL)
  106                         return (FALSE);
  107                 db_symbol_values(ssym, &name, valuep);
  108                 return (TRUE);
  109         }
  110 #endif
  111         db_symsplit(name, &mod, &sym);
  112         if (ksyms_getval(mod, sym, &uval, KSYMS_EXTERN) == 0) {
  113                 val = (long) uval;
  114                 *valuep = (db_expr_t)val;
  115                 return TRUE;
  116         }
  117         if (ksyms_getval(mod, sym, &uval, KSYMS_ANY) == 0) {
  118                 val = (long) uval;
  119                 *valuep = (db_expr_t)val;
  120                 return TRUE;
  121         }
  122         return FALSE;
  123 }
  124 
  125 #ifdef DB_AOUT_SYMBOLS
  126 /* Private structure for passing args to db_sift() from db_sifting(). */
  127 struct db_sift_args {
  128         char    *symstr;
  129         int     mode;
  130 };
  131 
  132 /*
  133  * Does the work of db_sifting(), called once for each
  134  * symbol via db_forall(), prints out symbols matching
  135  * criteria.
  136  */
  137 static void
  138 db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix,
  139     void *arg)
  140 {
  141         char c, sc;
  142         char *find, *p;
  143         size_t len;
  144         struct db_sift_args *dsa;
  145 
  146         dsa = (struct db_sift_args*)arg;
  147 
  148         find = dsa->symstr;     /* String we're looking for. */
  149         p = name;               /* String we're searching within. */
  150 
  151         /* Matching algorithm cribbed from strstr(), which is not
  152            in the kernel. */
  153         if ((c = *find++) != 0) {
  154                 len = strlen(find);
  155                 do {
  156                         do {
  157                                 if ((sc = *p++) == 0)
  158                                         return;
  159                         } while (sc != c);
  160                 } while (strncmp(p, find, len) != 0);
  161         }
  162         if (dsa->mode=='F')     /* ala ls -F */
  163                 db_printf("%s%s ", name, suffix);
  164         else
  165                 db_printf("%s ", name);
  166 }
  167 #endif
  168 
  169 /*
  170  * "Sift" for a partial symbol.
  171  * Named for the Sun OpenPROM command ("sifting").
  172  * If the symbol has a qualifier (e.g., ux:vm_map),
  173  * then only the specified symbol table will be searched;
  174  * otherwise, all symbol tables will be searched..
  175  *
  176  * "mode" is how-to-display, set from modifiers.
  177  */
  178 void
  179 db_sifting(char *symstr, int mode)
  180 {
  181         char *mod, *sym;
  182 
  183 #ifdef DB_AOUT_SYMBOLS
  184         struct db_sift_args dsa;
  185 
  186         if (using_aout_symtab) {
  187                 dsa.symstr = symstr;
  188                 dsa.mode = mode;
  189                 (*db_symformat->sym_forall)(NULL, db_sift, &dsa);
  190                 db_printf("\n");
  191                 return;
  192         }
  193 #endif
  194 
  195         db_symsplit(symstr, &mod, &sym);
  196         if (ksyms_sift(mod, sym, mode) == ENODEV)
  197                 db_error("invalid symbol table name");
  198 }
  199 
  200 /*
  201  * Find the closest symbol to val, and return its name
  202  * and the difference between val and the symbol found.
  203  */
  204 db_sym_t
  205 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
  206 {
  207 /*###207 [cc] warning: `diff' might be used uninitialized in this function%%%*/
  208         unsigned int diff;
  209         unsigned long naddr;
  210         db_sym_t ret = DB_SYM_NULL;
  211         const char *mod;
  212         char *sym;
  213 
  214 #ifdef DB_AOUT_SYMBOLS
  215         db_expr_t newdiff;
  216         db_sym_t ssym;
  217 
  218         if (using_aout_symtab) {
  219                 newdiff = diff = ~0;
  220                 ssym = (*db_symformat->sym_search)
  221                     (NULL, val, strategy, &newdiff);
  222                 if ((unsigned int) newdiff < diff) {
  223                         diff = newdiff;
  224                         ret = ssym;
  225                 }
  226                 *offp = diff;
  227                 return ret;
  228         }
  229 #endif
  230 
  231         if (ksyms_getname(&mod, &sym, (vaddr_t)val, strategy) == 0) {
  232                 (void)ksyms_getval(mod, sym, &naddr, KSYMS_ANY);
  233                 diff = val - (db_addr_t)naddr;
  234                 ret = (db_sym_t)naddr;
  235         } else
  236                 diff = 0;
  237         *offp = diff;
  238         return ret;
  239 }
  240 
  241 /*
  242  * Return name and value of a symbol
  243  */
  244 void
  245 db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep)
  246 {
  247         const char *mod;
  248 
  249         if (sym == DB_SYM_NULL) {
  250                 *namep = 0;
  251                 return;
  252         }
  253 
  254 #ifdef DB_AOUT_SYMBOLS
  255         if (using_aout_symtab) {
  256                 db_expr_t value;
  257                 (*db_symformat->sym_value)(NULL, sym, namep, &value);
  258                 if (valuep)
  259                         *valuep = value;
  260                 return;
  261         }
  262 #endif
  263 
  264         if (ksyms_getname(&mod, namep, (vaddr_t)sym,
  265             KSYMS_ANY|KSYMS_EXACT) == 0) {
  266                 if (valuep)
  267                         *valuep = sym;
  268         } else
  269                 *namep = NULL;
  270 }
  271 
  272 
  273 /*
  274  * Print a the closest symbol to value
  275  *
  276  * After matching the symbol according to the given strategy
  277  * we print it in the name+offset format, provided the symbol's
  278  * value is close enough (eg smaller than db_maxoff).
  279  * We also attempt to print [filename:linenum] when applicable
  280  * (eg for procedure names).
  281  *
  282  * If we could not find a reasonable name+offset representation,
  283  * then we just print the value in hex.  Small values might get
  284  * bogus symbol associations, e.g. 3 might get some absolute
  285  * value like _INCLUDE_VERSION or something, therefore we do
  286  * not accept symbols whose value is zero (and use plain hex).
  287  * Also, avoid printing as "end+0x????" which is useless.
  288  * The variable db_lastsym is used instead of "end" in case we
  289  * add support for symbols in loadable driver modules.
  290  */
  291 extern char end[];
  292 unsigned long   db_lastsym = (unsigned long)end;
  293 unsigned int    db_maxoff = 0x100000;
  294 
  295 void
  296 db_symstr(char *buf, size_t buflen, db_expr_t off, db_strategy_t strategy)
  297 {
  298         char  *name;
  299         const char *mod;
  300         unsigned long val;
  301 
  302 #ifdef DB_AOUT_SYMBOLS
  303         if (using_aout_symtab) {
  304                 db_expr_t       d;
  305                 char            *filename;
  306                 char            *name;
  307                 db_expr_t       value;
  308                 int             linenum;
  309                 db_sym_t        cursym;
  310 
  311                 if ((unsigned long) off <= db_lastsym) {
  312                         cursym = db_search_symbol(off, strategy, &d);
  313                         db_symbol_values(cursym, &name, &value);
  314                         if (name != NULL &&
  315                             ((unsigned int) d < db_maxoff) &&
  316                             value != 0) {
  317                                 strlcpy(buf, name, buflen);
  318                                 if (d) {
  319                                         strlcat(buf, "+", buflen);
  320                                         db_format_radix(buf+strlen(buf),
  321                                             24, d, TRUE);
  322                                 }
  323                                 if (strategy == DB_STGY_PROC) {
  324                                         if ((*db_symformat->sym_line_at_pc)
  325                                             (NULL, cursym, &filename,
  326                                             &linenum, off))
  327                                                 snprintf(buf + strlen(buf),
  328                                                     buflen - strlen(buf),
  329                                                     " [%s:%d]",
  330                                                     filename, linenum);
  331                                 }
  332                                 return;
  333                         }
  334                 }
  335                 strlcpy(buf, db_num_to_str(off), buflen);
  336                 return;
  337         }
  338 #endif
  339         if (ksyms_getname(&mod, &name, (vaddr_t)off,
  340             strategy|KSYMS_CLOSEST) == 0) {
  341                 (void)ksyms_getval(mod, name, &val, KSYMS_ANY);
  342                 if (((off - val) < db_maxoff) && val) {
  343                         snprintf(buf, buflen, "%s:%s", mod, name);
  344                         if (off - val) {
  345                                 strlcat(buf, "+", buflen);
  346                                 db_format_radix(buf+strlen(buf),
  347                                     24, off - val, TRUE);
  348                         }
  349 #ifdef notyet
  350                         if (strategy & KSYMS_PROC) {
  351                                 if (ksyms_fmaddr(off, &filename, &linenum) == 0)
  352                                         snprintf(buf + strlen(buf),
  353                                             buflen - strlen(buf),
  354                                             " [%s:%d]", filename, linenum);
  355                         }
  356 #endif
  357                         return;
  358                 }
  359         }
  360         strlcpy(buf, db_num_to_str(off), buflen);
  361 }
  362 
  363 void
  364 db_printsym(db_expr_t off, db_strategy_t strategy,
  365     void (*pr)(const char *, ...))
  366 {
  367         char  *name;
  368         const char *mod;
  369         unsigned long uval;
  370         long val;
  371 #ifdef notyet
  372         char *filename;
  373         int  linenum;
  374 #endif
  375 
  376 #ifdef DB_AOUT_SYMBOLS
  377         if (using_aout_symtab) {
  378                 db_expr_t       d;
  379                 char            *filename;
  380                 char            *name;
  381                 db_expr_t       value;
  382                 int             linenum;
  383                 db_sym_t        cursym;
  384                 if ((unsigned long) off <= db_lastsym) {
  385                         cursym = db_search_symbol(off, strategy, &d);
  386                         db_symbol_values(cursym, &name, &value);
  387                         if (name != NULL &&
  388                             ((unsigned int) d < db_maxoff) &&
  389                             value != 0) {
  390                                 (*pr)("%s", name);
  391                                 if (d) {
  392                                         char tbuf[24];
  393 
  394                                         db_format_radix(tbuf, 24, d, TRUE);
  395                                         (*pr)("+%s", tbuf);
  396                                 }
  397                                 if (strategy == DB_STGY_PROC) {
  398                                         if ((*db_symformat->sym_line_at_pc)
  399                                             (NULL, cursym, &filename,
  400                                             &linenum, off))
  401                                                 (*pr)(" [%s:%d]",
  402                                                     filename, linenum);
  403                                 }
  404                                 return;
  405                         }
  406                 }
  407                 (*pr)(db_num_to_str(off));
  408                 return;
  409         }
  410 #endif
  411         if (ksyms_getname(&mod, &name, (vaddr_t)off,
  412             strategy|KSYMS_CLOSEST) == 0) {
  413                 (void)ksyms_getval(mod, name, &uval, KSYMS_ANY);
  414                 val = (long) uval;
  415                 if (((off - val) < db_maxoff) && val) {
  416                         (*pr)("%s:%s", mod, name);
  417                         if (off - val) {
  418                                 char tbuf[24];
  419 
  420                                 db_format_radix(tbuf, 24, off - val, TRUE);
  421                                 (*pr)("+%s", tbuf);
  422                         }
  423 #ifdef notyet
  424                         if (strategy & KSYMS_PROC) {
  425                                 if (ksyms_fmaddr(off, &filename, &linenum) == 0)
  426                                         (*pr)(" [%s:%d]", filename, linenum);
  427                         }
  428 #endif
  429                         return;
  430                 }
  431         }
  432         (*pr)(db_num_to_str(off));
  433         return;
  434 }
  435 
  436 /*
  437  * Splits a string in the form "mod:sym" to two strings.
  438  */
  439 static void
  440 db_symsplit(char *str, char **mod, char **sym)
  441 {
  442         char *cp;
  443 
  444         if ((cp = strchr(str, ':')) != NULL) {
  445                 *cp++ = '\0';
  446                 *mod = str;
  447                 *sym = cp;
  448         } else {
  449                 *mod = NULL;
  450                 *sym = str;
  451         }
  452 }
  453 
  454 boolean_t
  455 db_sym_numargs(db_sym_t cursym, int *nargp, char **argnamep)
  456 {
  457 #ifdef DB_AOUT_SYMBOLS
  458         if (using_aout_symtab)
  459                 return ((*db_symformat->sym_numargs)(NULL, cursym, nargp,
  460                     argnamep));
  461 #endif
  462         return (FALSE);
  463 }
  464 

Cache object: bd6253ad34849ef1ded3ec23d8cdda5f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.