1d51e9074Sab /*
2d51e9074Sab * CDDL HEADER START
3d51e9074Sab *
4d51e9074Sab * The contents of this file are subject to the terms of the
5d51e9074Sab * Common Development and Distribution License (the "License").
6d51e9074Sab * You may not use this file except in compliance with the License.
7d51e9074Sab *
8d51e9074Sab * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d51e9074Sab * or http://www.opensolaris.org/os/licensing.
10d51e9074Sab * See the License for the specific language governing permissions
11d51e9074Sab * and limitations under the License.
12d51e9074Sab *
13d51e9074Sab * When distributing Covered Code, include this CDDL HEADER in each
14d51e9074Sab * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d51e9074Sab * If applicable, add the following below this CDDL HEADER, with the
16d51e9074Sab * fields enclosed by brackets "[]" replaced with your own identifying
17d51e9074Sab * information: Portions Copyright [yyyy] [name of copyright owner]
18d51e9074Sab *
19d51e9074Sab * CDDL HEADER END
20d51e9074Sab */
21d51e9074Sab
22d51e9074Sab /*
23d9452f23SEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24d51e9074Sab * Use is subject to license terms.
25d51e9074Sab */
26d51e9074Sab
27beee6fc0SBryan Cantrill /*
28beee6fc0SBryan Cantrill * Copyright (c) 2015, Joyent, Inc. All rights reserved.
29beee6fc0SBryan Cantrill */
30beee6fc0SBryan Cantrill
31d9452f23SEdward Pilatowicz #include <assert.h>
32d51e9074Sab #include <stdio.h>
33d51e9074Sab #include <stdlib.h>
34d51e9074Sab #include <stddef.h>
35d9452f23SEdward Pilatowicz #include <string.h>
36d51e9074Sab #include <memory.h>
37d51e9074Sab #include <sys/sysmacros.h>
38d51e9074Sab #include <sys/machelf.h>
39d51e9074Sab
40d51e9074Sab #include "Pcontrol.h"
41d51e9074Sab #include "Psymtab_machelf.h"
42d51e9074Sab
43d51e9074Sab
44d51e9074Sab /*
45d51e9074Sab * This file contains code for use by Psymtab.c that is compiled once
46d51e9074Sab * for each supported ELFCLASS.
47d51e9074Sab *
48d51e9074Sab * When processing ELF files, it is common to encounter a situation where
49d51e9074Sab * a program with one ELFCLASS (32 or 64-bit) is required to examine a
50d51e9074Sab * file with a different ELFCLASS. For example, the 32-bit linker (ld) may
51d51e9074Sab * be used to link a 64-bit program. The simplest solution to this problem
52d51e9074Sab * is to duplicate each such piece of code, modifying only the data types,
53d51e9074Sab * and to use if statements to select the code to run. The problem with
54d51e9074Sab * doing it that way is that the resulting code is difficult to maintain.
55d51e9074Sab * It is inevitable that the copies will not always get modified identically,
56d51e9074Sab * and will drift apart. The only robust solution is to generate the
57d51e9074Sab * multiple instances of code automatically from a single piece of code.
58d51e9074Sab *
59d51e9074Sab * The solution used within the Solaris linker is to write the code once,
60d51e9074Sab * using the data types defined in sys/machelf.h, and then to compile that
61d51e9074Sab * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and
62d51e9074Sab * once without (to generate ELFCLASS32). We use the same approach here.
63d51e9074Sab *
64d51e9074Sab * Note that the _ELF64 definition does not refer to the ELFCLASS of
65d51e9074Sab * the resulting code, but rather, to the ELFCLASS of the data it
66d51e9074Sab * examines. By repeating the above double-compilation for both 32-bit
67d51e9074Sab * and 64-bit builds, we end up with 4 instances, which collectively
68d51e9074Sab * can handle any combination of program and ELF data class:
69d51e9074Sab *
70d51e9074Sab * \ Compilation class
71d51e9074Sab * \ 32 64
72d51e9074Sab * \------------------
73d51e9074Sab * |
74d51e9074Sab * 32 | X X
75d51e9074Sab * ELF Data Class |
76d51e9074Sab * 64 | X X
77d51e9074Sab */
78d51e9074Sab
79d51e9074Sab
80d51e9074Sab
81d51e9074Sab /*
82d51e9074Sab * Read data from the specified process and construct an in memory
83d51e9074Sab * image of an ELF file that will let us use libelf for most of the
84d51e9074Sab * work we need to later (e.g. symbol table lookups). This is used
85d51e9074Sab * in cases where no usable on-disk image for the process is available.
86d51e9074Sab * We need sections for the dynsym, dynstr, and plt, and we need
87d51e9074Sab * the program headers from the text section. The former is used in
88d51e9074Sab * Pbuild_file_symtab(); the latter is used in several functions in
89d51e9074Sab * Pcore.c to reconstruct the origin of each mapping from the load
90d51e9074Sab * object that spawned it.
91d51e9074Sab *
92d51e9074Sab * Here are some useful pieces of elf trivia that will help
93d51e9074Sab * to elucidate this code.
94d51e9074Sab *
95d51e9074Sab * All the information we need about the dynstr can be found in these
96d51e9074Sab * two entries in the dynamic section:
97d51e9074Sab *
98d51e9074Sab * DT_STRTAB base of dynstr
99d51e9074Sab * DT_STRSZ size of dynstr
100d51e9074Sab *
101d51e9074Sab * So deciphering the dynstr is pretty straightforward.
102d51e9074Sab *
103d51e9074Sab * The dynsym is a little trickier.
104d51e9074Sab *
105d51e9074Sab * DT_SYMTAB base of dynsym
106d51e9074Sab * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym)
107d51e9074Sab * DT_HASH base of hash table for dynamic lookups
108d51e9074Sab *
109d51e9074Sab * The DT_SYMTAB entry gives us any easy way of getting to the base
110d51e9074Sab * of the dynsym, but getting the size involves rooting around in the
111d51e9074Sab * dynamic lookup hash table. Here's the layout of the hash table:
112d51e9074Sab *
113d51e9074Sab * +-------------------+
114d51e9074Sab * | nbucket | All values are 32-bit
115d51e9074Sab * +-------------------+ (Elf32_Word or Elf64_Word)
116d51e9074Sab * | nchain |
117d51e9074Sab * +-------------------+
118d51e9074Sab * | bucket[0] |
119d51e9074Sab * | . . . |
120d51e9074Sab * | bucket[nbucket-1] |
121d51e9074Sab * +-------------------+
122d51e9074Sab * | chain[0] |
123d51e9074Sab * | . . . |
124d51e9074Sab * | chain[nchain-1] |
125d51e9074Sab * +-------------------+
126d51e9074Sab * (figure 5-12 from the SYS V Generic ABI)
127d51e9074Sab *
128d51e9074Sab * Symbols names are hashed into a particular bucket which contains
129d51e9074Sab * an index into the symbol table. Each entry in the symbol table
130d51e9074Sab * has a corresponding entry in the chain table which tells the
131d51e9074Sab * consumer where the next entry in the hash chain is. We can use
132d51e9074Sab * the nchain field to find out the size of the dynsym.
133d51e9074Sab *
134d51e9074Sab * If there is a dynsym present, there may also be an optional
135d51e9074Sab * section called the SUNW_ldynsym that augments the dynsym by
136d51e9074Sab * providing local function symbols. When the Solaris linker lays
137d51e9074Sab * out a file that has both of these sections, it makes sure that
138d51e9074Sab * the data for the two sections is adjacent with the SUNW_ldynsym
139d51e9074Sab * in front. This allows the runtime linker to treat these two
140d51e9074Sab * symbol tables as being a single larger table. There are two
141d51e9074Sab * items in the dynamic section for this:
142d51e9074Sab *
143d51e9074Sab * DT_SUNW_SYMTAB base of the SUNW_ldynsym
144d51e9074Sab * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym
145d51e9074Sab * added together. We can figure out the
146d51e9074Sab * size of the SUNW_ldynsym section by
147d51e9074Sab * subtracting the size of the dynsym
148d51e9074Sab * (described above) from this value.
149d51e9074Sab *
150d51e9074Sab * We can figure out the size of the .plt section, but it takes some
151d51e9074Sab * doing. We need to use the following information:
152d51e9074Sab *
153d9452f23SEdward Pilatowicz * DT_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc)
154d51e9074Sab * DT_JMPREL base of the PLT's relocation section
155d51e9074Sab * DT_PLTRELSZ size of the PLT's relocation section
156d51e9074Sab * DT_PLTREL type of the PLT's relocation section
157d51e9074Sab *
158d9452f23SEdward Pilatowicz * We can use the number of relocation entries to calculate the size of
159d9452f23SEdward Pilatowicz * the PLT. We get the address of the PLT by looking up the
160d9452f23SEdward Pilatowicz * _PROCEDURE_LINKAGE_TABLE_ symbol.
161d51e9074Sab *
162d51e9074Sab * For more information, check out the System V Generic ABI.
163d51e9074Sab */
164d51e9074Sab
165d51e9074Sab
166d51e9074Sab /*
167d51e9074Sab * The fake_elfXX() function generated by this file uses the following
168d51e9074Sab * string as the string table for the section names. Since it is critical
169d51e9074Sab * to count correctly, and to improve readability, the SHSTR_NDX_ macros
170d51e9074Sab * supply the proper offset for each name within the string.
171d51e9074Sab */
172d51e9074Sab static char shstr[] =
173d51e9074Sab ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
174d51e9074Sab
175d51e9074Sab /* Offsets within shstr for each name */
176d51e9074Sab #define SHSTR_NDX_shstrtab 0
177d51e9074Sab #define SHSTR_NDX_dynsym 10
178d51e9074Sab #define SHSTR_NDX_dynstr 18
179d51e9074Sab #define SHSTR_NDX_dynamic 26
180d51e9074Sab #define SHSTR_NDX_plt 35
181d51e9074Sab #define SHSTR_NDX_SUNW_ldynsym 40
182d51e9074Sab
183d51e9074Sab
184d51e9074Sab /*
185d51e9074Sab * Section header alignment for 32 and 64-bit ELF files differs
186d51e9074Sab */
187d51e9074Sab #ifdef _ELF64
188d51e9074Sab #define SH_ADDRALIGN 8
189d51e9074Sab #else
190d51e9074Sab #define SH_ADDRALIGN 4
191d51e9074Sab #endif
192d51e9074Sab
193b93b7f88Sjj /*
194b93b7f88Sjj * This is the smallest number of PLT relocation entries allowed in a proper
195b93b7f88Sjj * .plt section.
196b93b7f88Sjj */
197b93b7f88Sjj #ifdef __sparc
198b93b7f88Sjj #define PLTREL_MIN_ENTRIES 4 /* SPARC psABI 3.0 and SCD 2.4 */
199b93b7f88Sjj #else
200b93b7f88Sjj #ifdef __lint
201b93b7f88Sjj /*
202b93b7f88Sjj * On x86, lint would complain about unsigned comparison with
203b93b7f88Sjj * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES
204b93b7f88Sjj * and silences lint. On SPARC, there is no such issue.
205b93b7f88Sjj */
206b93b7f88Sjj #define PLTREL_MIN_ENTRIES 1
207b93b7f88Sjj #else
208b93b7f88Sjj #define PLTREL_MIN_ENTRIES 0
209b93b7f88Sjj #endif
210b93b7f88Sjj #endif
211b93b7f88Sjj
212d51e9074Sab #ifdef _ELF64
213d51e9074Sab Elf *
fake_elf64(struct ps_prochandle * P,file_info_t * fptr,uintptr_t addr,Ehdr * ehdr,uint_t phnum,Phdr * phdr)214d51e9074Sab fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
215d51e9074Sab Ehdr *ehdr, uint_t phnum, Phdr *phdr)
216d51e9074Sab #else
217d51e9074Sab Elf *
218d51e9074Sab fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
219d51e9074Sab Ehdr *ehdr, uint_t phnum, Phdr *phdr)
220d51e9074Sab #endif
221d51e9074Sab {
222d51e9074Sab enum {
223d51e9074Sab DI_PLTGOT,
224d51e9074Sab DI_JMPREL,
225d51e9074Sab DI_PLTRELSZ,
226d51e9074Sab DI_PLTREL,
227d51e9074Sab DI_SYMTAB,
228d51e9074Sab DI_HASH,
229d51e9074Sab DI_SYMENT,
230d51e9074Sab DI_STRTAB,
231d51e9074Sab DI_STRSZ,
232d51e9074Sab DI_SUNW_SYMTAB,
233d51e9074Sab DI_SUNW_SYMSZ,
234d51e9074Sab DI_NENT
235d51e9074Sab };
236d51e9074Sab /*
237d51e9074Sab * Mask of dynamic options that must be present in a well
238d51e9074Sab * formed dynamic section. We need all of these in order to
239d51e9074Sab * put together a complete set of elf sections. They are
240d51e9074Sab * mandatory in both executables and shared objects so if one
241d51e9074Sab * of them is missing, we're in some trouble and should abort.
242d51e9074Sab * The PLT items are expected, but we will let them slide if
243d51e9074Sab * need be. The DI_SUNW_SYM* items are completely optional, so
244d51e9074Sab * we use them if they are present and ignore them otherwise.
245d51e9074Sab */
246044d68feSBryan Cantrill const int di_req_mask = (1 << DI_SYMTAB) |
247d51e9074Sab (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
248d51e9074Sab int di_mask = 0;
249d51e9074Sab size_t size = 0;
250d51e9074Sab caddr_t elfdata = NULL;
251d51e9074Sab Elf *elf;
252d9452f23SEdward Pilatowicz size_t dynsym_size = 0, ldynsym_size;
253d51e9074Sab int dynstr_shndx;
254d51e9074Sab Ehdr *ep;
255d51e9074Sab Shdr *sp;
25671990593SRichard Lowe Dyn *dp = NULL;
257d51e9074Sab Dyn *d[DI_NENT] = { 0 };
258d51e9074Sab uint_t i;
259d51e9074Sab Off off;
260d9452f23SEdward Pilatowicz size_t pltsz = 0, pltentries = 0;
261*c75682cdSToomas Soome uintptr_t hptr = (uintptr_t)NULL;
262044d68feSBryan Cantrill Word hnchains = 0, hnbuckets = 0;
263d51e9074Sab
264d51e9074Sab if (ehdr->e_type == ET_DYN)
265d51e9074Sab phdr->p_vaddr += addr;
266d51e9074Sab
26722872efbSedp if (P->rap != NULL) {
26822872efbSedp if (rd_get_dyns(P->rap, addr, (void **)&dp, NULL) != RD_OK)
26922872efbSedp goto bad;
27022872efbSedp } else {
27122872efbSedp if ((dp = malloc(phdr->p_filesz)) == NULL)
27222872efbSedp goto bad;
27322872efbSedp if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) !=
27422872efbSedp phdr->p_filesz)
27522872efbSedp goto bad;
276d51e9074Sab }
277d51e9074Sab
278d51e9074Sab /*
279d51e9074Sab * Iterate over the items in the dynamic section, grabbing
280d51e9074Sab * the address of items we want and saving them in dp[].
281d51e9074Sab */
282d51e9074Sab for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
283d51e9074Sab switch (dp[i].d_tag) {
284d51e9074Sab /* For the .plt section */
285d51e9074Sab case DT_PLTGOT:
286d51e9074Sab d[DI_PLTGOT] = &dp[i];
287d51e9074Sab break;
288d51e9074Sab case DT_JMPREL:
289d51e9074Sab d[DI_JMPREL] = &dp[i];
290d51e9074Sab break;
291d51e9074Sab case DT_PLTRELSZ:
292d51e9074Sab d[DI_PLTRELSZ] = &dp[i];
293d51e9074Sab break;
294d51e9074Sab case DT_PLTREL:
295d51e9074Sab d[DI_PLTREL] = &dp[i];
296d51e9074Sab break;
297d51e9074Sab
298d51e9074Sab /* For the .dynsym section */
299d51e9074Sab case DT_SYMTAB:
300d51e9074Sab d[DI_SYMTAB] = &dp[i];
301d51e9074Sab di_mask |= (1 << DI_SYMTAB);
302d51e9074Sab break;
303d51e9074Sab case DT_HASH:
304d51e9074Sab d[DI_HASH] = &dp[i];
305d51e9074Sab di_mask |= (1 << DI_HASH);
306d51e9074Sab break;
307d51e9074Sab case DT_SYMENT:
308d51e9074Sab d[DI_SYMENT] = &dp[i];
309d51e9074Sab di_mask |= (1 << DI_SYMENT);
310d51e9074Sab break;
311d51e9074Sab case DT_SUNW_SYMTAB:
312d51e9074Sab d[DI_SUNW_SYMTAB] = &dp[i];
313d51e9074Sab break;
314d51e9074Sab case DT_SUNW_SYMSZ:
315d51e9074Sab d[DI_SUNW_SYMSZ] = &dp[i];
316d51e9074Sab break;
317d51e9074Sab
318d51e9074Sab /* For the .dynstr section */
319d51e9074Sab case DT_STRTAB:
320d51e9074Sab d[DI_STRTAB] = &dp[i];
321d51e9074Sab di_mask |= (1 << DI_STRTAB);
322d51e9074Sab break;
323d51e9074Sab case DT_STRSZ:
324d51e9074Sab d[DI_STRSZ] = &dp[i];
325d51e9074Sab di_mask |= (1 << DI_STRSZ);
326d51e9074Sab break;
327d51e9074Sab }
328d51e9074Sab }
329d51e9074Sab
330d51e9074Sab /* Ensure all required entries were collected */
331d51e9074Sab if ((di_mask & di_req_mask) != di_req_mask) {
332044d68feSBryan Cantrill dprintf("text section missing required dynamic entries: "
333044d68feSBryan Cantrill "required 0x%x, found 0x%x\n", di_req_mask, di_mask);
334d51e9074Sab goto bad;
335d51e9074Sab }
336d51e9074Sab
337d51e9074Sab /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
338d51e9074Sab if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
339d51e9074Sab ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
340d51e9074Sab (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
341d51e9074Sab d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
342d51e9074Sab d[DI_SUNW_SYMTAB] = NULL;
343d51e9074Sab d[DI_SUNW_SYMSZ] = NULL;
344d51e9074Sab }
345d51e9074Sab
346d51e9074Sab /* elf header */
347d51e9074Sab size = sizeof (Ehdr);
348d51e9074Sab
349d51e9074Sab /* program headers from in-core elf fragment */
350d51e9074Sab size += phnum * ehdr->e_phentsize;
351d51e9074Sab
352d51e9074Sab /* unused shdr, and .shstrtab section */
353d51e9074Sab size += sizeof (Shdr);
354d51e9074Sab size += sizeof (Shdr);
355d51e9074Sab size += roundup(sizeof (shstr), SH_ADDRALIGN);
356d51e9074Sab
357d9452f23SEdward Pilatowicz if (d[DI_HASH] != NULL) {
358d9452f23SEdward Pilatowicz Word hash[2];
359d9452f23SEdward Pilatowicz
360d9452f23SEdward Pilatowicz hptr = d[DI_HASH]->d_un.d_ptr;
361d9452f23SEdward Pilatowicz if (ehdr->e_type == ET_DYN)
362d9452f23SEdward Pilatowicz hptr += addr;
363d9452f23SEdward Pilatowicz
364d9452f23SEdward Pilatowicz if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) {
365d9452f23SEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n",
366d9452f23SEdward Pilatowicz (long)(hptr));
367d9452f23SEdward Pilatowicz goto bad;
368d9452f23SEdward Pilatowicz }
369d9452f23SEdward Pilatowicz
370d9452f23SEdward Pilatowicz hnbuckets = hash[0];
371d9452f23SEdward Pilatowicz hnchains = hash[1];
372d9452f23SEdward Pilatowicz }
373d9452f23SEdward Pilatowicz
374d51e9074Sab /*
375d51e9074Sab * .dynsym and .SUNW_ldynsym sections.
376d51e9074Sab *
377d51e9074Sab * The string table section used for the symbol table and
378d51e9074Sab * dynamic sections lies immediately after the dynsym, so the
379d51e9074Sab * presence of SUNW_ldynsym changes the dynstr section index.
380d51e9074Sab */
381d51e9074Sab if (d[DI_SUNW_SYMTAB] != NULL) {
382d51e9074Sab size += sizeof (Shdr); /* SUNW_ldynsym shdr */
383d51e9074Sab ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
384d51e9074Sab dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
385d51e9074Sab - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
386d51e9074Sab ldynsym_size -= dynsym_size;
387d51e9074Sab dynstr_shndx = 4;
388d51e9074Sab } else {
389d9452f23SEdward Pilatowicz dynsym_size = sizeof (Sym) * hnchains;
390d51e9074Sab ldynsym_size = 0;
391d51e9074Sab dynstr_shndx = 3;
392d51e9074Sab }
393d51e9074Sab size += sizeof (Shdr) + ldynsym_size + dynsym_size;
394d51e9074Sab
395d51e9074Sab /* .dynstr section */
396d51e9074Sab size += sizeof (Shdr);
397d51e9074Sab size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
398d51e9074Sab
399d51e9074Sab /* .dynamic section */
400d51e9074Sab size += sizeof (Shdr);
401d51e9074Sab size += roundup(phdr->p_filesz, SH_ADDRALIGN);
402d51e9074Sab
403d51e9074Sab /* .plt section */
404d51e9074Sab if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
405d51e9074Sab d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
406d51e9074Sab size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
407d51e9074Sab
408d51e9074Sab if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
409d9452f23SEdward Pilatowicz pltentries = pltrelsz / sizeof (Rela);
410d51e9074Sab } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
411d9452f23SEdward Pilatowicz pltentries = pltrelsz / sizeof (Rel);
412d51e9074Sab } else {
413d9452f23SEdward Pilatowicz /* fall back to the platform default */
414d9452f23SEdward Pilatowicz #if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64))
415d9452f23SEdward Pilatowicz pltentries = pltrelsz / sizeof (Rel);
416d9452f23SEdward Pilatowicz dprintf("DI_PLTREL not found, defaulting to Rel");
417d9452f23SEdward Pilatowicz #else /* (!(__i386 || __amd64)) || _ELF64 */
418d9452f23SEdward Pilatowicz pltentries = pltrelsz / sizeof (Rela);
419d9452f23SEdward Pilatowicz dprintf("DI_PLTREL not found, defaulting to Rela");
420d9452f23SEdward Pilatowicz #endif /* (!(__i386 || __amd64) || _ELF64 */
421d51e9074Sab }
422d51e9074Sab
423d9452f23SEdward Pilatowicz if (pltentries < PLTREL_MIN_ENTRIES) {
424d9452f23SEdward Pilatowicz dprintf("too few PLT relocation entries "
425d9452f23SEdward Pilatowicz "(found %lu, expected at least %d)\n",
426d9452f23SEdward Pilatowicz (long)pltentries, PLTREL_MIN_ENTRIES);
427d9452f23SEdward Pilatowicz goto bad;
428d9452f23SEdward Pilatowicz }
429d9452f23SEdward Pilatowicz if (pltentries < PLTREL_MIN_ENTRIES + 2)
430d9452f23SEdward Pilatowicz goto done_with_plt;
431d9452f23SEdward Pilatowicz
432d9452f23SEdward Pilatowicz /*
433d9452f23SEdward Pilatowicz * Now that we know the number of plt relocation entries
434d9452f23SEdward Pilatowicz * we can calculate the size of the plt.
435d9452f23SEdward Pilatowicz */
436d9452f23SEdward Pilatowicz pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE;
437d9452f23SEdward Pilatowicz #if defined(__sparc)
438d9452f23SEdward Pilatowicz /* The sparc PLT always has a (delay slot) nop at the end */
439d9452f23SEdward Pilatowicz pltsz += 4;
440d9452f23SEdward Pilatowicz #endif /* __sparc */
441d51e9074Sab
442d51e9074Sab size += sizeof (Shdr);
443d51e9074Sab size += roundup(pltsz, SH_ADDRALIGN);
444d51e9074Sab }
445b93b7f88Sjj done_with_plt:
446d51e9074Sab
447044d68feSBryan Cantrill if ((elfdata = calloc(1, size)) == NULL) {
448044d68feSBryan Cantrill dprintf("failed to allocate size %ld\n", (long)size);
449d51e9074Sab goto bad;
450044d68feSBryan Cantrill }
451d51e9074Sab
452d51e9074Sab /* LINTED - alignment */
453d51e9074Sab ep = (Ehdr *)elfdata;
454d51e9074Sab (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
455d51e9074Sab
456d51e9074Sab ep->e_ehsize = sizeof (Ehdr);
457d51e9074Sab ep->e_phoff = sizeof (Ehdr);
458d51e9074Sab ep->e_phentsize = ehdr->e_phentsize;
459d51e9074Sab ep->e_phnum = phnum;
460d51e9074Sab ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
461d51e9074Sab ep->e_shentsize = sizeof (Shdr);
462d51e9074Sab /*
463d51e9074Sab * Plt and SUNW_ldynsym sections are optional. C logical
464d51e9074Sab * binary operators return a 0 or 1 value, so the following
465d51e9074Sab * adds 1 for each optional section present.
466d51e9074Sab */
467d51e9074Sab ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
468d51e9074Sab ep->e_shstrndx = 1;
469d51e9074Sab
470d51e9074Sab /* LINTED - alignment */
471d51e9074Sab sp = (Shdr *)(elfdata + ep->e_shoff);
472d51e9074Sab off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
473d51e9074Sab
474d51e9074Sab /*
475d51e9074Sab * Copying the program headers directly from the process's
476d51e9074Sab * address space is a little suspect, but since we only
477d51e9074Sab * use them for their address and size values, this is fine.
478d51e9074Sab */
479d51e9074Sab if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
480d51e9074Sab addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
481d51e9074Sab dprintf("failed to read program headers\n");
482d51e9074Sab goto bad;
483d51e9074Sab }
484d51e9074Sab
485d51e9074Sab /*
486d51e9074Sab * The first elf section is always skipped.
487d51e9074Sab */
488d51e9074Sab sp++;
489d51e9074Sab
490d51e9074Sab /*
491d51e9074Sab * Section Header: .shstrtab
492d51e9074Sab */
493d51e9074Sab sp->sh_name = SHSTR_NDX_shstrtab;
494d51e9074Sab sp->sh_type = SHT_STRTAB;
495d51e9074Sab sp->sh_flags = SHF_STRINGS;
496d51e9074Sab sp->sh_addr = 0;
497d51e9074Sab sp->sh_offset = off;
498d51e9074Sab sp->sh_size = sizeof (shstr);
499d51e9074Sab sp->sh_link = 0;
500d51e9074Sab sp->sh_info = 0;
501d51e9074Sab sp->sh_addralign = 1;
502d51e9074Sab sp->sh_entsize = 0;
503d51e9074Sab
504d51e9074Sab (void) memcpy(&elfdata[off], shstr, sizeof (shstr));
505d51e9074Sab off += roundup(sp->sh_size, SH_ADDRALIGN);
506d51e9074Sab sp++;
507d51e9074Sab
508d51e9074Sab /*
509d51e9074Sab * Section Header: .SUNW_ldynsym
510d51e9074Sab */
511d51e9074Sab if (d[DI_SUNW_SYMTAB] != NULL) {
512d51e9074Sab sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
513d51e9074Sab sp->sh_type = SHT_SUNW_LDYNSYM;
514d51e9074Sab sp->sh_flags = SHF_ALLOC;
515d51e9074Sab sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
516d51e9074Sab if (ehdr->e_type == ET_DYN)
517d9452f23SEdward Pilatowicz sp->sh_addr += addr;
518d51e9074Sab sp->sh_offset = off;
519d51e9074Sab sp->sh_size = ldynsym_size;
520d51e9074Sab sp->sh_link = dynstr_shndx;
521d51e9074Sab /* Index of 1st global in table that has none == # items */
522d51e9074Sab sp->sh_info = sp->sh_size / sizeof (Sym);
523d51e9074Sab sp->sh_addralign = SH_ADDRALIGN;
524d51e9074Sab sp->sh_entsize = sizeof (Sym);
525d51e9074Sab
526d51e9074Sab if (Pread(P, &elfdata[off], sp->sh_size,
527d9452f23SEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
528d51e9074Sab dprintf("failed to read .SUNW_ldynsym at %lx\n",
529d9452f23SEdward Pilatowicz (long)sp->sh_addr);
530d51e9074Sab goto bad;
531d51e9074Sab }
532d51e9074Sab off += sp->sh_size;
533d51e9074Sab /* No need to round up ldynsym data. Dynsym data is same type */
534d51e9074Sab sp++;
535d51e9074Sab }
536d51e9074Sab
537d51e9074Sab /*
538d51e9074Sab * Section Header: .dynsym
539d51e9074Sab */
540d51e9074Sab sp->sh_name = SHSTR_NDX_dynsym;
541d51e9074Sab sp->sh_type = SHT_DYNSYM;
542d51e9074Sab sp->sh_flags = SHF_ALLOC;
543d51e9074Sab sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
544d51e9074Sab if (ehdr->e_type == ET_DYN)
545d9452f23SEdward Pilatowicz sp->sh_addr += addr;
546d51e9074Sab sp->sh_offset = off;
547d51e9074Sab sp->sh_size = dynsym_size;
548d51e9074Sab sp->sh_link = dynstr_shndx;
549d51e9074Sab sp->sh_info = 1; /* Index of 1st global in table */
550d51e9074Sab sp->sh_addralign = SH_ADDRALIGN;
551d51e9074Sab sp->sh_entsize = sizeof (Sym);
552d51e9074Sab
553d51e9074Sab if (Pread(P, &elfdata[off], sp->sh_size,
554d9452f23SEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
555d51e9074Sab dprintf("failed to read .dynsym at %lx\n",
556d9452f23SEdward Pilatowicz (long)sp->sh_addr);
557d51e9074Sab goto bad;
558d51e9074Sab }
559d51e9074Sab
560d51e9074Sab off += roundup(sp->sh_size, SH_ADDRALIGN);
561d51e9074Sab sp++;
562d51e9074Sab
563d51e9074Sab /*
564d51e9074Sab * Section Header: .dynstr
565d51e9074Sab */
566d51e9074Sab sp->sh_name = SHSTR_NDX_dynstr;
567d51e9074Sab sp->sh_type = SHT_STRTAB;
568d51e9074Sab sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
569d51e9074Sab sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
570d51e9074Sab if (ehdr->e_type == ET_DYN)
571d9452f23SEdward Pilatowicz sp->sh_addr += addr;
572d51e9074Sab sp->sh_offset = off;
573d51e9074Sab sp->sh_size = d[DI_STRSZ]->d_un.d_val;
574d51e9074Sab sp->sh_link = 0;
575d51e9074Sab sp->sh_info = 0;
576d51e9074Sab sp->sh_addralign = 1;
577d51e9074Sab sp->sh_entsize = 0;
578d51e9074Sab
579d51e9074Sab if (Pread(P, &elfdata[off], sp->sh_size,
580d9452f23SEdward Pilatowicz sp->sh_addr) != sp->sh_size) {
581d51e9074Sab dprintf("failed to read .dynstr\n");
582d51e9074Sab goto bad;
583d51e9074Sab }
584d51e9074Sab off += roundup(sp->sh_size, SH_ADDRALIGN);
585d51e9074Sab sp++;
586d51e9074Sab
587d51e9074Sab /*
588d51e9074Sab * Section Header: .dynamic
589d51e9074Sab */
590d51e9074Sab sp->sh_name = SHSTR_NDX_dynamic;
591d51e9074Sab sp->sh_type = SHT_DYNAMIC;
592d51e9074Sab sp->sh_flags = SHF_WRITE | SHF_ALLOC;
593d51e9074Sab sp->sh_addr = phdr->p_vaddr;
594d51e9074Sab if (ehdr->e_type == ET_DYN)
595d51e9074Sab sp->sh_addr -= addr;
596d51e9074Sab sp->sh_offset = off;
597d51e9074Sab sp->sh_size = phdr->p_filesz;
598d51e9074Sab sp->sh_link = dynstr_shndx;
599d51e9074Sab sp->sh_info = 0;
600d51e9074Sab sp->sh_addralign = SH_ADDRALIGN;
601d51e9074Sab sp->sh_entsize = sizeof (Dyn);
602d51e9074Sab
603d51e9074Sab (void) memcpy(&elfdata[off], dp, sp->sh_size);
604d51e9074Sab off += roundup(sp->sh_size, SH_ADDRALIGN);
605d51e9074Sab sp++;
606d51e9074Sab
607d51e9074Sab /*
608d51e9074Sab * Section Header: .plt
609d51e9074Sab */
610d51e9074Sab if (pltsz != 0) {
611d9452f23SEdward Pilatowicz ulong_t plt_symhash;
612d9452f23SEdward Pilatowicz uint_t htmp, ndx;
613d9452f23SEdward Pilatowicz uintptr_t strtabptr, strtabname;
614d9452f23SEdward Pilatowicz Sym sym, *symtabptr;
615d9452f23SEdward Pilatowicz uint_t *hash;
616d9452f23SEdward Pilatowicz char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")];
617d9452f23SEdward Pilatowicz
618d9452f23SEdward Pilatowicz /*
619d9452f23SEdward Pilatowicz * Now we need to find the address of the plt by looking
620d9452f23SEdward Pilatowicz * up the "_PROCEDURE_LINKAGE_TABLE_" symbol.
621d9452f23SEdward Pilatowicz */
622d9452f23SEdward Pilatowicz
623d9452f23SEdward Pilatowicz /* get the address of the symtab and strtab sections */
624d9452f23SEdward Pilatowicz strtabptr = d[DI_STRTAB]->d_un.d_ptr;
625d9452f23SEdward Pilatowicz symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr;
626d9452f23SEdward Pilatowicz if (ehdr->e_type == ET_DYN) {
627d9452f23SEdward Pilatowicz strtabptr += addr;
628d9452f23SEdward Pilatowicz symtabptr = (Sym*)((uintptr_t)symtabptr + addr);
629d9452f23SEdward Pilatowicz }
630d9452f23SEdward Pilatowicz
631*c75682cdSToomas Soome if ((hptr == (uintptr_t)NULL) || (hnbuckets == 0) ||
632*c75682cdSToomas Soome (hnchains == 0)) {
633044d68feSBryan Cantrill dprintf("empty or missing .hash\n");
634044d68feSBryan Cantrill goto badplt;
635044d68feSBryan Cantrill }
636044d68feSBryan Cantrill
637d9452f23SEdward Pilatowicz /* find the .hash bucket address for this symbol */
638d9452f23SEdward Pilatowicz plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_");
639d9452f23SEdward Pilatowicz htmp = plt_symhash % hnbuckets;
640d9452f23SEdward Pilatowicz hash = &((uint_t *)hptr)[2 + htmp];
641d9452f23SEdward Pilatowicz
642d9452f23SEdward Pilatowicz /* read the elf hash bucket index */
643d9452f23SEdward Pilatowicz if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
644d9452f23SEdward Pilatowicz sizeof (ndx)) {
645d9452f23SEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n", (long)hash);
646beee6fc0SBryan Cantrill goto badplt;
647d9452f23SEdward Pilatowicz }
648d9452f23SEdward Pilatowicz
649d9452f23SEdward Pilatowicz while (ndx) {
650d9452f23SEdward Pilatowicz if (Pread(P, &sym, sizeof (sym),
651d9452f23SEdward Pilatowicz (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) {
652d9452f23SEdward Pilatowicz dprintf("Pread of .symtab at %lx failed\n",
653d9452f23SEdward Pilatowicz (long)&symtabptr[ndx]);
654beee6fc0SBryan Cantrill goto badplt;
655d9452f23SEdward Pilatowicz }
656d9452f23SEdward Pilatowicz
657d9452f23SEdward Pilatowicz strtabname = strtabptr + sym.st_name;
658d9452f23SEdward Pilatowicz if (Pread_string(P, strbuf, sizeof (strbuf),
659d9452f23SEdward Pilatowicz strtabname) < 0) {
660d9452f23SEdward Pilatowicz dprintf("Pread of .strtab at %lx failed\n",
661d9452f23SEdward Pilatowicz (long)strtabname);
662beee6fc0SBryan Cantrill goto badplt;
663d9452f23SEdward Pilatowicz }
664d9452f23SEdward Pilatowicz
665d9452f23SEdward Pilatowicz if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0)
666d9452f23SEdward Pilatowicz break;
667d9452f23SEdward Pilatowicz
668d9452f23SEdward Pilatowicz hash = &((uint_t *)hptr)[2 + hnbuckets + ndx];
669d9452f23SEdward Pilatowicz if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
670d9452f23SEdward Pilatowicz sizeof (ndx)) {
671d9452f23SEdward Pilatowicz dprintf("Pread of .hash at %lx failed\n",
672d9452f23SEdward Pilatowicz (long)hash);
673beee6fc0SBryan Cantrill goto badplt;
674d9452f23SEdward Pilatowicz }
675d9452f23SEdward Pilatowicz }
676d9452f23SEdward Pilatowicz
677d9452f23SEdward Pilatowicz #if defined(__sparc)
678d9452f23SEdward Pilatowicz if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) {
679d9452f23SEdward Pilatowicz dprintf("warning: DI_PLTGOT (%lx) doesn't match "
680d9452f23SEdward Pilatowicz ".plt symbol pointer (%lx)",
681d9452f23SEdward Pilatowicz (long)d[DI_PLTGOT]->d_un.d_ptr,
682d9452f23SEdward Pilatowicz (long)sym.st_value);
683d9452f23SEdward Pilatowicz }
684d9452f23SEdward Pilatowicz #endif /* __sparc */
685d9452f23SEdward Pilatowicz
686d9452f23SEdward Pilatowicz if (ndx == 0) {
687d9452f23SEdward Pilatowicz dprintf(
688d9452f23SEdward Pilatowicz "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
689beee6fc0SBryan Cantrill goto badplt;
690d9452f23SEdward Pilatowicz }
691d9452f23SEdward Pilatowicz
692d51e9074Sab sp->sh_name = SHSTR_NDX_plt;
693d51e9074Sab sp->sh_type = SHT_PROGBITS;
694d51e9074Sab sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
695d9452f23SEdward Pilatowicz sp->sh_addr = sym.st_value;
696d51e9074Sab if (ehdr->e_type == ET_DYN)
697d9452f23SEdward Pilatowicz sp->sh_addr += addr;
698d51e9074Sab sp->sh_offset = off;
699d51e9074Sab sp->sh_size = pltsz;
700d51e9074Sab sp->sh_link = 0;
701d51e9074Sab sp->sh_info = 0;
702d51e9074Sab sp->sh_addralign = SH_ADDRALIGN;
703d9452f23SEdward Pilatowicz sp->sh_entsize = M_PLT_ENTSIZE;
704d51e9074Sab
705d9452f23SEdward Pilatowicz if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) !=
706d9452f23SEdward Pilatowicz sp->sh_size) {
707d9452f23SEdward Pilatowicz dprintf("failed to read .plt at %lx\n",
708d9452f23SEdward Pilatowicz (long)sp->sh_addr);
709beee6fc0SBryan Cantrill goto badplt;
710d51e9074Sab }
711d51e9074Sab off += roundup(sp->sh_size, SH_ADDRALIGN);
712d51e9074Sab sp++;
713d51e9074Sab }
714d51e9074Sab
715beee6fc0SBryan Cantrill badplt:
716d9452f23SEdward Pilatowicz /* make sure we didn't write past the end of allocated memory */
717d9452f23SEdward Pilatowicz sp++;
718d9452f23SEdward Pilatowicz assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size));
719d9452f23SEdward Pilatowicz
720d51e9074Sab free(dp);
721d51e9074Sab if ((elf = elf_memory(elfdata, size)) == NULL) {
722044d68feSBryan Cantrill dprintf("failed to create ELF object "
723044d68feSBryan Cantrill "in memory for size %ld\n", (long)size);
724d51e9074Sab free(elfdata);
725d51e9074Sab return (NULL);
726d51e9074Sab }
727d51e9074Sab
728d51e9074Sab fptr->file_elfmem = elfdata;
729d51e9074Sab
730d51e9074Sab return (elf);
731d51e9074Sab
732d51e9074Sab bad:
733d51e9074Sab if (dp != NULL)
734d51e9074Sab free(dp);
735d51e9074Sab if (elfdata != NULL)
736d51e9074Sab free(elfdata);
737d51e9074Sab return (NULL);
738d51e9074Sab }
739