13347Sab196087 /*
23347Sab196087 * CDDL HEADER START
33347Sab196087 *
43347Sab196087 * The contents of this file are subject to the terms of the
53347Sab196087 * Common Development and Distribution License (the "License").
63347Sab196087 * You may not use this file except in compliance with the License.
73347Sab196087 *
83347Sab196087 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93347Sab196087 * or http://www.opensolaris.org/os/licensing.
103347Sab196087 * See the License for the specific language governing permissions
113347Sab196087 * and limitations under the License.
123347Sab196087 *
133347Sab196087 * When distributing Covered Code, include this CDDL HEADER in each
143347Sab196087 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153347Sab196087 * If applicable, add the following below this CDDL HEADER, with the
163347Sab196087 * fields enclosed by brackets "[]" replaced with your own identifying
173347Sab196087 * information: Portions Copyright [yyyy] [name of copyright owner]
183347Sab196087 *
193347Sab196087 * CDDL HEADER END
203347Sab196087 */
213347Sab196087
223347Sab196087 /*
23*10201SEdward.Pilatowicz@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
243347Sab196087 * Use is subject to license terms.
253347Sab196087 */
263347Sab196087
27*10201SEdward.Pilatowicz@Sun.COM #include <assert.h>
283347Sab196087 #include <stdio.h>
293347Sab196087 #include <stdlib.h>
303347Sab196087 #include <stddef.h>
31*10201SEdward.Pilatowicz@Sun.COM #include <string.h>
323347Sab196087 #include <memory.h>
333347Sab196087 #include <sys/sysmacros.h>
343347Sab196087 #include <sys/machelf.h>
353347Sab196087
363347Sab196087 #include "Pcontrol.h"
373347Sab196087 #include "Psymtab_machelf.h"
383347Sab196087
393347Sab196087
403347Sab196087 /*
413347Sab196087 * This file contains code for use by Psymtab.c that is compiled once
423347Sab196087 * for each supported ELFCLASS.
433347Sab196087 *
443347Sab196087 * When processing ELF files, it is common to encounter a situation where
453347Sab196087 * a program with one ELFCLASS (32 or 64-bit) is required to examine a
463347Sab196087 * file with a different ELFCLASS. For example, the 32-bit linker (ld) may
473347Sab196087 * be used to link a 64-bit program. The simplest solution to this problem
483347Sab196087 * is to duplicate each such piece of code, modifying only the data types,
493347Sab196087 * and to use if statements to select the code to run. The problem with
503347Sab196087 * doing it that way is that the resulting code is difficult to maintain.
513347Sab196087 * It is inevitable that the copies will not always get modified identically,
523347Sab196087 * and will drift apart. The only robust solution is to generate the
533347Sab196087 * multiple instances of code automatically from a single piece of code.
543347Sab196087 *
553347Sab196087 * The solution used within the Solaris linker is to write the code once,
563347Sab196087 * using the data types defined in sys/machelf.h, and then to compile that
573347Sab196087 * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and
583347Sab196087 * once without (to generate ELFCLASS32). We use the same approach here.
593347Sab196087 *
603347Sab196087 * Note that the _ELF64 definition does not refer to the ELFCLASS of
613347Sab196087 * the resulting code, but rather, to the ELFCLASS of the data it
623347Sab196087 * examines. By repeating the above double-compilation for both 32-bit
633347Sab196087 * and 64-bit builds, we end up with 4 instances, which collectively
643347Sab196087 * can handle any combination of program and ELF data class:
653347Sab196087 *
663347Sab196087 * \ Compilation class
673347Sab196087 * \ 32 64
683347Sab196087 * \------------------
693347Sab196087 * |
703347Sab196087 * 32 | X X
713347Sab196087 * ELF Data Class |
723347Sab196087 * 64 | X X
733347Sab196087 */
743347Sab196087
753347Sab196087
763347Sab196087
773347Sab196087 /*
783347Sab196087 * Read data from the specified process and construct an in memory
793347Sab196087 * image of an ELF file that will let us use libelf for most of the
803347Sab196087 * work we need to later (e.g. symbol table lookups). This is used
813347Sab196087 * in cases where no usable on-disk image for the process is available.
823347Sab196087 * We need sections for the dynsym, dynstr, and plt, and we need
833347Sab196087 * the program headers from the text section. The former is used in
843347Sab196087 * Pbuild_file_symtab(); the latter is used in several functions in
853347Sab196087 * Pcore.c to reconstruct the origin of each mapping from the load
863347Sab196087 * object that spawned it.
873347Sab196087 *
883347Sab196087 * Here are some useful pieces of elf trivia that will help
893347Sab196087 * to elucidate this code.
903347Sab196087 *
913347Sab196087 * All the information we need about the dynstr can be found in these
923347Sab196087 * two entries in the dynamic section:
933347Sab196087 *
943347Sab196087 * DT_STRTAB base of dynstr
953347Sab196087 * DT_STRSZ size of dynstr
963347Sab196087 *
973347Sab196087 * So deciphering the dynstr is pretty straightforward.
983347Sab196087 *
993347Sab196087 * The dynsym is a little trickier.
1003347Sab196087 *
1013347Sab196087 * DT_SYMTAB base of dynsym
1023347Sab196087 * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym)
1033347Sab196087 * DT_HASH base of hash table for dynamic lookups
1043347Sab196087 *
1053347Sab196087 * The DT_SYMTAB entry gives us any easy way of getting to the base
1063347Sab196087 * of the dynsym, but getting the size involves rooting around in the
1073347Sab196087 * dynamic lookup hash table. Here's the layout of the hash table:
1083347Sab196087 *
1093347Sab196087 * +-------------------+
1103347Sab196087 * | nbucket | All values are 32-bit
1113347Sab196087 * +-------------------+ (Elf32_Word or Elf64_Word)
1123347Sab196087 * | nchain |
1133347Sab196087 * +-------------------+
1143347Sab196087 * | bucket[0] |
1153347Sab196087 * | . . . |
1163347Sab196087 * | bucket[nbucket-1] |
1173347Sab196087 * +-------------------+
1183347Sab196087 * | chain[0] |
1193347Sab196087 * | . . . |
1203347Sab196087 * | chain[nchain-1] |
1213347Sab196087 * +-------------------+
1223347Sab196087 * (figure 5-12 from the SYS V Generic ABI)
1233347Sab196087 *
1243347Sab196087 * Symbols names are hashed into a particular bucket which contains
1253347Sab196087 * an index into the symbol table. Each entry in the symbol table
1263347Sab196087 * has a corresponding entry in the chain table which tells the
1273347Sab196087 * consumer where the next entry in the hash chain is. We can use
1283347Sab196087 * the nchain field to find out the size of the dynsym.
1293347Sab196087 *
1303347Sab196087 * If there is a dynsym present, there may also be an optional
1313347Sab196087 * section called the SUNW_ldynsym that augments the dynsym by
1323347Sab196087 * providing local function symbols. When the Solaris linker lays
1333347Sab196087 * out a file that has both of these sections, it makes sure that
1343347Sab196087 * the data for the two sections is adjacent with the SUNW_ldynsym
1353347Sab196087 * in front. This allows the runtime linker to treat these two
1363347Sab196087 * symbol tables as being a single larger table. There are two
1373347Sab196087 * items in the dynamic section for this:
1383347Sab196087 *
1393347Sab196087 * DT_SUNW_SYMTAB base of the SUNW_ldynsym
1403347Sab196087 * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym
1413347Sab196087 * added together. We can figure out the
1423347Sab196087 * size of the SUNW_ldynsym section by
1433347Sab196087 * subtracting the size of the dynsym
1443347Sab196087 * (described above) from this value.
1453347Sab196087 *
1463347Sab196087 * We can figure out the size of the .plt section, but it takes some
1473347Sab196087 * doing. We need to use the following information:
1483347Sab196087 *
149*10201SEdward.Pilatowicz@Sun.COM * DT_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc)
1503347Sab196087 * DT_JMPREL base of the PLT's relocation section
1513347Sab196087 * DT_PLTRELSZ size of the PLT's relocation section
1523347Sab196087 * DT_PLTREL type of the PLT's relocation section
1533347Sab196087 *
154*10201SEdward.Pilatowicz@Sun.COM * We can use the number of relocation entries to calculate the size of
155*10201SEdward.Pilatowicz@Sun.COM * the PLT. We get the address of the PLT by looking up the
156*10201SEdward.Pilatowicz@Sun.COM * _PROCEDURE_LINKAGE_TABLE_ symbol.
1573347Sab196087 *
1583347Sab196087 * For more information, check out the System V Generic ABI.
1593347Sab196087 */
1603347Sab196087
1613347Sab196087
1623347Sab196087 /*
1633347Sab196087 * The fake_elfXX() function generated by this file uses the following
1643347Sab196087 * string as the string table for the section names. Since it is critical
1653347Sab196087 * to count correctly, and to improve readability, the SHSTR_NDX_ macros
1663347Sab196087 * supply the proper offset for each name within the string.
1673347Sab196087 */
1683347Sab196087 static char shstr[] =
1693347Sab196087 ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
1703347Sab196087
1713347Sab196087 /* Offsets within shstr for each name */
1723347Sab196087 #define SHSTR_NDX_shstrtab 0
1733347Sab196087 #define SHSTR_NDX_dynsym 10
1743347Sab196087 #define SHSTR_NDX_dynstr 18
1753347Sab196087 #define SHSTR_NDX_dynamic 26
1763347Sab196087 #define SHSTR_NDX_plt 35
1773347Sab196087 #define SHSTR_NDX_SUNW_ldynsym 40
1783347Sab196087
1793347Sab196087
1803347Sab196087 /*
1813347Sab196087 * Section header alignment for 32 and 64-bit ELF files differs
1823347Sab196087 */
1833347Sab196087 #ifdef _ELF64
1843347Sab196087 #define SH_ADDRALIGN 8
1853347Sab196087 #else
1863347Sab196087 #define SH_ADDRALIGN 4
1873347Sab196087 #endif
1883347Sab196087
1893656Sjj204856 /*
1903656Sjj204856 * This is the smallest number of PLT relocation entries allowed in a proper
1913656Sjj204856 * .plt section.
1923656Sjj204856 */
1933656Sjj204856 #ifdef __sparc
1943656Sjj204856 #define PLTREL_MIN_ENTRIES 4 /* SPARC psABI 3.0 and SCD 2.4 */
1953656Sjj204856 #else
1963656Sjj204856 #ifdef __lint
1973656Sjj204856 /*
1983656Sjj204856 * On x86, lint would complain about unsigned comparison with
1993656Sjj204856 * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES
2003656Sjj204856 * and silences lint. On SPARC, there is no such issue.
2013656Sjj204856 */
2023656Sjj204856 #define PLTREL_MIN_ENTRIES 1
2033656Sjj204856 #else
2043656Sjj204856 #define PLTREL_MIN_ENTRIES 0
2053656Sjj204856 #endif
2063656Sjj204856 #endif
2073656Sjj204856
2083347Sab196087 #ifdef _ELF64
2093347Sab196087 Elf *
fake_elf64(struct ps_prochandle * P,file_info_t * fptr,uintptr_t addr,Ehdr * ehdr,uint_t phnum,Phdr * phdr)2103347Sab196087 fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
2113347Sab196087 Ehdr *ehdr, uint_t phnum, Phdr *phdr)
2123347Sab196087 #else
2133347Sab196087 Elf *
2143347Sab196087 fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
2153347Sab196087 Ehdr *ehdr, uint_t phnum, Phdr *phdr)
2163347Sab196087 #endif
2173347Sab196087 {
2183347Sab196087 enum {
2193347Sab196087 DI_PLTGOT,
2203347Sab196087 DI_JMPREL,
2213347Sab196087 DI_PLTRELSZ,
2223347Sab196087 DI_PLTREL,
2233347Sab196087 DI_SYMTAB,
2243347Sab196087 DI_HASH,
2253347Sab196087 DI_SYMENT,
2263347Sab196087 DI_STRTAB,
2273347Sab196087 DI_STRSZ,
2283347Sab196087 DI_SUNW_SYMTAB,
2293347Sab196087 DI_SUNW_SYMSZ,
2303347Sab196087 DI_NENT
2313347Sab196087 };
2323347Sab196087 /*
2333347Sab196087 * Mask of dynamic options that must be present in a well
2343347Sab196087 * formed dynamic section. We need all of these in order to
2353347Sab196087 * put together a complete set of elf sections. They are
2363347Sab196087 * mandatory in both executables and shared objects so if one
2373347Sab196087 * of them is missing, we're in some trouble and should abort.
2383347Sab196087 * The PLT items are expected, but we will let them slide if
2393347Sab196087 * need be. The DI_SUNW_SYM* items are completely optional, so
2403347Sab196087 * we use them if they are present and ignore them otherwise.
2413347Sab196087 */
2423347Sab196087 const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) |
2433347Sab196087 (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
2443347Sab196087 int di_mask = 0;
2453347Sab196087 size_t size = 0;
2463347Sab196087 caddr_t elfdata = NULL;
2473347Sab196087 Elf *elf;
248*10201SEdward.Pilatowicz@Sun.COM size_t dynsym_size = 0, ldynsym_size;
2493347Sab196087 int dynstr_shndx;
2503347Sab196087 Ehdr *ep;
2513347Sab196087 Shdr *sp;
2523347Sab196087 Dyn *dp;
2533347Sab196087 Dyn *d[DI_NENT] = { 0 };
2543347Sab196087 uint_t i;
2553347Sab196087 Off off;
256*10201SEdward.Pilatowicz@Sun.COM size_t pltsz = 0, pltentries = 0;
257*10201SEdward.Pilatowicz@Sun.COM uintptr_t hptr = NULL;
258*10201SEdward.Pilatowicz@Sun.COM Word hnchains, hnbuckets;
2593347Sab196087
2603347Sab196087 if (ehdr->e_type == ET_DYN)
2613347Sab196087 phdr->p_vaddr += addr;
2623347Sab196087
2636830Sedp if (P->rap != NULL) {
2646830Sedp if (rd_get_dyns(P->rap, addr, (void **)&dp, NULL) != RD_OK)
2656830Sedp goto bad;
2666830Sedp } else {
2676830Sedp if ((dp = malloc(phdr->p_filesz)) == NULL)
2686830Sedp goto bad;
2696830Sedp if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) !=
2706830Sedp phdr->p_filesz)
2716830Sedp goto bad;
2723347Sab196087 }
2733347Sab196087
2743347Sab196087 /*
2753347Sab196087 * Iterate over the items in the dynamic section, grabbing
2763347Sab196087 * the address of items we want and saving them in dp[].
2773347Sab196087 */
2783347Sab196087 for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
2793347Sab196087 switch (dp[i].d_tag) {
2803347Sab196087 /* For the .plt section */
2813347Sab196087 case DT_PLTGOT:
2823347Sab196087 d[DI_PLTGOT] = &dp[i];
2833347Sab196087 break;
2843347Sab196087 case DT_JMPREL:
2853347Sab196087 d[DI_JMPREL] = &dp[i];
2863347Sab196087 break;
2873347Sab196087 case DT_PLTRELSZ:
2883347Sab196087 d[DI_PLTRELSZ] = &dp[i];
2893347Sab196087 break;
2903347Sab196087 case DT_PLTREL:
2913347Sab196087 d[DI_PLTREL] = &dp[i];
2923347Sab196087 break;
2933347Sab196087
2943347Sab196087 /* For the .dynsym section */
2953347Sab196087 case DT_SYMTAB:
2963347Sab196087 d[DI_SYMTAB] = &dp[i];
2973347Sab196087 di_mask |= (1 << DI_SYMTAB);
2983347Sab196087 break;
2993347Sab196087 case DT_HASH:
3003347Sab196087 d[DI_HASH] = &dp[i];
3013347Sab196087 di_mask |= (1 << DI_HASH);
3023347Sab196087 break;
3033347Sab196087 case DT_SYMENT:
3043347Sab196087 d[DI_SYMENT] = &dp[i];
3053347Sab196087 di_mask |= (1 << DI_SYMENT);
3063347Sab196087 break;
3073347Sab196087 case DT_SUNW_SYMTAB:
3083347Sab196087 d[DI_SUNW_SYMTAB] = &dp[i];
3093347Sab196087 break;
3103347Sab196087 case DT_SUNW_SYMSZ:
3113347Sab196087 d[DI_SUNW_SYMSZ] = &dp[i];
3123347Sab196087 break;
3133347Sab196087
3143347Sab196087 /* For the .dynstr section */
3153347Sab196087 case DT_STRTAB:
3163347Sab196087 d[DI_STRTAB] = &dp[i];
3173347Sab196087 di_mask |= (1 << DI_STRTAB);
3183347Sab196087 break;
3193347Sab196087 case DT_STRSZ:
3203347Sab196087 d[DI_STRSZ] = &dp[i];
3213347Sab196087 di_mask |= (1 << DI_STRSZ);
3223347Sab196087 break;
3233347Sab196087 }
3243347Sab196087 }
3253347Sab196087
3263347Sab196087 /* Ensure all required entries were collected */
3273347Sab196087 if ((di_mask & di_req_mask) != di_req_mask) {
3283347Sab196087 dprintf("text section missing required dynamic entries\n");
3293347Sab196087 goto bad;
3303347Sab196087 }
3313347Sab196087
3323347Sab196087 /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
3333347Sab196087 if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
3343347Sab196087 ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
3353347Sab196087 (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
3363347Sab196087 d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
3373347Sab196087 d[DI_SUNW_SYMTAB] = NULL;
3383347Sab196087 d[DI_SUNW_SYMSZ] = NULL;
3393347Sab196087 }
3403347Sab196087
3413347Sab196087 /* elf header */
3423347Sab196087 size = sizeof (Ehdr);
3433347Sab196087
3443347Sab196087 /* program headers from in-core elf fragment */
3453347Sab196087 size += phnum * ehdr->e_phentsize;
3463347Sab196087
3473347Sab196087 /* unused shdr, and .shstrtab section */
3483347Sab196087 size += sizeof (Shdr);
3493347Sab196087 size += sizeof (Shdr);
3503347Sab196087 size += roundup(sizeof (shstr), SH_ADDRALIGN);
3513347Sab196087
352*10201SEdward.Pilatowicz@Sun.COM if (d[DI_HASH] != NULL) {
353*10201SEdward.Pilatowicz@Sun.COM Word hash[2];
354*10201SEdward.Pilatowicz@Sun.COM
355*10201SEdward.Pilatowicz@Sun.COM hptr = d[DI_HASH]->d_un.d_ptr;
356*10201SEdward.Pilatowicz@Sun.COM if (ehdr->e_type == ET_DYN)
357*10201SEdward.Pilatowicz@Sun.COM hptr += addr;
358*10201SEdward.Pilatowicz@Sun.COM
359*10201SEdward.Pilatowicz@Sun.COM if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) {
360*10201SEdward.Pilatowicz@Sun.COM dprintf("Pread of .hash at %lx failed\n",
361*10201SEdward.Pilatowicz@Sun.COM (long)(hptr));
362*10201SEdward.Pilatowicz@Sun.COM goto bad;
363*10201SEdward.Pilatowicz@Sun.COM }
364*10201SEdward.Pilatowicz@Sun.COM
365*10201SEdward.Pilatowicz@Sun.COM hnbuckets = hash[0];
366*10201SEdward.Pilatowicz@Sun.COM hnchains = hash[1];
367*10201SEdward.Pilatowicz@Sun.COM }
368*10201SEdward.Pilatowicz@Sun.COM
3693347Sab196087 /*
3703347Sab196087 * .dynsym and .SUNW_ldynsym sections.
3713347Sab196087 *
3723347Sab196087 * The string table section used for the symbol table and
3733347Sab196087 * dynamic sections lies immediately after the dynsym, so the
3743347Sab196087 * presence of SUNW_ldynsym changes the dynstr section index.
3753347Sab196087 */
3763347Sab196087 if (d[DI_SUNW_SYMTAB] != NULL) {
3773347Sab196087 size += sizeof (Shdr); /* SUNW_ldynsym shdr */
3783347Sab196087 ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
3793347Sab196087 dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
3803347Sab196087 - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
3813347Sab196087 ldynsym_size -= dynsym_size;
3823347Sab196087 dynstr_shndx = 4;
3833347Sab196087 } else {
384*10201SEdward.Pilatowicz@Sun.COM dynsym_size = sizeof (Sym) * hnchains;
3853347Sab196087 ldynsym_size = 0;
3863347Sab196087 dynstr_shndx = 3;
3873347Sab196087 }
3883347Sab196087 size += sizeof (Shdr) + ldynsym_size + dynsym_size;
3893347Sab196087
3903347Sab196087 /* .dynstr section */
3913347Sab196087 size += sizeof (Shdr);
3923347Sab196087 size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
3933347Sab196087
3943347Sab196087 /* .dynamic section */
3953347Sab196087 size += sizeof (Shdr);
3963347Sab196087 size += roundup(phdr->p_filesz, SH_ADDRALIGN);
3973347Sab196087
3983347Sab196087 /* .plt section */
3993347Sab196087 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
4003347Sab196087 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
4013347Sab196087 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
4023347Sab196087
4033347Sab196087 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
404*10201SEdward.Pilatowicz@Sun.COM pltentries = pltrelsz / sizeof (Rela);
4053347Sab196087 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
406*10201SEdward.Pilatowicz@Sun.COM pltentries = pltrelsz / sizeof (Rel);
407*10201SEdward.Pilatowicz@Sun.COM } else {
408*10201SEdward.Pilatowicz@Sun.COM /* fall back to the platform default */
409*10201SEdward.Pilatowicz@Sun.COM #if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64))
410*10201SEdward.Pilatowicz@Sun.COM pltentries = pltrelsz / sizeof (Rel);
411*10201SEdward.Pilatowicz@Sun.COM dprintf("DI_PLTREL not found, defaulting to Rel");
412*10201SEdward.Pilatowicz@Sun.COM #else /* (!(__i386 || __amd64)) || _ELF64 */
413*10201SEdward.Pilatowicz@Sun.COM pltentries = pltrelsz / sizeof (Rela);
414*10201SEdward.Pilatowicz@Sun.COM dprintf("DI_PLTREL not found, defaulting to Rela");
415*10201SEdward.Pilatowicz@Sun.COM #endif /* (!(__i386 || __amd64) || _ELF64 */
416*10201SEdward.Pilatowicz@Sun.COM }
4173347Sab196087
418*10201SEdward.Pilatowicz@Sun.COM if (pltentries < PLTREL_MIN_ENTRIES) {
419*10201SEdward.Pilatowicz@Sun.COM dprintf("too few PLT relocation entries "
420*10201SEdward.Pilatowicz@Sun.COM "(found %lu, expected at least %d)\n",
421*10201SEdward.Pilatowicz@Sun.COM (long)pltentries, PLTREL_MIN_ENTRIES);
4223347Sab196087 goto bad;
4233347Sab196087 }
424*10201SEdward.Pilatowicz@Sun.COM if (pltentries < PLTREL_MIN_ENTRIES + 2)
425*10201SEdward.Pilatowicz@Sun.COM goto done_with_plt;
4263347Sab196087
427*10201SEdward.Pilatowicz@Sun.COM /*
428*10201SEdward.Pilatowicz@Sun.COM * Now that we know the number of plt relocation entries
429*10201SEdward.Pilatowicz@Sun.COM * we can calculate the size of the plt.
430*10201SEdward.Pilatowicz@Sun.COM */
431*10201SEdward.Pilatowicz@Sun.COM pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE;
432*10201SEdward.Pilatowicz@Sun.COM #if defined(__sparc)
433*10201SEdward.Pilatowicz@Sun.COM /* The sparc PLT always has a (delay slot) nop at the end */
434*10201SEdward.Pilatowicz@Sun.COM pltsz += 4;
435*10201SEdward.Pilatowicz@Sun.COM #endif /* __sparc */
4363347Sab196087
4373347Sab196087 size += sizeof (Shdr);
4383347Sab196087 size += roundup(pltsz, SH_ADDRALIGN);
4393347Sab196087 }
4403656Sjj204856 done_with_plt:
4413347Sab196087
4423347Sab196087 if ((elfdata = calloc(1, size)) == NULL)
4433347Sab196087 goto bad;
4443347Sab196087
4453347Sab196087 /* LINTED - alignment */
4463347Sab196087 ep = (Ehdr *)elfdata;
4473347Sab196087 (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
4483347Sab196087
4493347Sab196087 ep->e_ehsize = sizeof (Ehdr);
4503347Sab196087 ep->e_phoff = sizeof (Ehdr);
4513347Sab196087 ep->e_phentsize = ehdr->e_phentsize;
4523347Sab196087 ep->e_phnum = phnum;
4533347Sab196087 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
4543347Sab196087 ep->e_shentsize = sizeof (Shdr);
4553347Sab196087 /*
4563347Sab196087 * Plt and SUNW_ldynsym sections are optional. C logical
4573347Sab196087 * binary operators return a 0 or 1 value, so the following
4583347Sab196087 * adds 1 for each optional section present.
4593347Sab196087 */
4603347Sab196087 ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
4613347Sab196087 ep->e_shstrndx = 1;
4623347Sab196087
4633347Sab196087 /* LINTED - alignment */
4643347Sab196087 sp = (Shdr *)(elfdata + ep->e_shoff);
4653347Sab196087 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
4663347Sab196087
4673347Sab196087 /*
4683347Sab196087 * Copying the program headers directly from the process's
4693347Sab196087 * address space is a little suspect, but since we only
4703347Sab196087 * use them for their address and size values, this is fine.
4713347Sab196087 */
4723347Sab196087 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
4733347Sab196087 addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
4743347Sab196087 dprintf("failed to read program headers\n");
4753347Sab196087 goto bad;
4763347Sab196087 }
4773347Sab196087
4783347Sab196087 /*
4793347Sab196087 * The first elf section is always skipped.
4803347Sab196087 */
4813347Sab196087 sp++;
4823347Sab196087
4833347Sab196087 /*
4843347Sab196087 * Section Header: .shstrtab
4853347Sab196087 */
4863347Sab196087 sp->sh_name = SHSTR_NDX_shstrtab;
4873347Sab196087 sp->sh_type = SHT_STRTAB;
4883347Sab196087 sp->sh_flags = SHF_STRINGS;
4893347Sab196087 sp->sh_addr = 0;
4903347Sab196087 sp->sh_offset = off;
4913347Sab196087 sp->sh_size = sizeof (shstr);
4923347Sab196087 sp->sh_link = 0;
4933347Sab196087 sp->sh_info = 0;
4943347Sab196087 sp->sh_addralign = 1;
4953347Sab196087 sp->sh_entsize = 0;
4963347Sab196087
4973347Sab196087 (void) memcpy(&elfdata[off], shstr, sizeof (shstr));
4983347Sab196087 off += roundup(sp->sh_size, SH_ADDRALIGN);
4993347Sab196087 sp++;
5003347Sab196087
5013347Sab196087 /*
5023347Sab196087 * Section Header: .SUNW_ldynsym
5033347Sab196087 */
5043347Sab196087 if (d[DI_SUNW_SYMTAB] != NULL) {
5053347Sab196087 sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
5063347Sab196087 sp->sh_type = SHT_SUNW_LDYNSYM;
5073347Sab196087 sp->sh_flags = SHF_ALLOC;
5083347Sab196087 sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
5093347Sab196087 if (ehdr->e_type == ET_DYN)
510*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr += addr;
5113347Sab196087 sp->sh_offset = off;
5123347Sab196087 sp->sh_size = ldynsym_size;
5133347Sab196087 sp->sh_link = dynstr_shndx;
5143347Sab196087 /* Index of 1st global in table that has none == # items */
5153347Sab196087 sp->sh_info = sp->sh_size / sizeof (Sym);
5163347Sab196087 sp->sh_addralign = SH_ADDRALIGN;
5173347Sab196087 sp->sh_entsize = sizeof (Sym);
5183347Sab196087
5193347Sab196087 if (Pread(P, &elfdata[off], sp->sh_size,
520*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr) != sp->sh_size) {
5213347Sab196087 dprintf("failed to read .SUNW_ldynsym at %lx\n",
522*10201SEdward.Pilatowicz@Sun.COM (long)sp->sh_addr);
5233347Sab196087 goto bad;
5243347Sab196087 }
5253347Sab196087 off += sp->sh_size;
5263347Sab196087 /* No need to round up ldynsym data. Dynsym data is same type */
5273347Sab196087 sp++;
5283347Sab196087 }
5293347Sab196087
5303347Sab196087 /*
5313347Sab196087 * Section Header: .dynsym
5323347Sab196087 */
5333347Sab196087 sp->sh_name = SHSTR_NDX_dynsym;
5343347Sab196087 sp->sh_type = SHT_DYNSYM;
5353347Sab196087 sp->sh_flags = SHF_ALLOC;
5363347Sab196087 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
5373347Sab196087 if (ehdr->e_type == ET_DYN)
538*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr += addr;
5393347Sab196087 sp->sh_offset = off;
5403347Sab196087 sp->sh_size = dynsym_size;
5413347Sab196087 sp->sh_link = dynstr_shndx;
5423347Sab196087 sp->sh_info = 1; /* Index of 1st global in table */
5433347Sab196087 sp->sh_addralign = SH_ADDRALIGN;
5443347Sab196087 sp->sh_entsize = sizeof (Sym);
5453347Sab196087
5463347Sab196087 if (Pread(P, &elfdata[off], sp->sh_size,
547*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr) != sp->sh_size) {
5483347Sab196087 dprintf("failed to read .dynsym at %lx\n",
549*10201SEdward.Pilatowicz@Sun.COM (long)sp->sh_addr);
5503347Sab196087 goto bad;
5513347Sab196087 }
5523347Sab196087
5533347Sab196087 off += roundup(sp->sh_size, SH_ADDRALIGN);
5543347Sab196087 sp++;
5553347Sab196087
5563347Sab196087 /*
5573347Sab196087 * Section Header: .dynstr
5583347Sab196087 */
5593347Sab196087 sp->sh_name = SHSTR_NDX_dynstr;
5603347Sab196087 sp->sh_type = SHT_STRTAB;
5613347Sab196087 sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
5623347Sab196087 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
5633347Sab196087 if (ehdr->e_type == ET_DYN)
564*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr += addr;
5653347Sab196087 sp->sh_offset = off;
5663347Sab196087 sp->sh_size = d[DI_STRSZ]->d_un.d_val;
5673347Sab196087 sp->sh_link = 0;
5683347Sab196087 sp->sh_info = 0;
5693347Sab196087 sp->sh_addralign = 1;
5703347Sab196087 sp->sh_entsize = 0;
5713347Sab196087
5723347Sab196087 if (Pread(P, &elfdata[off], sp->sh_size,
573*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr) != sp->sh_size) {
5743347Sab196087 dprintf("failed to read .dynstr\n");
5753347Sab196087 goto bad;
5763347Sab196087 }
5773347Sab196087 off += roundup(sp->sh_size, SH_ADDRALIGN);
5783347Sab196087 sp++;
5793347Sab196087
5803347Sab196087 /*
5813347Sab196087 * Section Header: .dynamic
5823347Sab196087 */
5833347Sab196087 sp->sh_name = SHSTR_NDX_dynamic;
5843347Sab196087 sp->sh_type = SHT_DYNAMIC;
5853347Sab196087 sp->sh_flags = SHF_WRITE | SHF_ALLOC;
5863347Sab196087 sp->sh_addr = phdr->p_vaddr;
5873347Sab196087 if (ehdr->e_type == ET_DYN)
5883347Sab196087 sp->sh_addr -= addr;
5893347Sab196087 sp->sh_offset = off;
5903347Sab196087 sp->sh_size = phdr->p_filesz;
5913347Sab196087 sp->sh_link = dynstr_shndx;
5923347Sab196087 sp->sh_info = 0;
5933347Sab196087 sp->sh_addralign = SH_ADDRALIGN;
5943347Sab196087 sp->sh_entsize = sizeof (Dyn);
5953347Sab196087
5963347Sab196087 (void) memcpy(&elfdata[off], dp, sp->sh_size);
5973347Sab196087 off += roundup(sp->sh_size, SH_ADDRALIGN);
5983347Sab196087 sp++;
5993347Sab196087
6003347Sab196087 /*
6013347Sab196087 * Section Header: .plt
6023347Sab196087 */
6033347Sab196087 if (pltsz != 0) {
604*10201SEdward.Pilatowicz@Sun.COM ulong_t plt_symhash;
605*10201SEdward.Pilatowicz@Sun.COM uint_t htmp, ndx;
606*10201SEdward.Pilatowicz@Sun.COM uintptr_t strtabptr, strtabname;
607*10201SEdward.Pilatowicz@Sun.COM Sym sym, *symtabptr;
608*10201SEdward.Pilatowicz@Sun.COM uint_t *hash;
609*10201SEdward.Pilatowicz@Sun.COM char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")];
610*10201SEdward.Pilatowicz@Sun.COM
611*10201SEdward.Pilatowicz@Sun.COM /*
612*10201SEdward.Pilatowicz@Sun.COM * Now we need to find the address of the plt by looking
613*10201SEdward.Pilatowicz@Sun.COM * up the "_PROCEDURE_LINKAGE_TABLE_" symbol.
614*10201SEdward.Pilatowicz@Sun.COM */
615*10201SEdward.Pilatowicz@Sun.COM
616*10201SEdward.Pilatowicz@Sun.COM /* get the address of the symtab and strtab sections */
617*10201SEdward.Pilatowicz@Sun.COM strtabptr = d[DI_STRTAB]->d_un.d_ptr;
618*10201SEdward.Pilatowicz@Sun.COM symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr;
619*10201SEdward.Pilatowicz@Sun.COM if (ehdr->e_type == ET_DYN) {
620*10201SEdward.Pilatowicz@Sun.COM strtabptr += addr;
621*10201SEdward.Pilatowicz@Sun.COM symtabptr = (Sym*)((uintptr_t)symtabptr + addr);
622*10201SEdward.Pilatowicz@Sun.COM }
623*10201SEdward.Pilatowicz@Sun.COM
624*10201SEdward.Pilatowicz@Sun.COM /* find the .hash bucket address for this symbol */
625*10201SEdward.Pilatowicz@Sun.COM plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_");
626*10201SEdward.Pilatowicz@Sun.COM htmp = plt_symhash % hnbuckets;
627*10201SEdward.Pilatowicz@Sun.COM hash = &((uint_t *)hptr)[2 + htmp];
628*10201SEdward.Pilatowicz@Sun.COM
629*10201SEdward.Pilatowicz@Sun.COM /* read the elf hash bucket index */
630*10201SEdward.Pilatowicz@Sun.COM if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
631*10201SEdward.Pilatowicz@Sun.COM sizeof (ndx)) {
632*10201SEdward.Pilatowicz@Sun.COM dprintf("Pread of .hash at %lx failed\n", (long)hash);
633*10201SEdward.Pilatowicz@Sun.COM goto bad;
634*10201SEdward.Pilatowicz@Sun.COM }
635*10201SEdward.Pilatowicz@Sun.COM
636*10201SEdward.Pilatowicz@Sun.COM while (ndx) {
637*10201SEdward.Pilatowicz@Sun.COM if (Pread(P, &sym, sizeof (sym),
638*10201SEdward.Pilatowicz@Sun.COM (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) {
639*10201SEdward.Pilatowicz@Sun.COM dprintf("Pread of .symtab at %lx failed\n",
640*10201SEdward.Pilatowicz@Sun.COM (long)&symtabptr[ndx]);
641*10201SEdward.Pilatowicz@Sun.COM goto bad;
642*10201SEdward.Pilatowicz@Sun.COM }
643*10201SEdward.Pilatowicz@Sun.COM
644*10201SEdward.Pilatowicz@Sun.COM strtabname = strtabptr + sym.st_name;
645*10201SEdward.Pilatowicz@Sun.COM if (Pread_string(P, strbuf, sizeof (strbuf),
646*10201SEdward.Pilatowicz@Sun.COM strtabname) < 0) {
647*10201SEdward.Pilatowicz@Sun.COM dprintf("Pread of .strtab at %lx failed\n",
648*10201SEdward.Pilatowicz@Sun.COM (long)strtabname);
649*10201SEdward.Pilatowicz@Sun.COM goto bad;
650*10201SEdward.Pilatowicz@Sun.COM }
651*10201SEdward.Pilatowicz@Sun.COM
652*10201SEdward.Pilatowicz@Sun.COM if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0)
653*10201SEdward.Pilatowicz@Sun.COM break;
654*10201SEdward.Pilatowicz@Sun.COM
655*10201SEdward.Pilatowicz@Sun.COM hash = &((uint_t *)hptr)[2 + hnbuckets + ndx];
656*10201SEdward.Pilatowicz@Sun.COM if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
657*10201SEdward.Pilatowicz@Sun.COM sizeof (ndx)) {
658*10201SEdward.Pilatowicz@Sun.COM dprintf("Pread of .hash at %lx failed\n",
659*10201SEdward.Pilatowicz@Sun.COM (long)hash);
660*10201SEdward.Pilatowicz@Sun.COM goto bad;
661*10201SEdward.Pilatowicz@Sun.COM }
662*10201SEdward.Pilatowicz@Sun.COM }
663*10201SEdward.Pilatowicz@Sun.COM
664*10201SEdward.Pilatowicz@Sun.COM #if defined(__sparc)
665*10201SEdward.Pilatowicz@Sun.COM if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) {
666*10201SEdward.Pilatowicz@Sun.COM dprintf("warning: DI_PLTGOT (%lx) doesn't match "
667*10201SEdward.Pilatowicz@Sun.COM ".plt symbol pointer (%lx)",
668*10201SEdward.Pilatowicz@Sun.COM (long)d[DI_PLTGOT]->d_un.d_ptr,
669*10201SEdward.Pilatowicz@Sun.COM (long)sym.st_value);
670*10201SEdward.Pilatowicz@Sun.COM }
671*10201SEdward.Pilatowicz@Sun.COM #endif /* __sparc */
672*10201SEdward.Pilatowicz@Sun.COM
673*10201SEdward.Pilatowicz@Sun.COM if (ndx == 0) {
674*10201SEdward.Pilatowicz@Sun.COM dprintf(
675*10201SEdward.Pilatowicz@Sun.COM "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
676*10201SEdward.Pilatowicz@Sun.COM goto bad;
677*10201SEdward.Pilatowicz@Sun.COM }
678*10201SEdward.Pilatowicz@Sun.COM
6793347Sab196087 sp->sh_name = SHSTR_NDX_plt;
6803347Sab196087 sp->sh_type = SHT_PROGBITS;
6813347Sab196087 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
682*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr = sym.st_value;
6833347Sab196087 if (ehdr->e_type == ET_DYN)
684*10201SEdward.Pilatowicz@Sun.COM sp->sh_addr += addr;
6853347Sab196087 sp->sh_offset = off;
6863347Sab196087 sp->sh_size = pltsz;
6873347Sab196087 sp->sh_link = 0;
6883347Sab196087 sp->sh_info = 0;
6893347Sab196087 sp->sh_addralign = SH_ADDRALIGN;
690*10201SEdward.Pilatowicz@Sun.COM sp->sh_entsize = M_PLT_ENTSIZE;
6913347Sab196087
692*10201SEdward.Pilatowicz@Sun.COM if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) !=
693*10201SEdward.Pilatowicz@Sun.COM sp->sh_size) {
694*10201SEdward.Pilatowicz@Sun.COM dprintf("failed to read .plt at %lx\n",
695*10201SEdward.Pilatowicz@Sun.COM (long)sp->sh_addr);
6963347Sab196087 goto bad;
6973347Sab196087 }
6983347Sab196087 off += roundup(sp->sh_size, SH_ADDRALIGN);
6993347Sab196087 sp++;
7003347Sab196087 }
7013347Sab196087
702*10201SEdward.Pilatowicz@Sun.COM /* make sure we didn't write past the end of allocated memory */
703*10201SEdward.Pilatowicz@Sun.COM sp++;
704*10201SEdward.Pilatowicz@Sun.COM assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size));
705*10201SEdward.Pilatowicz@Sun.COM
7063347Sab196087 free(dp);
7073347Sab196087 if ((elf = elf_memory(elfdata, size)) == NULL) {
7083347Sab196087 free(elfdata);
7093347Sab196087 return (NULL);
7103347Sab196087 }
7113347Sab196087
7123347Sab196087 fptr->file_elfmem = elfdata;
7133347Sab196087
7143347Sab196087 return (elf);
7153347Sab196087
7163347Sab196087 bad:
7173347Sab196087 if (dp != NULL)
7183347Sab196087 free(dp);
7193347Sab196087 if (elfdata != NULL)
7203347Sab196087 free(elfdata);
7213347Sab196087 return (NULL);
7223347Sab196087 }
723