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 | |
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')
-rw-r--r-- | sys/lib/libsa/exec.h | 9 | ||||
-rw-r--r-- | sys/lib/libsa/exec.new.c | 46 | ||||
-rw-r--r-- | sys/lib/libsa/exec_aout.c | 42 | ||||
-rw-r--r-- | sys/lib/libsa/exec_elf.c | 169 |
4 files changed, 203 insertions, 63 deletions
diff --git a/sys/lib/libsa/exec.h b/sys/lib/libsa/exec.h index a1493f483c5..2b513c4cbf9 100644 --- a/sys/lib/libsa/exec.h +++ b/sys/lib/libsa/exec.h @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.h,v 1.3 2000/01/06 02:59:23 mickey Exp $ */ +/* $OpenBSD: exec.h,v 1.4 2000/05/30 21:59:30 mickey Exp $ */ /* * Copyright (c) 1998 Michael Shalayeff @@ -70,6 +70,7 @@ struct x_sw { int (*probe) __P((int, union x_header *)); /* zero on success */ int (*load) __P((int, struct x_param *)); + int (*ldsym) __P((int, struct x_param *)); }; struct x_param { @@ -85,14 +86,14 @@ void machdep_exec __P((struct x_param *, int, void *)); int aout_probe __P((int, union x_header *)); int aout_load __P((int, struct x_param *)); +int aout_ldsym __P((int, struct x_param *)); int elf_probe __P((int, union x_header *)); int elf_load __P((int, struct x_param *)); +int elf_ldsym __P((int, struct x_param *)); int ecoff_probe __P((int, union x_header *)); int ecoff_load __P((int, struct x_param *)); - -int som_probe __P((int, union x_header *)); -int som_load __P((int, struct x_param *)); +int ecoff_ldsym __P((int, struct x_param *)); #endif /* _SA_EXEC_H_ */ diff --git a/sys/lib/libsa/exec.new.c b/sys/lib/libsa/exec.new.c index 8045e3da5b3..22d03a59b46 100644 --- a/sys/lib/libsa/exec.new.c +++ b/sys/lib/libsa/exec.new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.new.c,v 1.4 1998/08/27 20:36:00 mickey Exp $ */ +/* $OpenBSD: exec.new.c,v 1.5 2000/05/30 21:59:30 mickey Exp $ */ /* * Copyright (c) 1998 Michael Shalayeff @@ -53,7 +53,6 @@ exec(path, loadaddr, howto) union x_header hdr; register u_char *pa; register int save_err; - u_int sz; if ((fd = open(path, 0)) < 0 || fstat(fd, &sb)) return; @@ -109,45 +108,14 @@ exec(path, loadaddr, howto) printf("+%u", param.bss.size); bzero (pa + param.bss.addr, param.bss.size); - if (!param.sym.size) - pa += param.bss.addr + param.bss.size; - else { - *(u_int *)(pa + param.sym.addr) = param.sym.size; - param.sym.addr += sizeof(u_int); - printf("+[%u", param.sym.size); - if (lseek(fd, param.sym.foff, SEEK_SET) <= 0 || - read(fd,pa+param.sym.addr,param.sym.size) != param.sym.size) - goto err; - - /* .str */ - if (param.str.foff && lseek(fd, param.str.foff, SEEK_SET) <= 0) - goto err; - - pa += param.sym.addr + param.sym.size; - sz = param.str.size; - - /* special hack for a.out, where .str size is it's first int */ - if (param.str.foff && !sz) { - if (read(fd, pa, sizeof(u_int)) != sizeof(u_int)) - goto err; - else { - sz = param.str.size = *(u_int*)pa; - pa += sizeof(u_int); - sz -= sizeof(u_int); - } - } - if (sz) { - if (sz && read(fd, pa, sz) != sz) - goto err; - } - printf("+%u]", sz); - pa += sz; + param.xp_end = (int)pa + param.bss.addr + param.bss.size; + if (sw->ldsym && sw->ldsym(fd, ¶m)) { + errno = errno? errno : EFTYPE; + goto err; } - /* round to int */ - param.xp_end = ((u_int)pa + sizeof(int) - 1) & ~(sizeof(int) - 1); - - printf(" total=0x%x start=0x%x\n", param.xp_end, param.xp_entry); + /* ldsym will adjust the xp_end */ + printf("=0x%x start=0x%x\n", param.xp_end, param.xp_entry); /* call the joker */ machdep_exec(¶m, howto, loadaddr); diff --git a/sys/lib/libsa/exec_aout.c b/sys/lib/libsa/exec_aout.c index a44c7c0b0ca..b5fa341ab47 100644 --- a/sys/lib/libsa/exec_aout.c +++ b/sys/lib/libsa/exec_aout.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_aout.c,v 1.1 1998/07/14 03:29:08 mickey Exp $ */ +/* $OpenBSD: exec_aout.c,v 1.2 2000/05/30 21:59:30 mickey Exp $ */ /* * Copyright (c) 1998 Michael Shalayeff @@ -77,7 +77,45 @@ aout_load(fd, xp) xp->data.size = x->a_data; xp->bss.size = x->a_bss; xp->sym.size = x->a_syms; - xp->str.size = 0; /* will be hacked later in exec() */ + xp->str.size = 0; /* will be hacked later in aout_ldsym() */ + + return 0; +} + +int +aout_ldsym(fd, xp) + int fd; + register struct x_param *xp; +{ + char *pa; + u_int i; + + /* Symbols */ + if (xp->sym.size) { + pa = (char *)xp->xp_end; + + *(u_int *)pa = xp->sym.size; + pa += sizeof(u_int); + printf("+[%u", xp->sym.size); + if (read(fd, pa, xp->sym.size) != (ssize_t)xp->sym.size) + return -1; + pa += xp->sym.size; + + if (read(fd, pa, sizeof(u_int)) != sizeof(u_int)) + return -1; + + if ((i = *(u_int *)pa)) { + pa += sizeof(u_int); + i -= sizeof(u_int); + if (read(fd, pa, i) != i) + return -1; + pa += i; + } + + /* and that many bytes of string table */ + printf("+%d]", i); + xp->xp_end = (u_long)pa; + } return 0; } 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; } |