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

Cache object: 225d6f2f2e175a07c662f1a05ac26f22


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