summaryrefslogtreecommitdiff
path: root/sys/lib/libsa/exec_elf.c
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/libsa/exec_elf.c
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/libsa/exec_elf.c')
-rw-r--r--sys/lib/libsa/exec_elf.c169
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;
}