Psymtab_machelf32.c revision de1f518f033a642fe7aa3c2b59429241a01e387f
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d51e90740114c60620c0febffd4d3ce6e280a107ab * CDDL HEADER START
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * The contents of this file are subject to the terms of the
d51e90740114c60620c0febffd4d3ce6e280a107ab * Common Development and Distribution License (the "License").
d51e90740114c60620c0febffd4d3ce6e280a107ab * You may not use this file except in compliance with the License.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d51e90740114c60620c0febffd4d3ce6e280a107ab * or http://www.opensolaris.org/os/licensing.
d51e90740114c60620c0febffd4d3ce6e280a107ab * See the License for the specific language governing permissions
d51e90740114c60620c0febffd4d3ce6e280a107ab * and limitations under the License.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * When distributing Covered Code, include this CDDL HEADER in each
d51e90740114c60620c0febffd4d3ce6e280a107ab * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d51e90740114c60620c0febffd4d3ce6e280a107ab * If applicable, add the following below this CDDL HEADER, with the
d51e90740114c60620c0febffd4d3ce6e280a107ab * fields enclosed by brackets "[]" replaced with your own identifying
d51e90740114c60620c0febffd4d3ce6e280a107ab * information: Portions Copyright [yyyy] [name of copyright owner]
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * CDDL HEADER END
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d51e90740114c60620c0febffd4d3ce6e280a107ab * Use is subject to license terms.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#include <assert.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <stdio.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <stdlib.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <stddef.h>
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#include <string.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <memory.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <sys/sysmacros.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab#include <sys/machelf.h>
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab#include "Pcontrol.h"
d51e90740114c60620c0febffd4d3ce6e280a107ab#include "Psymtab_machelf.h"
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d51e90740114c60620c0febffd4d3ce6e280a107ab * This file contains code for use by Psymtab.c that is compiled once
d51e90740114c60620c0febffd4d3ce6e280a107ab * for each supported ELFCLASS.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * When processing ELF files, it is common to encounter a situation where
d51e90740114c60620c0febffd4d3ce6e280a107ab * a program with one ELFCLASS (32 or 64-bit) is required to examine a
d51e90740114c60620c0febffd4d3ce6e280a107ab * file with a different ELFCLASS. For example, the 32-bit linker (ld) may
d51e90740114c60620c0febffd4d3ce6e280a107ab * be used to link a 64-bit program. The simplest solution to this problem
d51e90740114c60620c0febffd4d3ce6e280a107ab * is to duplicate each such piece of code, modifying only the data types,
d51e90740114c60620c0febffd4d3ce6e280a107ab * and to use if statements to select the code to run. The problem with
d51e90740114c60620c0febffd4d3ce6e280a107ab * doing it that way is that the resulting code is difficult to maintain.
d51e90740114c60620c0febffd4d3ce6e280a107ab * It is inevitable that the copies will not always get modified identically,
d51e90740114c60620c0febffd4d3ce6e280a107ab * and will drift apart. The only robust solution is to generate the
d51e90740114c60620c0febffd4d3ce6e280a107ab * multiple instances of code automatically from a single piece of code.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * The solution used within the Solaris linker is to write the code once,
d51e90740114c60620c0febffd4d3ce6e280a107ab * using the data types defined in sys/machelf.h, and then to compile that
d51e90740114c60620c0febffd4d3ce6e280a107ab * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and
d51e90740114c60620c0febffd4d3ce6e280a107ab * once without (to generate ELFCLASS32). We use the same approach here.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * Note that the _ELF64 definition does not refer to the ELFCLASS of
d51e90740114c60620c0febffd4d3ce6e280a107ab * the resulting code, but rather, to the ELFCLASS of the data it
d51e90740114c60620c0febffd4d3ce6e280a107ab * examines. By repeating the above double-compilation for both 32-bit
d51e90740114c60620c0febffd4d3ce6e280a107ab * and 64-bit builds, we end up with 4 instances, which collectively
d51e90740114c60620c0febffd4d3ce6e280a107ab * can handle any combination of program and ELF data class:
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * \ Compilation class
d51e90740114c60620c0febffd4d3ce6e280a107ab * \ 32 64
d51e90740114c60620c0febffd4d3ce6e280a107ab * \------------------
d51e90740114c60620c0febffd4d3ce6e280a107ab * |
d51e90740114c60620c0febffd4d3ce6e280a107ab * 32 | X X
d51e90740114c60620c0febffd4d3ce6e280a107ab * ELF Data Class |
d51e90740114c60620c0febffd4d3ce6e280a107ab * 64 | X X
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Read data from the specified process and construct an in memory
d51e90740114c60620c0febffd4d3ce6e280a107ab * image of an ELF file that will let us use libelf for most of the
d51e90740114c60620c0febffd4d3ce6e280a107ab * work we need to later (e.g. symbol table lookups). This is used
d51e90740114c60620c0febffd4d3ce6e280a107ab * in cases where no usable on-disk image for the process is available.
d51e90740114c60620c0febffd4d3ce6e280a107ab * We need sections for the dynsym, dynstr, and plt, and we need
d51e90740114c60620c0febffd4d3ce6e280a107ab * the program headers from the text section. The former is used in
d51e90740114c60620c0febffd4d3ce6e280a107ab * Pbuild_file_symtab(); the latter is used in several functions in
d51e90740114c60620c0febffd4d3ce6e280a107ab * Pcore.c to reconstruct the origin of each mapping from the load
d51e90740114c60620c0febffd4d3ce6e280a107ab * object that spawned it.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * Here are some useful pieces of elf trivia that will help
d51e90740114c60620c0febffd4d3ce6e280a107ab * to elucidate this code.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * All the information we need about the dynstr can be found in these
d51e90740114c60620c0febffd4d3ce6e280a107ab * two entries in the dynamic section:
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_STRTAB base of dynstr
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_STRSZ size of dynstr
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * So deciphering the dynstr is pretty straightforward.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * The dynsym is a little trickier.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_SYMTAB base of dynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym)
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_HASH base of hash table for dynamic lookups
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * The DT_SYMTAB entry gives us any easy way of getting to the base
d51e90740114c60620c0febffd4d3ce6e280a107ab * of the dynsym, but getting the size involves rooting around in the
d51e90740114c60620c0febffd4d3ce6e280a107ab * dynamic lookup hash table. Here's the layout of the hash table:
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * +-------------------+
d51e90740114c60620c0febffd4d3ce6e280a107ab * | nbucket | All values are 32-bit
d51e90740114c60620c0febffd4d3ce6e280a107ab * +-------------------+ (Elf32_Word or Elf64_Word)
d51e90740114c60620c0febffd4d3ce6e280a107ab * | nchain |
d51e90740114c60620c0febffd4d3ce6e280a107ab * +-------------------+
d51e90740114c60620c0febffd4d3ce6e280a107ab * | bucket[0] |
d51e90740114c60620c0febffd4d3ce6e280a107ab * | . . . |
d51e90740114c60620c0febffd4d3ce6e280a107ab * | bucket[nbucket-1] |
d51e90740114c60620c0febffd4d3ce6e280a107ab * +-------------------+
d51e90740114c60620c0febffd4d3ce6e280a107ab * | chain[0] |
d51e90740114c60620c0febffd4d3ce6e280a107ab * | . . . |
d51e90740114c60620c0febffd4d3ce6e280a107ab * | chain[nchain-1] |
d51e90740114c60620c0febffd4d3ce6e280a107ab * +-------------------+
d51e90740114c60620c0febffd4d3ce6e280a107ab * (figure 5-12 from the SYS V Generic ABI)
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * Symbols names are hashed into a particular bucket which contains
d51e90740114c60620c0febffd4d3ce6e280a107ab * an index into the symbol table. Each entry in the symbol table
d51e90740114c60620c0febffd4d3ce6e280a107ab * has a corresponding entry in the chain table which tells the
d51e90740114c60620c0febffd4d3ce6e280a107ab * consumer where the next entry in the hash chain is. We can use
d51e90740114c60620c0febffd4d3ce6e280a107ab * the nchain field to find out the size of the dynsym.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * If there is a dynsym present, there may also be an optional
d51e90740114c60620c0febffd4d3ce6e280a107ab * section called the SUNW_ldynsym that augments the dynsym by
d51e90740114c60620c0febffd4d3ce6e280a107ab * providing local function symbols. When the Solaris linker lays
d51e90740114c60620c0febffd4d3ce6e280a107ab * out a file that has both of these sections, it makes sure that
d51e90740114c60620c0febffd4d3ce6e280a107ab * the data for the two sections is adjacent with the SUNW_ldynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab * in front. This allows the runtime linker to treat these two
d51e90740114c60620c0febffd4d3ce6e280a107ab * symbol tables as being a single larger table. There are two
d51e90740114c60620c0febffd4d3ce6e280a107ab * items in the dynamic section for this:
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_SUNW_SYMTAB base of the SUNW_ldynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab * added together. We can figure out the
d51e90740114c60620c0febffd4d3ce6e280a107ab * size of the SUNW_ldynsym section by
d51e90740114c60620c0febffd4d3ce6e280a107ab * subtracting the size of the dynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab * (described above) from this value.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * We can figure out the size of the .plt section, but it takes some
d51e90740114c60620c0febffd4d3ce6e280a107ab * doing. We need to use the following information:
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * DT_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc)
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_JMPREL base of the PLT's relocation section
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_PLTRELSZ size of the PLT's relocation section
d51e90740114c60620c0febffd4d3ce6e280a107ab * DT_PLTREL type of the PLT's relocation section
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * We can use the number of relocation entries to calculate the size of
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * the PLT. We get the address of the PLT by looking up the
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * _PROCEDURE_LINKAGE_TABLE_ symbol.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * For more information, check out the System V Generic ABI.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d51e90740114c60620c0febffd4d3ce6e280a107ab * The fake_elfXX() function generated by this file uses the following
d51e90740114c60620c0febffd4d3ce6e280a107ab * string as the string table for the section names. Since it is critical
d51e90740114c60620c0febffd4d3ce6e280a107ab * to count correctly, and to improve readability, the SHSTR_NDX_ macros
d51e90740114c60620c0febffd4d3ce6e280a107ab * supply the proper offset for each name within the string.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107abstatic char shstr[] =
d51e90740114c60620c0febffd4d3ce6e280a107ab ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/* Offsets within shstr for each name */
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_shstrtab 0
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_dynsym 10
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_dynstr 18
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_dynamic 26
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_plt 35
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SHSTR_NDX_SUNW_ldynsym 40
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab/*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section header alignment for 32 and 64-bit ELF files differs
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab#ifdef _ELF64
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SH_ADDRALIGN 8
d51e90740114c60620c0febffd4d3ce6e280a107ab#else
d51e90740114c60620c0febffd4d3ce6e280a107ab#define SH_ADDRALIGN 4
d51e90740114c60620c0febffd4d3ce6e280a107ab#endif
d51e90740114c60620c0febffd4d3ce6e280a107ab
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj/*
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj * This is the smallest number of PLT relocation entries allowed in a proper
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj * .plt section.
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj */
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#ifdef __sparc
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#define PLTREL_MIN_ENTRIES 4 /* SPARC psABI 3.0 and SCD 2.4 */
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#else
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#ifdef __lint
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj/*
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj * On x86, lint would complain about unsigned comparison with
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj * and silences lint. On SPARC, there is no such issue.
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj */
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#define PLTREL_MIN_ENTRIES 1
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#else
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#define PLTREL_MIN_ENTRIES 0
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#endif
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj#endif
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jj
d51e90740114c60620c0febffd4d3ce6e280a107ab#ifdef _ELF64
d51e90740114c60620c0febffd4d3ce6e280a107abElf *
d51e90740114c60620c0febffd4d3ce6e280a107abfake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
d51e90740114c60620c0febffd4d3ce6e280a107ab Ehdr *ehdr, uint_t phnum, Phdr *phdr)
d51e90740114c60620c0febffd4d3ce6e280a107ab#else
d51e90740114c60620c0febffd4d3ce6e280a107abElf *
d51e90740114c60620c0febffd4d3ce6e280a107abfake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
d51e90740114c60620c0febffd4d3ce6e280a107ab Ehdr *ehdr, uint_t phnum, Phdr *phdr)
d51e90740114c60620c0febffd4d3ce6e280a107ab#endif
d51e90740114c60620c0febffd4d3ce6e280a107ab{
d51e90740114c60620c0febffd4d3ce6e280a107ab enum {
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_PLTGOT,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_JMPREL,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_PLTRELSZ,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_PLTREL,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_SYMTAB,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_HASH,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_SYMENT,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_STRTAB,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_STRSZ,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_SUNW_SYMTAB,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_SUNW_SYMSZ,
d51e90740114c60620c0febffd4d3ce6e280a107ab DI_NENT
d51e90740114c60620c0febffd4d3ce6e280a107ab };
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Mask of dynamic options that must be present in a well
d51e90740114c60620c0febffd4d3ce6e280a107ab * formed dynamic section. We need all of these in order to
d51e90740114c60620c0febffd4d3ce6e280a107ab * put together a complete set of elf sections. They are
d51e90740114c60620c0febffd4d3ce6e280a107ab * mandatory in both executables and shared objects so if one
d51e90740114c60620c0febffd4d3ce6e280a107ab * of them is missing, we're in some trouble and should abort.
d51e90740114c60620c0febffd4d3ce6e280a107ab * The PLT items are expected, but we will let them slide if
d51e90740114c60620c0febffd4d3ce6e280a107ab * need be. The DI_SUNW_SYM* items are completely optional, so
d51e90740114c60620c0febffd4d3ce6e280a107ab * we use them if they are present and ignore them otherwise.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) |
d51e90740114c60620c0febffd4d3ce6e280a107ab (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
d51e90740114c60620c0febffd4d3ce6e280a107ab int di_mask = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab size_t size = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab caddr_t elfdata = NULL;
d51e90740114c60620c0febffd4d3ce6e280a107ab Elf *elf;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz size_t dynsym_size = 0, ldynsym_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab int dynstr_shndx;
d51e90740114c60620c0febffd4d3ce6e280a107ab Ehdr *ep;
d51e90740114c60620c0febffd4d3ce6e280a107ab Shdr *sp;
7199059354284218c1c31276b0a51935fb228cc2Richard Lowe Dyn *dp = NULL;
d51e90740114c60620c0febffd4d3ce6e280a107ab Dyn *d[DI_NENT] = { 0 };
d51e90740114c60620c0febffd4d3ce6e280a107ab uint_t i;
d51e90740114c60620c0febffd4d3ce6e280a107ab Off off;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz size_t pltsz = 0, pltentries = 0;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz uintptr_t hptr = NULL;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz Word hnchains, hnbuckets;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d51e90740114c60620c0febffd4d3ce6e280a107ab phdr->p_vaddr += addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab
22872efb9462b28180d11ea401344608e641a5aaedp if (P->rap != NULL) {
22872efb9462b28180d11ea401344608e641a5aaedp if (rd_get_dyns(P->rap, addr, (void **)&dp, NULL) != RD_OK)
22872efb9462b28180d11ea401344608e641a5aaedp goto bad;
22872efb9462b28180d11ea401344608e641a5aaedp } else {
22872efb9462b28180d11ea401344608e641a5aaedp if ((dp = malloc(phdr->p_filesz)) == NULL)
22872efb9462b28180d11ea401344608e641a5aaedp goto bad;
22872efb9462b28180d11ea401344608e641a5aaedp if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) !=
22872efb9462b28180d11ea401344608e641a5aaedp phdr->p_filesz)
22872efb9462b28180d11ea401344608e641a5aaedp goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Iterate over the items in the dynamic section, grabbing
d51e90740114c60620c0febffd4d3ce6e280a107ab * the address of items we want and saving them in dp[].
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
d51e90740114c60620c0febffd4d3ce6e280a107ab switch (dp[i].d_tag) {
d51e90740114c60620c0febffd4d3ce6e280a107ab /* For the .plt section */
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_PLTGOT:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_PLTGOT] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_JMPREL:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_JMPREL] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_PLTRELSZ:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_PLTRELSZ] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_PLTREL:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_PLTREL] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* For the .dynsym section */
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_SYMTAB:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SYMTAB] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab di_mask |= (1 << DI_SYMTAB);
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_HASH:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_HASH] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab di_mask |= (1 << DI_HASH);
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_SYMENT:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SYMENT] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab di_mask |= (1 << DI_SYMENT);
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_SUNW_SYMTAB:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SUNW_SYMTAB] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_SUNW_SYMSZ:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SUNW_SYMSZ] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* For the .dynstr section */
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_STRTAB:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_STRTAB] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab di_mask |= (1 << DI_STRTAB);
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab case DT_STRSZ:
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_STRSZ] = &dp[i];
d51e90740114c60620c0febffd4d3ce6e280a107ab di_mask |= (1 << DI_STRSZ);
d51e90740114c60620c0febffd4d3ce6e280a107ab break;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* Ensure all required entries were collected */
d51e90740114c60620c0febffd4d3ce6e280a107ab if ((di_mask & di_req_mask) != di_req_mask) {
d51e90740114c60620c0febffd4d3ce6e280a107ab dprintf("text section missing required dynamic entries\n");
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
d51e90740114c60620c0febffd4d3ce6e280a107ab if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
d51e90740114c60620c0febffd4d3ce6e280a107ab ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
d51e90740114c60620c0febffd4d3ce6e280a107ab (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SUNW_SYMTAB] = NULL;
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_SUNW_SYMSZ] = NULL;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* elf header */
d51e90740114c60620c0febffd4d3ce6e280a107ab size = sizeof (Ehdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* program headers from in-core elf fragment */
d51e90740114c60620c0febffd4d3ce6e280a107ab size += phnum * ehdr->e_phentsize;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* unused shdr, and .shstrtab section */
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab size += roundup(sizeof (shstr), SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (d[DI_HASH] != NULL) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz Word hash[2];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hptr = d[DI_HASH]->d_un.d_ptr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (ehdr->e_type == ET_DYN)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hptr += addr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)(hptr));
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hnbuckets = hash[0];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hnchains = hash[1];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
de1f518f033a642fe7aa3c2b59429241a01e387fRichard Lowe if ((d[DI_HASH] == NULL) || (hnbuckets == 0) || (hnchains == 0)) {
de1f518f033a642fe7aa3c2b59429241a01e387fRichard Lowe dprintf("empty or missing .hash\n");
de1f518f033a642fe7aa3c2b59429241a01e387fRichard Lowe goto bad;
de1f518f033a642fe7aa3c2b59429241a01e387fRichard Lowe }
de1f518f033a642fe7aa3c2b59429241a01e387fRichard Lowe
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * .dynsym and .SUNW_ldynsym sections.
d51e90740114c60620c0febffd4d3ce6e280a107ab *
d51e90740114c60620c0febffd4d3ce6e280a107ab * The string table section used for the symbol table and
d51e90740114c60620c0febffd4d3ce6e280a107ab * dynamic sections lies immediately after the dynsym, so the
d51e90740114c60620c0febffd4d3ce6e280a107ab * presence of SUNW_ldynsym changes the dynstr section index.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab if (d[DI_SUNW_SYMTAB] != NULL) {
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr); /* SUNW_ldynsym shdr */
d51e90740114c60620c0febffd4d3ce6e280a107ab ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
d51e90740114c60620c0febffd4d3ce6e280a107ab dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
d51e90740114c60620c0febffd4d3ce6e280a107ab - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
d51e90740114c60620c0febffd4d3ce6e280a107ab ldynsym_size -= dynsym_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab dynstr_shndx = 4;
d51e90740114c60620c0febffd4d3ce6e280a107ab } else {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dynsym_size = sizeof (Sym) * hnchains;
d51e90740114c60620c0febffd4d3ce6e280a107ab ldynsym_size = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab dynstr_shndx = 3;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr) + ldynsym_size + dynsym_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* .dynstr section */
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* .dynamic section */
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab size += roundup(phdr->p_filesz, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* .plt section */
d51e90740114c60620c0febffd4d3ce6e280a107ab if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
d51e90740114c60620c0febffd4d3ce6e280a107ab d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
d51e90740114c60620c0febffd4d3ce6e280a107ab size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltentries = pltrelsz / sizeof (Rela);
d51e90740114c60620c0febffd4d3ce6e280a107ab } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltentries = pltrelsz / sizeof (Rel);
d51e90740114c60620c0febffd4d3ce6e280a107ab } else {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* fall back to the platform default */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64))
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltentries = pltrelsz / sizeof (Rel);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("DI_PLTREL not found, defaulting to Rel");
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#else /* (!(__i386 || __amd64)) || _ELF64 */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltentries = pltrelsz / sizeof (Rela);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("DI_PLTREL not found, defaulting to Rela");
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#endif /* (!(__i386 || __amd64) || _ELF64 */
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (pltentries < PLTREL_MIN_ENTRIES) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("too few PLT relocation entries "
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz "(found %lu, expected at least %d)\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)pltentries, PLTREL_MIN_ENTRIES);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (pltentries < PLTREL_MIN_ENTRIES + 2)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto done_with_plt;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /*
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * Now that we know the number of plt relocation entries
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * we can calculate the size of the plt.
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#if defined(__sparc)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* The sparc PLT always has a (delay slot) nop at the end */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz pltsz += 4;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#endif /* __sparc */
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab size += sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab size += roundup(pltsz, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab }
b93b7f88faf1df7e4a0046bc3fa6f74516688d16jjdone_with_plt:
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if ((elfdata = calloc(1, size)) == NULL)
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* LINTED - alignment */
d51e90740114c60620c0febffd4d3ce6e280a107ab ep = (Ehdr *)elfdata;
d51e90740114c60620c0febffd4d3ce6e280a107ab (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_ehsize = sizeof (Ehdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_phoff = sizeof (Ehdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_phentsize = ehdr->e_phentsize;
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_phnum = phnum;
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_shentsize = sizeof (Shdr);
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Plt and SUNW_ldynsym sections are optional. C logical
d51e90740114c60620c0febffd4d3ce6e280a107ab * binary operators return a 0 or 1 value, so the following
d51e90740114c60620c0febffd4d3ce6e280a107ab * adds 1 for each optional section present.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
d51e90740114c60620c0febffd4d3ce6e280a107ab ep->e_shstrndx = 1;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /* LINTED - alignment */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp = (Shdr *)(elfdata + ep->e_shoff);
d51e90740114c60620c0febffd4d3ce6e280a107ab off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Copying the program headers directly from the process's
d51e90740114c60620c0febffd4d3ce6e280a107ab * address space is a little suspect, but since we only
d51e90740114c60620c0febffd4d3ce6e280a107ab * use them for their address and size values, this is fine.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
d51e90740114c60620c0febffd4d3ce6e280a107ab addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
d51e90740114c60620c0febffd4d3ce6e280a107ab dprintf("failed to read program headers\n");
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * The first elf section is always skipped.
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .shstrtab
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_shstrtab;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_STRTAB;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_STRINGS;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = sizeof (shstr);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = 1;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_entsize = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab (void) memcpy(&elfdata[off], shstr, sizeof (shstr));
d51e90740114c60620c0febffd4d3ce6e280a107ab off += roundup(sp->sh_size, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .SUNW_ldynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab if (d[DI_SUNW_SYMTAB] != NULL) {
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_SUNW_LDYNSYM;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_ALLOC;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr += addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = ldynsym_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = dynstr_shndx;
d51e90740114c60620c0febffd4d3ce6e280a107ab /* Index of 1st global in table that has none == # items */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = sp->sh_size / sizeof (Sym);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = SH_ADDRALIGN;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_entsize = sizeof (Sym);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if (Pread(P, &elfdata[off], sp->sh_size,
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
d51e90740114c60620c0febffd4d3ce6e280a107ab dprintf("failed to read .SUNW_ldynsym at %lx\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)sp->sh_addr);
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab off += sp->sh_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab /* No need to round up ldynsym data. Dynsym data is same type */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .dynsym
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_dynsym;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_DYNSYM;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_ALLOC;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr += addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = dynsym_size;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = dynstr_shndx;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = 1; /* Index of 1st global in table */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = SH_ADDRALIGN;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_entsize = sizeof (Sym);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if (Pread(P, &elfdata[off], sp->sh_size,
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
d51e90740114c60620c0febffd4d3ce6e280a107ab dprintf("failed to read .dynsym at %lx\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)sp->sh_addr);
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab off += roundup(sp->sh_size, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .dynstr
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_dynstr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_STRTAB;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr += addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = d[DI_STRSZ]->d_un.d_val;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = 1;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_entsize = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab if (Pread(P, &elfdata[off], sp->sh_size,
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
d51e90740114c60620c0febffd4d3ce6e280a107ab dprintf("failed to read .dynstr\n");
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab off += roundup(sp->sh_size, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .dynamic
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_dynamic;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_DYNAMIC;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_WRITE | SHF_ALLOC;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr = phdr->p_vaddr;
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addr -= addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = phdr->p_filesz;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = dynstr_shndx;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = SH_ADDRALIGN;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_entsize = sizeof (Dyn);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab (void) memcpy(&elfdata[off], dp, sp->sh_size);
d51e90740114c60620c0febffd4d3ce6e280a107ab off += roundup(sp->sh_size, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab /*
d51e90740114c60620c0febffd4d3ce6e280a107ab * Section Header: .plt
d51e90740114c60620c0febffd4d3ce6e280a107ab */
d51e90740114c60620c0febffd4d3ce6e280a107ab if (pltsz != 0) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz ulong_t plt_symhash;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz uint_t htmp, ndx;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz uintptr_t strtabptr, strtabname;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz Sym sym, *symtabptr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz uint_t *hash;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /*
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * Now we need to find the address of the plt by looking
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz * up the "_PROCEDURE_LINKAGE_TABLE_" symbol.
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* get the address of the symtab and strtab sections */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz strtabptr = d[DI_STRTAB]->d_un.d_ptr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (ehdr->e_type == ET_DYN) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz strtabptr += addr;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz symtabptr = (Sym*)((uintptr_t)symtabptr + addr);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* find the .hash bucket address for this symbol */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_");
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz htmp = plt_symhash % hnbuckets;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hash = &((uint_t *)hptr)[2 + htmp];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* read the elf hash bucket index */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sizeof (ndx)) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n", (long)hash);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz while (ndx) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread(P, &sym, sizeof (sym),
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("Pread of .symtab at %lx failed\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)&symtabptr[ndx]);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz strtabname = strtabptr + sym.st_name;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread_string(P, strbuf, sizeof (strbuf),
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz strtabname) < 0) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("Pread of .strtab at %lx failed\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)strtabname);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz break;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz hash = &((uint_t *)hptr)[2 + hnbuckets + ndx];
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sizeof (ndx)) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)hash);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#if defined(__sparc)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("warning: DI_PLTGOT (%lx) doesn't match "
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz ".plt symbol pointer (%lx)",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)d[DI_PLTGOT]->d_un.d_ptr,
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)sym.st_value);
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz#endif /* __sparc */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (ndx == 0) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf(
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz goto bad;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz }
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_name = SHSTR_NDX_plt;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_type = SHT_PROGBITS;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr = sym.st_value;
d51e90740114c60620c0febffd4d3ce6e280a107ab if (ehdr->e_type == ET_DYN)
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_addr += addr;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_offset = off;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_size = pltsz;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_link = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_info = 0;
d51e90740114c60620c0febffd4d3ce6e280a107ab sp->sh_addralign = SH_ADDRALIGN;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_entsize = M_PLT_ENTSIZE;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) !=
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp->sh_size) {
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz dprintf("failed to read .plt at %lx\n",
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz (long)sp->sh_addr);
d51e90740114c60620c0febffd4d3ce6e280a107ab goto bad;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab off += roundup(sp->sh_size, SH_ADDRALIGN);
d51e90740114c60620c0febffd4d3ce6e280a107ab sp++;
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz /* make sure we didn't write past the end of allocated memory */
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz sp++;
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size));
d9452f237f843c1321abb5810d2f9ee6cbeae43cEdward Pilatowicz
d51e90740114c60620c0febffd4d3ce6e280a107ab free(dp);
d51e90740114c60620c0febffd4d3ce6e280a107ab if ((elf = elf_memory(elfdata, size)) == NULL) {
d51e90740114c60620c0febffd4d3ce6e280a107ab free(elfdata);
d51e90740114c60620c0febffd4d3ce6e280a107ab return (NULL);
d51e90740114c60620c0febffd4d3ce6e280a107ab }
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab fptr->file_elfmem = elfdata;
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107ab return (elf);
d51e90740114c60620c0febffd4d3ce6e280a107ab
d51e90740114c60620c0febffd4d3ce6e280a107abbad:
d51e90740114c60620c0febffd4d3ce6e280a107ab if (dp != NULL)
d51e90740114c60620c0febffd4d3ce6e280a107ab free(dp);
d51e90740114c60620c0febffd4d3ce6e280a107ab if (elfdata != NULL)
d51e90740114c60620c0febffd4d3ce6e280a107ab free(elfdata);
d51e90740114c60620c0febffd4d3ce6e280a107ab return (NULL);
d51e90740114c60620c0febffd4d3ce6e280a107ab}