freebsd-dev/sys/ddb/db_aout.c
Bruce Evans b5d89ca8ad Load the kernel symbol table in the boot loader and not at compile time.
(Boot with the -D flag if you want symbols.)

Make it easier to extend `struct bootinfo' without losing either forwards
or backwards compatibility.

ddb_aout.c:
Get the symbol table from wherever the loader put it.
Nuke db_symtab[SYMTAB_SPACE].

boot.c:
Enable loading of symbols.  Align them on a page boundary.  Add printfs
about the symbol table sizes.
Pass the memory sizes to the kernel.
Fix initialization of `unit' (it got moved out of the loop).
Fix adding the bss size (it got moved inside an ifdef).
Initialize serial port when RB_SERIAL is toggled on.
Fix comments.
Clean up formatting of recently added code.

io.c:
Clean up formatting of recently added code.

netboot/main.c, machdep.c, wd.c:
Change names of bootinfo fields.

LINT:
Nuke SYMTAB_SPACE.
Fix comment about DODUMP.

Makefile.i386:
Nuke use of dbsym.
Exclude gcc symbols from kernel unless compiling with -g.
Remove unused macro.
Fix comments and formatting.

genassym.c:
Generate defines for some new bootinfo fields.  Change names of old ones.

locore.s:
Copy only the valid part of the `struct bootinfo' passed by the loader.
Reserve space for symbol table, if any.

machdep.c:
Check the memory sizes passed by the loader, if any.  Don't use them yet.

bootinfo.h:
Add a size field so that we can resolve some mismatches between the loader
bootinfo and the kernel boot info.  The version number is not so good for
this because of historical botches and because it's harder to maintain.
Add memory size and symbol table fields.  Change the names of everything.

Hacks to save a few bytes:

asm.S, boot.c, boot2.S:
Replace `ouraddr' by `(BOOTSEG << 4)'.

