Annotation of sys/ddb/db_aout.c, Revision 1.1
1.1 ! nbrk 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 */
CVSweb