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.54 2006/11/16 01:32:44 christos 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.54 2006/11/16 01:32:44 christos 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(const char *src, const 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(const char *name, db_expr_t *valuep)
   91 {
   92         char symbol[128];
   93         char *mod, *sym;
   94         unsigned long uval;
   95         long val;
   96 
   97 #ifdef DB_AOUT_SYMBOLS
   98         db_sym_t        ssym;
   99 
  100         if (using_aout_symtab) {
  101                 /*
  102                  * Cannot load symtabs in a.out kernels, so the ':'
  103                  * style of selecting modules is irrelevant.
  104                  */
  105                 ssym = (*db_symformat->sym_lookup)(NULL, name);
  106                 if (ssym == DB_SYM_NULL)
  107                         return (FALSE);
  108                 db_symbol_values(ssym, &name, valuep);
  109                 return (TRUE);
  110         }
  111 #endif
  112         (void)strlcpy(symbol, name, sizeof(symbol));
  113         db_symsplit(symbol, &mod, &sym);
  114         if (ksyms_getval(mod, sym, &uval, KSYMS_EXTERN) == 0) {
  115                 val = (long) uval;
  116                 *valuep = (db_expr_t)val;
  117                 return TRUE;
  118         }
  119         if (ksyms_getval(mod, sym, &uval, KSYMS_ANY) == 0) {
  120                 val = (long) uval;
  121                 *valuep = (db_expr_t)val;
  122                 return TRUE;
  123         }
  124         return FALSE;
  125 }
  126 
  127 #ifdef DB_AOUT_SYMBOLS
  128 /* Private structure for passing args to db_sift() from db_sifting(). */
  129 struct db_sift_args {
  130         char    *symstr;
  131         int     mode;
  132 };
  133 
  134 /*
  135  * Does the work of db_sifting(), called once for each
  136  * symbol via db_forall(), prints out symbols matching
  137  * criteria.
  138  */
  139 static void
  140 db_sift(db_symtab_t *stab, db_sym_t sym, char *name,
  141     char *suffix, int prefix, void *arg)
  142 {
  143         char c, sc;
  144         char *find, *p;
  145         size_t len;
  146         struct db_sift_args *dsa;
  147 
  148         dsa = (struct db_sift_args*)arg;
  149 
  150         find = dsa->symstr;     /* String we're looking for. */
  151         p = name;               /* String we're searching within. */
  152 
  153         /* Matching algorithm cribbed from strstr(), which is not
  154            in the kernel. */
  155         if ((c = *find++) != 0) {
  156                 len = strlen(find);
  157                 do {
  158                         do {
  159                                 if ((sc = *p++) == 0)
  160                                         return;
  161                         } while (sc != c);
  162                 } while (strncmp(p, find, len) != 0);
  163         }
  164         if (dsa->mode=='F')     /* ala ls -F */
  165                 db_printf("%s%s ", name, suffix);
  166         else
  167                 db_printf("%s ", name);
  168 }
  169 #endif
  170 
  171 /*
  172  * "Sift" for a partial symbol.
  173  * Named for the Sun OpenPROM command ("sifting").
  174  * If the symbol has a qualifier (e.g., ux:vm_map),
  175  * then only the specified symbol table will be searched;
  176  * otherwise, all symbol tables will be searched..
  177  *
  178  * "mode" is how-to-display, set from modifiers.
  179  */
  180 void
  181 db_sifting(char *symstr, int mode)
  182 {
  183         char *mod, *sym;
  184 
  185 #ifdef DB_AOUT_SYMBOLS
  186         struct db_sift_args dsa;
  187 
  188         if (using_aout_symtab) {
  189                 dsa.symstr = symstr;
  190                 dsa.mode = mode;
  191                 (*db_symformat->sym_forall)(NULL, db_sift, &dsa);
  192                 db_printf("\n");
  193                 return;
  194         }
  195 #endif
  196 
  197         db_symsplit(symstr, &mod, &sym);
  198         if (ksyms_sift(mod, sym, mode) == ENODEV)
  199                 db_error("invalid symbol table name");
  200 }
  201 
  202 /*
  203  * Find the closest symbol to val, and return its name
  204  * and the difference between val and the symbol found.
  205  */
  206 db_sym_t
  207 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
  208 {
  209         unsigned int diff;
  210         unsigned long naddr;
  211         db_sym_t ret = DB_SYM_NULL;
  212         const char *mod;
  213         const char *sym;
  214 
  215 #ifdef DB_AOUT_SYMBOLS
  216         db_expr_t newdiff;
  217         db_sym_t ssym;
  218 
  219         if (using_aout_symtab) {
  220                 newdiff = diff = ~0;
  221                 ssym = (*db_symformat->sym_search)
  222                     (NULL, val, strategy, &newdiff);
  223                 if ((unsigned int) newdiff < diff) {
  224                         diff = newdiff;
  225                         ret = ssym;
  226                 }
  227                 *offp = diff;
  228                 return ret;
  229         }
  230 #endif
  231 
  232         if (ksyms_getname(&mod, &sym, (vaddr_t)val, strategy) == 0) {
  233                 (void)ksyms_getval(mod, sym, &naddr, KSYMS_ANY);
  234                 diff = val - (db_addr_t)naddr;
  235                 ret = (db_sym_t)naddr;
  236         } else
  237                 diff = 0;
  238         *offp = diff;
  239         return ret;
  240 }
  241 
  242 /*
  243  * Return name and value of a symbol
  244  */
  245 void
  246 db_symbol_values(db_sym_t sym, const char **namep, db_expr_t *valuep)
  247 {
  248         const char *mod;
  249 
  250         if (sym == DB_SYM_NULL) {
  251                 *namep = 0;
  252                 return;
  253         }
  254 
  255 #ifdef DB_AOUT_SYMBOLS
  256         if (using_aout_symtab) {
  257                 db_expr_t value;
  258                 (*db_symformat->sym_value)(NULL, sym, namep, &value);
  259                 if (valuep)
  260                         *valuep = value;
  261                 return;
  262         }
  263 #endif
  264 
  265         if (ksyms_getname(&mod, namep, (vaddr_t)sym,
  266             KSYMS_ANY|KSYMS_EXACT) == 0) {
  267                 if (valuep)
  268                         *valuep = sym;
  269         } else
  270                 *namep = NULL;
  271 }
  272 
  273 
  274 /*
  275  * Print a the closest symbol to value
  276  *
  277  * After matching the symbol according to the given strategy
  278  * we print it in the name+offset format, provided the symbol's
  279  * value is close enough (eg smaller than db_maxoff).
  280  * We also attempt to print [filename:linenum] when applicable
  281  * (eg for procedure names).
  282  *
  283  * If we could not find a reasonable name+offset representation,
  284  * then we just print the value in hex.  Small values might get
  285  * bogus symbol associations, e.g. 3 might get some absolute
  286  * value like _INCLUDE_VERSION or something, therefore we do
  287  * not accept symbols whose value is zero (and use plain hex).
  288  * Also, avoid printing as "end+0x????" which is useless.
  289  * The variable db_lastsym is used instead of "end" in case we
  290  * add support for symbols in loadable driver modules.
  291  */
  292 extern char end[];
  293 unsigned long   db_lastsym = (unsigned long)end;
  294 unsigned int    db_maxoff = 0x100000;
  295 
  296 void
  297 db_symstr(char *buf, size_t buflen, db_expr_t off, db_strategy_t strategy)
  298 {
  299         const char  *name;
  300         const char *mod;
  301         unsigned long val;
  302 
  303 #ifdef DB_AOUT_SYMBOLS
  304         if (using_aout_symtab) {
  305                 db_expr_t       d;
  306                 char            *filename;
  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         const 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                 db_expr_t       value;
  381                 int             linenum;
  382                 db_sym_t        cursym;
  383                 if ((unsigned long) off <= db_lastsym) {
  384                         cursym = db_search_symbol(off, strategy, &d);
  385                         db_symbol_values(cursym, &name, &value);
  386                         if (name != NULL &&
  387                             ((unsigned int) d < db_maxoff) &&
  388                             value != 0) {
  389                                 (*pr)("%s", name);
  390                                 if (d) {
  391                                         char tbuf[24];
  392 
  393                                         db_format_radix(tbuf, 24, d, TRUE);
  394                                         (*pr)("+%s", tbuf);
  395                                 }
  396                                 if (strategy == DB_STGY_PROC) {
  397                                         if ((*db_symformat->sym_line_at_pc)
  398                                             (NULL, cursym, &filename,
  399                                             &linenum, off))
  400                                                 (*pr)(" [%s:%d]",
  401                                                     filename, linenum);
  402                                 }
  403                                 return;
  404                         }
  405                 }
  406                 (*pr)(db_num_to_str(off));
  407                 return;
  408         }
  409 #endif
  410         if (ksyms_getname(&mod, &name, (vaddr_t)off,
  411             strategy|KSYMS_CLOSEST) == 0) {
  412                 (void)ksyms_getval(mod, name, &uval, KSYMS_ANY);
  413                 val = (long) uval;
  414                 if (((off - val) < db_maxoff) && val) {
  415                         (*pr)("%s:%s", mod, name);
  416                         if (off - val) {
  417                                 char tbuf[24];
  418 
  419                                 db_format_radix(tbuf, 24, off - val, TRUE);
  420                                 (*pr)("+%s", tbuf);
  421                         }
  422 #ifdef notyet
  423                         if (strategy & KSYMS_PROC) {
  424                                 if (ksyms_fmaddr(off, &filename, &linenum) == 0)
  425                                         (*pr)(" [%s:%d]", filename, linenum);
  426                         }
  427 #endif
  428                         return;
  429                 }
  430         }
  431         (*pr)(db_num_to_str(off));
  432         return;
  433 }
  434 
  435 /*
  436  * Splits a string in the form "mod:sym" to two strings.
  437  */
  438 static void
  439 db_symsplit(char *str, char **mod, char **sym)
  440 {
  441         char *cp;
  442 
  443         if ((cp = strchr(str, ':')) != NULL) {
  444                 *cp++ = '\0';
  445                 *mod = str;
  446                 *sym = cp;
  447         } else {
  448                 *mod = NULL;
  449                 *sym = str;
  450         }
  451 }
  452 
  453 boolean_t
  454 db_sym_numargs(db_sym_t cursym, int *nargp, char **argnamep)
  455 {
  456 #ifdef DB_AOUT_SYMBOLS
  457         if (using_aout_symtab)
  458                 return ((*db_symformat->sym_numargs)(NULL, cursym, nargp,
  459                     argnamep));
  460 #endif
  461         return (FALSE);
  462 }
  463 

Cache object: ba8d6fd7f7dfd9f4e5525da1b2750e67


[ 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.