boot.c:
Don't statically initialize `loadflags' to 0.  Disable the "REDUNDANT"
code that skips the BIOS variables.  Eliminate `total'.  Combine some
more printfs.

boot.h, disk.c, io.c, table.c:
Move all statically initialzed data to table.c.

io.c:
Don't put the A20 gate bits in a variable.
1995-01-25 21:40:47 +00:00

400 lines
8.7 KiB
C

/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* $Id: db_aout.c,v 1.9 1994/09/27 03:34:52 phk Exp $
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Symbol table routines for a.out format files.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <machine/bootinfo.h>
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
#ifndef DB_NO_AOUT
#define _AOUT_INCLUDE_
#include <nlist.h>
#include <stab.h>
/*
* An a.out symbol table as loaded into the kernel debugger:
*
* symtab -> size of symbol entries, in bytes
* sp -> first symbol entry
* ...
* ep -> last symbol entry + 1
* strtab == start of string table
* size of string table in bytes,
* including this word
* -> strings
*/
/*
* Find pointers to the start and end of the symbol entries,
* given a pointer to the start of the symbol table.
*/
#define db_get_aout_symtab(symtab, sp, ep) \
(sp = (struct nlist *)((symtab) + 1), \
ep = (struct nlist *)((char *)sp + *(symtab)))
void
X_db_sym_init(symtab, esymtab, name)
int * symtab; /* pointer to start of symbol table */
char * esymtab; /* pointer to end of string table,
for checking - rounded up to integer
boundary */
char * name;
{
register struct nlist *sym_start, *sym_end;
register struct nlist *sp;
register char * strtab;
register int strlen;
if (*symtab < 4) {
printf ("DDB: no symbols\n");
return;
}
db_get_aout_symtab(symtab, sym_start, sym_end);
strtab = (char *)sym_end;
strlen = *(int *)strtab;
if (strtab + ((strlen + sizeof(int) - 1) & ~(sizeof(int)-1))
!= esymtab)
{
db_printf("[ %s symbol table not valid ]\n", name);
return;
}
db_printf("[ preserving %#x bytes of %s symbol table ]\n",
esymtab - (char *)symtab, name);
for (sp = sym_start; sp < sym_end; sp++) {
register int strx;
strx = sp->n_un.n_strx;
if (strx != 0) {
if (strx > strlen) {
db_printf("Bad string table index (%#x)\n", strx);
sp->n_un.n_name = 0;
continue;
}
sp->n_un.n_name = strtab + strx;
}
}
db_add_symbol_table(sym_start, sym_end, name, (char *)symtab);
}
db_sym_t
X_db_lookup(stab, symstr)
db_symtab_t *stab;
char * symstr;
{
register struct nlist *sp, *ep;
sp = (struct nlist *)stab->start;
ep = (struct nlist *)stab->end;
for (; sp < ep; sp++) {
if (sp->n_un.n_name == 0)
continue;
if ((sp->n_type & N_STAB) == 0 &&
sp->n_un.n_name != 0 &&
db_eqname(sp->n_un.n_name, symstr, '_'))
{
return ((db_sym_t)sp);
}
}
return ((db_sym_t)0);
}
db_sym_t
X_db_search_symbol(symtab, off, strategy, diffp)
db_symtab_t * symtab;
register
db_addr_t off;
db_strategy_t strategy;
db_expr_t *diffp; /* in/out */
{
register unsigned int diff = *diffp;
register struct nlist *symp = 0;
register struct nlist *sp, *ep;
sp = (struct nlist *)symtab->start;
ep = (struct nlist *)symtab->end;
for (; sp < ep; sp++) {
if (sp->n_un.n_name == 0)
continue;
if ((sp->n_type & N_STAB) != 0 || (sp->n_type & N_TYPE) == N_FN)
continue;
if (off >= sp->n_value) {
if (off - sp->n_value < diff) {
diff = off - sp->n_value;
symp = sp;
if (diff == 0) {
if (strategy == DB_STGY_PROC &&
sp->n_type == (N_TEXT|N_EXT))
break;
if (strategy == DB_STGY_ANY &&
(sp->n_type & N_EXT))
break;
}
}
else if (off - sp->n_value == diff) {
if (symp == 0)
symp = sp;
else if ((symp->n_type & N_EXT) == 0 &&
(sp->n_type & N_EXT) != 0)
symp = sp; /* pick the external symbol */
}
}
}
if (symp == 0) {
*diffp = off;
}
else {
*diffp = diff;
}
return ((db_sym_t)symp);
}
/*
* Return the name and value for a symbol.
*/
void
X_db_symbol_values(sym, namep, valuep)
db_sym_t sym;
char **namep;
db_expr_t *valuep;
{
register struct nlist *sp;
sp = (struct nlist *)sym;
if (namep)
*namep = sp->n_un.n_name;
if (valuep)
*valuep = sp->n_value;
}
boolean_t
X_db_line_at_pc(symtab, cursym, filename, linenum, off)
db_symtab_t * symtab;
db_sym_t cursym;
char **filename;
int *linenum;
db_expr_t off;
{
register struct nlist *sp, *ep;
unsigned long sodiff = -1UL, lndiff = -1UL, ln = 0;
char *fname = NULL;
sp = (struct nlist *)symtab->start;
ep = (struct nlist *)symtab->end;
/*
* XXX - this used to remove "gcc_compiled.", but that is obsolete. We
* now remove unwanted names using symorder.
*/
#define NEWSRC(str) 0
for (; sp < ep; sp++) {
/*
* Prevent bogus linenumbers in case module not compiled
* with debugging options
*/
#if 0
if (sp->n_value <= off && (off - sp->n_value) <= sodiff &&
NEWSRC(sp->n_un.n_name)) {
#endif
if ((sp->n_type & N_TYPE) == N_FN || NEWSRC(sp->n_un.n_name)) {
sodiff = lndiff = -1UL;
ln = 0;
fname = NULL;
}
if (sp->n_type == N_SO) {
if (sp->n_value <= off && (off - sp->n_value) < sodiff) {
sodiff = off - sp->n_value;
fname = sp->n_un.n_name;
}
continue;
}
if (sp->n_type != N_SLINE)
continue;
if (sp->n_value > off)
break;
if (off - sp->n_value < lndiff) {
lndiff = off - sp->n_value;
ln = sp->n_desc;
}
}
if (fname != NULL && ln != 0) {
*filename = fname;
*linenum = ln;
return TRUE;
}
return (FALSE);
}
boolean_t
X_db_sym_numargs(symtab, cursym, nargp, argnamep)
db_symtab_t * symtab;
db_sym_t cursym;
int *nargp;
char **argnamep;
{
register struct nlist *sp, *ep;
u_long addr;
int maxnarg = *nargp, nargs = 0;
if (cursym == NULL)
return FALSE;
addr = ((struct nlist *)cursym)->n_value;
sp = (struct nlist *)symtab->start;
ep = (struct nlist *)symtab->end;
for (; sp < ep; sp++) {
if (sp->n_type == N_FUN && sp->n_value == addr) {
while (++sp < ep && sp->n_type == N_PSYM) {
if (nargs >= maxnarg)
break;
nargs++;
*argnamep++ = sp->n_un.n_name?sp->n_un.n_name:"???";
{
/* XXX - remove trailers */
char *cp = *(argnamep-1);
while (*cp != '\0' && *cp != ':') cp++;
if (*cp == ':') *cp = '\0';
}
}
*nargp = nargs;
return TRUE;
}
}
return FALSE;
}
/*
* Initialization routine for a.out files.
*/
void
kdb_init(void)
{
if (bootinfo.bi_esymtab != bootinfo.bi_symtab)
X_db_sym_init((int *)bootinfo.bi_symtab,
(char *)((bootinfo.bi_esymtab + sizeof(int) - 1)
& ~(sizeof(int) - 1)),
"kernel");
}
#if 0
/*
* Read symbol table from file.
* (should be somewhere else)
*/
#include <boot_ufs/file_io.h>
#include <vm/vm_kern.h>
read_symtab_from_file(fp, symtab_name)
struct file *fp;
char * symtab_name;
{
vm_size_t resid;
kern_return_t result;
vm_offset_t symoff;
vm_size_t symsize;
vm_offset_t stroff;
vm_size_t strsize;
vm_size_t table_size;
vm_offset_t symtab;
if (!get_symtab(fp, &symoff, &symsize)) {
boot_printf("[ error %d reading %s file header ]\n",
result, symtab_name);
return;
}
stroff = symoff + symsize;
result = read_file(fp, (vm_offset_t)stroff,
(vm_offset_t)&strsize, sizeof(strsize), &resid);
if (result || resid) {
boot_printf("[ no valid symbol table present for %s ]\n",
symtab_name);
return;
}
table_size = sizeof(int) + symsize + strsize;
table_size = (table_size + sizeof(int)-1) & ~(sizeof(int)-1);
symtab = kmem_alloc_wired(kernel_map, table_size);
*(int *)symtab = symsize;
result = read_file(fp, symoff,
symtab + sizeof(int), symsize, &resid);
if (result || resid) {
boot_printf("[ error %d reading %s symbol table ]\n",
result, symtab_name);
return;
}
result = read_file(fp, stroff,
symtab + sizeof(int) + symsize, strsize, &resid);
if (result || resid) {
boot_printf("[ error %d reading %s string table ]\n",
result, symtab_name);
return;
}
X_db_sym_init((int *)symtab,
(char *)(symtab + table_size),
symtab_name);
}
#endif
#endif /* DB_NO_AOUT */