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

Cache object: eec622eff3198f576c1fbbe44c45ee8d


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