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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_sym.c,v $
   29  * Revision 2.18  93/11/17  16:25:12  dbg
   30  *      Added ANSI function prototypes.
   31  *      [93/10/11            dbg]
   32  * 
   33  * Revision 2.17  93/03/09  10:53:50  danner
   34  *      String protos.
   35  *      [93/03/07            af]
   36  * 
   37  * Revision 2.16  93/01/14  17:25:45  danner
   38  *      Handle multiple, coexisting symbol table types.
   39  *      64bit cleanup.
   40  *      [92/11/30            af]
   41  * 
   42  *      Check for null db_last_symtab in db_line_at_pc.
   43  *      [92/10/06            jvh]
   44  * 
   45  * Revision 2.15  92/08/03  17:32:03  jfriedl
   46  *      removed silly prototypes
   47  *      [92/08/02            jfriedl]
   48  * 
   49  * Revision 2.14  92/05/21  17:07:47  jfriedl
   50  *      Cleanup to quiet gcc warnings.
   51  *      Changed CHAR arg of db_eqname to UNSIGNED.
   52  *      Made arg types proper for db_line_at_pc().
   53  *      [92/05/16            jfriedl]
   54  * 
   55  * Revision 2.13  92/05/05  11:05:16  danner
   56  *      typo correction
   57  * 
   58  * Revision 2.12  92/05/05  10:52:16  danner
   59  *      Bulletproof db_search_in_task_symbol against symbol tables that return
   60  *      success and huge offsets for address outside of their domain.
   61  * 
   62  * Revision 2.11  92/05/04  13:48:25  danner
   63  *      Rewrote db_search_task_symbol to deal more reasonably 
   64  *       with overlapping user and kernel address ranges.
   65  *      [92/03/23  15:03:21  danner]
   66  *      Complete rewrite of db_search_task_symbol logic to deal
   67  *       gracefully with the case of overlapping user and kernel address
   68  *       space.
   69  *      [92/03/21            danner]
   70  *      Upped MAXNOSYMTABS from 3 to 5. Now there is space for kernel,
   71  *       bootstrap, server, and emulator symbols - plus one for future
   72  *       expansion.
   73  *      [92/03/21            danner]
   74  * 
   75  * Revision 2.10  91/10/09  16:02:30  af
   76  *       Changed symbol table name qualification syntax from "xxx:yyy"
   77  *        to "xxx::yyy" to allow "file:func:line" in "yyy" part.
   78  *        "db_sym_parse_and_lookup" is also added for "yyy" part parsing.
   79  *        Replaced db_search_symbol with db_search_task_symbol, and moved
   80  *        it to "db_sym.h" as a macro.
   81  *        Added db_task_printsym, and changed db_printsym to call it.
   82  *        Added include "db_task_thread.h".
   83  *        Fixed infinite recursion of db_symbol_values.
   84  *       [91/08/29            tak]
   85  * 
   86  * Revision 2.9  91/07/31  17:31:14  dbg
   87  *      Add task pointer and space for string storage to symbol table
   88  *      descriptor.
   89  *      [91/07/31            dbg]
   90  * 
   91  * Revision 2.8  91/07/09  23:16:08  danner
   92  *      Changed a printf.
   93  *      [91/07/08            danner]
   94  * 
   95  * Revision 2.7  91/05/14  15:35:54  mrt
   96  *      Correcting copyright
   97  * 
   98  * Revision 2.6  91/03/16  14:42:40  rpd
   99  *      Changed the default db_maxoff to 4K.
  100  *      [91/03/10            rpd]
  101  * 
  102  * Revision 2.5  91/02/05  17:07:07  mrt
  103  *      Changed to new Mach copyright
  104  *      [91/01/31  16:19:17  mrt]
  105  * 
  106  * Revision 2.4  90/10/25  14:44:05  rwd
  107  *      Changed db_printsym to print unsigned.
  108  *      [90/10/19            rpd]
  109  * 
  110  * Revision 2.3  90/09/09  23:19:56  rpd
  111  *      Avoid totally incorrect guesses of symbol names for small values.
  112  *      [90/08/30  17:39:48  af]
  113  * 
  114  * Revision 2.2  90/08/27  21:52:18  dbg
  115  *      Removed nlist.h.  Fixed some type declarations.
  116  *      Qualifier character is ':'.
  117  *      [90/08/20            dbg]
  118  *      Modularized symtab info into a new db_symtab_t type.
  119  *      Modified db_add_symbol_table  and others accordingly.
  120  *      Defined db_sym_t, a new (opaque) type used to represent
  121  *      symbols.  This should support all sort of future symtable
  122  *      formats. Functions like db_qualify take a db_sym_t now.
  123  *      New db_symbol_values() function to explode the content
  124  *      of a db_sym_t.
  125  *      db_search_symbol() replaces db_find_sym_and_offset(), which is
  126  *      now a macro defined in our (new) header file.  This new
  127  *      function accepts more restrictive searches, which are
  128  *      entirely delegated to the symtab-specific code.
  129  *      Accordingly, db_printsym() accepts a strategy parameter.
  130  *      New db_line_at_pc() function.
  131  *      Renamed misleading db_eqsym into db_eqname.
  132  *      [90/08/20  10:47:06  af]
  133  * 
  134  *      Created.
  135  *      [90/07/25            dbg]
  136  * 
  137  * Revision 2.1  90/07/26  16:43:52  dbg
  138  * Created.
  139  * 
  140  */
  141 /*
  142  *      Author: David B. Golub, Carnegie Mellon University
  143  *      Date:   7/90
  144  */
  145 
  146 #include <mach/std_types.h>
  147 #include <kern/strings.h>
  148 #include <machine/db_machdep.h>
  149 #include <ddb/db_sym.h>
  150 #include <ddb/db_task_thread.h>
  151 #include <ddb/db_command.h>
  152 #include <ddb/db_output.h>
  153 
  154 #include <vm/vm_map.h>  /* vm_map_t */
  155 
  156 /*
  157  * Multiple symbol tables
  158  */
  159 #define MAXNOSYMTABS    5       /* mach, bootstrap, ux, emulator, 1 spare */
  160 
  161 db_symtab_t     db_symtabs[MAXNOSYMTABS] = {{0,},};
  162 int db_nsymtab = 0;
  163 
  164 db_symtab_t     *db_last_symtab;
  165 
  166 db_sym_t        db_lookup(char *symstr);        /* forward */
  167 
  168 /*
  169  * Add symbol table, with given name, to list of symbol tables.
  170  */
  171 boolean_t
  172 db_add_symbol_table(
  173         int type,
  174         char *start,
  175         char *end,
  176         char *name,
  177         char *ref,
  178         char *map_pointer)
  179 {
  180         register db_symtab_t *st;
  181         extern vm_map_t kernel_map;
  182 
  183         if (db_nsymtab >= MAXNOSYMTABS)
  184             return FALSE;
  185 
  186         st = &db_symtabs[db_nsymtab];
  187         st->type = type;
  188         st->start = start;
  189         st->end = end;
  190         st->private = ref;
  191         st->map_pointer = (map_pointer == (char *)kernel_map)? 0: map_pointer;
  192         strcpy(st->name, name);
  193 
  194         db_nsymtab++;
  195 
  196         return TRUE;
  197 }
  198 
  199 /*
  200  *  db_qualify("vm_map", "ux") returns "ux::vm_map".
  201  *
  202  *  Note: return value points to static data whose content is
  203  *  overwritten by each call... but in practice this seems okay.
  204  */
  205 static char *
  206 db_qualify(
  207         char            *symname,
  208         register char   *symtabname)
  209 {
  210         static char     tmp[256];
  211         register char   *s;
  212 
  213         s = tmp;
  214         while ((*s++ = *symtabname++) != '\0')
  215             continue;
  216         s[-1] = ':';
  217         *s++ = ':';
  218         while ((*s++ = *symname++) != '\0')
  219             continue;
  220         return tmp;
  221 }
  222 
  223 
  224 boolean_t
  225 db_eqname( char* src, char* dst, char c )
  226 {
  227         if (!strcmp(src, dst))
  228             return TRUE;
  229         if (src[0] == c)
  230             return !strcmp(src+1,dst);
  231         return FALSE;
  232 }
  233 
  234 boolean_t
  235 db_value_of_name(
  236         char            *name,
  237         db_expr_t       *valuep)
  238 {
  239         db_sym_t        sym;
  240 
  241         sym = db_lookup(name);
  242         if (sym == DB_SYM_NULL)
  243             return FALSE;
  244         db_symbol_values(0, sym, &name, valuep);
  245         return TRUE;
  246 }
  247 
  248 /*
  249  * Lookup a symbol.
  250  * If the symbol has a qualifier (e.g., ux::vm_map),
  251  * then only the specified symbol table will be searched;
  252  * otherwise, all symbol tables will be searched.
  253  */
  254 db_sym_t
  255 db_lookup(
  256         char *symstr)
  257 {
  258         db_sym_t sp;
  259         register int i;
  260         int symtab_start = 0;
  261         int symtab_end = db_nsymtab;
  262         register char *cp;
  263 
  264         /*
  265          * Look for, remove, and remember any symbol table specifier.
  266          */
  267         for (cp = symstr; *cp; cp++) {
  268                 if (*cp == ':' && cp[1] == ':') {
  269                         *cp = '\0';
  270                         for (i = 0; i < db_nsymtab; i++) {
  271                                 if (! strcmp(symstr, db_symtabs[i].name)) {
  272                                         symtab_start = i;
  273                                         symtab_end = i + 1;
  274                                         break;
  275                                 }
  276                         }
  277                         *cp = ':';
  278                         if (i == db_nsymtab)
  279                                 db_error("Invalid symbol table name\n");
  280                         symstr = cp+2;
  281                 }
  282         }
  283 
  284         /*
  285          * Look in the specified set of symbol tables.
  286          * Return on first match.
  287          */
  288         for (i = symtab_start; i < symtab_end; i++) {
  289                 if ((sp = X_db_lookup(&db_symtabs[i], symstr)) != 0) {
  290                         db_last_symtab = &db_symtabs[i];
  291                         return sp;
  292                 }
  293         }
  294         return 0;
  295 }
  296 
  297 /*
  298  * Common utility routine to parse a symbol string into a file
  299  * name, a symbol name and line number.
  300  * This routine is called from X_db_lookup if the object dependent
  301  * handler supports qualified search with a file name or a line number.
  302  * It parses the symbol string, and call an object dependent routine
  303  * with parsed file name, symbol name and line number.
  304  */ 
  305 db_sym_t
  306 db_sym_parse_and_lookup(
  307         db_sym_t        (*func)(
  308                             db_symtab_t *symtab,
  309                             char        *file_name,
  310                             char        *sym_name,
  311                             int         line_number),
  312         db_symtab_t     *symtab,
  313         char            *symstr)
  314 {
  315         register char * p;
  316         register int    n;
  317         int             n_name;
  318         int             line_number;
  319         char            *file_name = 0;
  320         char            *sym_name = 0;
  321         char            *component[3];
  322         db_sym_t        found = DB_SYM_NULL;
  323 
  324         /*
  325          * disassemble the symbol into components:
  326          *      [file_name:]symbol[:line_nubmer]
  327          */
  328         component[0] = symstr;
  329         component[1] = component[2] = 0;
  330         for (p = symstr, n = 1; *p; p++) {
  331                 if (*p == ':') {
  332                         if (n >= 3)
  333                                 break;
  334                         *p = 0;
  335                         component[n++] = p+1;
  336                 }
  337         }
  338         if (*p != 0)
  339                 goto out;
  340         line_number = 0;
  341         n_name = n;
  342         p = component[n-1];
  343         if (*p >= '' && *p <= '9') {
  344                 if (n == 1)
  345                         goto out;
  346                 for (line_number = 0; *p; p++) {
  347                         if (*p < '' || *p > '9')
  348                                 goto out;
  349                         line_number = line_number*10 + *p - '';
  350                 }
  351                 n_name--;
  352         } else if (n >= 3)
  353                 goto out;
  354         if (n_name == 1) {
  355                 for (p = component[0]; *p && *p != '.'; p++);
  356                 if (*p == '.') {
  357                         file_name = component[0];
  358                         sym_name = 0;
  359                 } else {
  360                         file_name = 0;
  361                         sym_name = component[0];
  362                 }
  363         } else {
  364                 file_name = component[0];
  365                 sym_name = component[1];
  366         }
  367         found = func(symtab, file_name, sym_name, line_number);
  368         
  369 out:
  370         while (--n >= 1)
  371                 component[n][-1] = ':';
  372         return found;
  373 }
  374 
  375 /*
  376  * Does this symbol name appear in more than one symbol table?
  377  * Used by db_symbol_values to decide whether to qualify a symbol.
  378  */
  379 boolean_t db_qualify_ambiguous_names = FALSE;
  380 
  381 boolean_t
  382 db_name_is_ambiguous(
  383         char            *sym_name)
  384 {
  385         register int    i;
  386         register
  387         boolean_t       found_once = FALSE;
  388 
  389         if (!db_qualify_ambiguous_names)
  390                 return FALSE;
  391 
  392         for (i = 0; i < db_nsymtab; i++) {
  393                 if (X_db_lookup(&db_symtabs[i], sym_name)) {
  394                         if (found_once)
  395                                 return TRUE;
  396                         found_once = TRUE;
  397                 }
  398         }
  399         return FALSE;
  400 }
  401 
  402 
  403 db_sym_t
  404 db_search_in_task_symbol(
  405         register db_addr_t      val,
  406         db_strategy_t           strategy,
  407         db_addr_t               *offp,
  408         task_t                  task);          /* forward */
  409 
  410 /*
  411  * Find the closest symbol to val, and return its name
  412  * and the difference between val and the symbol found.
  413  *
  414  * Logic change. If the task argument is non NULL and a
  415  * matching symbol is found in a symbol table which explictly
  416  * specifies its map to be task->map, that symbol will have 
  417  * precedence over any symbol from a symbol table will a null 
  418  * map. This allows overlapping kernel/user maps to work correctly.
  419  *
  420  */
  421 db_sym_t
  422 db_search_task_symbol(
  423         register db_addr_t      val,
  424         db_strategy_t           strategy,
  425         db_addr_t               *offp, /* better be unsigned */
  426         task_t                  task)
  427 {
  428   db_sym_t ret;
  429 
  430   if (task != TASK_NULL)
  431     ret = db_search_in_task_symbol(val, strategy, offp, task);
  432   else
  433     {
  434       ret = db_search_in_task_symbol(val, strategy, offp, task);
  435       /* 
  436         db_search_in_task_symbol will return success with 
  437         a very large offset when it should have failed. 
  438         */
  439       if (ret == DB_SYM_NULL || (*offp) > 0x1000000)
  440         {
  441           task = db_current_task();
  442           ret = db_search_in_task_symbol(val, strategy, offp, task);
  443         }
  444     }
  445 
  446   return ret;
  447 }
  448 
  449 db_sym_t
  450 db_search_in_task_symbol(
  451         register db_addr_t      val,
  452         db_strategy_t           strategy,
  453         db_addr_t               *offp,
  454         task_t                  task)
  455 {
  456   register vm_size_t diff;
  457   vm_size_t     newdiff;
  458   register int  i;
  459   db_symtab_t   *sp;
  460   db_sym_t      ret = DB_SYM_NULL, sym;
  461   vm_map_t      map_for_val;
  462 
  463   map_for_val = (task == TASK_NULL)? VM_MAP_NULL: task->map;
  464   newdiff = diff = ~0;
  465   db_last_symtab = (db_symtab_t *) 0;
  466   for (sp = &db_symtabs[0], i = 0; i < db_nsymtab;  sp++, i++) 
  467     {
  468       newdiff = ~0;
  469       if ((vm_map_t)sp->map_pointer == VM_MAP_NULL ||
  470           (vm_map_t)sp->map_pointer == map_for_val) 
  471         {
  472           sym = X_db_search_symbol(sp, val, strategy, (db_expr_t*)&newdiff);
  473           if (sym == DB_SYM_NULL)
  474             continue;
  475           if (db_last_symtab == (db_symtab_t *) 0)
  476             { /* first hit */
  477               db_last_symtab = sp;
  478               diff = newdiff;
  479               ret = sym;
  480               continue;
  481             }
  482           if ((vm_map_t) sp->map_pointer == VM_MAP_NULL && 
  483               (vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL &&
  484               newdiff < diff )
  485             { /* closer null map match */
  486               db_last_symtab = sp;
  487               diff = newdiff;
  488               ret = sym;
  489               continue;
  490             }               
  491           if ((vm_map_t) sp->map_pointer != VM_MAP_NULL && 
  492               (newdiff < 0x100000) &&
  493               ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL ||
  494                newdiff < diff ))
  495             {
  496                /*
  497                 * update if new is in matching map and symbol is "close", 
  498                 * and 
  499                 * old is VM_MAP_NULL or old in is matching map
  500                 * but is further away 
  501                 */
  502               db_last_symtab = sp;
  503               diff = newdiff;
  504               ret = sym;
  505               continue;
  506             }               
  507         }
  508     }
  509   
  510   *offp = diff;
  511   return ret;
  512 }
  513 
  514 /*
  515  * Return name and value of a symbol
  516  */
  517 void
  518 db_symbol_values(
  519         db_symtab_t     *stab,
  520         db_sym_t        sym,
  521         char            **namep,
  522         db_expr_t       *valuep)
  523 {
  524         db_expr_t       value;
  525         char            *name;
  526 
  527         if (sym == DB_SYM_NULL) {
  528                 *namep = 0;
  529                 return;
  530         }
  531         if (stab == 0)
  532                 stab = db_last_symtab;
  533 
  534         X_db_symbol_values(stab, sym, &name, &value);
  535 
  536         if (db_name_is_ambiguous(name))
  537                 *namep = db_qualify(name, db_last_symtab->name);
  538         else
  539                 *namep = name;
  540         if (valuep)
  541                 *valuep = value;
  542 }
  543 
  544 
  545 /*
  546  * Print the closest symbol to value
  547  *
  548  * After matching the symbol according to the given strategy
  549  * we print it in the name+offset format, provided the symbol's
  550  * value is close enough (eg smaller than db_maxoff).
  551  * We also attempt to print [filename:linenum] when applicable
  552  * (eg for procedure names).
  553  *
  554  * If we could not find a reasonable name+offset representation,
  555  * then we just print the value in hex.  Small values might get
  556  * bogus symbol associations, e.g. 3 might get some absolute
  557  * value like _INCLUDE_VERSION or something, therefore we do
  558  * not accept symbols whose value is zero (and use plain hex).
  559  */
  560 
  561 unsigned int    db_maxoff = 0x4000;
  562 
  563 void
  564 db_task_printsym(
  565         db_expr_t       off,
  566         db_strategy_t   strategy,
  567         task_t          task)
  568 {
  569         db_addr_t       d;
  570         char            *filename;
  571         char            *name;
  572         db_expr_t       value;
  573         int             linenum;
  574         db_sym_t        cursym;
  575 
  576         cursym = db_search_task_symbol(off, strategy, &d, task);
  577         db_symbol_values(0, cursym, &name, &value);
  578         if (name == 0 || d >= db_maxoff || value == 0) {
  579                 db_printf("%#n", off);
  580                 return;
  581         }
  582         db_printf("%s", name);
  583         if (d)
  584                 db_printf("+0x%x", d);
  585         if (strategy == DB_STGY_PROC) {
  586                 if (db_line_at_pc(cursym, &filename, &linenum, off)) {
  587                         db_printf(" [%s", filename);
  588                         if (linenum > 0)
  589                                 db_printf(":%d", linenum);
  590                         db_printf("]");
  591                 }
  592         }
  593 }
  594 
  595 void
  596 db_printsym(
  597         db_expr_t       off,
  598         db_strategy_t   strategy)
  599 {
  600         db_task_printsym(off, strategy, TASK_NULL);
  601 }
  602 
  603 boolean_t
  604 db_line_at_pc(
  605         db_sym_t        sym,
  606         char            **filename,
  607         int             *linenum,
  608         db_expr_t       pc)
  609 {
  610         return (db_last_symtab) ?
  611                 X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc) :
  612                 FALSE;
  613 }
  614 
  615 /*
  616  * Switch into symbol-table specific routines
  617  */
  618 
  619 #ifdef  DB_NO_AOUT
  620 #else
  621 extern boolean_t aout_db_sym_init(), aout_db_line_at_pc();
  622 extern db_sym_t aout_db_lookup(), aout_db_search_symbol();
  623 extern void aout_db_symbol_values();
  624 #endif  /* DB_NO_AOUT */
  625 
  626 #ifdef  DB_NO_COFF
  627 #else
  628 extern boolean_t coff_db_sym_init(), coff_db_line_at_pc();
  629 extern db_sym_t coff_db_lookup(), coff_db_search_symbol();
  630 extern void coff_db_symbol_values();
  631 #endif  /* DB_NO_COFF */
  632 
  633 struct db_sym_switch x_db[] = {
  634 
  635         /* BSD a.out format (really, sdb/dbx(1) symtabs) */
  636 #ifdef  DB_NO_AOUT
  637         { 0,},
  638 #else   /* DB_NO_AOUT */
  639         { aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
  640           aout_db_line_at_pc, aout_db_symbol_values },
  641 #endif  /* DB_NO_AOUT */
  642 
  643 #ifdef  DB_NO_COFF
  644         { 0,},
  645 #else   /* DB_NO_COFF */
  646         { coff_db_sym_init, coff_db_lookup, coff_db_search_symbol,
  647           coff_db_line_at_pc, coff_db_symbol_values },
  648 #endif  /* DB_NO_COFF */
  649 
  650         /* Machdep, not inited here */
  651         { 0,}
  652 
  653 };

Cache object: 36b09d773dedbb4ea967023f6751e058


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