diff options
author | peter <peter@FreeBSD.org> | 1998-10-13 09:27:00 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-10-13 09:27:00 +0000 |
commit | a368279cfc5b5c1e349a7f695b7739469af4164a (patch) | |
tree | 3029d6658bf798d714e424c3faa1e6c095f14513 /sys/kern/link_elf.c | |
parent | f2663735958365d7f75ecf218d992509be005b5a (diff) | |
download | FreeBSD-src-a368279cfc5b5c1e349a7f695b7739469af4164a.zip FreeBSD-src-a368279cfc5b5c1e349a7f695b7739469af4164a.tar.gz |
Load the full symbol tables if they are present. This means that ddb
and tracebacks have access to local symbols. This is particularly
important for the Alpha.
Diffstat (limited to 'sys/kern/link_elf.c')
-rw-r--r-- | sys/kern/link_elf.c | 88 |
1 files changed, 78 insertions, 10 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 1a1266b..578589d 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_elf.c,v 1.3 1998/10/09 23:55:31 peter Exp $ + * $Id: link_elf.c,v 1.4 1998/10/12 09:13:47 peter Exp $ */ #include <sys/param.h> @@ -110,6 +110,8 @@ typedef struct elf_file { long ddbsymcnt; /* Number of symbols */ caddr_t ddbstrtab; /* String table */ long ddbstrcnt; /* number of bytes in string table */ + caddr_t symbase; /* malloc'ed symbold base */ + caddr_t strbase; /* malloc'ed string base */ } *elf_file_t; static int parse_dynamic(linker_file_t lf); @@ -196,6 +198,8 @@ parse_module_symbols(linker_file_t lf) Elf_Sym* symtab; int symcnt; + if (ef->modptr == NULL) + return 0; pointer = preload_search_info(ef->modptr, MODINFO_METADATA|MODINFOMD_SSYM); if (pointer == NULL) return 0; @@ -354,6 +358,7 @@ link_elf_load_module(const char *filename, linker_file_t *result) ef = malloc(sizeof(struct elf_file), M_LINKER, M_WAITOK); if (ef == NULL) return (ENOMEM); + ef->modptr = modptr; ef->address = *(caddr_t *)baseptr; #ifdef SPARSE_MAPPING ef->object = 0; @@ -425,6 +430,14 @@ link_elf_load_file(const char* filename, linker_file_t* result) elf_file_t ef; linker_file_t lf; char *pathname; + Elf_Shdr *shdr; + int symtabindex; + int symstrindex; + int symcnt; + int strcnt; + + shdr = NULL; + lf = NULL; pathname = linker_search_path(filename); if (pathname == NULL) @@ -610,24 +623,74 @@ link_elf_load_file(const char* filename, linker_file_t* result) lf->size = mapsize; error = parse_dynamic(lf); - if (error) { - linker_file_unload(lf); + if (error) goto out; - } error = load_dependancies(lf); - if (error) { - linker_file_unload(lf); + if (error) goto out; - } error = relocate_file(lf); - if (error) { - linker_file_unload(lf); + if (error) + goto out; + + /* Try and load the symbol table if it's present. (you can strip it!) */ + nbytes = u.hdr.e_shnum * u.hdr.e_shentsize; + if (nbytes == 0 || u.hdr.e_shoff == 0) + goto nosyms; + shdr = malloc(nbytes, M_LINKER, M_WAITOK); + if (shdr == NULL) { + error = ENOMEM; goto out; } + error = vn_rdwr(UIO_READ, nd.ni_vp, + (caddr_t)shdr, nbytes, u.hdr.e_shoff, + UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); + if (error) + goto out; + symtabindex = -1; + symstrindex = -1; + for (i = 0; i < u.hdr.e_shnum; i++) { + if (shdr[i].sh_type == SHT_SYMTAB) { + symtabindex = i; + symstrindex = shdr[i].sh_link; + } + } + if (symtabindex < 0 || symstrindex < 0) + goto nosyms; + + symcnt = shdr[symtabindex].sh_size; + ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK); + strcnt = shdr[symstrindex].sh_size; + ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK); + + if (ef->symbase == NULL || ef->strbase == NULL) { + error = ENOMEM; + goto out; + } + error = vn_rdwr(UIO_READ, nd.ni_vp, + ef->symbase, symcnt, shdr[symtabindex].sh_offset, + UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); + if (error) + goto out; + error = vn_rdwr(UIO_READ, nd.ni_vp, + ef->strbase, strcnt, shdr[symstrindex].sh_offset, + UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); + if (error) + goto out; + + ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->ddbsymtab = (const Elf_Sym *)ef->symbase; + ef->ddbstrcnt = strcnt; + ef->ddbstrtab = ef->strbase; + +nosyms: *result = lf; out: + if (error && lf) + linker_file_unload(lf); + if (shdr) + free(shdr, M_LINKER); VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, FREAD, p->p_ucred, p); @@ -648,8 +711,13 @@ link_elf_unload_file(linker_file_t file) vm_object_deallocate(ef->object); } #else - free(ef->address, M_LINKER); + if (ef->address) + free(ef->address, M_LINKER); #endif + if (ef->symbase) + free(ef->symbase, M_LINKER); + if (ef->strbase) + free(ef->strbase, M_LINKER); free(ef, M_LINKER); } } |