diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2000-05-30 21:59:31 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2000-05-30 21:59:31 +0000 |
commit | 74f1c0e7ac50e618d1b8fe339a9b0dd7c94c00a3 (patch) | |
tree | 7b344224842be17c1389ec58f2d45d0bfc19305f /sys/lib/libsa/exec_elf.c | |
parent | 45f0ff7ee11beaae4d1ffe122abe37142441114b (diff) |
split symbol loading for a.out into a separate routine (tested on i386)
add symbol loading for elf (tested on hppa)
Diffstat (limited to 'sys/lib/libsa/exec_elf.c')
-rw-r--r-- | sys/lib/libsa/exec_elf.c | 169 |
1 files changed, 151 insertions, 18 deletions
diff --git a/sys/lib/libsa/exec_elf.c b/sys/lib/libsa/exec_elf.c index 04dc58ad3dd..0af5c810274 100644 --- a/sys/lib/libsa/exec_elf.c +++ b/sys/lib/libsa/exec_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_elf.c,v 1.4 1998/08/27 20:38:15 mickey Exp $ */ +/* $OpenBSD: exec_elf.c,v 1.5 2000/05/30 21:59:30 mickey Exp $ */ /* * Copyright (c) 1998 Michael Shalayeff @@ -33,6 +33,7 @@ #include "libsa.h" #include <lib/libsa/exec.h> #include <sys/exec_elf.h> +#include <ddb/db_aout.h> int elf_probe(fd, hdr) @@ -49,10 +50,8 @@ elf_load(fd, xp) { register Elf32_Ehdr *ehdr = (Elf32_Ehdr *)xp->xp_hdr; register Elf32_Phdr *ph; - register Elf32_Shdr *sh; Elf32_Phdr phdr[8]; /* XXX hope this is enough */ - Elf32_Shdr shdr[32]; /* XXX hope this is enough */ - size_t phsize, shsize; + size_t phsize; register u_int pa; #ifdef EXEC_DEBUG @@ -91,7 +90,7 @@ elf_load(fd, xp) for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ph++) { #ifdef EXEC_DEBUG if (debug) - printf("ph%d: type=%x, off==%d, va=%x, fs=%d, ms=%d, " + printf("ph%d: type=%x, off=%d, va=%x, fs=%d, ms=%d, " "flags=%x\n", (ph - phdr), ph->p_type, ph->p_offset, ph->p_vaddr, ph->p_filesz, ph->p_memsz, ph->p_flags); @@ -117,10 +116,24 @@ elf_load(fd, xp) } } + return 0; +} + +int +elf_ldsym(fd, xp) + int fd; + struct x_param *xp; +{ + register Elf32_Ehdr *ehdr = (Elf32_Ehdr *)xp->xp_hdr; + Elf32_Sym elfsym; + Elf32_Shdr shdr[32]; /* XXX hope this is enough */ + register Elf32_Shdr *sh; + register struct nlist *nl; + register u_int ss, shsize; + if (lseek(fd, ehdr->e_shoff, SEEK_SET) <= 0) { -#ifdef EXEC_DEBUG - if (debug) - printf("lseek failed (%d)\n", errno); +#ifdef DEBUG + printf("ehdr lseek: %s\n", strerror(errno)); #endif return -1; } @@ -128,27 +141,147 @@ elf_load(fd, xp) /* calc symbols location, scanning section headers */ shsize = ehdr->e_shnum * ehdr->e_shentsize; sh = shdr; -#if notyet + if (shsize > sizeof(shdr) || read(fd, shdr, shsize) != shsize) { -#ifdef EXEC_DEBUG - if (debug) - printf("shdr read failed (%d)\n", errno); +#ifdef DEBUG + printf("shdr read: %s\n", strerror(errno)); #endif return -1; } for (sh = shdr; sh < &shdr[ehdr->e_shnum]; sh++) { - switch (sh->sh_type) { - case SHT_SYMTAB: +#ifdef EXEC_DEBUG + if (debug) + printf ("sh%d: type=%x, flags=%x, addr=%x, " + "foff=%x, sz=%x, link=%x, info=%x, " + "allign=%x, esz=%x\n", sh - shdr, + sh->sh_type, sh->sh_flags, sh->sh_addr, + sh->sh_offset, sh->sh_size, sh->sh_link, + sh->sh_info, sh->sh_addralign, sh->sh_entsize); +#endif + if (sh->sh_type == SHT_SYMTAB) { + xp->sym.addr = xp->bss.addr + xp->bss.size; xp->sym.foff = sh->sh_offset; xp->sym.size = sh->sh_size; - case SHT_STRTAB: - xp->str.foff = sh->sh_offset; - xp->str.size = sh->sh_size; + if (sh->sh_link && sh->sh_link < ehdr->e_shnum && + shdr[sh->sh_link].sh_type == SHT_STRTAB) { + xp->str.foff = shdr[sh->sh_link].sh_offset; + xp->str.size = shdr[sh->sh_link].sh_size; + } + } + } + + if (!xp->sym.size || !xp->str.size) + return 0; + + if (lseek(fd, xp->sym.foff, SEEK_SET) <= 0) { +#ifdef DEBUG + printf("syms lseek: %s\n", strerror(errno)); +#endif + return -1; + } + + nl = (struct nlist *)((long *)xp->xp_end + 1); + for (ss = xp->sym.size; ss >= sizeof(elfsym); + ss -= sizeof(elfsym), nl++) { + + if (read(fd, &elfsym, sizeof(elfsym)) != sizeof(elfsym)) { +#ifdef DEBUG + printf ("read elfsym: %s\n", strerror(errno)); +#endif + return -1; + } + nl->n_un.n_strx = (long)elfsym.st_name + sizeof(int); + nl->n_value = elfsym.st_value; + nl->n_desc = 0; + nl->n_other = 0; + switch (ELF32_ST_TYPE(elfsym.st_info)) { + case STT_FILE: + nl->n_type = N_FN; + break; + case STT_FUNC: + nl->n_type = N_TEXT; + break; + case STT_OBJECT: + nl->n_type = N_DATA; + break; + case STT_NOTYPE: + if (elfsym.st_shndx == SHN_UNDEF) { + nl->n_type = N_UNDF; + break; + } else if (elfsym.st_shndx == SHN_ABS) { + nl->n_type = N_ABS; + break; + } else if (shdr[elfsym.st_shndx - 1].sh_type == + SHT_NULL) { + /* XXX this is probably bogus */ + nl->n_type = N_ABS; + break; + } else if (shdr[elfsym.st_shndx - 1].sh_type == + SHT_PROGBITS) { + /* XXX this is probably bogus */ + nl->n_type = N_BSS; + break; + } +#ifdef EXEC_DEBUG + else + printf ("sec[%d]=0x%x,val=0x%lx\n", + elfsym.st_shndx, + shdr[elfsym.st_shndx - 1].sh_type, + nl->n_value); +#endif + case STT_LOPROC: + case STT_HIPROC: + case STT_SECTION: + nl--; + continue; + + default: +#ifdef DEBUG + printf ("elf_ldsym: unknown type %d\n", + ELF32_ST_TYPE(elfsym.st_info)); +#endif + nl--; + continue; + } + switch (ELF32_ST_BIND(elfsym.st_info)) { + case STB_WEAK: + case STB_GLOBAL: + nl->n_type |= N_EXT; + break; + case STB_LOCAL: + break; + default: +#ifdef DEBUG + printf ("elf_ldsym: unknown bind %d\n", + ELF32_ST_BIND(elfsym.st_info)); +#endif + break; } - break; } + + printf (" [%d", (char *)nl - (char *)xp->xp_end); + *(long *)xp->xp_end = (char *)nl - (char *)xp->xp_end - sizeof(long); + + if (lseek(fd, xp->str.foff, SEEK_SET) <= 0) { +#ifdef DEBUG + printf("strings lseek: %s\n", strerror(errno)); #endif + return -1; + } + + *((int *)nl)++ = xp->str.size + sizeof(int); + if (read(fd, nl, xp->str.size) != xp->str.size) { +#ifdef DEBUG + printf ("read strings: %s\n", strerror(errno)); +#endif + return -1; + } + + printf ("+%d]", xp->str.size); + + xp->xp_end = ((u_int)nl + xp->str.size + 3) & ~3; + return 0; } |