Psymtab_machelf32.c revision 044d68fe853b07e9e4ff16d7aecb76fefd609ab5
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License (the "License"). 0N/A * You may not use this file except in compliance with the License. 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * information: Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 0N/A * Use is subject to license terms. 0N/A * Copyright (c) 2015, Joyent, Inc. All rights reserved. 0N/A * This file contains code for use by Psymtab.c that is compiled once 0N/A * for each supported ELFCLASS. 0N/A * When processing ELF files, it is common to encounter a situation where 0N/A * a program with one ELFCLASS (32 or 64-bit) is required to examine a 0N/A * file with a different ELFCLASS. For example, the 32-bit linker (ld) may 0N/A * be used to link a 64-bit program. The simplest solution to this problem 0N/A * is to duplicate each such piece of code, modifying only the data types, 0N/A * and to use if statements to select the code to run. The problem with 0N/A * doing it that way is that the resulting code is difficult to maintain. 0N/A * It is inevitable that the copies will not always get modified identically, 0N/A * and will drift apart. The only robust solution is to generate the 0N/A * multiple instances of code automatically from a single piece of code. 0N/A * The solution used within the Solaris linker is to write the code once, 0N/A * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and 0N/A * once without (to generate ELFCLASS32). We use the same approach here. 0N/A * Note that the _ELF64 definition does not refer to the ELFCLASS of 0N/A * the resulting code, but rather, to the ELFCLASS of the data it 0N/A * examines. By repeating the above double-compilation for both 32-bit 0N/A * and 64-bit builds, we end up with 4 instances, which collectively 0N/A * can handle any combination of program and ELF data class: 0N/A * \ Compilation class 0N/A * \------------------ 0N/A * Read data from the specified process and construct an in memory 0N/A * image of an ELF file that will let us use libelf for most of the 0N/A * work we need to later (e.g. symbol table lookups). This is used 0N/A * in cases where no usable on-disk image for the process is available. 0N/A * We need sections for the dynsym, dynstr, and plt, and we need 0N/A * the program headers from the text section. The former is used in 0N/A * Pbuild_file_symtab(); the latter is used in several functions in 0N/A * Pcore.c to reconstruct the origin of each mapping from the load 0N/A * object that spawned it. 0N/A * Here are some useful pieces of elf trivia that will help 0N/A * to elucidate this code. 0N/A * All the information we need about the dynstr can be found in these 0N/A * two entries in the dynamic section: 0N/A * DT_STRTAB base of dynstr 0N/A * DT_STRSZ size of dynstr 0N/A * So deciphering the dynstr is pretty straightforward. 0N/A * The dynsym is a little trickier. 0N/A * DT_SYMTAB base of dynsym 0N/A * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym) 0N/A * DT_HASH base of hash table for dynamic lookups 0N/A * The DT_SYMTAB entry gives us any easy way of getting to the base 0N/A * of the dynsym, but getting the size involves rooting around in the 0N/A * dynamic lookup hash table. Here's the layout of the hash table: 0N/A * +-------------------+ 0N/A * | nbucket | All values are 32-bit 0N/A * +-------------------+ (Elf32_Word or Elf64_Word) 0N/A * +-------------------+ 0N/A * | bucket[nbucket-1] | 0N/A * +-------------------+ 0N/A * | chain[nchain-1] | 0N/A * +-------------------+ 0N/A * (figure 5-12 from the SYS V Generic ABI) 0N/A * Symbols names are hashed into a particular bucket which contains 0N/A * an index into the symbol table. Each entry in the symbol table 0N/A * has a corresponding entry in the chain table which tells the 0N/A * consumer where the next entry in the hash chain is. We can use 0N/A * the nchain field to find out the size of the dynsym. 0N/A * If there is a dynsym present, there may also be an optional 0N/A * section called the SUNW_ldynsym that augments the dynsym by 0N/A * providing local function symbols. When the Solaris linker lays 0N/A * out a file that has both of these sections, it makes sure that 0N/A * the data for the two sections is adjacent with the SUNW_ldynsym 0N/A * in front. This allows the runtime linker to treat these two 0N/A * symbol tables as being a single larger table. There are two 0N/A * items in the dynamic section for this: 0N/A * DT_SUNW_SYMTAB base of the SUNW_ldynsym 0N/A * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym 0N/A * added together. We can figure out the 0N/A * size of the SUNW_ldynsym section by 0N/A * subtracting the size of the dynsym 0N/A * (described above) from this value. 0N/A * We can figure out the size of the .plt section, but it takes some 0N/A * doing. We need to use the following information: 0N/A * DT_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc) 0N/A * DT_JMPREL base of the PLT's relocation section 0N/A * DT_PLTRELSZ size of the PLT's relocation section 0N/A * DT_PLTREL type of the PLT's relocation section 0N/A * We can use the number of relocation entries to calculate the size of 0N/A * the PLT. We get the address of the PLT by looking up the 0N/A * _PROCEDURE_LINKAGE_TABLE_ symbol. 0N/A * For more information, check out the System V Generic ABI. 0N/A * The fake_elfXX() function generated by this file uses the following 0N/A * string as the string table for the section names. Since it is critical 0N/A * to count correctly, and to improve readability, the SHSTR_NDX_ macros 0N/A * supply the proper offset for each name within the string. 0N/A ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
0N/A/* Offsets within shstr for each name */ 0N/A * Section header alignment for 32 and 64-bit ELF files differs 0N/A * This is the smallest number of PLT relocation entries allowed in a proper 0N/A * On x86, lint would complain about unsigned comparison with 0N/A * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES 0N/A * and silences lint. On SPARC, there is no such issue. 0N/A * Mask of dynamic options that must be present in a well 0N/A * formed dynamic section. We need all of these in order to 0N/A * put together a complete set of elf sections. They are 0N/A * mandatory in both executables and shared objects so if one 0N/A * of them is missing, we're in some trouble and should abort. 0N/A * The PLT items are expected, but we will let them slide if 0N/A * need be. The DI_SUNW_SYM* items are completely optional, so 0N/A * we use them if they are present and ignore them otherwise. * Iterate over the items in the dynamic section, grabbing * the address of items we want and saving them in dp[]. /* For the .plt section */ /* For the .dynsym section */ /* For the .dynstr section */ /* Ensure all required entries were collected */ dprintf(
"text section missing required dynamic entries: " /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */ /* program headers from in-core elf fragment */ /* unused shdr, and .shstrtab section */ dprintf(
"Pread of .hash at %lx failed\n",
* .dynsym and .SUNW_ldynsym sections. * The string table section used for the symbol table and * dynamic sections lies immediately after the dynsym, so the * presence of SUNW_ldynsym changes the dynstr section index. size +=
sizeof (
Shdr);
/* SUNW_ldynsym shdr */ /* fall back to the platform default */ dprintf(
"DI_PLTREL not found, defaulting to Rel");
#
else /* (!(__i386 || __amd64)) || _ELF64 */ dprintf(
"DI_PLTREL not found, defaulting to Rela");
#
endif /* (!(__i386 || __amd64) || _ELF64 */ dprintf(
"too few PLT relocation entries " "(found %lu, expected at least %d)\n",
* Now that we know the number of plt relocation entries * we can calculate the size of the plt. /* The sparc PLT always has a (delay slot) nop at the end */ * Plt and SUNW_ldynsym sections are optional. C logical * binary operators return a 0 or 1 value, so the following * adds 1 for each optional section present. * Copying the program headers directly from the process's * address space is a little suspect, but since we only * use them for their address and size values, this is fine. dprintf(
"failed to read program headers\n");
* The first elf section is always skipped. * Section Header: .shstrtab * Section Header: .SUNW_ldynsym /* Index of 1st global in table that has none == # items */ dprintf(
"failed to read .SUNW_ldynsym at %lx\n",
/* No need to round up ldynsym data. Dynsym data is same type */ * Section Header: .dynsym sp->
sh_info =
1;
/* Index of 1st global in table */ dprintf(
"failed to read .dynsym at %lx\n",
* Section Header: .dynstr dprintf(
"failed to read .dynstr\n");
* Section Header: .dynamic char strbuf[
sizeof (
"_PROCEDURE_LINKAGE_TABLE_")];
* Now we need to find the address of the plt by looking * up the "_PROCEDURE_LINKAGE_TABLE_" symbol. /* get the address of the symtab and strtab sections */ dprintf(
"empty or missing .hash\n");
/* find the .hash bucket address for this symbol */ /* read the elf hash bucket index */ dprintf(
"Pread of .symtab at %lx failed\n",
dprintf(
"Pread of .strtab at %lx failed\n",
dprintf(
"Pread of .hash at %lx failed\n",
dprintf(
"warning: DI_PLTGOT (%lx) doesn't match " ".plt symbol pointer (%lx)",
"Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
dprintf(
"failed to read .plt at %lx\n",
/* make sure we didn't write past the end of allocated memory */ dprintf(
"failed to create ELF object " "in memory for size %ld\n", (
long)
size);