diff options
Diffstat (limited to 'sys/kern/link_elf.c')
-rw-r--r-- | sys/kern/link_elf.c | 94 |
1 files changed, 48 insertions, 46 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index c5e84daf0a3e2..26b6213745d98 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_elf.c,v 1.10 1998/11/06 15:16:07 peter Exp $ + * $Id: link_elf.c,v 1.6 1998/10/15 17:16:24 peter Exp $ */ #include <sys/param.h> @@ -58,6 +58,13 @@ static int link_elf_search_symbol(linker_file_t, caddr_t value, static void link_elf_unload_file(linker_file_t); static void link_elf_unload_module(linker_file_t); +/* + * The file representing the currently running kernel. This contains + * the global symbol table. + */ + +linker_file_t linker_kernel_file; + static struct linker_class_ops link_elf_class_ops = { link_elf_load_module, }; @@ -393,8 +400,10 @@ link_elf_load_file(const char* filename, linker_file_t* result) { struct nameidata nd; struct proc* p = curproc; /* XXX */ - Elf_Ehdr *hdr; - caddr_t firstpage; + union { + Elf_Ehdr hdr; + char buf[PAGE_SIZE]; + } u; int nbytes, i; Elf_Phdr *phdr; Elf_Phdr *phlimit; @@ -407,6 +416,17 @@ link_elf_load_file(const char* filename, linker_file_t* result) Elf_Off base_offset; Elf_Addr base_vaddr; Elf_Addr base_vlimit; + caddr_t base_addr; + Elf_Off data_offset; + Elf_Addr data_vaddr; + Elf_Addr data_vlimit; + caddr_t data_addr; + Elf_Addr clear_vaddr; + caddr_t clear_addr; + size_t nclear; + Elf_Addr bss_vaddr; + Elf_Addr bss_vlimit; + caddr_t bss_addr; int error = 0; int resid; elf_file_t ef; @@ -424,7 +444,6 @@ link_elf_load_file(const char* filename, linker_file_t* result) pathname = linker_search_path(filename); if (pathname == NULL) return ENOENT; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p); error = vn_open(&nd, FREAD, 0); free(pathname, M_LINKER); @@ -434,41 +453,35 @@ link_elf_load_file(const char* filename, linker_file_t* result) /* * Read the elf header from the file. */ - firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK); - if (firstpage == NULL) { - error = ENOMEM; - goto out; - } - hdr = (Elf_Ehdr *)firstpage; - error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0, + error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &u, sizeof u, 0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); - nbytes = PAGE_SIZE - resid; + nbytes = sizeof u - resid; if (error) goto out; - if (!IS_ELF(*hdr)) { + if (!IS_ELF(u.hdr)) { error = ENOEXEC; goto out; } - if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS - || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) { + if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS + || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) { link_elf_error("Unsupported file layout"); error = ENOEXEC; goto out; } - if (hdr->e_ident[EI_VERSION] != EV_CURRENT - || hdr->e_version != EV_CURRENT) { + if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT + || u.hdr.e_version != EV_CURRENT) { link_elf_error("Unsupported file version"); error = ENOEXEC; goto out; } - if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { + if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) { link_elf_error("Unsupported file type"); error = ENOEXEC; goto out; } - if (hdr->e_machine != ELF_TARG_MACH) { + if (u.hdr.e_machine != ELF_TARG_MACH) { link_elf_error("Unsupported machine"); error = ENOEXEC; goto out; @@ -479,9 +492,9 @@ link_elf_load_file(const char* filename, linker_file_t* result) * not strictly required by the ABI specification, but it seems to * always true in practice. And, it simplifies things considerably. */ - if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) && - (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) && - (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes))) + if (!((u.hdr.e_phentsize == sizeof(Elf_Phdr)) + || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) + || (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes))) link_elf_error("Unreadable program headers"); /* @@ -490,8 +503,8 @@ link_elf_load_file(const char* filename, linker_file_t* result) * We rely on there being exactly two load segments, text and data, * in that order. */ - phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff); - phlimit = phdr + hdr->e_phnum; + phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff); + phlimit = phdr + u.hdr.e_phnum; nsegs = 0; phdyn = NULL; phphdr = NULL; @@ -623,8 +636,8 @@ link_elf_load_file(const char* filename, linker_file_t* result) goto out; /* Try and load the symbol table if it's present. (you can strip it!) */ - nbytes = hdr->e_shnum * hdr->e_shentsize; - if (nbytes == 0 || hdr->e_shoff == 0) + nbytes = u.hdr.e_shnum * u.hdr.e_shentsize; + if (nbytes == 0 || u.hdr.e_shoff == 0) goto nosyms; shdr = malloc(nbytes, M_LINKER, M_WAITOK); if (shdr == NULL) { @@ -633,13 +646,13 @@ link_elf_load_file(const char* filename, linker_file_t* result) } bzero(shdr, nbytes); error = vn_rdwr(UIO_READ, nd.ni_vp, - (caddr_t)shdr, nbytes, hdr->e_shoff, + (caddr_t)shdr, nbytes, u.hdr.e_shoff, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); if (error) goto out; symtabindex = -1; symstrindex = -1; - for (i = 0; i < hdr->e_shnum; i++) { + for (i = 0; i < u.hdr.e_shnum; i++) { if (shdr[i].sh_type == SHT_SYMTAB) { symtabindex = i; symstrindex = shdr[i].sh_link; @@ -682,8 +695,6 @@ out: linker_file_unload(lf); if (shdr) free(shdr, M_LINKER); - if (firstpage) - free(firstpage, M_LINKER); VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, FREAD, p->p_ucred, p); @@ -738,11 +749,10 @@ load_dependancies(linker_file_t lf) /* * All files are dependant on /kernel. */ - if (linker_kernel_file) { - linker_kernel_file->refs++; - linker_file_add_dependancy(lf, linker_kernel_file); - } + linker_kernel_file->refs++; + linker_file_add_dependancy(lf, linker_kernel_file); + for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) { if (dp->d_tag == DT_NEEDED) { name = ef->strtab + dp->d_un.d_val; @@ -788,10 +798,8 @@ relocate_file(linker_file_t lf) rellim = (const Elf_Rel *) ((caddr_t) ef->rel + ef->relsize); while (rel < rellim) { symname = symbol_name(ef, rel->r_info); - if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) { - printf("link_elf: symbol %s undefined\n", symname); + if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) return ENOENT; - } rel++; } } @@ -802,10 +810,8 @@ relocate_file(linker_file_t lf) relalim = (const Elf_Rela *) ((caddr_t) ef->rela + ef->relasize); while (rela < relalim) { symname = symbol_name(ef, rela->r_info); - if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) { - printf("link_elf: symbol %s undefined\n", symname); + if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) return ENOENT; - } rela++; } } @@ -816,10 +822,8 @@ relocate_file(linker_file_t lf) rellim = (const Elf_Rel *) ((caddr_t) ef->pltrel + ef->pltrelsize); while (rel < rellim) { symname = symbol_name(ef, rel->r_info); - if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) { - printf("link_elf: symbol %s undefined\n", symname); + if (elf_reloc(lf, rel, ELF_RELOC_REL, symname)) return ENOENT; - } rel++; } } @@ -830,10 +834,8 @@ relocate_file(linker_file_t lf) relalim = (const Elf_Rela *) ((caddr_t) ef->pltrela + ef->pltrelasize); while (rela < relalim) { symname = symbol_name(ef, rela->r_info); - if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) { - printf("link_elf: symbol %s undefined\n", symname); + if (elf_reloc(lf, rela, ELF_RELOC_RELA, symname)) return ENOENT; - } rela++; } } |