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 * 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