xref: /titanic_50/usr/src/lib/libproc/common/Psymtab_machelf32.c (revision d6114e2d100d9ec3b45f9968d45ac2e3a0827af0)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <assert.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <string.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	GOT PLT entry offset (on x86) or PLT offset (on sparc)
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 number of relocation entries to calculate the size of
155  * the PLT.  We get the address of the PLT by looking up the
156  * _PROCEDURE_LINKAGE_TABLE_ symbol.
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 /*
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
209 Elf *
210 fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
211     Ehdr *ehdr, uint_t phnum, Phdr *phdr)
212 #else
213 Elf *
214 fake_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 = 0, 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, pltentries = 0;
257 	uintptr_t hptr = NULL;
258 	Word hnchains, hnbuckets;
259 
260 	if (ehdr->e_type == ET_DYN)
261 		phdr->p_vaddr += addr;
262 
263 	if (P->rap != NULL) {
264 		if (rd_get_dyns(P->rap, addr, (void **)&dp, NULL) != RD_OK)
265 			goto bad;
266 	} else {
267 		if ((dp = malloc(phdr->p_filesz)) == NULL)
268 			goto bad;
269 		if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) !=
270 		    phdr->p_filesz)
271 			goto bad;
272 	}
273 
274 	/*
275 	 * Iterate over the items in the dynamic section, grabbing
276 	 * the address of items we want and saving them in dp[].
277 	 */
278 	for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
279 		switch (dp[i].d_tag) {
280 		/* For the .plt section */
281 		case DT_PLTGOT:
282 			d[DI_PLTGOT] = &dp[i];
283 			break;
284 		case DT_JMPREL:
285 			d[DI_JMPREL] = &dp[i];
286 			break;
287 		case DT_PLTRELSZ:
288 			d[DI_PLTRELSZ] = &dp[i];
289 			break;
290 		case DT_PLTREL:
291 			d[DI_PLTREL] = &dp[i];
292 			break;
293 
294 		/* For the .dynsym section */
295 		case DT_SYMTAB:
296 			d[DI_SYMTAB] = &dp[i];
297 			di_mask |= (1 << DI_SYMTAB);
298 			break;
299 		case DT_HASH:
300 			d[DI_HASH] = &dp[i];
301 			di_mask |= (1 << DI_HASH);
302 			break;
303 		case DT_SYMENT:
304 			d[DI_SYMENT] = &dp[i];
305 			di_mask |= (1 << DI_SYMENT);
306 			break;
307 		case DT_SUNW_SYMTAB:
308 			d[DI_SUNW_SYMTAB] = &dp[i];
309 			break;
310 		case DT_SUNW_SYMSZ:
311 			d[DI_SUNW_SYMSZ] = &dp[i];
312 			break;
313 
314 		/* For the .dynstr section */
315 		case DT_STRTAB:
316 			d[DI_STRTAB] = &dp[i];
317 			di_mask |= (1 << DI_STRTAB);
318 			break;
319 		case DT_STRSZ:
320 			d[DI_STRSZ] = &dp[i];
321 			di_mask |= (1 << DI_STRSZ);
322 			break;
323 		}
324 	}
325 
326 	/* Ensure all required entries were collected */
327 	if ((di_mask & di_req_mask) != di_req_mask) {
328 		dprintf("text section missing required dynamic entries\n");
329 		goto bad;
330 	}
331 
332 	/* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
333 	if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
334 	    ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
335 	    (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
336 	    d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
337 		d[DI_SUNW_SYMTAB] = NULL;
338 		d[DI_SUNW_SYMSZ] = NULL;
339 	}
340 
341 	/* elf header */
342 	size = sizeof (Ehdr);
343 
344 	/* program headers from in-core elf fragment */
345 	size += phnum * ehdr->e_phentsize;
346 
347 	/* unused shdr, and .shstrtab section */
348 	size += sizeof (Shdr);
349 	size += sizeof (Shdr);
350 	size += roundup(sizeof (shstr), SH_ADDRALIGN);
351 
352 	if (d[DI_HASH] != NULL) {
353 		Word hash[2];
354 
355 		hptr = d[DI_HASH]->d_un.d_ptr;
356 		if (ehdr->e_type == ET_DYN)
357 			hptr += addr;
358 
359 		if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) {
360 			dprintf("Pread of .hash at %lx failed\n",
361 			    (long)(hptr));
362 			goto bad;
363 		}
364 
365 		hnbuckets = hash[0];
366 		hnchains = hash[1];
367 	}
368 
369 	/*
370 	 * .dynsym and .SUNW_ldynsym sections.
371 	 *
372 	 * The string table section used for the symbol table and
373 	 * dynamic sections lies immediately after the dynsym, so the
374 	 * presence of SUNW_ldynsym changes the dynstr section index.
375 	 */
376 	if (d[DI_SUNW_SYMTAB] != NULL) {
377 		size += sizeof (Shdr);	/* SUNW_ldynsym shdr */
378 		ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
379 		dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
380 		    - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
381 		ldynsym_size -= dynsym_size;
382 		dynstr_shndx = 4;
383 	} else {
384 		dynsym_size = sizeof (Sym) * hnchains;
385 		ldynsym_size = 0;
386 		dynstr_shndx = 3;
387 	}
388 	size += sizeof (Shdr) + ldynsym_size + dynsym_size;
389 
390 	/* .dynstr section */
391 	size += sizeof (Shdr);
392 	size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
393 
394 	/* .dynamic section */
395 	size += sizeof (Shdr);
396 	size += roundup(phdr->p_filesz, SH_ADDRALIGN);
397 
398 	/* .plt section */
399 	if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
400 	    d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
401 		size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
402 
403 		if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
404 			pltentries = pltrelsz / sizeof (Rela);
405 		} else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
406 			pltentries = pltrelsz / sizeof (Rel);
407 		} else {
408 			/* fall back to the platform default */
409 #if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64))
410 			pltentries = pltrelsz / sizeof (Rel);
411 			dprintf("DI_PLTREL not found, defaulting to Rel");
412 #else /* (!(__i386 || __amd64)) || _ELF64 */
413 			pltentries = pltrelsz / sizeof (Rela);
414 			dprintf("DI_PLTREL not found, defaulting to Rela");
415 #endif /* (!(__i386 || __amd64) || _ELF64 */
416 		}
417 
418 		if (pltentries < PLTREL_MIN_ENTRIES) {
419 			dprintf("too few PLT relocation entries "
420 			    "(found %lu, expected at least %d)\n",
421 			    (long)pltentries, PLTREL_MIN_ENTRIES);
422 			goto bad;
423 		}
424 		if (pltentries < PLTREL_MIN_ENTRIES + 2)
425 			goto done_with_plt;
426 
427 		/*
428 		 * Now that we know the number of plt relocation entries
429 		 * we can calculate the size of the plt.
430 		 */
431 		pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE;
432 #if defined(__sparc)
433 		/* The sparc PLT always has a (delay slot) nop at the end */
434 		pltsz += 4;
435 #endif /* __sparc */
436 
437 		size += sizeof (Shdr);
438 		size += roundup(pltsz, SH_ADDRALIGN);
439 	}
440 done_with_plt:
441 
442 	if ((elfdata = calloc(1, size)) == NULL)
443 		goto bad;
444 
445 	/* LINTED - alignment */
446 	ep = (Ehdr *)elfdata;
447 	(void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
448 
449 	ep->e_ehsize = sizeof (Ehdr);
450 	ep->e_phoff = sizeof (Ehdr);
451 	ep->e_phentsize = ehdr->e_phentsize;
452 	ep->e_phnum = phnum;
453 	ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
454 	ep->e_shentsize = sizeof (Shdr);
455 	/*
456 	 * Plt and SUNW_ldynsym sections are optional. C logical
457 	 * binary operators return a 0 or 1 value, so the following
458 	 * adds 1 for each optional section present.
459 	 */
460 	ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
461 	ep->e_shstrndx = 1;
462 
463 	/* LINTED - alignment */
464 	sp = (Shdr *)(elfdata + ep->e_shoff);
465 	off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
466 
467 	/*
468 	 * Copying the program headers directly from the process's
469 	 * address space is a little suspect, but since we only
470 	 * use them for their address and size values, this is fine.
471 	 */
472 	if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
473 	    addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
474 		dprintf("failed to read program headers\n");
475 		goto bad;
476 	}
477 
478 	/*
479 	 * The first elf section is always skipped.
480 	 */
481 	sp++;
482 
483 	/*
484 	 * Section Header: .shstrtab
485 	 */
486 	sp->sh_name = SHSTR_NDX_shstrtab;
487 	sp->sh_type = SHT_STRTAB;
488 	sp->sh_flags = SHF_STRINGS;
489 	sp->sh_addr = 0;
490 	sp->sh_offset = off;
491 	sp->sh_size = sizeof (shstr);
492 	sp->sh_link = 0;
493 	sp->sh_info = 0;
494 	sp->sh_addralign = 1;
495 	sp->sh_entsize = 0;
496 
497 	(void) memcpy(&elfdata[off], shstr, sizeof (shstr));
498 	off += roundup(sp->sh_size, SH_ADDRALIGN);
499 	sp++;
500 
501 	/*
502 	 * Section Header: .SUNW_ldynsym
503 	 */
504 	if (d[DI_SUNW_SYMTAB] != NULL) {
505 		sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
506 		sp->sh_type = SHT_SUNW_LDYNSYM;
507 		sp->sh_flags = SHF_ALLOC;
508 		sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
509 		if (ehdr->e_type == ET_DYN)
510 			sp->sh_addr += addr;
511 		sp->sh_offset = off;
512 		sp->sh_size = ldynsym_size;
513 		sp->sh_link = dynstr_shndx;
514 		/* Index of 1st global in table that has none == # items */
515 		sp->sh_info = sp->sh_size / sizeof (Sym);
516 		sp->sh_addralign = SH_ADDRALIGN;
517 		sp->sh_entsize = sizeof (Sym);
518 
519 		if (Pread(P, &elfdata[off], sp->sh_size,
520 		    sp->sh_addr) != sp->sh_size) {
521 			dprintf("failed to read .SUNW_ldynsym at %lx\n",
522 			    (long)sp->sh_addr);
523 			goto bad;
524 		}
525 		off += sp->sh_size;
526 		/* No need to round up ldynsym data. Dynsym data is same type */
527 		sp++;
528 	}
529 
530 	/*
531 	 * Section Header: .dynsym
532 	 */
533 	sp->sh_name = SHSTR_NDX_dynsym;
534 	sp->sh_type = SHT_DYNSYM;
535 	sp->sh_flags = SHF_ALLOC;
536 	sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
537 	if (ehdr->e_type == ET_DYN)
538 		sp->sh_addr += addr;
539 	sp->sh_offset = off;
540 	sp->sh_size = dynsym_size;
541 	sp->sh_link = dynstr_shndx;
542 	sp->sh_info = 1;	/* Index of 1st global in table */
543 	sp->sh_addralign = SH_ADDRALIGN;
544 	sp->sh_entsize = sizeof (Sym);
545 
546 	if (Pread(P, &elfdata[off], sp->sh_size,
547 	    sp->sh_addr) != sp->sh_size) {
548 		dprintf("failed to read .dynsym at %lx\n",
549 		    (long)sp->sh_addr);
550 		goto bad;
551 	}
552 
553 	off += roundup(sp->sh_size, SH_ADDRALIGN);
554 	sp++;
555 
556 	/*
557 	 * Section Header: .dynstr
558 	 */
559 	sp->sh_name = SHSTR_NDX_dynstr;
560 	sp->sh_type = SHT_STRTAB;
561 	sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
562 	sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
563 	if (ehdr->e_type == ET_DYN)
564 		sp->sh_addr += addr;
565 	sp->sh_offset = off;
566 	sp->sh_size = d[DI_STRSZ]->d_un.d_val;
567 	sp->sh_link = 0;
568 	sp->sh_info = 0;
569 	sp->sh_addralign = 1;
570 	sp->sh_entsize = 0;
571 
572 	if (Pread(P, &elfdata[off], sp->sh_size,
573 	    sp->sh_addr) != sp->sh_size) {
574 		dprintf("failed to read .dynstr\n");
575 		goto bad;
576 	}
577 	off += roundup(sp->sh_size, SH_ADDRALIGN);
578 	sp++;
579 
580 	/*
581 	 * Section Header: .dynamic
582 	 */
583 	sp->sh_name = SHSTR_NDX_dynamic;
584 	sp->sh_type = SHT_DYNAMIC;
585 	sp->sh_flags = SHF_WRITE | SHF_ALLOC;
586 	sp->sh_addr = phdr->p_vaddr;
587 	if (ehdr->e_type == ET_DYN)
588 		sp->sh_addr -= addr;
589 	sp->sh_offset = off;
590 	sp->sh_size = phdr->p_filesz;
591 	sp->sh_link = dynstr_shndx;
592 	sp->sh_info = 0;
593 	sp->sh_addralign = SH_ADDRALIGN;
594 	sp->sh_entsize = sizeof (Dyn);
595 
596 	(void) memcpy(&elfdata[off], dp, sp->sh_size);
597 	off += roundup(sp->sh_size, SH_ADDRALIGN);
598 	sp++;
599 
600 	/*
601 	 * Section Header: .plt
602 	 */
603 	if (pltsz != 0) {
604 		ulong_t		plt_symhash;
605 		uint_t		htmp, ndx;
606 		uintptr_t	strtabptr, strtabname;
607 		Sym		sym, *symtabptr;
608 		uint_t		*hash;
609 		char		strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")];
610 
611 		/*
612 		 * Now we need to find the address of the plt by looking
613 		 * up the "_PROCEDURE_LINKAGE_TABLE_" symbol.
614 		 */
615 
616 		/* get the address of the symtab and strtab sections */
617 		strtabptr = d[DI_STRTAB]->d_un.d_ptr;
618 		symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr;
619 		if (ehdr->e_type == ET_DYN) {
620 			strtabptr += addr;
621 			symtabptr = (Sym*)((uintptr_t)symtabptr + addr);
622 		}
623 
624 		/* find the .hash bucket address for this symbol */
625 		plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_");
626 		htmp = plt_symhash % hnbuckets;
627 		hash = &((uint_t *)hptr)[2 + htmp];
628 
629 		/* read the elf hash bucket index */
630 		if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
631 		    sizeof (ndx)) {
632 			dprintf("Pread of .hash at %lx failed\n", (long)hash);
633 			goto bad;
634 		}
635 
636 		while (ndx) {
637 			if (Pread(P, &sym, sizeof (sym),
638 			    (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) {
639 				dprintf("Pread of .symtab at %lx failed\n",
640 				    (long)&symtabptr[ndx]);
641 				goto bad;
642 			}
643 
644 			strtabname = strtabptr + sym.st_name;
645 			if (Pread_string(P, strbuf, sizeof (strbuf),
646 			    strtabname) < 0) {
647 				dprintf("Pread of .strtab at %lx failed\n",
648 				    (long)strtabname);
649 				goto bad;
650 			}
651 
652 			if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0)
653 				break;
654 
655 			hash = &((uint_t *)hptr)[2 + hnbuckets + ndx];
656 			if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
657 			    sizeof (ndx)) {
658 				dprintf("Pread of .hash at %lx failed\n",
659 				    (long)hash);
660 				goto bad;
661 			}
662 		}
663 
664 #if defined(__sparc)
665 		if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) {
666 			dprintf("warning: DI_PLTGOT (%lx) doesn't match "
667 			    ".plt symbol pointer (%lx)",
668 			    (long)d[DI_PLTGOT]->d_un.d_ptr,
669 			    (long)sym.st_value);
670 		}
671 #endif /* __sparc */
672 
673 		if (ndx == 0) {
674 			dprintf(
675 			    "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
676 			goto bad;
677 		}
678 
679 		sp->sh_name = SHSTR_NDX_plt;
680 		sp->sh_type = SHT_PROGBITS;
681 		sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
682 		sp->sh_addr = sym.st_value;
683 		if (ehdr->e_type == ET_DYN)
684 			sp->sh_addr += addr;
685 		sp->sh_offset = off;
686 		sp->sh_size = pltsz;
687 		sp->sh_link = 0;
688 		sp->sh_info = 0;
689 		sp->sh_addralign = SH_ADDRALIGN;
690 		sp->sh_entsize = M_PLT_ENTSIZE;
691 
692 		if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) !=
693 		    sp->sh_size) {
694 			dprintf("failed to read .plt at %lx\n",
695 			    (long)sp->sh_addr);
696 			goto bad;
697 		}
698 		off += roundup(sp->sh_size, SH_ADDRALIGN);
699 		sp++;
700 	}
701 
702 	/* make sure we didn't write past the end of allocated memory */
703 	sp++;
704 	assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size));
705 
706 	free(dp);
707 	if ((elf = elf_memory(elfdata, size)) == NULL) {
708 		free(elfdata);
709 		return (NULL);
710 	}
711 
712 	fptr->file_elfmem = elfdata;
713 
714 	return (elf);
715 
716 bad:
717 	if (dp != NULL)
718 		free(dp);
719 	if (elfdata != NULL)
720 		free(elfdata);
721 	return (NULL);
722 }
723