FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_aout.c
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
|