xref: /titanic_52/usr/src/lib/libproc/common/Psymtab_machelf32.c (revision f345c0beb4c8f75cb54c2e070498e56febd468ac)
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  */
168 static 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 #ifdef _ELF64
190 Elf *
191 fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
192     Ehdr *ehdr, uint_t phnum, Phdr *phdr)
193 #else
194 Elf *
195 fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
196     Ehdr *ehdr, uint_t phnum, Phdr *phdr)
197 #endif
198 {
199 	enum {
200 		DI_PLTGOT,
201 		DI_JMPREL,
202 		DI_PLTRELSZ,
203 		DI_PLTREL,
204 		DI_SYMTAB,
205 		DI_HASH,
206 		DI_SYMENT,
207 		DI_STRTAB,
208 		DI_STRSZ,
209 		DI_SUNW_SYMTAB,
210 		DI_SUNW_SYMSZ,
211 		DI_NENT
212 	};
213 	/*
214 	 * Mask of dynamic options that must be present in a well
215 	 * formed dynamic section. We need all of these in order to
216 	 * put together a complete set of elf sections. They are
217 	 * mandatory in both executables and shared objects so if one
218 	 * of them is missing, we're in some trouble and should abort.
219 	 * The PLT items are expected, but we will let them slide if
220 	 * need be. The DI_SUNW_SYM* items are completely optional, so
221 	 * we use them if they are present and ignore them otherwise.
222 	 */
223 	const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) |
224 		(1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
225 	int di_mask = 0;
226 	size_t size = 0;
227 	caddr_t elfdata = NULL;
228 	Elf *elf;
229 	size_t dynsym_size, ldynsym_size;
230 	int dynstr_shndx;
231 	Ehdr *ep;
232 	Shdr *sp;
233 	Dyn *dp;
234 	Dyn *d[DI_NENT] = { 0 };
235 	uint_t i;
236 	Off off;
237 	size_t pltsz = 0, pltentsz;
238 
239 
240 	if (ehdr->e_type == ET_DYN)
241 		phdr->p_vaddr += addr;
242 
243 	if ((dp = malloc(phdr->p_filesz)) == NULL)
244 		goto bad;
245 
246 	if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) != phdr->p_filesz)
247 		goto bad;
248 
249 #ifndef _ELF64
250 	/*
251 	 * Allow librtld_db the opportunity to "fix" the program
252 	 * headers, if it needs to, before we process them.
253 	 */
254 	if (P->rap != NULL && ehdr->e_type == ET_DYN) {
255 		rd_fix_phdrs(P->rap, dp, phdr->p_filesz, addr);
256 	}
257 #endif
258 
259 	/*
260 	 * Iterate over the items in the dynamic section, grabbing
261 	 * the address of items we want and saving them in dp[].
262 	 */
263 	for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
264 		switch (dp[i].d_tag) {
265 		/* For the .plt section */
266 		case DT_PLTGOT:
267 			d[DI_PLTGOT] = &dp[i];
268 			break;
269 		case DT_JMPREL:
270 			d[DI_JMPREL] = &dp[i];
271 			break;
272 		case DT_PLTRELSZ:
273 			d[DI_PLTRELSZ] = &dp[i];
274 			break;
275 		case DT_PLTREL:
276 			d[DI_PLTREL] = &dp[i];
277 			break;
278 
279 		/* For the .dynsym section */
280 		case DT_SYMTAB:
281 			d[DI_SYMTAB] = &dp[i];
282 			di_mask |= (1 << DI_SYMTAB);
283 			break;
284 		case DT_HASH:
285 			d[DI_HASH] = &dp[i];
286 			di_mask |= (1 << DI_HASH);
287 			break;
288 		case DT_SYMENT:
289 			d[DI_SYMENT] = &dp[i];
290 			di_mask |= (1 << DI_SYMENT);
291 			break;
292 		case DT_SUNW_SYMTAB:
293 			d[DI_SUNW_SYMTAB] = &dp[i];
294 			break;
295 		case DT_SUNW_SYMSZ:
296 			d[DI_SUNW_SYMSZ] = &dp[i];
297 			break;
298 
299 		/* For the .dynstr section */
300 		case DT_STRTAB:
301 			d[DI_STRTAB] = &dp[i];
302 			di_mask |= (1 << DI_STRTAB);
303 			break;
304 		case DT_STRSZ:
305 			d[DI_STRSZ] = &dp[i];
306 			di_mask |= (1 << DI_STRSZ);
307 			break;
308 		}
309 	}
310 
311 	/* Ensure all required entries were collected */
312 	if ((di_mask & di_req_mask) != di_req_mask) {
313 		dprintf("text section missing required dynamic entries\n");
314 		goto bad;
315 	}
316 
317 	if (ehdr->e_type == ET_DYN) {
318 		if (d[DI_PLTGOT] != NULL)
319 			d[DI_PLTGOT]->d_un.d_ptr += addr;
320 		if (d[DI_JMPREL] != NULL)
321 			d[DI_JMPREL]->d_un.d_ptr += addr;
322 		d[DI_SYMTAB]->d_un.d_ptr += addr;
323 		d[DI_HASH]->d_un.d_ptr += addr;
324 		d[DI_STRTAB]->d_un.d_ptr += addr;
325 		if (d[DI_SUNW_SYMTAB] != NULL)
326 			d[DI_SUNW_SYMTAB]->d_un.d_ptr += addr;
327 	}
328 
329 	/* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
330 	if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
331 	    ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
332 	    (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
333 	    d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
334 		d[DI_SUNW_SYMTAB] = NULL;
335 		d[DI_SUNW_SYMSZ] = NULL;
336 	}
337 
338 	/* elf header */
339 	size = sizeof (Ehdr);
340 
341 	/* program headers from in-core elf fragment */
342 	size += phnum * ehdr->e_phentsize;
343 
344 	/* unused shdr, and .shstrtab section */
345 	size += sizeof (Shdr);
346 	size += sizeof (Shdr);
347 	size += roundup(sizeof (shstr), SH_ADDRALIGN);
348 
349 	/*
350 	 * .dynsym and .SUNW_ldynsym sections.
351 	 *
352 	 * The string table section used for the symbol table and
353 	 * dynamic sections lies immediately after the dynsym, so the
354 	 * presence of SUNW_ldynsym changes the dynstr section index.
355 	 */
356 	if (d[DI_SUNW_SYMTAB] != NULL) {
357 		size += sizeof (Shdr);	/* SUNW_ldynsym shdr */
358 		ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
359 		dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
360 		    - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
361 		ldynsym_size -= dynsym_size;
362 		dynstr_shndx = 4;
363 	} else {
364 		Word nchain;
365 
366 		if (Pread(P, &nchain, sizeof (nchain),
367 		    d[DI_HASH]->d_un.d_ptr + sizeof (nchain)) !=
368 		    sizeof (nchain)) {
369 			dprintf("Pread of .dynsym at %lx failed\n",
370 			    (long)(d[DI_HASH]->d_un.d_val + sizeof (nchain)));
371 			goto bad;
372 		}
373 		dynsym_size = sizeof (Sym) * nchain;
374 		ldynsym_size = 0;
375 		dynstr_shndx = 3;
376 	}
377 	size += sizeof (Shdr) + ldynsym_size + dynsym_size;
378 
379 	/* .dynstr section */
380 	size += sizeof (Shdr);
381 	size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
382 
383 	/* .dynamic section */
384 	size += sizeof (Shdr);
385 	size += roundup(phdr->p_filesz, SH_ADDRALIGN);
386 
387 	/* .plt section */
388 	if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
389 	    d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
390 		uintptr_t penult, ult;
391 		uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr;
392 		size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
393 
394 		if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
395 			uint_t ndx = pltrelsz / sizeof (Rela) - 2;
396 			Rela r[2];
397 
398 			if (Pread(P, r, sizeof (r), jmprel +
399 			    sizeof (r[0]) * ndx) != sizeof (r)) {
400 				dprintf("Pread of DT_RELA failed\n");
401 				goto bad;
402 			}
403 
404 			penult = r[0].r_offset;
405 			ult = r[1].r_offset;
406 
407 		} else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
408 			uint_t ndx = pltrelsz / sizeof (Rel) - 2;
409 			Rel r[2];
410 
411 			if (Pread(P, r, sizeof (r), jmprel +
412 			    sizeof (r[0]) * ndx) != sizeof (r)) {
413 				dprintf("Pread of DT_REL failed\n");
414 				goto bad;
415 			}
416 
417 			penult = r[0].r_offset;
418 			ult = r[1].r_offset;
419 		} else {
420 			dprintf(".plt: unknown jmprel value\n");
421 			goto bad;
422 		}
423 
424 		pltentsz = ult - penult;
425 
426 		if (ehdr->e_type == ET_DYN)
427 			ult += addr;
428 
429 		pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz;
430 
431 		size += sizeof (Shdr);
432 		size += roundup(pltsz, SH_ADDRALIGN);
433 	}
434 
435 	if ((elfdata = calloc(1, size)) == NULL)
436 		goto bad;
437 
438 	/* LINTED - alignment */
439 	ep = (Ehdr *)elfdata;
440 	(void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
441 
442 	ep->e_ehsize = sizeof (Ehdr);
443 	ep->e_phoff = sizeof (Ehdr);
444 	ep->e_phentsize = ehdr->e_phentsize;
445 	ep->e_phnum = phnum;
446 	ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
447 	ep->e_shentsize = sizeof (Shdr);
448 	/*
449 	 * Plt and SUNW_ldynsym sections are optional. C logical
450 	 * binary operators return a 0 or 1 value, so the following
451 	 * adds 1 for each optional section present.
452 	 */
453 	ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
454 	ep->e_shstrndx = 1;
455 
456 	/* LINTED - alignment */
457 	sp = (Shdr *)(elfdata + ep->e_shoff);
458 	off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
459 
460 	/*
461 	 * Copying the program headers directly from the process's
462 	 * address space is a little suspect, but since we only
463 	 * use them for their address and size values, this is fine.
464 	 */
465 	if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
466 	    addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
467 		dprintf("failed to read program headers\n");
468 		goto bad;
469 	}
470 
471 	/*
472 	 * The first elf section is always skipped.
473 	 */
474 	sp++;
475 
476 	/*
477 	 * Section Header: .shstrtab
478 	 */
479 	sp->sh_name = SHSTR_NDX_shstrtab;
480 	sp->sh_type = SHT_STRTAB;
481 	sp->sh_flags = SHF_STRINGS;
482 	sp->sh_addr = 0;
483 	sp->sh_offset = off;
484 	sp->sh_size = sizeof (shstr);
485 	sp->sh_link = 0;
486 	sp->sh_info = 0;
487 	sp->sh_addralign = 1;
488 	sp->sh_entsize = 0;
489 
490 	(void) memcpy(&elfdata[off], shstr, sizeof (shstr));
491 	off += roundup(sp->sh_size, SH_ADDRALIGN);
492 	sp++;
493 
494 	/*
495 	 * Section Header: .SUNW_ldynsym
496 	 */
497 	if (d[DI_SUNW_SYMTAB] != NULL) {
498 		sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
499 		sp->sh_type = SHT_SUNW_LDYNSYM;
500 		sp->sh_flags = SHF_ALLOC;
501 		sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
502 		if (ehdr->e_type == ET_DYN)
503 			sp->sh_addr -= addr;
504 		sp->sh_offset = off;
505 		sp->sh_size = ldynsym_size;
506 		sp->sh_link = dynstr_shndx;
507 		/* Index of 1st global in table that has none == # items */
508 		sp->sh_info = sp->sh_size / sizeof (Sym);
509 		sp->sh_addralign = SH_ADDRALIGN;
510 		sp->sh_entsize = sizeof (Sym);
511 
512 		if (Pread(P, &elfdata[off], sp->sh_size,
513 		    d[DI_SUNW_SYMTAB]->d_un.d_ptr) != sp->sh_size) {
514 			dprintf("failed to read .SUNW_ldynsym at %lx\n",
515 			    (long)d[DI_SUNW_SYMTAB]->d_un.d_ptr);
516 			goto bad;
517 		}
518 		off += sp->sh_size;
519 		/* No need to round up ldynsym data. Dynsym data is same type */
520 		sp++;
521 	}
522 
523 	/*
524 	 * Section Header: .dynsym
525 	 */
526 	sp->sh_name = SHSTR_NDX_dynsym;
527 	sp->sh_type = SHT_DYNSYM;
528 	sp->sh_flags = SHF_ALLOC;
529 	sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
530 	if (ehdr->e_type == ET_DYN)
531 		sp->sh_addr -= addr;
532 	sp->sh_offset = off;
533 	sp->sh_size = dynsym_size;
534 	sp->sh_link = dynstr_shndx;
535 	sp->sh_info = 1;	/* Index of 1st global in table */
536 	sp->sh_addralign = SH_ADDRALIGN;
537 	sp->sh_entsize = sizeof (Sym);
538 
539 	if (Pread(P, &elfdata[off], sp->sh_size,
540 	    d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) {
541 		dprintf("failed to read .dynsym at %lx\n",
542 		    (long)d[DI_SYMTAB]->d_un.d_ptr);
543 		goto bad;
544 	}
545 
546 	off += roundup(sp->sh_size, SH_ADDRALIGN);
547 	sp++;
548 
549 	/*
550 	 * Section Header: .dynstr
551 	 */
552 	sp->sh_name = SHSTR_NDX_dynstr;
553 	sp->sh_type = SHT_STRTAB;
554 	sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
555 	sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
556 	if (ehdr->e_type == ET_DYN)
557 		sp->sh_addr -= addr;
558 	sp->sh_offset = off;
559 	sp->sh_size = d[DI_STRSZ]->d_un.d_val;
560 	sp->sh_link = 0;
561 	sp->sh_info = 0;
562 	sp->sh_addralign = 1;
563 	sp->sh_entsize = 0;
564 
565 	if (Pread(P, &elfdata[off], sp->sh_size,
566 	    d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) {
567 		dprintf("failed to read .dynstr\n");
568 		goto bad;
569 	}
570 	off += roundup(sp->sh_size, SH_ADDRALIGN);
571 	sp++;
572 
573 	/*
574 	 * Section Header: .dynamic
575 	 */
576 	sp->sh_name = SHSTR_NDX_dynamic;
577 	sp->sh_type = SHT_DYNAMIC;
578 	sp->sh_flags = SHF_WRITE | SHF_ALLOC;
579 	sp->sh_addr = phdr->p_vaddr;
580 	if (ehdr->e_type == ET_DYN)
581 		sp->sh_addr -= addr;
582 	sp->sh_offset = off;
583 	sp->sh_size = phdr->p_filesz;
584 	sp->sh_link = dynstr_shndx;
585 	sp->sh_info = 0;
586 	sp->sh_addralign = SH_ADDRALIGN;
587 	sp->sh_entsize = sizeof (Dyn);
588 
589 	(void) memcpy(&elfdata[off], dp, sp->sh_size);
590 	off += roundup(sp->sh_size, SH_ADDRALIGN);
591 	sp++;
592 
593 	/*
594 	 * Section Header: .plt
595 	 */
596 	if (pltsz != 0) {
597 		sp->sh_name = SHSTR_NDX_plt;
598 		sp->sh_type = SHT_PROGBITS;
599 		sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
600 		sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr;
601 		if (ehdr->e_type == ET_DYN)
602 			sp->sh_addr -= addr;
603 		sp->sh_offset = off;
604 		sp->sh_size = pltsz;
605 		sp->sh_link = 0;
606 		sp->sh_info = 0;
607 		sp->sh_addralign = SH_ADDRALIGN;
608 		sp->sh_entsize = pltentsz;
609 
610 		if (Pread(P, &elfdata[off], sp->sh_size,
611 		    d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) {
612 			dprintf("failed to read .plt\n");
613 			goto bad;
614 		}
615 		off += roundup(sp->sh_size, SH_ADDRALIGN);
616 		sp++;
617 	}
618 
619 	free(dp);
620 	if ((elf = elf_memory(elfdata, size)) == NULL) {
621 		free(elfdata);
622 		return (NULL);
623 	}
624 
625 	fptr->file_elfmem = elfdata;
626 
627 	return (elf);
628 
629 bad:
630 	if (dp != NULL)
631 		free(dp);
632 	if (elfdata != NULL)
633 		free(elfdata);
634 	return (NULL);
635 
636 
637 }
638