From owner-p4-projects@FreeBSD.ORG Thu Mar 25 15:38:09 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E0BAD16A4D0; Thu, 25 Mar 2004 15:38:08 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id AF65316A4CE for ; Thu, 25 Mar 2004 15:38:08 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id A3F0F43D1D for ; Thu, 25 Mar 2004 15:38:08 -0800 (PST) (envelope-from peter@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i2PNc8Ge072752 for ; Thu, 25 Mar 2004 15:38:08 -0800 (PST) (envelope-from peter@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i2PNc81Y072749 for perforce@freebsd.org; Thu, 25 Mar 2004 15:38:08 -0800 (PST) (envelope-from peter@freebsd.org) Date: Thu, 25 Mar 2004 15:38:08 -0800 (PST) Message-Id: <200403252338.i2PNc81Y072749@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to peter@freebsd.org using -f From: Peter Wemm To: Perforce Change Reviews Subject: PERFORCE change 49690 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 Mar 2004 23:38:09 -0000 http://perforce.freebsd.org/chv.cgi?CH=49690 Change 49690 by peter@peter_daintree on 2004/03/25 15:37:13 checkpoint. note that I got fed up and reindented. There are changes, but not that many. Mostly preperation and validation. Affected files ... .. //depot/projects/hammer/sys/kern/link_elf_obj.c#3 edit Differences ... ==== //depot/projects/hammer/sys/kern/link_elf_obj.c#3 (text+ko) ==== @@ -60,70 +60,69 @@ #include "linker_if.h" typedef struct elf_file { - struct linker_file lf; /* Common fields */ - caddr_t address; /* Relocation address */ + struct linker_file lf; /* Common fields */ + caddr_t address; /* Relocation address */ #ifdef SPARSE_MAPPING - vm_object_t object; /* VM object to hold file pages */ + vm_object_t object; /* VM object to hold file pages */ #endif - caddr_t strtab; /* DT_STRTAB */ - int strsz; /* DT_STRSZ */ - const Elf_Sym* symtab; /* DT_SYMTAB */ - const Elf_Rel* pltrel; /* DT_JMPREL */ - int pltrelsize; /* DT_PLTRELSZ */ - const Elf_Rela* pltrela; /* DT_JMPREL */ - int pltrelasize; /* DT_PLTRELSZ */ - const Elf_Rel* rel; /* DT_REL */ - int relsize; /* DT_RELSZ */ - const Elf_Rela* rela; /* DT_RELA */ - int relasize; /* DT_RELASZ */ - caddr_t modptr; - const Elf_Sym* ddbsymtab; /* The symbol table we are using */ - long ddbsymcnt; /* Number of symbols */ - caddr_t ddbstrtab; /* String table */ - long ddbstrcnt; /* number of bytes in string table */ - caddr_t symbase; /* malloc'ed symbold base */ - caddr_t strbase; /* malloc'ed string base */ + caddr_t strtab; /* DT_STRTAB */ + int strsz; /* DT_STRSZ */ + const Elf_Sym* symtab; /* DT_SYMTAB */ + const Elf_Rel* pltrel; /* DT_JMPREL */ + int pltrelsize; /* DT_PLTRELSZ */ + const Elf_Rela* pltrela; /* DT_JMPREL */ + int pltrelasize; /* DT_PLTRELSZ */ + const Elf_Rel* rel; /* DT_REL */ + int relsize; /* DT_RELSZ */ + const Elf_Rela* rela; /* DT_RELA */ + int relasize; /* DT_RELASZ */ + caddr_t modptr; + const Elf_Sym* ddbsymtab; /* The symbol table we are using */ + long ddbsymcnt; /* Number of symbols */ + caddr_t ddbstrtab; /* String table */ + long ddbstrcnt; /* number of bytes in string table */ + caddr_t symbase; /* malloc'ed symbold base */ + caddr_t strbase; /* malloc'ed string base */ } *elf_file_t; static int link_elf_link_common_finish(linker_file_t); static int link_elf_link_preload(linker_class_t cls, - const char*, linker_file_t*); + const char*, linker_file_t*); static int link_elf_link_preload_finish(linker_file_t); static int link_elf_load_file(linker_class_t, const char*, linker_file_t*); static int link_elf_lookup_symbol(linker_file_t, const char*, - c_linker_sym_t*); + c_linker_sym_t*); static int link_elf_symbol_values(linker_file_t, c_linker_sym_t, linker_symval_t*); static int link_elf_search_symbol(linker_file_t, caddr_t value, - c_linker_sym_t* sym, long* diffp); + c_linker_sym_t* sym, long* diffp); static void link_elf_unload_file(linker_file_t); static int link_elf_lookup_set(linker_file_t, const char *, - void ***, void ***, int *); + void ***, void ***, int *); static int link_elf_each_function_name(linker_file_t, - int (*)(const char *, void *), - void *); + int (*)(const char *, void *), void *); static void link_elf_reloc_local(linker_file_t); static kobj_method_t link_elf_methods[] = { - KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), - KOBJMETHOD(linker_symbol_values, link_elf_symbol_values), - KOBJMETHOD(linker_search_symbol, link_elf_search_symbol), - KOBJMETHOD(linker_unload, link_elf_unload_file), - KOBJMETHOD(linker_load_file, link_elf_load_file), - KOBJMETHOD(linker_link_preload, link_elf_link_preload), - KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish), - KOBJMETHOD(linker_lookup_set, link_elf_lookup_set), - KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), - { 0, 0 } + KOBJMETHOD(linker_lookup_symbol, link_elf_lookup_symbol), + KOBJMETHOD(linker_symbol_values, link_elf_symbol_values), + KOBJMETHOD(linker_search_symbol, link_elf_search_symbol), + KOBJMETHOD(linker_unload, link_elf_unload_file), + KOBJMETHOD(linker_load_file, link_elf_load_file), + KOBJMETHOD(linker_link_preload, link_elf_link_preload), + KOBJMETHOD(linker_link_preload_finish, link_elf_link_preload_finish), + KOBJMETHOD(linker_lookup_set, link_elf_lookup_set), + KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), + { 0, 0 } }; static struct linker_class link_elf_class = { #if ELF_TARG_CLASS == ELFCLASS32 - "elf32", + "elf32", #else - "elf64", + "elf64", #endif - link_elf_methods, sizeof(struct elf_file) + link_elf_methods, sizeof(struct elf_file) }; static int relocate_file(elf_file_t ef); @@ -131,7 +130,7 @@ static void link_elf_error(const char *s) { - printf("kldload: %s\n", s); + printf("kldload: %s\n", s); } /* @@ -141,14 +140,14 @@ static int link_elf_link_common_finish(linker_file_t lf) { - int error; + int error; - /* Notify MD code that a module is being loaded. */ - error = elf_cpu_load_file(lf); - if (error) - return (error); + /* Notify MD code that a module is being loaded. */ + error = elf_cpu_load_file(lf); + if (error) + return (error); - return (0); + return (0); } static void @@ -161,8 +160,8 @@ SYSINIT(link_elf, SI_SUB_KLD, SI_ORDER_SECOND, link_elf_init, 0); static int -link_elf_link_preload(linker_class_t cls, - const char* filename, linker_file_t *result) +link_elf_link_preload(linker_class_t cls, const char* filename, + linker_file_t *result) { return (EFTYPE); } @@ -175,460 +174,455 @@ static int link_elf_load_file(linker_class_t cls, const char* filename, - linker_file_t* result) + linker_file_t* result) { - struct nameidata nd; - struct thread* td = curthread; /* XXX */ - Elf_Ehdr *hdr; - caddr_t firstpage; - int nbytes, i; - Elf_Phdr *phdr; - Elf_Phdr *phlimit; - Elf_Phdr *segs[2]; - int nsegs; - Elf_Phdr *phdyn; - Elf_Phdr *phphdr; - caddr_t mapbase; - size_t mapsize; - Elf_Off base_offset; - Elf_Addr base_vaddr; - Elf_Addr base_vlimit; - int error = 0; - int resid, flags; - elf_file_t ef; - linker_file_t lf; - Elf_Shdr *shdr; - int symtabindex; - int symstrindex; - int symcnt; - int strcnt; + struct nameidata nd; + struct thread* td = curthread; /* XXX */ + Elf_Ehdr *hdr; + caddr_t firstpage; + int nbytes, i; + Elf_Phdr *phdr; + Elf_Phdr *phlimit; + Elf_Phdr *segs[2]; + int nsegs; + caddr_t mapbase; + size_t mapsize; + Elf_Off base_offset; + Elf_Addr base_vaddr; + Elf_Addr base_vlimit; + int error = 0; + int resid, flags; + elf_file_t ef; + linker_file_t lf; + Elf_Shdr *shdr; + int symtabindex; + int symstrindex; + int symcnt; + int strcnt; - GIANT_REQUIRED; + GIANT_REQUIRED; - shdr = NULL; - lf = NULL; + shdr = NULL; + lf = NULL; - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); - flags = FREAD; - error = vn_open(&nd, &flags, 0, -1); - if (error) - return error; - NDFREE(&nd, NDF_ONLY_PNBUF); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); + flags = FREAD; + error = vn_open(&nd, &flags, 0, -1); + if (error) + return error; + NDFREE(&nd, NDF_ONLY_PNBUF); #ifdef MAC - error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp); - if (error) { - firstpage = NULL; - goto out; - } + error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp); + if (error) { + firstpage = NULL; + goto out; + } #endif - /* - * 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, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, - &resid, td); - nbytes = PAGE_SIZE - resid; - if (error) - goto out; + /* + * 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, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, + &resid, td); + nbytes = PAGE_SIZE - resid; + if (error) + goto out; + if (nbytes < sizeof(Elf_Ehdr)) + error = ENOEXEC; + goto out; + } - if (!IS_ELF(*hdr)) { - error = ENOEXEC; - goto out; - } + if (!IS_ELF(*hdr)) { + error = ENOEXEC; + goto out; + } - if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS - || 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) { - link_elf_error("Unsupported file version"); - error = ENOEXEC; - goto out; - } - if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { - link_elf_error("Unsupported file type"); - error = ENOEXEC; - goto out; - } - if (hdr->e_machine != ELF_TARG_MACH) { - link_elf_error("Unsupported machine"); - error = ENOEXEC; - goto out; - } + if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS + || 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) { + link_elf_error("Unsupported file version"); + error = ENOEXEC; + goto out; + } + if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { + link_elf_error("Unsupported file type"); + error = ENOEXEC; + goto out; + } + if (hdr->e_machine != ELF_TARG_MACH) { + link_elf_error("Unsupported machine"); + error = ENOEXEC; + goto out; + } - /* - * We rely on the program header being in the first page. This is - * not strictly required by the ABI specification, but it seems to - * always true in practice. And, it simplifies things considerably. - * XXX section table, not program header. And we should not depend - * XXX on this because the section table is likely to be bigger. - */ - 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))) - link_elf_error("Unreadable program headers"); + /* Read in the section header */ + nbytes = hdr->e_shnum * hdr->e_shentsize; + if (nbytes == 0 || hdr->e_shoff == 0 || + hdr->e_shentsize != sizeof(Elf_Shdr)) { + error = ENOEXEC; + goto out; + } + shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO); + if (shdr == NULL) { + error = ENOMEM; + goto out; + } + error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes, hdr->e_shoff, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); + if (error) + goto out; + if (resid) { + error = ENOEXEC; + goto out; + } - /* - * Scan the program header entries, and save key information. - * - * We rely on there being exactly two load segments, text and data, - * in that order. - * - * XXX do several passes of section table instead. - * XXX 1) count various things needed to size arrays - * XXX 2) grab info about things like PROGBITS/REL/RELA/STRTAB/SYMTAB - * XXX 3) read the string and symbol tables so we can do relocations etc - * XXX 4) (later on) load the rest of the entries. - */ + /* + * Scan the program header entries, and save key information. + * + * We rely on there being exactly two load segments, text and data, + * in that order. + * + * XXX do several passes of section table instead. + * XXX 1) count various things needed to size arrays + * XXX 2) grab info about things like PROGBITS/REL/RELA/STRTAB/SYMTAB + * XXX 3) read the string and symbol tables so we can do relocations etc + * XXX 4) (later on) load the rest of the entries. + */ /* XXX *************** STEP 1 GOES HERE ************* XXX */ - phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff); - phlimit = phdr + hdr->e_phnum; - nsegs = 0; - phdyn = NULL; - phphdr = NULL; - while (phdr < phlimit) { - switch (phdr->p_type) { - - case PT_LOAD: - if (nsegs == 2) { - link_elf_error("Too many sections"); + shdr = (Elf_Shdr *)shtbuf; + shlimit = shdr + hdr->e_phnum; + nbits = 0; + nnobits = 0; + nsym = 0; + nrel = 0; + nrela = 0; + for (i = 0; i < hdr->e_shnum; i++) { + switch (shdr[i].sh_type) { + case SHT_PROGBITS: + nprogbits++; + break; + case SHT_NOBITS: + nnobits++; + break; + case SHT_SYMTAB: + nsym++; + symstrindex = shdr[i].sh_link; + break; + case SHT_REL: + nrel++; + break; + case SHT_RELA: + nrela++; + break; + } + } + if (nprogbits == 0 && nnobits == 0) { + link_elf_error("file has no contents"); + error = ENOEXEC; + goto out; + } + if (nsym != 1) { + link_elf_error("file has no valid symbol table"); + error = ENOEXEC; + goto out; + } + if (symstrindex < 0 || sysmstrindex > hdr->e_shnum || + shdr[symstrindex].sh_type != SHT_STRTAB) { + link_elf_error("file has invalid symbol strings"); error = ENOEXEC; goto out; - } - /* - * XXX: We just trust they come in right order ?? - */ - segs[nsegs] = phdr; - ++nsegs; - break; + } - case PT_PHDR: - phphdr = phdr; - break; +/* XXX *************** STEP 2 GOES HERE ************* XXX */ + symtabindex = -1; + symstrindex = -1; + for (i = 0; i < hdr->e_shnum; i++) { + switch (shdr[i].sh_type) { - case PT_DYNAMIC: - phdyn = phdr; - break; - - case PT_INTERP: - link_elf_error("Unsupported file type"); - error = ENOEXEC; - goto out; + case SHT_SYMTAB: + symtabindex = i; + symstrindex = shdr[i].sh_link; + break; + } } - - ++phdr; - } - if (phdyn == NULL) { - link_elf_error("Object is not dynamically-linked"); - error = ENOEXEC; - goto out; - } - if (nsegs != 2) { - link_elf_error("Too few sections"); - error = ENOEXEC; - goto out; - } -/* XXX *************** STEP 2 GOES HERE ************* XXX */ /* XXX *************** STEP 3 GOES HERE ************* XXX */ - /* 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) - goto nosyms; - shdr = malloc(nbytes, M_LINKER, M_WAITOK | M_ZERO); - if (shdr == NULL) { - error = ENOMEM; - goto out; - } - error = vn_rdwr(UIO_READ, nd.ni_vp, - (caddr_t)shdr, nbytes, hdr->e_shoff, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, - &resid, td); - if (error) - goto out; - symtabindex = -1; - symstrindex = -1; - for (i = 0; i < hdr->e_shnum; i++) { - if (shdr[i].sh_type == SHT_SYMTAB) { - symtabindex = i; - symstrindex = shdr[i].sh_link; - } - } - if (symtabindex < 0 || symstrindex < 0) - goto nosyms; + /* Load the symbol table. */ + if (symtabindex < 0 || symstrindex < 0) + goto nosyms; - symcnt = shdr[symtabindex].sh_size; - ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK); - strcnt = shdr[symstrindex].sh_size; - ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK); + symcnt = shdr[symtabindex].sh_size; + ef->symbase = malloc(symcnt, M_LINKER, M_WAITOK); + strcnt = shdr[symstrindex].sh_size; + ef->strbase = malloc(strcnt, M_LINKER, M_WAITOK); - if (ef->symbase == NULL || ef->strbase == NULL) { - error = ENOMEM; - goto out; - } - error = vn_rdwr(UIO_READ, nd.ni_vp, - ef->symbase, symcnt, shdr[symtabindex].sh_offset, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, - &resid, td); - if (error) - goto out; - error = vn_rdwr(UIO_READ, nd.ni_vp, - ef->strbase, strcnt, shdr[symstrindex].sh_offset, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, - &resid, td); - if (error) - goto out; + if (ef->symbase == NULL || ef->strbase == NULL) { + error = ENOMEM; + goto out; + } + error = vn_rdwr(UIO_READ, nd.ni_vp, + ef->symbase, symcnt, shdr[symtabindex].sh_offset, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, + &resid, td); + if (error) + goto out; + error = vn_rdwr(UIO_READ, nd.ni_vp, + ef->strbase, strcnt, shdr[symstrindex].sh_offset, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, + &resid, td); + if (error) + goto out; - ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); - ef->ddbsymtab = (const Elf_Sym *)ef->symbase; - ef->ddbstrcnt = strcnt; - ef->ddbstrtab = ef->strbase; + ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); + ef->ddbsymtab = (const Elf_Sym *)ef->symbase; + ef->ddbstrcnt = strcnt; + ef->ddbstrtab = ef->strbase; /* XXX *************** STEP 4 GOES HERE ************* XXX */ - /* - * Allocate the entire address space of the object, to stake out our - * contiguous region, and to establish the base address for relocation. - */ - base_offset = trunc_page(segs[0]->p_offset); - base_vaddr = trunc_page(segs[0]->p_vaddr); - base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); - mapsize = base_vlimit - base_vaddr; + /* + * Allocate the entire address space of the object, to stake out our + * contiguous region, and to establish the base address for relocation. + */ + base_offset = trunc_page(segs[0]->p_offset); + base_vaddr = trunc_page(segs[0]->p_vaddr); + base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); + mapsize = base_vlimit - base_vaddr; - lf = linker_make_file(filename, &link_elf_class); - if (!lf) { - error = ENOMEM; - goto out; - } + lf = linker_make_file(filename, &link_elf_class); + if (!lf) { + error = ENOMEM; + goto out; + } - ef = (elf_file_t) lf; + ef = (elf_file_t) lf; #ifdef SPARSE_MAPPING - ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT); - if (ef->object == NULL) { - error = ENOMEM; - goto out; - } - vm_object_reference(ef->object); - ef->address = (caddr_t) vm_map_min(kernel_map); - error = vm_map_find(kernel_map, ef->object, 0, - (vm_offset_t *) &ef->address, - mapsize, 1, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) { - vm_object_deallocate(ef->object); - ef->object = 0; - goto out; - } + ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT); + if (ef->object == NULL) { + error = ENOMEM; + goto out; + } + vm_object_reference(ef->object); + ef->address = (caddr_t) vm_map_min(kernel_map); + error = vm_map_find(kernel_map, ef->object, 0, + (vm_offset_t *) &ef->address, + mapsize, 1, + VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) { + vm_object_deallocate(ef->object); + ef->object = 0; + goto out; + } #else - ef->address = malloc(mapsize, M_LINKER, M_WAITOK); - if (!ef->address) { - error = ENOMEM; - goto out; - } + ef->address = malloc(mapsize, M_LINKER, M_WAITOK); + if (!ef->address) { + error = ENOMEM; + goto out; + } #endif - mapbase = ef->address; + mapbase = ef->address; - /* - * Read the text and data sections and zero the bss. - */ - for (i = 0; i < 2; i++) { - caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr; - error = vn_rdwr(UIO_READ, nd.ni_vp, - segbase, segs[i]->p_filesz, segs[i]->p_offset, - UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, - &resid, td); - if (error) { - goto out; - } - bzero(segbase + segs[i]->p_filesz, - segs[i]->p_memsz - segs[i]->p_filesz); + /* + * Read the text and data sections and zero the bss. + */ + for (i = 0; i < 2; i++) { + caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr; + error = vn_rdwr(UIO_READ, nd.ni_vp, + segbase, segs[i]->p_filesz, segs[i]->p_offset, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, + &resid, td); + if (error) { + goto out; + } + bzero(segbase + segs[i]->p_filesz, + segs[i]->p_memsz - segs[i]->p_filesz); #ifdef SPARSE_MAPPING - /* - * Wire down the pages - */ - vm_map_wire(kernel_map, + /* + * Wire down the pages + */ + vm_map_wire(kernel_map, (vm_offset_t) segbase, (vm_offset_t) segbase + segs[i]->p_memsz, VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES); #endif - } + } - /* ef->dynamic = (Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); */ + lf->address = ef->address; + lf->size = mapsize; - lf->address = ef->address; - lf->size = mapsize; + link_elf_reloc_local(lf); - link_elf_reloc_local(lf); + error = linker_load_dependencies(lf); + if (error) + goto out; + error = relocate_file(ef); + if (error) + goto out; - error = linker_load_dependencies(lf); - if (error) - goto out; - error = relocate_file(ef); - if (error) - goto out; + error = link_elf_link_common_finish(lf); + if (error) + goto out; - error = link_elf_link_common_finish(lf); - if (error) - goto out; + nosyms: -nosyms: + *result = lf; - *result = lf; + out: + if (error && lf) + linker_file_unload(lf); + if (shdr) + free(shdr, M_LINKER); + if (firstpage) + free(firstpage, M_LINKER); + VOP_UNLOCK(nd.ni_vp, 0, td); + vn_close(nd.ni_vp, FREAD, td->td_ucred, td); -out: - if (error && lf) - linker_file_unload(lf); - if (shdr) - free(shdr, M_LINKER); - if (firstpage) - free(firstpage, M_LINKER); - VOP_UNLOCK(nd.ni_vp, 0, td); - vn_close(nd.ni_vp, FREAD, td->td_ucred, td); - - return error; + return error; } static void link_elf_unload_file(linker_file_t file) { - elf_file_t ef = (elf_file_t) file; + elf_file_t ef = (elf_file_t) file; - /* Notify MD code that a module is being unloaded. */ - elf_cpu_unload_file(file); + /* Notify MD code that a module is being unloaded. */ + elf_cpu_unload_file(file); #ifdef SPARSE_MAPPING - if (ef->object) { - vm_map_remove(kernel_map, (vm_offset_t) ef->address, - (vm_offset_t) ef->address - + (ef->object->size << PAGE_SHIFT)); - vm_object_deallocate(ef->object); - } + if (ef->object) { + vm_map_remove(kernel_map, (vm_offset_t) ef->address, + (vm_offset_t) ef->address + + (ef->object->size << PAGE_SHIFT)); + vm_object_deallocate(ef->object); + } #else - if (ef->address) - free(ef->address, M_LINKER); + if (ef->address) + free(ef->address, M_LINKER); #endif - if (ef->symbase) - free(ef->symbase, M_LINKER); - if (ef->strbase) - free(ef->strbase, M_LINKER); + if (ef->symbase) + free(ef->symbase, M_LINKER); + if (ef->strbase) + free(ef->strbase, M_LINKER); } static const char * symbol_name(elf_file_t ef, Elf_Word r_info) { - const Elf_Sym *ref; + const Elf_Sym *ref; - if (ELF_R_SYM(r_info)) { - ref = ef->symtab + ELF_R_SYM(r_info); - return ef->strtab + ref->st_name; - } else - return NULL; + if (ELF_R_SYM(r_info)) { + ref = ef->symtab + ELF_R_SYM(r_info); + return ef->strtab + ref->st_name; + } else + return NULL; } static int relocate_file(elf_file_t ef) { - const Elf_Rel *rellim; - const Elf_Rel *rel; - const Elf_Rela *relalim; - const Elf_Rela *rela; - const char *symname; + const Elf_Rel *rellim; + const Elf_Rel *rel; + const Elf_Rela *relalim; + const Elf_Rela *rela; + const char *symname; - /* Perform relocations without addend if there are any: */ - rel = ef->rel; - if (rel) { - rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); - while (rel < rellim) { - if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { - symname = symbol_name(ef, rel->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; - } - rel++; + /* Perform relocations without addend if there are any: */ + rel = ef->rel; + if (rel) { + rellim = (const Elf_Rel *)((const char *)ef->rel + ef->relsize); + while (rel < rellim) { + if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { + symname = symbol_name(ef, rel->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + rel++; + } } - } - /* Perform relocations with addend if there are any: */ - rela = ef->rela; - if (rela) { - relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); - while (rela < relalim) { - if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { - symname = symbol_name(ef, rela->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; - } - rela++; + /* Perform relocations with addend if there are any: */ + rela = ef->rela; + if (rela) { + relalim = (const Elf_Rela *)((const char *)ef->rela + ef->relasize); + while (rela < relalim) { + if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { + symname = symbol_name(ef, rela->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + rela++; + } } - } - /* Perform PLT relocations without addend if there are any: */ - rel = ef->pltrel; - if (rel) { - rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize); - while (rel < rellim) { - if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { - symname = symbol_name(ef, rel->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; - } - rel++; + /* Perform PLT relocations without addend if there are any: */ + rel = ef->pltrel; + if (rel) { + rellim = (const Elf_Rel *)((const char *)ef->pltrel + ef->pltrelsize); + while (rel < rellim) { + if (elf_reloc(&ef->lf, rel, ELF_RELOC_REL)) { + symname = symbol_name(ef, rel->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + rel++; + } } - } - /* Perform relocations with addend if there are any: */ - rela = ef->pltrela; - if (rela) { - relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize); - while (rela < relalim) { - if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { - symname = symbol_name(ef, rela->r_info); - printf("link_elf: symbol %s undefined\n", symname); - return ENOENT; - } - rela++; + /* Perform relocations with addend if there are any: */ + rela = ef->pltrela; + if (rela) { + relalim = (const Elf_Rela *)((const char *)ef->pltrela + ef->pltrelasize); + while (rela < relalim) { + if (elf_reloc(&ef->lf, rela, ELF_RELOC_RELA)) { + symname = symbol_name(ef, rela->r_info); + printf("link_elf: symbol %s undefined\n", symname); + return ENOENT; + } + rela++; + } } - } - return 0; + return 0; } static int link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) { - elf_file_t ef = (elf_file_t) lf; - unsigned long symnum; - const Elf_Sym* symp; - const char *strp; - int i; + elf_file_t ef = (elf_file_t) lf; + unsigned long symnum; + const Elf_Sym* symp; + const char *strp; + int i; /* XXX search for globals first */ - /* Exhaustive search */ - for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { - strp = ef->ddbstrtab + symp->st_name; - if (strcmp(name, strp) == 0) { - if (symp->st_shndx != SHN_UNDEF || - (symp->st_value != 0 && - ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { - *sym = (c_linker_sym_t) symp; - return 0; - } else - return ENOENT; + /* Exhaustive search */ + for (i = 0, symp = ef->ddbsymtab; i < ef->ddbsymcnt; i++, symp++) { + strp = ef->ddbstrtab + symp->st_name; + if (strcmp(name, strp) == 0) { + if (symp->st_shndx != SHN_UNDEF || + (symp->st_value != 0 && + ELF_ST_TYPE(symp->st_info) == STT_FUNC)) { + *sym = (c_linker_sym_t) symp; + return 0; + } else + return ENOENT; + } } - } - return ENOENT; + return ENOENT; } static int @@ -638,17 +632,17 @@ const Elf_Sym* es = (const Elf_Sym*) sym; if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { - symval->name = ef->ddbstrtab + es->st_name; - symval->value = (caddr_t) ef->address + es->st_value; - symval->size = es->st_size; - return 0; + symval->name = ef->ddbstrtab + es->st_name; + symval->value = (caddr_t) ef->address + es->st_value; >>> TRUNCATED FOR MAIL (1000 lines) <<<