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