ioapic_abi: More consistent function name w/ legacy interrupt
[dragonfly.git] / 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.27 1999/08/28 00:41:05 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 #if !defined(__ELF__)
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41
42 #include <machine/bootinfo.h>
43
44 #include <ddb/ddb.h>
45 #include <ddb/db_sym.h>
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 (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 /*
74  * Parameters:
75  *     symtab:  pointer to start of symbol table
76  *     esymtab: pointer to end of string table, for checking - rounded up to
77  *              integer boundary
78  */
79 static void
80 X_db_sym_init(int *symtab, char *esymtab, char *name)
81 {
82         struct nlist    *sym_start, *sym_end;
83         struct nlist    *sp;
84         char    *       strtab;
85         int     strlen;
86
87         if (*symtab < 4) {
88                 kprintf ("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             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
124 c_db_sym_t
125 X_db_lookup(db_symtab_t *stab, const char *symstr)
126 {
127         struct nlist *sp, *ep;
128
129         sp = (struct nlist *)stab->start;
130         ep = (struct nlist *)stab->end;
131
132         for (; sp < ep; sp++) {
133             if (sp->n_un.n_name == 0)
134                 continue;
135             if ((sp->n_type & N_STAB) == 0 &&
136                 sp->n_un.n_name != 0 &&
137                 db_eqname(sp->n_un.n_name, symstr, '_'))
138             {
139                 return ((db_sym_t)sp);
140             }
141         }
142         return ((db_sym_t)0);
143 }
144
145 /*
146  * Parameters:
147  *     diffp:   in/out
148  */
149 c_db_sym_t
150 X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strategy,
151                    db_expr_t *diffp)
152 {
153         unsigned int    diff = *diffp;
154         struct nlist    *symp = NULL;
155         struct nlist    *sp, *ep;
156
157         sp = (struct nlist *)symtab->start;
158         ep = (struct nlist *)symtab->end;
159
160         for (; sp < ep; sp++) {
161             if (sp->n_un.n_name == 0)
162                 continue;
163             if ((sp->n_type & N_STAB) != 0 || (sp->n_type & N_TYPE) == N_FN)
164                 continue;
165             if (off >= sp->n_value) {
166                 if (off - sp->n_value < diff) {
167                     diff = off - sp->n_value;
168                     symp = sp;
169                     if (diff == 0) {
170                         if (strategy == DB_STGY_PROC &&
171                                         sp->n_type == (N_TEXT|N_EXT))
172                             break;
173                         if (strategy == DB_STGY_ANY &&
174                                         (sp->n_type & N_EXT))
175                             break;
176                     }
177                 }
178                 else if (off - sp->n_value == diff) {
179                     if (symp == NULL)
180                         symp = sp;
181                     else if ((symp->n_type & N_EXT) == 0 &&
182                                 (sp->n_type & N_EXT) != 0)
183                         symp = sp;      /* pick the external symbol */
184                 }
185             }
186         }
187         if (symp == NULL) {
188             *diffp = off;
189         }
190         else {
191             *diffp = diff;
192         }
193         return ((db_sym_t)symp);
194 }
195
196 /*
197  * Return the name and value for a symbol.
198  */
199 void
200 X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep,
201                    db_expr_t *valuep)
202 {
203         const struct nlist *sp;
204
205         sp = (const struct nlist *)sym;
206         if (namep)
207             *namep = sp->n_un.n_name;
208         if (valuep)
209             *valuep = sp->n_value;
210 }
211
212
213 boolean_t
214 X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t cursym, char **filename,
215                 int *linenum, db_expr_t off)
216 {
217         struct nlist    *sp, *ep;
218         unsigned long           sodiff = -1UL, lndiff = -1UL, ln = 0;
219         char                    *fname = NULL;
220
221         sp = (struct nlist *)symtab->start;
222         ep = (struct nlist *)symtab->end;
223
224 /*
225  * XXX - this used to remove "gcc_compiled.", but that is obsolete.  We
226  * now remove unwanted names using symorder.
227  */
228 #define NEWSRC(str)     0
229
230         for (; sp < ep; sp++) {
231
232             /*
233              * Prevent bogus linenumbers in case module not compiled
234              * with debugging options
235              */
236 #if 0
237             if (sp->n_value <= off && (off - sp->n_value) <= sodiff &&
238                 NEWSRC(sp->n_un.n_name)) {
239 #endif
240             if ((sp->n_type & N_TYPE) == N_FN || NEWSRC(sp->n_un.n_name)) {
241                 sodiff = lndiff = -1UL;
242                 ln = 0;
243                 fname = NULL;
244             }
245
246             if (sp->n_type == N_SO && *sp->n_un.n_name != '/') {
247                 if (sp->n_value <= off && (off - sp->n_value) < sodiff) {
248                         sodiff = off - sp->n_value;
249                         fname = sp->n_un.n_name;
250                 }
251                 continue;
252             }
253
254             if (sp->n_type != N_SLINE)
255                 continue;
256
257             if (sp->n_value > off)
258                 break;
259
260             if (off - sp->n_value < lndiff) {
261                 lndiff = off - sp->n_value;
262                 ln = sp->n_desc;
263             }
264         }
265
266         if (fname != NULL && ln != 0) {
267                 *filename = fname;
268                 *linenum = ln;
269                 return TRUE;
270         }
271
272         return (FALSE);
273 }
274
275 boolean_t
276 X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t cursym, int *nargp,
277                  char **argnamep)
278 {
279         struct nlist    *sp, *ep;
280         u_long                  addr;
281         int                     maxnarg = *nargp, nargs = 0;
282
283         if (cursym == NULL)
284                 return FALSE;
285
286         addr = ((const struct nlist *)cursym)->n_value;
287         sp = (struct nlist *)symtab->start;
288         ep = (struct nlist *)symtab->end;
289
290         for (; sp < ep; sp++) {
291             if (sp->n_type == N_FUN && sp->n_value == addr) {
292                 while (++sp < ep && sp->n_type == N_PSYM) {
293                         if (nargs >= maxnarg)
294                                 break;
295                         nargs++;
296                         *argnamep++ = sp->n_un.n_name?sp->n_un.n_name:"???";
297                         {
298                         /* XXX - remove trailers */
299                         char *cp = *(argnamep-1);
300                         while (*cp != '\0' && *cp != ':') cp++;
301                         if (*cp == ':') *cp = '\0';
302                         }
303                 }
304                 *nargp = nargs;
305                 return TRUE;
306             }
307         }
308         return FALSE;
309 }
310
311 /*
312  * Initialization routine for a.out files.
313  */
314 void
315 kdb_init(void)
316 {
317 #ifdef __i386__
318         if (bootinfo.bi_esymtab != bootinfo.bi_symtab)
319                 X_db_sym_init((int *)bootinfo.bi_symtab,
320                               (char *)((bootinfo.bi_esymtab + sizeof(int) - 1)
321                                        & ~(sizeof(int) - 1)),
322                               "kernel");
323 #endif
324 }
325
326 #if 0
327 /*
328  * Read symbol table from file.
329  * (should be somewhere else)
330  */
331 #include <boot_ufs/file_io.h>
332 #include <vm/vm_kern.h>
333
334 read_symtab_from_file(struct file *fp, char *symtab_name)
335 {
336         vm_size_t       resid;
337         kern_return_t   result;
338         vm_offset_t     symoff;
339         vm_size_t       symsize;
340         vm_offset_t     stroff;
341         vm_size_t       strsize;
342         vm_size_t       table_size;
343         vm_offset_t     symtab;
344
345         if (!get_symtab(fp, &symoff, &symsize)) {
346             boot_printf("[ error %d reading %s file header ]\n",
347                         result, symtab_name);
348             return;
349         }
350
351         stroff = symoff + symsize;
352         result = read_file(fp, (vm_offset_t)stroff,
353                         (vm_offset_t)&strsize, sizeof(strsize), &resid);
354         if (result || resid) {
355             boot_printf("[ no valid symbol table present for %s ]\n",
356                 symtab_name);
357                 return;
358         }
359
360         table_size = sizeof(int) + symsize + strsize;
361         table_size = (table_size + sizeof(int)-1) & ~(sizeof(int)-1);
362
363         symtab = kmem_alloc_wired(&kernel_map, table_size);
364
365         *(int *)symtab = symsize;
366
367         result = read_file(fp, symoff,
368                         symtab + sizeof(int), symsize, &resid);
369         if (result || resid) {
370             boot_printf("[ error %d reading %s symbol table ]\n",
371                         result, symtab_name);
372             return;
373         }
374
375         result = read_file(fp, stroff,
376                         symtab + sizeof(int) + symsize, strsize, &resid);
377         if (result || resid) {
378             boot_printf("[ error %d reading %s string table ]\n",
379                         result, symtab_name);
380             return;
381         }
382
383         X_db_sym_init((int *)symtab,
384                         (char *)(symtab + table_size),
385                         symtab_name);
386
387 }
388 #endif
389 #endif