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