From 6b6324985aeec7efd9d76a6897f9d6667bdb2f18 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Wed, 21 Feb 2018 19:42:54 +0000 Subject: [PATCH] load_elf.c: Use consistent indentation As noted in D14267 load_elf.c has a variety of indentation styles. Move to standard 8 column hard tab indents, 4 space second level indents. Also includes some whitespace cleanups found by clang-format. --- stand/common/load_elf.c | 1274 ++++++++++++++++++++------------------- 1 file changed, 656 insertions(+), 618 deletions(-) diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c index 89c073381ad1..572f062fe7f0 100644 --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -52,29 +52,31 @@ __FBSDID("$FreeBSD$"); #endif typedef struct elf_file { - Elf_Phdr *ph; - Elf_Ehdr *ehdr; - Elf_Sym *symtab; - Elf_Hashelt *hashtab; - Elf_Hashelt nbuckets; - Elf_Hashelt nchains; - Elf_Hashelt *buckets; - Elf_Hashelt *chains; - Elf_Rel *rel; - size_t relsz; - Elf_Rela *rela; - size_t relasz; - char *strtab; - size_t strsz; - int fd; - caddr_t firstpage; - size_t firstlen; - int kernel; - u_int64_t off; + Elf_Phdr *ph; + Elf_Ehdr *ehdr; + Elf_Sym *symtab; + Elf_Hashelt *hashtab; + Elf_Hashelt nbuckets; + Elf_Hashelt nchains; + Elf_Hashelt *buckets; + Elf_Hashelt *chains; + Elf_Rel *rel; + size_t relsz; + Elf_Rela *rela; + size_t relasz; + char *strtab; + size_t strsz; + int fd; + caddr_t firstpage; + size_t firstlen; + int kernel; + u_int64_t off; } *elf_file_t; -static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t loadaddr); -static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); +static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, + u_int64_t loadaddr); +static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, + const char* name, Elf_Sym* sym); static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len); static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef, @@ -198,11 +200,11 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef) { ssize_t bytes_read; Elf_Ehdr *ehdr; - int err; + int err; /* - * Open the image, read and validate the ELF header - */ + * Open the image, read and validate the ELF header + */ if (filename == NULL) /* can't handle nameless */ return (EFTYPE); if ((ef->fd = open(filename, O_RDONLY)) == -1) @@ -237,7 +239,8 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef) if (err) goto error; - if (ehdr->e_version != EV_CURRENT || ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ + if (ehdr->e_version != EV_CURRENT || ehdr->e_machine != ELF_TARG_MACH) { + /* Machine ? */ err = EFTYPE; goto error; } @@ -271,136 +274,144 @@ int __elfN(loadfile_raw)(char *filename, u_int64_t dest, struct preloaded_file **result, int multiboot) { - struct preloaded_file *fp, *kfp; - struct elf_file ef; - Elf_Ehdr *ehdr; - int err; + struct preloaded_file *fp, *kfp; + struct elf_file ef; + Elf_Ehdr *ehdr; + int err; - fp = NULL; - bzero(&ef, sizeof(struct elf_file)); - ef.fd = -1; + fp = NULL; + bzero(&ef, sizeof(struct elf_file)); + ef.fd = -1; - err = __elfN(load_elf_header)(filename, &ef); - if (err != 0) - return (err); + err = __elfN(load_elf_header)(filename, &ef); + if (err != 0) + return (err); - ehdr = ef.ehdr; + ehdr = ef.ehdr; - /* - * Check to see what sort of module we are. - */ - kfp = file_findfile(NULL, __elfN(kerneltype)); -#ifdef __powerpc__ - /* - * Kernels can be ET_DYN, so just assume the first loaded object is the - * kernel. This assumption will be checked later. - */ - if (kfp == NULL) - ef.kernel = 1; -#endif - if (ef.kernel || ehdr->e_type == ET_EXEC) { - /* Looks like a kernel */ - if (kfp != NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n"); - err = EPERM; - goto oerr; - } - /* - * Calculate destination address based on kernel entrypoint. - * - * For ARM, the destination address is independent of any values in the - * elf header (an ARM kernel can be loaded at any 2MB boundary), so we - * leave dest set to the value calculated by archsw.arch_loadaddr() and - * passed in to this function. + /* + * Check to see what sort of module we are. */ -#ifndef __arm__ - if (ehdr->e_type == ET_EXEC) - dest = (ehdr->e_entry & ~PAGE_MASK); + kfp = file_findfile(NULL, __elfN(kerneltype)); +#ifdef __powerpc__ + /* + * Kernels can be ET_DYN, so just assume the first loaded object is the + * kernel. This assumption will be checked later. + */ + if (kfp == NULL) + ef.kernel = 1; #endif - if ((ehdr->e_entry & ~PAGE_MASK) == 0) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); - err = EPERM; - goto oerr; - } - ef.kernel = 1; + if (ef.kernel || ehdr->e_type == ET_EXEC) { + /* Looks like a kernel */ + if (kfp != NULL) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: kernel already loaded\n"); + err = EPERM; + goto oerr; + } + /* + * Calculate destination address based on kernel entrypoint. + * + * For ARM, the destination address is independent of any values + * in the elf header (an ARM kernel can be loaded at any 2MB + * boundary), so we leave dest set to the value calculated by + * archsw.arch_loadaddr() and passed in to this function. + */ +#ifndef __arm__ + if (ehdr->e_type == ET_EXEC) + dest = (ehdr->e_entry & ~PAGE_MASK); +#endif + if ((ehdr->e_entry & ~PAGE_MASK) == 0) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: not a kernel (maybe static binary?)\n"); + err = EPERM; + goto oerr; + } + ef.kernel = 1; - } else if (ehdr->e_type == ET_DYN) { - /* Looks like a kld module */ - if (multiboot != 0) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n"); - err = EPERM; + } else if (ehdr->e_type == ET_DYN) { + /* Looks like a kld module */ + if (multiboot != 0) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: can't load module as multiboot\n"); + err = EPERM; + goto oerr; + } + if (kfp == NULL) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: can't load module before kernel\n"); + err = EPERM; + goto oerr; + } + if (strcmp(__elfN(kerneltype), kfp->f_type)) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: can't load module with kernel type '%s'\n", + kfp->f_type); + err = EPERM; + goto oerr; + } + /* Looks OK, got ahead */ + ef.kernel = 0; + + } else { + err = EFTYPE; goto oerr; } - if (kfp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n"); - err = EPERM; - goto oerr; + + if (archsw.arch_loadaddr != NULL) + dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest); + else + dest = roundup(dest, PAGE_SIZE); + + /* + * Ok, we think we should handle this. + */ + fp = file_alloc(); + if (fp == NULL) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadfile: cannot allocate module info\n"); + err = EPERM; + goto out; } - if (strcmp(__elfN(kerneltype), kfp->f_type)) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); - err = EPERM; - goto oerr; - } - /* Looks OK, got ahead */ - ef.kernel = 0; - - } else { - err = EFTYPE; - goto oerr; - } - - if (archsw.arch_loadaddr != NULL) - dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest); - else - dest = roundup(dest, PAGE_SIZE); - - /* - * Ok, we think we should handle this. - */ - fp = file_alloc(); - if (fp == NULL) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n"); - err = EPERM; - goto out; - } - if (ef.kernel == 1 && multiboot == 0) - setenv("kernelname", filename, 1); - fp->f_name = strdup(filename); - if (multiboot == 0) - fp->f_type = strdup(ef.kernel ? - __elfN(kerneltype) : __elfN(moduletype)); - else - fp->f_type = strdup("elf multiboot kernel"); + if (ef.kernel == 1 && multiboot == 0) + setenv("kernelname", filename, 1); + fp->f_name = strdup(filename); + if (multiboot == 0) + fp->f_type = strdup(ef.kernel ? + __elfN(kerneltype) : __elfN(moduletype)); + else + fp->f_type = strdup("elf multiboot kernel"); #ifdef ELF_VERBOSE - if (ef.kernel) - printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry); + if (ef.kernel) + printf("%s entry at 0x%jx\n", filename, + (uintmax_t)ehdr->e_entry); #else - printf("%s ", filename); + printf("%s ", filename); #endif - fp->f_size = __elfN(loadimage)(fp, &ef, dest); - if (fp->f_size == 0 || fp->f_addr == 0) - goto ioerr; + fp->f_size = __elfN(loadimage)(fp, &ef, dest); + if (fp->f_size == 0 || fp->f_addr == 0) + goto ioerr; - /* save exec header as metadata */ - file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); + /* save exec header as metadata */ + file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); - /* Load OK, return module pointer */ - *result = (struct preloaded_file *)fp; - err = 0; - goto out; - - ioerr: - err = EIO; - oerr: - file_discard(fp); - out: - if (ef.firstpage) - free(ef.firstpage); - if (ef.fd != -1) - close(ef.fd); - return(err); + /* Load OK, return module pointer */ + *result = (struct preloaded_file *)fp; + err = 0; + goto out; + +ioerr: + err = EIO; +oerr: + file_discard(fp); +out: + if (ef.firstpage) + free(ef.firstpage); + if (ef.fd != -1) + close(ef.fd); + return (err); } /* @@ -410,408 +421,431 @@ __elfN(loadfile_raw)(char *filename, u_int64_t dest, static int __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) { - int i; - u_int j; - Elf_Ehdr *ehdr; - Elf_Phdr *phdr, *php; - Elf_Shdr *shdr; - char *shstr; - int ret; - vm_offset_t firstaddr; - vm_offset_t lastaddr; - size_t chunk; - ssize_t result; - Elf_Addr ssym, esym; - Elf_Dyn *dp; - Elf_Addr adp; - Elf_Addr ctors; - int ndp; - int symstrindex; - int symtabindex; - Elf_Size size; - u_int fpcopy; - Elf_Sym sym; - Elf_Addr p_start, p_end; + int i; + u_int j; + Elf_Ehdr *ehdr; + Elf_Phdr *phdr, *php; + Elf_Shdr *shdr; + char *shstr; + int ret; + vm_offset_t firstaddr; + vm_offset_t lastaddr; + size_t chunk; + ssize_t result; + Elf_Addr ssym, esym; + Elf_Dyn *dp; + Elf_Addr adp; + Elf_Addr ctors; + int ndp; + int symstrindex; + int symtabindex; + Elf_Size size; + u_int fpcopy; + Elf_Sym sym; + Elf_Addr p_start, p_end; - dp = NULL; - shdr = NULL; - ret = 0; - firstaddr = lastaddr = 0; - ehdr = ef->ehdr; - if (ehdr->e_type == ET_EXEC) { + dp = NULL; + shdr = NULL; + ret = 0; + firstaddr = lastaddr = 0; + ehdr = ef->ehdr; + if (ehdr->e_type == ET_EXEC) { #if defined(__i386__) || defined(__amd64__) #if __ELF_WORD_SIZE == 64 - off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */ + /* x86_64 relocates after locore */ + off = - (off & 0xffffffffff000000ull); #else - off = - (off & 0xff000000u); /* i386 relocates after locore */ + /* i386 relocates after locore */ + off = - (off & 0xff000000u); #endif #elif defined(__powerpc__) - /* - * On the purely virtual memory machines like e500, the kernel is - * linked against its final VA range, which is most often not - * available at the loader stage, but only after kernel initializes - * and completes its VM settings. In such cases we cannot use p_vaddr - * field directly to load ELF segments, but put them at some - * 'load-time' locations. - */ - if (off & 0xf0000000u) { - off = -(off & 0xf0000000u); - /* - * XXX the physical load address should not be hardcoded. Note - * that the Book-E kernel assumes that it's loaded at a 16MB - * boundary for now... - */ - off += 0x01000000; - ehdr->e_entry += off; + /* + * On the purely virtual memory machines like e500, the kernel + * is linked against its final VA range, which is most often + * not available at the loader stage, but only after kernel + * initializes and completes its VM settings. In such cases we + * cannot use p_vaddr field directly to load ELF segments, but + * put them at some 'load-time' locations. + */ + if (off & 0xf0000000u) { + off = -(off & 0xf0000000u); + /* + * XXX the physical load address should not be + * hardcoded. Note that the Book-E kernel assumes that + * it's loaded at a 16MB boundary for now... + */ + off += 0x01000000; + ehdr->e_entry += off; #ifdef ELF_VERBOSE - printf("Converted entry 0x%08x\n", ehdr->e_entry); + printf("Converted entry 0x%08x\n", ehdr->e_entry); #endif - } else - off = 0; + } else + off = 0; #elif defined(__arm__) && !defined(EFI) - /* - * The elf headers in arm kernels specify virtual addresses in all - * header fields, even the ones that should be physical addresses. - * We assume the entry point is in the first page, and masking the page - * offset will leave us with the virtual address the kernel was linked - * at. We subtract that from the load offset, making 'off' into the - * value which, when added to a virtual address in an elf header, - * translates it to a physical address. We do the va->pa conversion on - * the entry point address in the header now, so that later we can - * launch the kernel by just jumping to that address. - * - * When booting from UEFI the copyin and copyout functions handle - * adjusting the location relative to the first virtual address. - * Because of this there is no need to adjust the offset or entry - * point address as these will both be handled by the efi code. - */ - off -= ehdr->e_entry & ~PAGE_MASK; - ehdr->e_entry += off; + /* + * The elf headers in arm kernels specify virtual addresses in + * all header fields, even the ones that should be physical + * addresses. We assume the entry point is in the first page, + * and masking the page offset will leave us with the virtual + * address the kernel was linked at. We subtract that from the + * load offset, making 'off' into the value which, when added + * to a virtual address in an elf header, translates it to a + * physical address. We do the va->pa conversion on the entry + * point address in the header now, so that later we can launch + * the kernel by just jumping to that address. + * + * When booting from UEFI the copyin and copyout functions + * handle adjusting the location relative to the first virtual + * address. Because of this there is no need to adjust the + * offset or entry point address as these will both be handled + * by the efi code. + */ + off -= ehdr->e_entry & ~PAGE_MASK; + ehdr->e_entry += off; #ifdef ELF_VERBOSE - printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); + printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", + ehdr->e_entry, off); #endif #else - off = 0; /* other archs use direct mapped kernels */ + off = 0; /* other archs use direct mapped kernels */ #endif - } - ef->off = off; - - if (ef->kernel) - __elfN(relocation_offset) = off; - - if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { - printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n"); - goto out; - } - phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - if (elf_program_header_convert(ehdr, phdr)) - continue; - - /* We want to load PT_LOAD segments only.. */ - if (phdr[i].p_type != PT_LOAD) - continue; - -#ifdef ELF_VERBOSE - printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", - (long)phdr[i].p_filesz, (long)phdr[i].p_offset, - (long)(phdr[i].p_vaddr + off), - (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); -#else - if ((phdr[i].p_flags & PF_W) == 0) { - printf("text=0x%lx ", (long)phdr[i].p_filesz); - } else { - printf("data=0x%lx", (long)phdr[i].p_filesz); - if (phdr[i].p_filesz < phdr[i].p_memsz) - printf("+0x%lx", (long)(phdr[i].p_memsz -phdr[i].p_filesz)); - printf(" "); } -#endif - fpcopy = 0; - if (ef->firstlen > phdr[i].p_offset) { - fpcopy = ef->firstlen - phdr[i].p_offset; - archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, - phdr[i].p_vaddr + off, fpcopy); - } - if (phdr[i].p_filesz > fpcopy) { - if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, - phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_loadimage: read failed\n"); + ef->off = off; + + if (ef->kernel) + __elfN(relocation_offset) = off; + + if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { + printf("elf" __XSTRING(__ELF_WORD_SIZE) + "_loadimage: program header not within first page\n"); goto out; - } } - /* clear space from oversized segments; eg: bss */ - if (phdr[i].p_filesz < phdr[i].p_memsz) { + phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; i++) { + if (elf_program_header_convert(ehdr, phdr)) + continue; + + /* We want to load PT_LOAD segments only.. */ + if (phdr[i].p_type != PT_LOAD) + continue; + #ifdef ELF_VERBOSE - printf(" (bss: 0x%lx-0x%lx)", - (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), - (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); + printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", + (long)phdr[i].p_filesz, (long)phdr[i].p_offset, + (long)(phdr[i].p_vaddr + off), + (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); +#else + if ((phdr[i].p_flags & PF_W) == 0) { + printf("text=0x%lx ", (long)phdr[i].p_filesz); + } else { + printf("data=0x%lx", (long)phdr[i].p_filesz); + if (phdr[i].p_filesz < phdr[i].p_memsz) + printf("+0x%lx", (long)(phdr[i].p_memsz - + phdr[i].p_filesz)); + printf(" "); + } +#endif + fpcopy = 0; + if (ef->firstlen > phdr[i].p_offset) { + fpcopy = ef->firstlen - phdr[i].p_offset; + archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, + phdr[i].p_vaddr + off, fpcopy); + } + if (phdr[i].p_filesz > fpcopy) { + if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, + phdr[i].p_filesz - fpcopy, + phdr[i].p_offset + fpcopy) != 0) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "_loadimage: read failed\n"); + goto out; + } + } + /* clear space from oversized segments; eg: bss */ + if (phdr[i].p_filesz < phdr[i].p_memsz) { +#ifdef ELF_VERBOSE + printf(" (bss: 0x%lx-0x%lx)", + (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), + (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz -1)); #endif - kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz, - phdr[i].p_memsz - phdr[i].p_filesz); - } + kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz, + phdr[i].p_memsz - phdr[i].p_filesz); + } #ifdef ELF_VERBOSE - printf("\n"); + printf("\n"); #endif - if (archsw.arch_loadseg != NULL) - archsw.arch_loadseg(ehdr, phdr + i, off); + if (archsw.arch_loadseg != NULL) + archsw.arch_loadseg(ehdr, phdr + i, off); - if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) - firstaddr = phdr[i].p_vaddr + off; - if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz)) - lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; - } - lastaddr = roundup(lastaddr, sizeof(long)); - - /* - * Get the section headers. We need this for finding the .ctors - * section as well as for loading any symbols. Both may be hard - * to do if reading from a .gz file as it involves seeking. I - * think the rule is going to have to be that you must strip a - * file to remove symbols before gzipping it. - */ - chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize; - if (chunk == 0 || ehdr->e_shoff == 0) - goto nosyms; - shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); - if (shdr == NULL) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) - "_loadimage: failed to read section headers"); - goto nosyms; - } - - for (i = 0; i < ehdr->e_shnum; i++) - elf_section_header_convert(ehdr, &shdr[i]); - - file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr); - - /* - * Read the section string table and look for the .ctors section. - * We need to tell the kernel where it is so that it can call the - * ctors. - */ - chunk = shdr[ehdr->e_shstrndx].sh_size; - if (chunk) { - shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, chunk); - if (shstr) { - for (i = 0; i < ehdr->e_shnum; i++) { - if (strcmp(shstr + shdr[i].sh_name, ".ctors") != 0) - continue; - ctors = shdr[i].sh_addr; - file_addmetadata(fp, MODINFOMD_CTORS_ADDR, sizeof(ctors), - &ctors); - size = shdr[i].sh_size; - file_addmetadata(fp, MODINFOMD_CTORS_SIZE, sizeof(size), - &size); - break; - } - free(shstr); + if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) + firstaddr = phdr[i].p_vaddr + off; + if (lastaddr == 0 || lastaddr < + (phdr[i].p_vaddr + off + phdr[i].p_memsz)) + lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; } - } + lastaddr = roundup(lastaddr, sizeof(long)); - /* - * Now load any symbols. - */ - symtabindex = -1; - symstrindex = -1; - for (i = 0; i < ehdr->e_shnum; i++) { - if (shdr[i].sh_type != SHT_SYMTAB) - continue; - for (j = 0; j < ehdr->e_phnum; j++) { - if (phdr[j].p_type != PT_LOAD) - continue; - if (shdr[i].sh_offset >= phdr[j].p_offset && - (shdr[i].sh_offset + shdr[i].sh_size <= - phdr[j].p_offset + phdr[j].p_filesz)) { - shdr[i].sh_offset = 0; - shdr[i].sh_size = 0; - break; - } + /* + * Get the section headers. We need this for finding the .ctors + * section as well as for loading any symbols. Both may be hard + * to do if reading from a .gz file as it involves seeking. I + * think the rule is going to have to be that you must strip a + * file to remove symbols before gzipping it. + */ + chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize; + if (chunk == 0 || ehdr->e_shoff == 0) + goto nosyms; + shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); + if (shdr == NULL) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "_loadimage: failed to read section headers"); + goto nosyms; } - if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) - continue; /* alread loaded in a PT_LOAD above */ - /* Save it for loading below */ - symtabindex = i; - symstrindex = shdr[i].sh_link; - } - if (symtabindex < 0 || symstrindex < 0) - goto nosyms; - /* Ok, committed to a load. */ + for (i = 0; i < ehdr->e_shnum; i++) + elf_section_header_convert(ehdr, &shdr[i]); + + file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr); + + /* + * Read the section string table and look for the .ctors section. + * We need to tell the kernel where it is so that it can call the + * ctors. + */ + chunk = shdr[ehdr->e_shstrndx].sh_size; + if (chunk) { + shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, + chunk); + if (shstr) { + for (i = 0; i < ehdr->e_shnum; i++) { + if (strcmp(shstr + shdr[i].sh_name, + ".ctors") != 0) + continue; + ctors = shdr[i].sh_addr; + file_addmetadata(fp, MODINFOMD_CTORS_ADDR, + sizeof(ctors), &ctors); + size = shdr[i].sh_size; + file_addmetadata(fp, MODINFOMD_CTORS_SIZE, + sizeof(size), &size); + break; + } + free(shstr); + } + } + + /* + * Now load any symbols. + */ + symtabindex = -1; + symstrindex = -1; + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type != SHT_SYMTAB) + continue; + for (j = 0; j < ehdr->e_phnum; j++) { + if (phdr[j].p_type != PT_LOAD) + continue; + if (shdr[i].sh_offset >= phdr[j].p_offset && + (shdr[i].sh_offset + shdr[i].sh_size <= + phdr[j].p_offset + phdr[j].p_filesz)) { + shdr[i].sh_offset = 0; + shdr[i].sh_size = 0; + break; + } + } + if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) + continue; /* alread loaded in a PT_LOAD above */ + /* Save it for loading below */ + symtabindex = i; + symstrindex = shdr[i].sh_link; + } + if (symtabindex < 0 || symstrindex < 0) + goto nosyms; + + /* Ok, committed to a load. */ #ifndef ELF_VERBOSE - printf("syms=["); + printf("syms=["); #endif - ssym = lastaddr; - for (i = symtabindex; i >= 0; i = symstrindex) { + ssym = lastaddr; + for (i = symtabindex; i >= 0; i = symstrindex) { #ifdef ELF_VERBOSE - char *secname; + char *secname; - switch(shdr[i].sh_type) { - case SHT_SYMTAB: /* Symbol table */ - secname = "symtab"; - break; - case SHT_STRTAB: /* String table */ - secname = "strtab"; - break; - default: - secname = "WHOA!!"; - break; - } + switch(shdr[i].sh_type) { + case SHT_SYMTAB: /* Symbol table */ + secname = "symtab"; + break; + case SHT_STRTAB: /* String table */ + secname = "strtab"; + break; + default: + secname = "WHOA!!"; + break; + } #endif - size = shdr[i].sh_size; + size = shdr[i].sh_size; #if defined(__powerpc__) #if __ELF_WORD_SIZE == 64 - size = htobe64(size); + size = htobe64(size); #else - size = htobe32(size); + size = htobe32(size); #endif #endif - archsw.arch_copyin(&size, lastaddr, sizeof(size)); - lastaddr += sizeof(size); + archsw.arch_copyin(&size, lastaddr, sizeof(size)); + lastaddr += sizeof(size); #ifdef ELF_VERBOSE - printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname, - (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset, - (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size)); + printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname, + (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset, + (uintmax_t)lastaddr, + (uintmax_t)(lastaddr + shdr[i].sh_size)); #else - if (i == symstrindex) - printf("+"); - printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); + if (i == symstrindex) + printf("+"); + printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); #endif - if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!"); - lastaddr = ssym; - ssym = 0; - goto nosyms; + if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "_loadimage: could not seek for symbols - skipped!"); + lastaddr = ssym; + ssym = 0; + goto nosyms; + } + result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); + if (result < 0 || (size_t)result != shdr[i].sh_size) { + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) + "_loadimage: could not read symbols - skipped! " + "(%ju != %ju)", (uintmax_t)result, + (uintmax_t)shdr[i].sh_size); + lastaddr = ssym; + ssym = 0; + goto nosyms; + } + /* Reset offsets relative to ssym */ + lastaddr += shdr[i].sh_size; + lastaddr = roundup(lastaddr, sizeof(size)); + if (i == symtabindex) + symtabindex = -1; + else if (i == symstrindex) + symstrindex = -1; } - result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); - if (result < 0 || (size_t)result != shdr[i].sh_size) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result, - (uintmax_t)shdr[i].sh_size); - lastaddr = ssym; - ssym = 0; - goto nosyms; - } - /* Reset offsets relative to ssym */ - lastaddr += shdr[i].sh_size; - lastaddr = roundup(lastaddr, sizeof(size)); - if (i == symtabindex) - symtabindex = -1; - else if (i == symstrindex) - symstrindex = -1; - } - esym = lastaddr; + esym = lastaddr; #ifndef ELF_VERBOSE - printf("]"); + printf("]"); #endif #if defined(__powerpc__) /* On PowerPC we always need to provide BE data to the kernel */ #if __ELF_WORD_SIZE == 64 - ssym = htobe64((uint64_t)ssym); - esym = htobe64((uint64_t)esym); + ssym = htobe64((uint64_t)ssym); + esym = htobe64((uint64_t)esym); #else - ssym = htobe32((uint32_t)ssym); - esym = htobe32((uint32_t)esym); + ssym = htobe32((uint32_t)ssym); + esym = htobe32((uint32_t)esym); #endif #endif - file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); + file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); + file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); nosyms: - printf("\n"); + printf("\n"); - ret = lastaddr - firstaddr; - fp->f_addr = firstaddr; + ret = lastaddr - firstaddr; + fp->f_addr = firstaddr; - php = NULL; - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_DYNAMIC) { - php = phdr + i; - adp = php->p_vaddr; - file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp); - break; + php = NULL; + for (i = 0; i < ehdr->e_phnum; i++) { + if (phdr[i].p_type == PT_DYNAMIC) { + php = phdr + i; + adp = php->p_vaddr; + file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), + &adp); + break; + } } - } - if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ - goto out; + if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ + goto out; - ndp = php->p_filesz / sizeof(Elf_Dyn); - if (ndp == 0) - goto out; - dp = malloc(php->p_filesz); - if (dp == NULL) - goto out; - archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); + ndp = php->p_filesz / sizeof(Elf_Dyn); + if (ndp == 0) + goto out; + dp = malloc(php->p_filesz); + if (dp == NULL) + goto out; + archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); - ef->strsz = 0; - for (i = 0; i < ndp; i++) { - if (dp[i].d_tag == 0) - break; - switch (dp[i].d_tag) { - case DT_HASH: - ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_STRTAB: - ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_STRSZ: - ef->strsz = dp[i].d_un.d_val; - break; - case DT_SYMTAB: - ef->symtab = (Elf_Sym*)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_REL: - ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_RELSZ: - ef->relsz = dp[i].d_un.d_val; - break; - case DT_RELA: - ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off); - break; - case DT_RELASZ: - ef->relasz = dp[i].d_un.d_val; - break; - default: - break; + ef->strsz = 0; + for (i = 0; i < ndp; i++) { + if (dp[i].d_tag == 0) + break; + switch (dp[i].d_tag) { + case DT_HASH: + ef->hashtab = + (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off); + break; + case DT_STRTAB: + ef->strtab = + (char *)(uintptr_t)(dp[i].d_un.d_ptr + off); + break; + case DT_STRSZ: + ef->strsz = dp[i].d_un.d_val; + break; + case DT_SYMTAB: + ef->symtab = + (Elf_Sym *)(uintptr_t)(dp[i].d_un.d_ptr + off); + break; + case DT_REL: + ef->rel = + (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off); + break; + case DT_RELSZ: + ef->relsz = dp[i].d_un.d_val; + break; + case DT_RELA: + ef->rela = + (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off); + break; + case DT_RELASZ: + ef->relasz = dp[i].d_un.d_val; + break; + default: + break; + } } - } - if (ef->hashtab == NULL || ef->symtab == NULL || - ef->strtab == NULL || ef->strsz == 0) - goto out; - COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); - COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); - ef->buckets = ef->hashtab + 2; - ef->chains = ef->buckets + ef->nbuckets; + if (ef->hashtab == NULL || ef->symtab == NULL || + ef->strtab == NULL || ef->strsz == 0) + goto out; + COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); + COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); + ef->buckets = ef->hashtab + 2; + ef->chains = ef->buckets + ef->nbuckets; - if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) - return 0; - p_start = sym.st_value + ef->off; - if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) - return ENOENT; - p_end = sym.st_value + ef->off; + if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", + &sym) != 0) + return 0; + p_start = sym.st_value + ef->off; + if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", + &sym) != 0) + return ENOENT; + p_end = sym.st_value + ef->off; - if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0) - goto out; + if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0) + goto out; - if (ef->kernel) /* kernel must not depend on anything */ - goto out; + if (ef->kernel) /* kernel must not depend on anything */ + goto out; out: - if (dp) - free(dp); - if (shdr) - free(shdr); - return ret; + if (dp) + free(dp); + if (shdr) + free(shdr); + return ret; } static char invalid_name[] = "bad"; @@ -819,35 +853,35 @@ static char invalid_name[] = "bad"; char * fake_modname(const char *name) { - const char *sp, *ep; - char *fp; - size_t len; + const char *sp, *ep; + char *fp; + size_t len; - sp = strrchr(name, '/'); - if (sp) - sp++; - else - sp = name; - ep = strrchr(name, '.'); - if (ep) { - if (ep == name) { - sp = invalid_name; - ep = invalid_name + sizeof(invalid_name) - 1; - } - } else - ep = name + strlen(name); - len = ep - sp; - fp = malloc(len + 1); - if (fp == NULL) - return NULL; - memcpy(fp, sp, len); - fp[len] = '\0'; - return fp; + sp = strrchr(name, '/'); + if (sp) + sp++; + else + sp = name; + ep = strrchr(name, '.'); + if (ep) { + if (ep == name) { + sp = invalid_name; + ep = invalid_name + sizeof(invalid_name) - 1; + } + } else + ep = name + strlen(name); + len = ep - sp; + fp = malloc(len + 1); + if (fp == NULL) + return NULL; + memcpy(fp, sp, len); + fp[len] = '\0'; + return fp; } #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 struct mod_metadata64 { - int md_version; /* structure version MDTV_* */ + int md_version; /* structure version MDTV_* */ int md_type; /* type of entry MDT_* */ u_int64_t md_data; /* specific data */ u_int64_t md_cval; /* common string label */ @@ -855,7 +889,7 @@ struct mod_metadata64 { #endif #if defined(__amd64__) && __ELF_WORD_SIZE == 32 struct mod_metadata32 { - int md_version; /* structure version MDTV_* */ + int md_version; /* structure version MDTV_* */ int md_type; /* type of entry MDT_* */ u_int32_t md_data; /* specific data */ u_int32_t md_cval; /* common string label */ @@ -981,149 +1015,153 @@ int __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, Elf_Addr p_start, Elf_Addr p_end) { - struct mod_metadata md; + struct mod_metadata md; #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 - struct mod_metadata64 md64; + struct mod_metadata64 md64; #elif defined(__amd64__) && __ELF_WORD_SIZE == 32 - struct mod_metadata32 md32; + struct mod_metadata32 md32; #endif - struct mod_depend *mdepend; - struct mod_version mver; - char *s; - int error, modcnt, minfolen; - Elf_Addr v, p; + struct mod_depend *mdepend; + struct mod_version mver; + char *s; + int error, modcnt, minfolen; + Elf_Addr v, p; - modcnt = 0; - p = p_start; - while (p < p_end) { - COPYOUT(p, &v, sizeof(v)); - error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); - if (error == EOPNOTSUPP) - v += ef->off; - else if (error != 0) - return (error); + modcnt = 0; + p = p_start; + while (p < p_end) { + COPYOUT(p, &v, sizeof(v)); + error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); + if (error == EOPNOTSUPP) + v += ef->off; + else if (error != 0) + return (error); #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 - COPYOUT(v, &md64, sizeof(md64)); - error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); - if (error == EOPNOTSUPP) { - md64.md_cval += ef->off; - md64.md_data += ef->off; - } else if (error != 0) - return (error); - md.md_version = md64.md_version; - md.md_type = md64.md_type; - md.md_cval = (const char *)(uintptr_t)md64.md_cval; - md.md_data = (void *)(uintptr_t)md64.md_data; + COPYOUT(v, &md64, sizeof(md64)); + error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); + if (error == EOPNOTSUPP) { + md64.md_cval += ef->off; + md64.md_data += ef->off; + } else if (error != 0) + return (error); + md.md_version = md64.md_version; + md.md_type = md64.md_type; + md.md_cval = (const char *)(uintptr_t)md64.md_cval; + md.md_data = (void *)(uintptr_t)md64.md_data; #elif defined(__amd64__) && __ELF_WORD_SIZE == 32 - COPYOUT(v, &md32, sizeof(md32)); - error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32)); - if (error == EOPNOTSUPP) { - md32.md_cval += ef->off; - md32.md_data += ef->off; - } else if (error != 0) - return (error); - md.md_version = md32.md_version; - md.md_type = md32.md_type; - md.md_cval = (const char *)(uintptr_t)md32.md_cval; - md.md_data = (void *)(uintptr_t)md32.md_data; + COPYOUT(v, &md32, sizeof(md32)); + error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32)); + if (error == EOPNOTSUPP) { + md32.md_cval += ef->off; + md32.md_data += ef->off; + } else if (error != 0) + return (error); + md.md_version = md32.md_version; + md.md_type = md32.md_type; + md.md_cval = (const char *)(uintptr_t)md32.md_cval; + md.md_data = (void *)(uintptr_t)md32.md_data; #else - COPYOUT(v, &md, sizeof(md)); - error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); - if (error == EOPNOTSUPP) { - md.md_cval += ef->off; - md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off); - } else if (error != 0) - return (error); + COPYOUT(v, &md, sizeof(md)); + error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); + if (error == EOPNOTSUPP) { + md.md_cval += ef->off; + md.md_data = (void *)((uintptr_t)md.md_data + + (uintptr_t)ef->off); + } else if (error != 0) + return (error); #endif - p += sizeof(Elf_Addr); - switch(md.md_type) { - case MDT_DEPEND: - if (ef->kernel) /* kernel must not depend on anything */ - break; - s = strdupout((vm_offset_t)md.md_cval); - minfolen = sizeof(*mdepend) + strlen(s) + 1; - mdepend = malloc(minfolen); - if (mdepend == NULL) - return ENOMEM; - COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); - strcpy((char*)(mdepend + 1), s); - free(s); - file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); - free(mdepend); - break; - case MDT_VERSION: - s = strdupout((vm_offset_t)md.md_cval); - COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); - file_addmodule(fp, s, mver.mv_version, NULL); - free(s); - modcnt++; - break; + p += sizeof(Elf_Addr); + switch(md.md_type) { + case MDT_DEPEND: + if (ef->kernel) /* kernel must not depend on anything */ + break; + s = strdupout((vm_offset_t)md.md_cval); + minfolen = sizeof(*mdepend) + strlen(s) + 1; + mdepend = malloc(minfolen); + if (mdepend == NULL) + return ENOMEM; + COPYOUT((vm_offset_t)md.md_data, mdepend, + sizeof(*mdepend)); + strcpy((char*)(mdepend + 1), s); + free(s); + file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, + mdepend); + free(mdepend); + break; + case MDT_VERSION: + s = strdupout((vm_offset_t)md.md_cval); + COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); + file_addmodule(fp, s, mver.mv_version, NULL); + free(s); + modcnt++; + break; + } } - } - if (modcnt == 0) { - s = fake_modname(fp->f_name); - file_addmodule(fp, s, 1, NULL); - free(s); - } - return 0; + if (modcnt == 0) { + s = fake_modname(fp->f_name); + file_addmodule(fp, s, 1, NULL); + free(s); + } + return 0; } static unsigned long elf_hash(const char *name) { - const unsigned char *p = (const unsigned char *) name; - unsigned long h = 0; - unsigned long g; + const unsigned char *p = (const unsigned char *) name; + unsigned long h = 0; + unsigned long g; - while (*p != '\0') { - h = (h << 4) + *p++; - if ((g = h & 0xf0000000) != 0) - h ^= g >> 24; - h &= ~g; - } - return h; + while (*p != '\0') { + h = (h << 4) + *p++; + if ((g = h & 0xf0000000) != 0) + h ^= g >> 24; + h &= ~g; + } + return h; } -static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n"; +static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) + "_lookup_symbol: corrupt symbol table\n"; int -__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name, - Elf_Sym *symp) +__elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, + const char* name, Elf_Sym *symp) { - Elf_Hashelt symnum; - Elf_Sym sym; - char *strp; - unsigned long hash; + Elf_Hashelt symnum; + Elf_Sym sym; + char *strp; + unsigned long hash; - hash = elf_hash(name); - COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); + hash = elf_hash(name); + COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); - while (symnum != STN_UNDEF) { - if (symnum >= ef->nchains) { - printf(__elfN(bad_symtable)); - return ENOENT; + while (symnum != STN_UNDEF) { + if (symnum >= ef->nchains) { + printf(__elfN(bad_symtable)); + return ENOENT; + } + + COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); + if (sym.st_name == 0) { + printf(__elfN(bad_symtable)); + return ENOENT; + } + + strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); + if (strcmp(name, strp) == 0) { + free(strp); + if (sym.st_shndx != SHN_UNDEF || + (sym.st_value != 0 && + ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { + *symp = sym; + return 0; + } + return ENOENT; + } + free(strp); + COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); } - - COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); - if (sym.st_name == 0) { - printf(__elfN(bad_symtable)); - return ENOENT; - } - - strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); - if (strcmp(name, strp) == 0) { - free(strp); - if (sym.st_shndx != SHN_UNDEF || - (sym.st_value != 0 && - ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { - *symp = sym; - return 0; - } - return ENOENT; - } - free(strp); - COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); - } - return ENOENT; + return ENOENT; } /*