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 = NULL; 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 if ((d[DI_HASH] == NULL) || (hnbuckets == 0) || (hnchains == 0)) { 370 dprintf("empty or missing .hash\n"); 371 goto bad; 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 goto bad; 449 450 /* LINTED - alignment */ 451 ep = (Ehdr *)elfdata; 452 (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff)); 453 454 ep->e_ehsize = sizeof (Ehdr); 455 ep->e_phoff = sizeof (Ehdr); 456 ep->e_phentsize = ehdr->e_phentsize; 457 ep->e_phnum = phnum; 458 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize; 459 ep->e_shentsize = sizeof (Shdr); 460 /* 461 * Plt and SUNW_ldynsym sections are optional. C logical 462 * binary operators return a 0 or 1 value, so the following 463 * adds 1 for each optional section present. 464 */ 465 ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL); 466 ep->e_shstrndx = 1; 467 468 /* LINTED - alignment */ 469 sp = (Shdr *)(elfdata + ep->e_shoff); 470 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum; 471 472 /* 473 * Copying the program headers directly from the process's 474 * address space is a little suspect, but since we only 475 * use them for their address and size values, this is fine. 476 */ 477 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize, 478 addr + ehdr->e_phoff) != phnum * ep->e_phentsize) { 479 dprintf("failed to read program headers\n"); 480 goto bad; 481 } 482 483 /* 484 * The first elf section is always skipped. 485 */ 486 sp++; 487 488 /* 489 * Section Header: .shstrtab 490 */ 491 sp->sh_name = SHSTR_NDX_shstrtab; 492 sp->sh_type = SHT_STRTAB; 493 sp->sh_flags = SHF_STRINGS; 494 sp->sh_addr = 0; 495 sp->sh_offset = off; 496 sp->sh_size = sizeof (shstr); 497 sp->sh_link = 0; 498 sp->sh_info = 0; 499 sp->sh_addralign = 1; 500 sp->sh_entsize = 0; 501 502 (void) memcpy(&elfdata[off], shstr, sizeof (shstr)); 503 off += roundup(sp->sh_size, SH_ADDRALIGN); 504 sp++; 505 506 /* 507 * Section Header: .SUNW_ldynsym 508 */ 509 if (d[DI_SUNW_SYMTAB] != NULL) { 510 sp->sh_name = SHSTR_NDX_SUNW_ldynsym; 511 sp->sh_type = SHT_SUNW_LDYNSYM; 512 sp->sh_flags = SHF_ALLOC; 513 sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr; 514 if (ehdr->e_type == ET_DYN) 515 sp->sh_addr += addr; 516 sp->sh_offset = off; 517 sp->sh_size = ldynsym_size; 518 sp->sh_link = dynstr_shndx; 519 /* Index of 1st global in table that has none == # items */ 520 sp->sh_info = sp->sh_size / sizeof (Sym); 521 sp->sh_addralign = SH_ADDRALIGN; 522 sp->sh_entsize = sizeof (Sym); 523 524 if (Pread(P, &elfdata[off], sp->sh_size, 525 sp->sh_addr) != sp->sh_size) { 526 dprintf("failed to read .SUNW_ldynsym at %lx\n", 527 (long)sp->sh_addr); 528 goto bad; 529 } 530 off += sp->sh_size; 531 /* No need to round up ldynsym data. Dynsym data is same type */ 532 sp++; 533 } 534 535 /* 536 * Section Header: .dynsym 537 */ 538 sp->sh_name = SHSTR_NDX_dynsym; 539 sp->sh_type = SHT_DYNSYM; 540 sp->sh_flags = SHF_ALLOC; 541 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr; 542 if (ehdr->e_type == ET_DYN) 543 sp->sh_addr += addr; 544 sp->sh_offset = off; 545 sp->sh_size = dynsym_size; 546 sp->sh_link = dynstr_shndx; 547 sp->sh_info = 1; /* Index of 1st global in table */ 548 sp->sh_addralign = SH_ADDRALIGN; 549 sp->sh_entsize = sizeof (Sym); 550 551 if (Pread(P, &elfdata[off], sp->sh_size, 552 sp->sh_addr) != sp->sh_size) { 553 dprintf("failed to read .dynsym at %lx\n", 554 (long)sp->sh_addr); 555 goto bad; 556 } 557 558 off += roundup(sp->sh_size, SH_ADDRALIGN); 559 sp++; 560 561 /* 562 * Section Header: .dynstr 563 */ 564 sp->sh_name = SHSTR_NDX_dynstr; 565 sp->sh_type = SHT_STRTAB; 566 sp->sh_flags = SHF_ALLOC | SHF_STRINGS; 567 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr; 568 if (ehdr->e_type == ET_DYN) 569 sp->sh_addr += addr; 570 sp->sh_offset = off; 571 sp->sh_size = d[DI_STRSZ]->d_un.d_val; 572 sp->sh_link = 0; 573 sp->sh_info = 0; 574 sp->sh_addralign = 1; 575 sp->sh_entsize = 0; 576 577 if (Pread(P, &elfdata[off], sp->sh_size, 578 sp->sh_addr) != sp->sh_size) { 579 dprintf("failed to read .dynstr\n"); 580 goto bad; 581 } 582 off += roundup(sp->sh_size, SH_ADDRALIGN); 583 sp++; 584 585 /* 586 * Section Header: .dynamic 587 */ 588 sp->sh_name = SHSTR_NDX_dynamic; 589 sp->sh_type = SHT_DYNAMIC; 590 sp->sh_flags = SHF_WRITE | SHF_ALLOC; 591 sp->sh_addr = phdr->p_vaddr; 592 if (ehdr->e_type == ET_DYN) 593 sp->sh_addr -= addr; 594 sp->sh_offset = off; 595 sp->sh_size = phdr->p_filesz; 596 sp->sh_link = dynstr_shndx; 597 sp->sh_info = 0; 598 sp->sh_addralign = SH_ADDRALIGN; 599 sp->sh_entsize = sizeof (Dyn); 600 601 (void) memcpy(&elfdata[off], dp, sp->sh_size); 602 off += roundup(sp->sh_size, SH_ADDRALIGN); 603 sp++; 604 605 /* 606 * Section Header: .plt 607 */ 608 if (pltsz != 0) { 609 ulong_t plt_symhash; 610 uint_t htmp, ndx; 611 uintptr_t strtabptr, strtabname; 612 Sym sym, *symtabptr; 613 uint_t *hash; 614 char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")]; 615 616 /* 617 * Now we need to find the address of the plt by looking 618 * up the "_PROCEDURE_LINKAGE_TABLE_" symbol. 619 */ 620 621 /* get the address of the symtab and strtab sections */ 622 strtabptr = d[DI_STRTAB]->d_un.d_ptr; 623 symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr; 624 if (ehdr->e_type == ET_DYN) { 625 strtabptr += addr; 626 symtabptr = (Sym*)((uintptr_t)symtabptr + addr); 627 } 628 629 /* find the .hash bucket address for this symbol */ 630 plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_"); 631 htmp = plt_symhash % hnbuckets; 632 hash = &((uint_t *)hptr)[2 + htmp]; 633 634 /* read the elf hash bucket index */ 635 if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) != 636 sizeof (ndx)) { 637 dprintf("Pread of .hash at %lx failed\n", (long)hash); 638 goto bad; 639 } 640 641 while (ndx) { 642 if (Pread(P, &sym, sizeof (sym), 643 (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) { 644 dprintf("Pread of .symtab at %lx failed\n", 645 (long)&symtabptr[ndx]); 646 goto bad; 647 } 648 649 strtabname = strtabptr + sym.st_name; 650 if (Pread_string(P, strbuf, sizeof (strbuf), 651 strtabname) < 0) { 652 dprintf("Pread of .strtab at %lx failed\n", 653 (long)strtabname); 654 goto bad; 655 } 656 657 if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0) 658 break; 659 660 hash = &((uint_t *)hptr)[2 + hnbuckets + ndx]; 661 if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) != 662 sizeof (ndx)) { 663 dprintf("Pread of .hash at %lx failed\n", 664 (long)hash); 665 goto bad; 666 } 667 } 668 669 #if defined(__sparc) 670 if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) { 671 dprintf("warning: DI_PLTGOT (%lx) doesn't match " 672 ".plt symbol pointer (%lx)", 673 (long)d[DI_PLTGOT]->d_un.d_ptr, 674 (long)sym.st_value); 675 } 676 #endif /* __sparc */ 677 678 if (ndx == 0) { 679 dprintf( 680 "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n"); 681 goto bad; 682 } 683 684 sp->sh_name = SHSTR_NDX_plt; 685 sp->sh_type = SHT_PROGBITS; 686 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; 687 sp->sh_addr = sym.st_value; 688 if (ehdr->e_type == ET_DYN) 689 sp->sh_addr += addr; 690 sp->sh_offset = off; 691 sp->sh_size = pltsz; 692 sp->sh_link = 0; 693 sp->sh_info = 0; 694 sp->sh_addralign = SH_ADDRALIGN; 695 sp->sh_entsize = M_PLT_ENTSIZE; 696 697 if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) != 698 sp->sh_size) { 699 dprintf("failed to read .plt at %lx\n", 700 (long)sp->sh_addr); 701 goto bad; 702 } 703 off += roundup(sp->sh_size, SH_ADDRALIGN); 704 sp++; 705 } 706 707 /* make sure we didn't write past the end of allocated memory */ 708 sp++; 709 assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size)); 710 711 free(dp); 712 if ((elf = elf_memory(elfdata, size)) == NULL) { 713 free(elfdata); 714 return (NULL); 715 } 716 717 fptr->file_elfmem = elfdata; 718 719 return (elf); 720 721 bad: 722 if (dp != NULL) 723 free(dp); 724 if (elfdata != NULL) 725 free(elfdata); 726 return (NULL); 727 } 728