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