Register keyword removal
[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  * $DragonFly: src/sys/ddb/db_aout.c,v 1.3 2003/07/26 14:18:51 rob Exp $
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
65 static 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
74 static void
75 X_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         struct nlist    *sym_start, *sym_end;
83         struct nlist    *sp;
84         char    *       strtab;
85         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             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(stab, symstr)
126         db_symtab_t     *stab;
127         const char *    symstr;
128 {
129         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
147 c_db_sym_t
148 X_db_search_symbol(symtab, off, strategy, diffp)
149         db_symtab_t *   symtab;
150         
151         db_addr_t       off;
152         db_strategy_t   strategy;
153         db_expr_t       *diffp;         /* in/out */
154 {
155         unsigned int    diff = *diffp;
156         struct nlist    *symp = 0;
157         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  */
201 void
202 X_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         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
218 boolean_t
219 X_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         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
284 boolean_t
285 X_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         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  */
326 void
327 kdb_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
346 read_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