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