root/ddb/db_aout.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_aout_sym_init
  2. db_aout_lookup
  3. db_aout_search_symbol
  4. db_aout_symbol_values
  5. db_aout_line_at_pc
  6. db_aout_sym_numargs
  7. db_aout_forall

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

/* [<][>][^][v][top][bottom][index][help] */