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.45 2003/11/17 10:16:18 cube 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.45 2003/11/17 10:16:18 cube 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_from_kernel(mod, sym, &uval, KSYMS_EXTERN) == 0) {
  113                 val = (long) uval;
  114                 *valuep = (db_expr_t)val;
  115                 return TRUE;
  116         }
  117         if (ksyms_getval_from_kernel(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_from_kernel(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 = 0x10000000;
  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                                                 sprintf(buf+strlen(buf),
  328                                                     " [%s:%d]",
  329                                                     filename, linenum);
  330                                 }
  331                                 return;
  332                         }
  333                 }
  334                 strlcpy(buf, db_num_to_str(off), buflen);
  335                 return;
  336         }
  337 #endif
  338         if (ksyms_getname(&mod, &name, (vaddr_t)off,
  339             strategy|KSYMS_CLOSEST) == 0) {
  340                 (void)ksyms_getval_from_kernel(mod, name, &val, KSYMS_ANY);
  341                 if (((off - val) < db_maxoff) && val) {
  342                         sprintf(buf, "%s:%s", mod, name);
  343                         if (off - val) {
  344                                 strlcat(buf, "+", buflen);
  345                                 db_format_radix(buf+strlen(buf),
  346                                     24, off - val, TRUE);
  347                         }
  348 #ifdef notyet
  349                         if (strategy & KSYMS_PROC) {
  350                                 if (ksyms_fmaddr(off, &filename, &linenum) == 0)                                        sprintf(buf+strlen(buf),
  351                                             " [%s:%d]", filename, linenum);
  352                         }
  353 #endif
  354                         return;
  355                 }
  356         }
  357         strlcpy(buf, db_num_to_str(off), buflen);
  358 }
  359 
  360 void
  361 db_printsym(db_expr_t off, db_strategy_t strategy,
  362     void (*pr)(const char *, ...))
  363 {
  364         char  *name;
  365         const char *mod;
  366         unsigned long uval;
  367         long val;
  368 #ifdef notyet
  369         char *filename;
  370         int  linenum;
  371 #endif
  372 
  373 #ifdef DB_AOUT_SYMBOLS
  374         if (using_aout_symtab) {
  375                 db_expr_t       d;
  376                 char            *filename;
  377                 char            *name;
  378                 db_expr_t       value;
  379                 int             linenum;
  380                 db_sym_t        cursym;
  381                 if ((unsigned long) off <= db_lastsym) {
  382                         cursym = db_search_symbol(off, strategy, &d);
  383                         db_symbol_values(cursym, &name, &value);
  384                         if (name != NULL &&
  385                             ((unsigned int) d < db_maxoff) &&
  386                             value != 0) {
  387                                 (*pr)("%s", name);
  388                                 if (d) {
  389                                         char tbuf[24];
  390         
  391                                         db_format_radix(tbuf, 24, d, TRUE);
  392                                         (*pr)("+%s", tbuf);
  393                                 }
  394                                 if (strategy == DB_STGY_PROC) {
  395                                         if ((*db_symformat->sym_line_at_pc)
  396                                             (NULL, cursym, &filename,
  397                                             &linenum, off))
  398                                                 (*pr)(" [%s:%d]",
  399                                                     filename, linenum);
  400                                 }
  401                                 return;
  402                         }
  403                 }
  404                 (*pr)(db_num_to_str(off));
  405                 return;
  406         }
  407 #endif
  408         if (ksyms_getname(&mod, &name, (vaddr_t)off,
  409             strategy|KSYMS_CLOSEST) == 0) {
  410                 (void)ksyms_getval_from_kernel(mod, name, &uval, KSYMS_ANY);
  411                 val = (long) uval;
  412                 if (((off - val) < db_maxoff) && val) {
  413                         (*pr)("%s:%s", mod, name);
  414                         if (off - val) {
  415                                 char tbuf[24];
  416 
  417                                 db_format_radix(tbuf, 24, off - val, TRUE);
  418                                 (*pr)("+%s", tbuf);
  419                         }
  420 #ifdef notyet
  421                         if (strategy & KSYMS_PROC) {
  422                                 if (ksyms_fmaddr(off, &filename, &linenum) == 0)
  423                                         (*pr)(" [%s:%d]", filename, linenum);
  424                         }
  425 #endif
  426                         return;
  427                 }
  428         }
  429         (*pr)(db_num_to_str(off));
  430         return;
  431 }
  432 
  433 /*
  434  * Splits a string in the form "mod:sym" to two strings.
  435  */
  436 static void
  437 db_symsplit(char *str, char **mod, char **sym)
  438 {
  439         char *cp;
  440 
  441         if ((cp = strchr(str, ':')) != NULL) {
  442                 *cp++ = '\0';
  443                 *mod = str;
  444                 *sym = cp;
  445         } else {
  446                 *mod = NULL;
  447                 *sym = str;
  448         }
  449 }
  450 
  451 boolean_t
  452 db_sym_numargs(db_sym_t cursym, int *nargp, char **argnamep)
  453 {
  454 #ifdef DB_AOUT_SYMBOLS
  455         if (using_aout_symtab)
  456                 return ((*db_symformat->sym_numargs)(NULL, cursym, nargp,
  457                     argnamep));
  458 #endif
  459         return (FALSE);
  460 }  
  461 

Cache object: 25a6d3e2ddfb3c97838f398000b034e7


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