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