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 /*      $NetBSD: db_aout.c,v 1.35 2003/05/17 00:28:44 kristerw Exp $    */
    2 
    3 /*
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: db_aout.c,v 1.35 2003/05/17 00:28:44 kristerw Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/proc.h>
   35 
   36 #include <machine/db_machdep.h>
   37 
   38 #include <ddb/db_sym.h>
   39 #include <ddb/db_output.h>
   40 #include <ddb/db_extern.h>
   41 
   42 #ifdef  DB_AOUT_SYMBOLS
   43 
   44 #include <ddb/db_aout.h>
   45 
   46 static boolean_t db_aout_sym_init(int, void *, void *, const char *);
   47 static db_sym_t db_aout_lookup(db_symtab_t *, char *);
   48 static db_sym_t db_aout_search_symbol(db_symtab_t *, db_addr_t, db_strategy_t,
   49                     db_expr_t *);
   50 static void     db_aout_symbol_values(db_symtab_t *, db_sym_t, char **,
   51                     db_expr_t *);
   52 static boolean_t db_aout_line_at_pc(db_symtab_t *, db_sym_t, char **, int *,
   53                     db_expr_t);
   54 static boolean_t db_aout_sym_numargs(db_symtab_t *, db_sym_t, int *, char **);
   55 static void     db_aout_forall(db_symtab_t *, db_forall_func_t db_forall_func,
   56                     void *);
   57 static int db_add_symbol_table(char *, char *, const char *, char *);
   58 
   59 /* Only one symbol table, please */
   60 static db_symtab_t db_symtabs;
   61 
   62 
   63 const db_symformat_t db_symformat_aout = {
   64         "a.out",
   65         db_aout_sym_init,
   66         db_aout_lookup,
   67         db_aout_search_symbol,
   68         db_aout_symbol_values,
   69         db_aout_line_at_pc,
   70         db_aout_sym_numargs,
   71         db_aout_forall
   72 };
   73 
   74 /*
   75  * An a.out symbol table as loaded into the kernel debugger:
   76  *
   77  * symtab       -> size of symbol entries, in bytes
   78  * sp           -> first symbol entry
   79  *                 ...
   80  * ep           -> last symbol entry + 1
   81  * strtab       == start of string table
   82  *                 size of string table in bytes,
   83  *                 including this word
   84  *              -> strings
   85  */
   86 
   87 /*
   88  * Find the symbol table and strings; tell ddb about them.
   89  */
   90 static boolean_t
   91 db_aout_sym_init(
   92         int symsize,            /* size of symbol table */
   93         void *vsymtab,          /* pointer to start of symbol table */
   94         void *vesymtab,         /* pointer to end of string table,
   95                                    for checking - rounded up to integer
   96                                    boundary */
   97         const char *name
   98 )
   99 {
  100         struct nlist    *sym_start, *sym_end;
  101         struct nlist    *sp;
  102         char *strtab;
  103         int slen, bad = 0;
  104         char *estrtab;
  105 
  106         if (ALIGNED_POINTER(vsymtab, long) == 0) {
  107                 printf("[ %s symbol table has bad start address %p ]\n",
  108                     name, vsymtab);
  109                 return (FALSE);
  110         }
  111 
  112         /*
  113          * Find pointers to the start and end of the symbol entries,
  114          * given a pointer to the start of the symbol table.
  115          */
  116         sym_start = (struct nlist *)vsymtab;
  117         sym_end   = (struct nlist *)((char *)sym_start + symsize);
  118 
  119         strtab = (char *)sym_end;
  120         if (ALIGNED_POINTER(strtab, int) == 0) {
  121                 printf("[ %s symbol table has bad string table address %p ]\n",
  122                     name, strtab);
  123                 return (FALSE);
  124         }
  125         slen = *(int *)strtab;
  126 
  127         estrtab = strtab + slen;
  128 
  129 #define round_to_size(x) \
  130         (((vaddr_t)(x) + sizeof(vsize_t) - 1) & ~(sizeof(vsize_t) - 1))
  131 
  132         if (round_to_size(estrtab) != round_to_size(vesymtab)) {
  133                 printf("[ %s a.out symbol table not valid ]\n", name);
  134                 return (FALSE);
  135         }
  136 #undef  round_to_size
  137 
  138         for (sp = sym_start; sp < sym_end; sp++) {
  139                 int strx;
  140                 strx = sp->n_un.n_strx;
  141                 if (strx != 0) {
  142                         if (strx > slen) {
  143                                 printf("[ %s has bad a.out string table "
  144                                     "index (0x%x) ]\n", name, strx);
  145                                 sp->n_un.n_name = 0;
  146                                 bad = 1;
  147                                 continue;
  148                         }
  149                         sp->n_un.n_name = strtab + strx;
  150                 }
  151         }
  152 
  153         if (bad)
  154                 return (FALSE);
  155 
  156         if (db_add_symbol_table((char *)sym_start, (char *)sym_end, name,
  157             NULL) !=  -1) {
  158                 printf("[ using %ld bytes of %s a.out symbol table ]\n",
  159                           (long)vesymtab - (long)vsymtab, name);
  160                 return (TRUE);
  161         }
  162 
  163         return (FALSE);
  164 }
  165 
  166 static db_sym_t
  167 db_aout_lookup(db_symtab_t *stab, char *symstr)
  168 {
  169         struct nlist *sp, *ep;
  170 
  171         stab = &db_symtabs;
  172 
  173         sp = (struct nlist *)stab->start;
  174         ep = (struct nlist *)stab->end;
  175 
  176         for (; sp < ep; sp++) {
  177                 if (sp->n_un.n_name == 0)
  178                         continue;
  179                 if ((sp->n_type & N_STAB) == 0 &&
  180                     sp->n_un.n_name != 0 &&
  181                     db_eqname(sp->n_un.n_name, symstr, '_'))
  182                         return ((db_sym_t)sp);
  183         }
  184         return ((db_sym_t)0);
  185 }
  186 
  187 static db_sym_t
  188 db_aout_search_symbol(db_symtab_t *symtab, db_addr_t off,
  189     db_strategy_t strategy, db_expr_t *diffp)
  190 {
  191         unsigned int    diff = *diffp;
  192         struct nlist    *symp = 0;
  193         struct nlist    *sp, *ep;
  194 
  195         symtab = &db_symtabs;
  196 
  197         sp = (struct nlist *)symtab->start;
  198         ep = (struct nlist *)symtab->end;
  199 
  200         for (; sp < ep; sp++) {
  201                 if (sp->n_un.n_name == 0)
  202                         continue;
  203                 if ((sp->n_type & N_STAB) != 0 || (sp->n_type & N_TYPE) == N_FN)
  204                         continue;
  205                 if (off >= sp->n_value) {
  206                         if (off - sp->n_value < diff) {
  207                                 diff = off - sp->n_value;
  208                                 symp = sp;
  209                                 if (diff == 0 &&
  210                                     ((strategy == DB_STGY_PROC &&
  211                                      sp->n_type == (N_TEXT|N_EXT)) ||
  212                                      (strategy == DB_STGY_ANY &&
  213                                      (sp->n_type & N_EXT))))
  214                                         break;
  215                         }
  216                         else if (off - sp->n_value == diff) {
  217                                 if (symp == 0)
  218                                         symp = sp;
  219                                 else if ((symp->n_type & N_EXT) == 0 &&
  220                                     (sp->n_type & N_EXT) != 0)
  221                                         /* pick the external symbol */
  222                                         symp = sp;
  223                         }
  224                 }
  225         }
  226         if (symp == 0)
  227                 *diffp = off;
  228         else
  229                 *diffp = diff;
  230         return ((db_sym_t)symp);
  231 }
  232 
  233 /*
  234  * Return the name and value for a symbol.
  235  */
  236 static void
  237 db_aout_symbol_values(db_symtab_t *symtab, db_sym_t sym, char **namep,
  238     db_expr_t *valuep)
  239 {
  240         struct nlist *sp;
  241 
  242         sp = (struct nlist *)sym;
  243         if (namep)
  244                 *namep = sp->n_un.n_name;
  245         if (valuep)
  246                 *valuep = sp->n_value;
  247 }
  248 
  249 
  250 static boolean_t
  251 db_aout_line_at_pc(db_symtab_t *symtab, db_sym_t cursym, char **filename,
  252     int *linenum, db_expr_t off)
  253 {
  254         struct nlist    *sp, *ep;
  255         unsigned long           sodiff = -1UL, lndiff = -1UL, ln = 0;
  256         char                    *fname = NULL;
  257 
  258         symtab = &db_symtabs;
  259 
  260         sp = (struct nlist *)symtab->start;
  261         ep = (struct nlist *)symtab->end;
  262 
  263 /* XXX - gcc specific */
  264 #define NEWSRC(str)     ((str) != NULL && \
  265                         (str)[0] == 'g' && strcmp((str), "gcc_compiled.") == 0)
  266 
  267         for (; sp < ep; sp++) {
  268 
  269                 /*
  270                  * Prevent bogus linenumbers in case module not compiled
  271                  * with debugging options
  272                  */
  273 #if 0
  274                 if (sp->n_value <= off && (off - sp->n_value) <= sodiff &&
  275                         NEWSRC(sp->n_un.n_name)) {
  276 #endif
  277                 if ((sp->n_type & N_TYPE) == N_FN || NEWSRC(sp->n_un.n_name)) {
  278                         sodiff = lndiff = -1UL;
  279                         ln = 0;
  280                         fname = NULL;
  281                 }
  282 
  283                 if (sp->n_type == N_SO) {
  284                         if (sp->n_value <= off && (off - sp->n_value) < sodiff) {
  285                                 sodiff = off - sp->n_value;
  286                                 fname = sp->n_un.n_name;
  287                         }
  288                         continue;
  289                 }
  290 
  291                 if (sp->n_type != N_SLINE)
  292                         continue;
  293 
  294                 if (sp->n_value > off)
  295                         break;
  296 
  297                 if (off - sp->n_value < lndiff) {
  298                         lndiff = off - sp->n_value;
  299                         ln = sp->n_desc;
  300                 }
  301         }
  302 
  303         if (fname != NULL && ln != 0) {
  304                 *filename = fname;
  305                 *linenum = ln;
  306                 return TRUE;
  307         }
  308 
  309         return (FALSE);
  310 }
  311 
  312 static boolean_t
  313 db_aout_sym_numargs(db_symtab_t *symtab, db_sym_t cursym, int *nargp,
  314     char **argnamep)
  315 {
  316         struct nlist            *sp, *ep;
  317         u_long                  addr;
  318         int                     maxnarg = *nargp, nargs = 0;
  319 
  320         if ((struct nlist *)cursym == NULL)
  321                 return FALSE;
  322 
  323         symtab = &db_symtabs;
  324 
  325         addr = ((struct nlist *)cursym)->n_value;
  326         sp = (struct nlist *)symtab->start;
  327         ep = (struct nlist *)symtab->end;
  328 
  329         for (; sp < ep; sp++) {
  330                 if (sp->n_type == N_FUN && sp->n_value == addr) {
  331                         while (++sp < ep && sp->n_type == N_PSYM) {
  332                                 if (nargs >= maxnarg)
  333                                         break;
  334                                 nargs++;
  335                                 *argnamep++ = sp->n_un.n_name ?
  336                                     sp->n_un.n_name : "???";
  337                                 {
  338                                 /* XXX - remove trailers */
  339                                 char *cp = *(argnamep-1);
  340                                 while (*cp != '\0' && *cp != ':') cp++;
  341                                 if (*cp == ':') *cp = '\0';
  342                                 }
  343                         }
  344                         *nargp = nargs;
  345                         return TRUE;
  346                 }
  347         }
  348         return FALSE;
  349 }
  350 
  351 static void
  352 db_aout_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg)
  353 {
  354         static char suffix[2];
  355         struct nlist *sp, *ep;
  356 
  357         stab = &db_symtabs;
  358 
  359         sp = (struct nlist *)stab->start;
  360         ep = (struct nlist *)stab->end;
  361 
  362         for (; sp < ep; sp++) {
  363                 if (sp->n_un.n_name == 0)
  364                         continue;
  365                 if ((sp->n_type & N_STAB) == 0 && sp->n_un.n_name != 0) {
  366                         suffix[1] = '\0';
  367                         switch(sp->n_type & N_TYPE) {
  368                         case N_ABS:
  369                                 suffix[0] = '@';
  370                                 break;
  371                         case N_TEXT:
  372                                 suffix[0] = '*';
  373                                 break;
  374                         case N_DATA:
  375                                 suffix[0] = '+';
  376                                 break;
  377                         case N_BSS:
  378                                 suffix[0] = '-';
  379                                 break;
  380                         case N_FN:
  381                                 suffix[0] = '/';
  382                                 break;
  383                         default:
  384                                 suffix[0] = '\0';
  385                         }
  386                         (*db_forall_func)(stab, (db_sym_t)sp, sp->n_un.n_name,
  387                             suffix, '_', arg);
  388                 }
  389         }
  390         return;
  391 }
  392 
  393 /*
  394  * Add symbol table, with given name, to symbol tables.
  395  */
  396 int
  397 db_add_symbol_table(char *start, char *end, const char *name, char *ref)
  398 {
  399 
  400         db_symtabs.start = start;
  401         db_symtabs.end = end;
  402         db_symtabs.name = name;
  403         db_symtabs.private = ref;
  404 
  405         return(0);
  406 }
  407 
  408 #endif  /* DB_AOUT_SYMBOLS */

Cache object: 60001d624006d63ab15f110ad87e171c


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