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 */
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 = 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	}
440done_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
716bad:
717	if (dp != NULL)
718		free(dp);
719	if (elfdata != NULL)
720		free(elfdata);
721	return (NULL);
722}
723