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