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