summaryrefslogtreecommitdiff
path: root/sys/lib
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2000-05-30 21:59:31 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2000-05-30 21:59:31 +0000
commit74f1c0e7ac50e618d1b8fe339a9b0dd7c94c00a3 (patch)
tree7b344224842be17c1389ec58f2d45d0bfc19305f /sys/lib
parent45f0ff7ee11beaae4d1ffe122abe37142441114b (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.h9
-rw-r--r--sys/lib/libsa/exec.new.c46
-rw-r--r--sys/lib/libsa/exec_aout.c42
-rw-r--r--sys/lib/libsa/exec_elf.c169
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, &param)) {
+ 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(&param, 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;
}