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