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_aout.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_aout.c,v $
   29  * Revision 2.16  93/11/17  16:19:36  dbg
   30  *      ANSI-fied.
   31  *      [93/10/13            dbg]
   32  * 
   33  * Revision 2.15  93/03/09  10:53:19  danner
   34  *      Make searching slightly less confusing if the symtab has not
   35  *      been xstripped.
   36  *      [93/03/05            af]
   37  * 
   38  * Revision 2.14  93/02/01  09:55:09  danner
   39  *      aout_db_search_by_addr returns boolean_t.
   40  *      [93/01/25            jfriedl]
   41  * 
   42  * Revision 2.13  93/01/14  17:24:24  danner
   43  *      Support for coexhistance of multiple symbol table types.
   44  *      64bit cleanup.
   45  *      [92/11/30            af]
   46  * 
   47  * Revision 2.12  92/08/03  17:30:27  jfriedl
   48  *      removed silly prototypes
   49  *      [92/08/02            jfriedl]
   50  * 
   51  * Revision 2.11  92/05/21  17:06:15  jfriedl
   52  *      Added init for func_diff and line_diff in X_db_search_by_addr().
   53  *      Also added proper declaration for that function.
   54  *      [92/05/16            jfriedl]
   55  * 
   56  * Revision 2.10  92/01/03  20:02:21  dbg
   57  *      Don't print 'preserving symbols' if loading symbol table fails.
   58  *      [91/11/29            dbg]
   59  * 
   60  *      Use kern_sym_start, kern_sym_size to locate kernel symbol table.
   61  *      Rename routine to ddb_init.
   62  *      [91/10/30            dbg]
   63  * 
   64  * Revision 2.9  91/10/09  15:57:16  af
   65  *      Supported address lookup with line number.
   66  *      Changed X_db_line_at_pc to get file name without compiled
   67  *        with -g option.
   68  *      Included "stab.h" for symbol type definitions.
   69  *      [91/08/29            tak]
   70  * 
   71  * Revision 2.8  91/08/28  11:10:58  jsb
   72  *      Added line number support, via X_db_line_at_pc.
   73  *      [91/08/13  18:12:37  jsb]
   74  * 
   75  * Revision 2.7  91/07/31  17:29:43  dbg
   76  *      Removed read_symtab_from_file.
   77  *      Added task argument to X_db_sym_init.
   78  *      [91/07/30  16:42:51  dbg]
   79  * 
   80  * Revision 2.6  91/07/09  23:15:35  danner
   81  *      On luna, kdb_init needs to be called ddb_init. Add ifndef
   82  *       DB_SYMBOLS_PRELOADED for machines that use a.out format but
   83  *       whose prom loaders load generously load the symbol table.
   84  *      [91/07/08            danner]
   85  * 
   86  * Revision 2.5  91/05/14  15:32:00  mrt
   87  *      Correcting copyright
   88  * 
   89  * Revision 2.4  91/03/16  14:42:23  rpd
   90  *      Updated for new kmem_alloc interface.
   91  *      [91/03/03            rpd]
   92  * 
   93  * Revision 2.3  91/02/05  17:05:55  mrt
   94  *      Changed to new Mach copyright
   95  *      [91/01/31  16:16:44  mrt]
   96  * 
   97  * Revision 2.2  90/08/27  21:48:35  dbg
   98  *      Created.
   99  *      [90/08/17            dbg]
  100  * 
  101  */
  102 /*
  103  *      Author: David B. Golub, Carnegie Mellon University
  104  *      Date:   7/90
  105  */
  106 /*
  107  * Symbol table routines for a.out format files.
  108  */
  109 
  110 #include <mach/std_types.h>
  111 #include <machine/db_machdep.h>         /* data types */
  112 #include <ddb/db_sym.h>
  113 #include <ddb/db_output.h>
  114 
  115 #ifndef DB_NO_AOUT
  116 
  117 #include <ddb/nlist.h>                  /* a.out symbol table */
  118 #include <ddb/stab.h>
  119 
  120 #define private static
  121 
  122 /*
  123  * An a.out symbol table as loaded into the kernel debugger:
  124  *
  125  * symtab       -> size of symbol entries, in bytes
  126  * sp           -> first symbol entry
  127  *                 ...
  128  * ep           -> last symbol entry + 1
  129  * strtab       == start of string table
  130  *                 size of string table in bytes,
  131  *                 including this word
  132  *              -> strings
  133  */
  134 
  135 /*
  136  * Find pointers to the start and end of the symbol entries,
  137  * given a pointer to the start of the symbol table.
  138  */
  139 #define db_get_aout_symtab(symtab, sp, ep) \
  140         (sp = (struct nlist *)((vm_offset_t *)(symtab) + 1), \
  141          ep = (struct nlist *)((char *)sp + *((int*)symtab)))
  142 
  143 boolean_t
  144 aout_db_sym_init(
  145         char *  symtab,         /* pointer to start of symbol table */
  146         char *  esymtab,        /* pointer to end of string table,
  147                                    for checking - may be rounded up to
  148                                    integer boundary */
  149         char *  name,
  150         char *  task_addr)      /* use for this task only */
  151 {
  152         register struct nlist   *sym_start, *sym_end;
  153         register struct nlist   *sp;
  154         register char * strtab;
  155         register int    strlen;
  156         char *          estrtab;
  157 
  158         db_get_aout_symtab(symtab, sym_start, sym_end);
  159 
  160         strtab = (char *)sym_end;
  161         strlen = *(int *)strtab;
  162         estrtab = strtab + strlen;
  163 
  164 #define round_to_size(x) \
  165         (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1))
  166 
  167         if (round_to_size(estrtab) != round_to_size(esymtab)) {
  168             db_printf("[ %s symbol table not valid ]\n", name);
  169             return FALSE;
  170         }
  171 
  172 #undef  round_to_size
  173 
  174         for (sp = sym_start; sp < sym_end; sp++) {
  175             register long strx;
  176             strx = sp->n_un.n_strx;
  177             if (strx != 0) {
  178                 if (strx > strlen) {
  179                     db_printf("Bad string table index (%#x)\n", strx);
  180                     sp->n_un.n_name = 0;
  181                     continue;
  182                 }
  183                 sp->n_un.n_name = strtab + strx;
  184             }
  185         }
  186 
  187         if (db_add_symbol_table(SYMTAB_AOUT,
  188                                 (char *)sym_start,
  189                                 (char *)sym_end,
  190                                 name,
  191                                 symtab,
  192                                 task_addr))
  193         {
  194             /* Successfully added symbol table */
  195             db_printf("[ preserving %d bytes of %s symbol table ]\n",
  196                 esymtab - (char *)symtab, name);
  197             return TRUE;
  198         }
  199         else
  200             return FALSE;
  201 }
  202 
  203 /*
  204  * check file name or not (check xxxx.x pattern)
  205  */
  206 private boolean_t
  207 aout_db_is_filename(
  208         register char *name)
  209 {
  210         while (*name) {
  211             if (*name == '.') {
  212                 if (name[1])
  213                     return TRUE;
  214             }
  215             name++;
  216         }
  217         return FALSE;
  218 }
  219 
  220 /*
  221  * special name comparison routine with a name in the symbol table entry
  222  */
  223 private boolean_t
  224 aout_db_eq_name(
  225         struct nlist *sp,
  226         char *name)
  227 {
  228         register char *s1, *s2;
  229 
  230         s1 = sp->n_un.n_name;
  231         s2 = name;
  232         if (*s1 == '_' && *s2 && *s2 != '_')
  233             s1++;
  234         while (*s2) {
  235             if (*s1++ != *s2++) {
  236                 /*
  237                  * check .c .o file name comparison case
  238                  */
  239                 if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 
  240                         && s1[-2] == '.' && s1[-1] == 'o')
  241                     return TRUE;
  242                 return FALSE;
  243             }
  244         }
  245         /*
  246          * do special check for
  247          *     xxx:yyy for N_FUN
  248          *     xxx.ttt for N_DATA and N_BSS
  249          */
  250         return (*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || 
  251                 (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS)));
  252 }
  253 
  254 /*
  255  * search a symbol table with name and type
  256  *      fp(in,out): last found text file name symbol entry
  257  */
  258 private struct nlist *
  259 aout_db_search_name(
  260         register struct nlist *sp,
  261         struct nlist    *ep,
  262         char            *name,
  263         int             type,
  264         struct nlist    **fp)
  265 {
  266         struct nlist    *file_sp = *fp;
  267         struct nlist    *found_sp = 0;
  268 
  269         for ( ; sp < ep; sp++) {
  270             if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name))
  271                 *fp = sp;
  272             if (type) {
  273                 if (sp->n_type == type) {
  274                     if (aout_db_eq_name(sp, name))
  275                         return sp;
  276                 }
  277                 if (sp->n_type == N_SO)
  278                     *fp = sp;
  279                 continue;
  280             }
  281             if (sp->n_type & N_STAB)
  282                 continue;
  283             if (sp->n_un.n_name && aout_db_eq_name(sp, name)) {
  284                 /*
  285                  * In case of qaulified search by a file,
  286                  * return it immediately with some check.
  287                  * Otherwise, search external one
  288                  */
  289                 if (file_sp) {
  290                     if ((file_sp == *fp) || (sp->n_type & N_EXT))
  291                         return sp;
  292                 } else if (sp->n_type & N_EXT)
  293                     return sp;
  294                 else
  295                     found_sp = sp;
  296             }
  297         }
  298         return found_sp;
  299 }
  300 
  301 /*
  302  * search a symbol with file, func and line qualification
  303  */
  304 private db_sym_t
  305 aout_db_qualified_search(
  306         db_symtab_t     *stab,
  307         char            *file,
  308         char            *sym,
  309         int             line)
  310 {
  311         register struct nlist *sp = (struct nlist *)stab->start;
  312         struct nlist    *ep = (struct nlist *)stab->end;
  313         struct nlist    *fp = 0;
  314         struct nlist    *found_sp;
  315         unsigned long   func_top;
  316         boolean_t       in_file;
  317 
  318         if (file == 0 && sym == 0)
  319             return 0;
  320         if (file) {
  321             if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp)) == 0)
  322                 return 0;
  323         }
  324         if (sym) {
  325             sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp);
  326             if (sp == 0)
  327                 return 0;
  328         }
  329         if (line > 0) {
  330             if (file && !aout_db_eq_name(fp, file))
  331                 return 0;
  332             found_sp = 0;
  333             if (sp->n_type == N_FUN) {
  334                 /*
  335                  * qualified by function name
  336                  *     search backward because line number entries
  337                  *     for the function are above it in this case.
  338                  */
  339                 func_top = sp->n_value;
  340                 for (sp--; sp >= (struct nlist *)stab->start; sp--) {
  341                     if (sp->n_type != N_SLINE)
  342                         continue;
  343                     if (sp->n_value < func_top)
  344                         break;
  345                     if (sp->n_desc <= line) {
  346                         if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
  347                             found_sp = sp;
  348                         if (sp->n_desc == line)
  349                             break;
  350                     }
  351                 }
  352                 if (sp->n_type != N_SLINE || sp->n_value < func_top)
  353                     return 0;
  354             } else {
  355                 /*
  356                  * qualified by only file name
  357                  *    search forward in this case
  358                  */
  359                 in_file = TRUE;
  360                 for (sp++; sp < ep; sp++) {
  361                     if (sp->n_type == N_TEXT 
  362                         && aout_db_is_filename(sp->n_un.n_name))
  363                         break;          /* enter into another file */
  364                     if (sp->n_type == N_SOL) {
  365                         in_file = aout_db_eq_name(sp, file);
  366                         continue;
  367                     }
  368                     if (!in_file || sp->n_type != N_SLINE)
  369                         continue;
  370                     if (sp->n_desc <= line) {
  371                         if (found_sp == 0 || found_sp->n_desc < sp->n_desc)
  372                             found_sp = sp;
  373                         if (sp->n_desc == line)
  374                             break;
  375                     }
  376                 }
  377             }
  378             sp = found_sp;
  379         }
  380         return (db_sym_t) sp;
  381 }
  382 
  383 /*
  384  * lookup symbol by name
  385  */
  386 db_sym_t
  387 aout_db_lookup(
  388         db_symtab_t     *stab,
  389         char *          symstr)
  390 {
  391         return db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr);
  392 }
  393 
  394 db_sym_t
  395 aout_db_search_symbol(
  396         db_symtab_t *   symtab,
  397         register
  398         db_addr_t       off,
  399         db_strategy_t   strategy,
  400         db_expr_t       *diffp)         /* in/out */
  401 {
  402         register unsigned long  diff = *diffp;
  403         register struct nlist   *symp = 0;
  404         register struct nlist   *sp, *ep;
  405 
  406         sp = (struct nlist *)symtab->start;
  407         ep = (struct nlist *)symtab->end;
  408 
  409         for (; sp < ep; sp++) {
  410             if (sp->n_un.n_name == 0)
  411                 continue;
  412             if ((sp->n_type & N_STAB) != 0)
  413                 continue;
  414             if (strategy == DB_STGY_XTRN && (sp->n_type & N_EXT) == 0)
  415                 continue;
  416             if (off >= sp->n_value) {
  417 
  418                 unsigned int type = sp->n_type;
  419 
  420                 if (type == N_FN) continue;
  421                 if (off - sp->n_value < diff) {
  422                     diff = off - sp->n_value;
  423                     symp = sp;
  424                     if (diff == 0 && (type & N_EXT))
  425                         break;
  426                 }
  427                 else if (off - sp->n_value == diff) {
  428                     if (symp == 0)
  429                         symp = sp;
  430                     else if ((symp->n_type & N_EXT) == 0 &&
  431                                 (type & N_EXT) != 0)
  432                         symp = sp;      /* pick the external symbol */
  433                 }
  434             }
  435         }
  436         if (symp == 0) {
  437             *diffp = off;
  438         }
  439         else {
  440             *diffp = diff;
  441         }
  442         return (db_sym_t)symp;
  443 }
  444 
  445 /*
  446  * Return the name and value for a symbol.
  447  */
  448 void
  449 aout_db_symbol_values(
  450         db_sym_t        sym,
  451         char            **namep,
  452         db_expr_t       *valuep)
  453 {
  454         register struct nlist *sp;
  455 
  456         sp = (struct nlist *)sym;
  457         if (namep)
  458             *namep = sp->n_un.n_name;
  459         if (valuep)
  460             *valuep = sp->n_value;
  461 }
  462 
  463 #define X_DB_MAX_DIFF   8       /* maximum allowable diff at the end of line */
  464 
  465 /*
  466  * search symbol by value
  467  */
  468 private boolean_t
  469 aout_db_search_by_addr(
  470         db_symtab_t     *stab,
  471         register        vm_offset_t addr,
  472         char            **file,
  473         char            **func,
  474         int             *line,
  475         unsigned long   *diff)
  476 {
  477         register        struct nlist *sp;
  478         register        struct nlist *line_sp, *func_sp, *file_sp, *line_func;
  479         register vm_size_t func_diff, line_diff;
  480         boolean_t       found_line = FALSE;
  481         struct          nlist *ep = (struct nlist *)stab->end;
  482 
  483         line_sp = func_sp = file_sp = line_func = 0;
  484         *file = *func = 0;
  485         *line = 0;
  486         func_diff = line_diff = ~0;
  487         for (sp = (struct nlist *)stab->start; sp < ep; sp++) {
  488             switch(sp->n_type) {
  489             case N_SLINE:
  490                 if (sp->n_value <= addr) {
  491                     if (line_sp == 0 || line_diff >= addr - sp->n_value) {
  492                         if (line_func)
  493                             line_func = 0;
  494                         line_sp = sp;
  495                         line_diff = addr - sp->n_value;
  496                     }
  497                 }
  498                 if (sp->n_value >= addr && line_sp)
  499                     found_line = TRUE;
  500                 continue;
  501             case N_FUN:
  502                 if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF))
  503                     && line_func == 0)
  504                     line_func = sp;
  505                 continue;
  506             case N_SO:
  507                 if (sp->n_value > addr)
  508                     continue;
  509                 if (file_sp == 0 || file_sp->n_value <= sp->n_value)
  510                     file_sp = sp;
  511                 continue;
  512             case N_TEXT:
  513                 if (aout_db_is_filename(sp->n_un.n_name)) {
  514                     if (sp->n_value > addr)
  515                         continue;
  516                     if (file_sp == 0 || file_sp->n_value <= sp->n_value)
  517                         file_sp = sp;
  518                 } else if (sp->n_value <= addr &&
  519                          (func_sp == 0 || func_diff > addr - sp->n_value)) {
  520                     func_sp = sp;
  521                     func_diff = addr - sp->n_value;
  522                 }
  523                 continue;
  524             case N_TEXT|N_EXT:
  525                 if (sp->n_value <= addr &&
  526                          (func_sp == 0 || func_diff >= addr - sp->n_value)) {
  527                     func_sp = sp;
  528                     func_diff = addr - sp->n_value;
  529                     if (func_diff == 0 && file_sp && func_sp)
  530                         break;
  531                 }
  532             default:
  533                 continue;
  534             }
  535             break;
  536         }
  537         if (line_sp) {
  538             if (line_func == 0 || func_sp == 0
  539                 || line_func->n_value != func_sp->n_value)
  540                 line_sp = 0;
  541         }
  542         if (file_sp) {
  543             *diff = addr - file_sp->n_value;
  544             *file = file_sp->n_un.n_name;
  545         }
  546         if (func_sp) {
  547             *diff = addr - func_sp->n_value;
  548             *func = (func_sp->n_un.n_name[0] == '_')?
  549                         func_sp->n_un.n_name + 1: func_sp->n_un.n_name;
  550         }
  551         if (line_sp) {
  552             *diff = addr - line_sp->n_value;
  553             *line = line_sp->n_desc;
  554         }
  555         return (file_sp || func_sp || line_sp);
  556 }
  557 
  558 /*
  559  * Find filename and lineno within, given the current pc.
  560  */
  561 boolean_t
  562 aout_db_line_at_pc(
  563         db_symtab_t     *stab,
  564         db_sym_t        sym,
  565         char            **file,
  566         int             *line,
  567         db_expr_t       pc)
  568 {
  569         char            *func;
  570         unsigned long   diff;
  571         boolean_t       found;
  572 
  573         found = aout_db_search_by_addr(stab,
  574                                        (vm_offset_t)pc,
  575                                        file,
  576                                        &func,
  577                                        line,
  578                                        &diff);
  579         return (found && func && *file);
  580 }
  581 
  582 /*
  583  * Initialization routine for a.out files.
  584  */
  585 void
  586 ddb_init(void)
  587 {
  588         extern vm_offset_t      kern_sym_start;
  589         extern vm_size_t        kern_sym_size;
  590 
  591         if (kern_sym_size != 0) {
  592             aout_db_sym_init((char *) kern_sym_start,
  593                           (char *)(kern_sym_start + kern_sym_size),
  594                           "mach",
  595                           (char *)0);
  596         }
  597 }
  598 
  599 #endif  /* DB_NO_AOUT */

Cache object: 782c4e8b7a2006cdda7cf8fe2535f424


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