diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2003-08-11 06:37:40 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2003-08-11 06:37:40 +0000 |
commit | 733dbb9d1f3d6b4a8b971e63c97c447af112f57d (patch) | |
tree | 8d607fa22d898f7e7c72b57905c66679e595178a /sys/lib | |
parent | c5ad97eefa2759171b1b56bc27178406f85e8771 (diff) |
load file in one pass avoiding seeking the headers back and forth; miod@ testing & ok (two months ago and then i forgot ;)
Diffstat (limited to 'sys/lib')
-rw-r--r-- | sys/lib/libsa/loadfile.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/sys/lib/libsa/loadfile.c b/sys/lib/libsa/loadfile.c index 3000583965a..c9b8ee1a7d9 100644 --- a/sys/lib/libsa/loadfile.c +++ b/sys/lib/libsa/loadfile.c @@ -1,5 +1,5 @@ /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */ -/* $OpenBSD: loadfile.c,v 1.7 2003/08/11 06:23:09 deraadt Exp $ */ +/* $OpenBSD: loadfile.c,v 1.8 2003/08/11 06:37:39 mickey Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -259,6 +259,7 @@ static int elf_exec(int fd, Elf_Ehdr *elf, u_long *marks, int flags) { Elf_Shdr *shp; + Elf_Phdr *phdr; Elf_Off off; int i; size_t sz; @@ -267,19 +268,24 @@ elf_exec(int fd, Elf_Ehdr *elf, u_long *marks, int flags) paddr_t minp = ~0, maxp = 0, pos = 0; paddr_t offset = marks[MARK_START], shpp, elfp; + sz = elf->e_phnum * sizeof(Elf_Phdr); + phdr = ALLOC(sz); + + if (lseek(fd, elf->e_phoff, SEEK_SET) == -1) { + WARN(("lseek phdr")); + FREE(phdr, sz); + return 1; + } + if (read(fd, phdr, sz) != sz) { + WARN(("read program headers")); + FREE(phdr, sz); + return 1; + } + for (first = 1, i = 0; i < elf->e_phnum; i++) { - Elf_Phdr phdr; - if (lseek(fd, elf->e_phoff + sizeof(phdr) * i, SEEK_SET) - == -1) { - WARN(("lseek phdr")); - return 1; - } - if (read(fd, (void *)&phdr, sizeof(phdr)) != sizeof(phdr)) { - WARN(("read phdr")); - return 1; - } - if (phdr.p_type != PT_LOAD || - (phdr.p_flags & (PF_W|PF_X)) == 0) + + if (phdr[i].p_type != PT_LOAD || + (phdr[i].p_flags & (PF_W|PF_X)) == 0) continue; #define IS_TEXT(p) (p.p_flags & PF_X) @@ -288,48 +294,51 @@ elf_exec(int fd, Elf_Ehdr *elf, u_long *marks, int flags) /* * XXX: Assume first address is lowest */ - if ((IS_TEXT(phdr) && (flags & LOAD_TEXT)) || - (IS_DATA(phdr) && (flags & LOAD_DATA))) { + if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) || + (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) { /* Read in segment. */ PROGRESS(("%s%lu", first ? "" : "+", - (u_long)phdr.p_filesz)); + (u_long)phdr[i].p_filesz)); - if (lseek(fd, phdr.p_offset, SEEK_SET) == -1) { + if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1) { WARN(("lseek text")); + FREE(phdr, sz); return 1; } - if (READ(fd, phdr.p_vaddr, phdr.p_filesz) != - phdr.p_filesz) { + if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) != + phdr[i].p_filesz) { WARN(("read text")); + FREE(phdr, sz); return 1; } first = 0; } - if ((IS_TEXT(phdr) && (flags & (LOAD_TEXT|COUNT_TEXT))) || - (IS_DATA(phdr) && (flags & (LOAD_DATA|COUNT_TEXT)))) { - pos = phdr.p_vaddr; + if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) || + (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) { + pos = phdr[i].p_vaddr; if (minp > pos) minp = pos; - pos += phdr.p_filesz; + pos += phdr[i].p_filesz; if (maxp < pos) maxp = pos; } /* Zero out bss. */ - if (IS_BSS(phdr) && (flags & LOAD_BSS)) { + if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) { PROGRESS(("+%lu", - (u_long)(phdr.p_memsz - phdr.p_filesz))); - BZERO((phdr.p_vaddr + phdr.p_filesz), - phdr.p_memsz - phdr.p_filesz); + (u_long)(phdr[i].p_memsz - phdr[i].p_filesz))); + BZERO((phdr[i].p_vaddr + phdr[i].p_filesz), + phdr[i].p_memsz - phdr[i].p_filesz); } - if (IS_BSS(phdr) && (flags & (LOAD_BSS|COUNT_BSS))) { - pos += phdr.p_memsz - phdr.p_filesz; + if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) { + pos += phdr[i].p_memsz - phdr[i].p_filesz; if (maxp < pos) maxp = pos; } } + FREE(phdr, sz); /* * Copy the ELF and section headers. |