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 2007 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 259 if (ehdr->e_type == ET_DYN) 260 phdr->p_vaddr += addr; 261 262 if ((dp = malloc(phdr->p_filesz)) == NULL) 263 goto bad; 264 265 if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) != phdr->p_filesz) 266 goto bad; 267 268 #ifndef _ELF64 269 /* 270 * Allow librtld_db the opportunity to "fix" the program 271 * headers, if it needs to, before we process them. 272 */ 273 if (P->rap != NULL && ehdr->e_type == ET_DYN) { 274 rd_fix_phdrs(P->rap, dp, phdr->p_filesz, addr); 275 } 276 #endif 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\n"); 333 goto bad; 334 } 335 336 if (ehdr->e_type == ET_DYN) { 337 if (d[DI_PLTGOT] != NULL) 338 d[DI_PLTGOT]->d_un.d_ptr += addr; 339 if (d[DI_JMPREL] != NULL) 340 d[DI_JMPREL]->d_un.d_ptr += addr; 341 d[DI_SYMTAB]->d_un.d_ptr += addr; 342 d[DI_HASH]->d_un.d_ptr += addr; 343 d[DI_STRTAB]->d_un.d_ptr += addr; 344 if (d[DI_SUNW_SYMTAB] != NULL) 345 d[DI_SUNW_SYMTAB]->d_un.d_ptr += addr; 346 } 347 348 /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */ 349 if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) && 350 ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) || 351 (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr + 352 d[DI_SUNW_SYMSZ]->d_un.d_val)))) { 353 d[DI_SUNW_SYMTAB] = NULL; 354 d[DI_SUNW_SYMSZ] = NULL; 355 } 356 357 /* elf header */ 358 size = sizeof (Ehdr); 359 360 /* program headers from in-core elf fragment */ 361 size += phnum * ehdr->e_phentsize; 362 363 /* unused shdr, and .shstrtab section */ 364 size += sizeof (Shdr); 365 size += sizeof (Shdr); 366 size += roundup(sizeof (shstr), SH_ADDRALIGN); 367 368 /* 369 * .dynsym and .SUNW_ldynsym sections. 370 * 371 * The string table section used for the symbol table and 372 * dynamic sections lies immediately after the dynsym, so the 373 * presence of SUNW_ldynsym changes the dynstr section index. 374 */ 375 if (d[DI_SUNW_SYMTAB] != NULL) { 376 size += sizeof (Shdr); /* SUNW_ldynsym shdr */ 377 ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val; 378 dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr 379 - d[DI_SUNW_SYMTAB]->d_un.d_ptr); 380 ldynsym_size -= dynsym_size; 381 dynstr_shndx = 4; 382 } else { 383 Word nchain; 384 385 if (Pread(P, &nchain, sizeof (nchain), 386 d[DI_HASH]->d_un.d_ptr + sizeof (nchain)) != 387 sizeof (nchain)) { 388 dprintf("Pread of .dynsym at %lx failed\n", 389 (long)(d[DI_HASH]->d_un.d_val + sizeof (nchain))); 390 goto bad; 391 } 392 dynsym_size = sizeof (Sym) * nchain; 393 ldynsym_size = 0; 394 dynstr_shndx = 3; 395 } 396 size += sizeof (Shdr) + ldynsym_size + dynsym_size; 397 398 /* .dynstr section */ 399 size += sizeof (Shdr); 400 size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN); 401 402 /* .dynamic section */ 403 size += sizeof (Shdr); 404 size += roundup(phdr->p_filesz, SH_ADDRALIGN); 405 406 /* .plt section */ 407 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL && 408 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) { 409 uintptr_t penult, ult; 410 uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr; 411 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val; 412 413 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) { 414 uint_t entries = pltrelsz / sizeof (Rela); 415 Rela r[2]; 416 417 if (entries < PLTREL_MIN_ENTRIES) { 418 dprintf("too few PLT relocation entries " 419 "(found %d, expected at least %d)\n", 420 entries, PLTREL_MIN_ENTRIES); 421 goto bad; 422 } 423 if (entries < PLTREL_MIN_ENTRIES + 2) 424 goto done_with_plt; 425 426 if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * 427 entries - sizeof (r)) != sizeof (r)) { 428 dprintf("Pread of DT_RELA failed\n"); 429 goto bad; 430 } 431 432 penult = r[0].r_offset; 433 ult = r[1].r_offset; 434 435 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { 436 uint_t entries = pltrelsz / sizeof (Rel); 437 Rel r[2]; 438 439 if (entries < PLTREL_MIN_ENTRIES) { 440 dprintf("too few PLT relocation entries " 441 "(found %d, expected at least %d)\n", 442 entries, PLTREL_MIN_ENTRIES); 443 goto bad; 444 } 445 if (entries < PLTREL_MIN_ENTRIES + 2) 446 goto done_with_plt; 447 448 if (Pread(P, r, sizeof (r), jmprel + sizeof (r[0]) * 449 entries - sizeof (r)) != sizeof (r)) { 450 dprintf("Pread of DT_REL failed\n"); 451 goto bad; 452 } 453 454 penult = r[0].r_offset; 455 ult = r[1].r_offset; 456 } else { 457 dprintf(".plt: unknown jmprel value\n"); 458 goto bad; 459 } 460 461 pltentsz = ult - penult; 462 463 if (ehdr->e_type == ET_DYN) 464 ult += addr; 465 466 pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz; 467 468 size += sizeof (Shdr); 469 size += roundup(pltsz, SH_ADDRALIGN); 470 } 471 done_with_plt: 472 473 if ((elfdata = calloc(1, size)) == NULL) 474 goto bad; 475 476 /* LINTED - alignment */ 477 ep = (Ehdr *)elfdata; 478 (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff)); 479 480 ep->e_ehsize = sizeof (Ehdr); 481 ep->e_phoff = sizeof (Ehdr); 482 ep->e_phentsize = ehdr->e_phentsize; 483 ep->e_phnum = phnum; 484 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize; 485 ep->e_shentsize = sizeof (Shdr); 486 /* 487 * Plt and SUNW_ldynsym sections are optional. C logical 488 * binary operators return a 0 or 1 value, so the following 489 * adds 1 for each optional section present. 490 */ 491 ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL); 492 ep->e_shstrndx = 1; 493 494 /* LINTED - alignment */ 495 sp = (Shdr *)(elfdata + ep->e_shoff); 496 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum; 497 498 /* 499 * Copying the program headers directly from the process's 500 * address space is a little suspect, but since we only 501 * use them for their address and size values, this is fine. 502 */ 503 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize, 504 addr + ehdr->e_phoff) != phnum * ep->e_phentsize) { 505 dprintf("failed to read program headers\n"); 506 goto bad; 507 } 508 509 /* 510 * The first elf section is always skipped. 511 */ 512 sp++; 513 514 /* 515 * Section Header: .shstrtab 516 */ 517 sp->sh_name = SHSTR_NDX_shstrtab; 518 sp->sh_type = SHT_STRTAB; 519 sp->sh_flags = SHF_STRINGS; 520 sp->sh_addr = 0; 521 sp->sh_offset = off; 522 sp->sh_size = sizeof (shstr); 523 sp->sh_link = 0; 524 sp->sh_info = 0; 525 sp->sh_addralign = 1; 526 sp->sh_entsize = 0; 527 528 (void) memcpy(&elfdata[off], shstr, sizeof (shstr)); 529 off += roundup(sp->sh_size, SH_ADDRALIGN); 530 sp++; 531 532 /* 533 * Section Header: .SUNW_ldynsym 534 */ 535 if (d[DI_SUNW_SYMTAB] != NULL) { 536 sp->sh_name = SHSTR_NDX_SUNW_ldynsym; 537 sp->sh_type = SHT_SUNW_LDYNSYM; 538 sp->sh_flags = SHF_ALLOC; 539 sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr; 540 if (ehdr->e_type == ET_DYN) 541 sp->sh_addr -= addr; 542 sp->sh_offset = off; 543 sp->sh_size = ldynsym_size; 544 sp->sh_link = dynstr_shndx; 545 /* Index of 1st global in table that has none == # items */ 546 sp->sh_info = sp->sh_size / sizeof (Sym); 547 sp->sh_addralign = SH_ADDRALIGN; 548 sp->sh_entsize = sizeof (Sym); 549 550 if (Pread(P, &elfdata[off], sp->sh_size, 551 d[DI_SUNW_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 552 dprintf("failed to read .SUNW_ldynsym at %lx\n", 553 (long)d[DI_SUNW_SYMTAB]->d_un.d_ptr); 554 goto bad; 555 } 556 off += sp->sh_size; 557 /* No need to round up ldynsym data. Dynsym data is same type */ 558 sp++; 559 } 560 561 /* 562 * Section Header: .dynsym 563 */ 564 sp->sh_name = SHSTR_NDX_dynsym; 565 sp->sh_type = SHT_DYNSYM; 566 sp->sh_flags = SHF_ALLOC; 567 sp->sh_addr = d[DI_SYMTAB]->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 = dynsym_size; 572 sp->sh_link = dynstr_shndx; 573 sp->sh_info = 1; /* Index of 1st global in table */ 574 sp->sh_addralign = SH_ADDRALIGN; 575 sp->sh_entsize = sizeof (Sym); 576 577 if (Pread(P, &elfdata[off], sp->sh_size, 578 d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 579 dprintf("failed to read .dynsym at %lx\n", 580 (long)d[DI_SYMTAB]->d_un.d_ptr); 581 goto bad; 582 } 583 584 off += roundup(sp->sh_size, SH_ADDRALIGN); 585 sp++; 586 587 /* 588 * Section Header: .dynstr 589 */ 590 sp->sh_name = SHSTR_NDX_dynstr; 591 sp->sh_type = SHT_STRTAB; 592 sp->sh_flags = SHF_ALLOC | SHF_STRINGS; 593 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr; 594 if (ehdr->e_type == ET_DYN) 595 sp->sh_addr -= addr; 596 sp->sh_offset = off; 597 sp->sh_size = d[DI_STRSZ]->d_un.d_val; 598 sp->sh_link = 0; 599 sp->sh_info = 0; 600 sp->sh_addralign = 1; 601 sp->sh_entsize = 0; 602 603 if (Pread(P, &elfdata[off], sp->sh_size, 604 d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) { 605 dprintf("failed to read .dynstr\n"); 606 goto bad; 607 } 608 off += roundup(sp->sh_size, SH_ADDRALIGN); 609 sp++; 610 611 /* 612 * Section Header: .dynamic 613 */ 614 sp->sh_name = SHSTR_NDX_dynamic; 615 sp->sh_type = SHT_DYNAMIC; 616 sp->sh_flags = SHF_WRITE | SHF_ALLOC; 617 sp->sh_addr = phdr->p_vaddr; 618 if (ehdr->e_type == ET_DYN) 619 sp->sh_addr -= addr; 620 sp->sh_offset = off; 621 sp->sh_size = phdr->p_filesz; 622 sp->sh_link = dynstr_shndx; 623 sp->sh_info = 0; 624 sp->sh_addralign = SH_ADDRALIGN; 625 sp->sh_entsize = sizeof (Dyn); 626 627 (void) memcpy(&elfdata[off], dp, sp->sh_size); 628 off += roundup(sp->sh_size, SH_ADDRALIGN); 629 sp++; 630 631 /* 632 * Section Header: .plt 633 */ 634 if (pltsz != 0) { 635 sp->sh_name = SHSTR_NDX_plt; 636 sp->sh_type = SHT_PROGBITS; 637 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; 638 sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr; 639 if (ehdr->e_type == ET_DYN) 640 sp->sh_addr -= addr; 641 sp->sh_offset = off; 642 sp->sh_size = pltsz; 643 sp->sh_link = 0; 644 sp->sh_info = 0; 645 sp->sh_addralign = SH_ADDRALIGN; 646 sp->sh_entsize = pltentsz; 647 648 if (Pread(P, &elfdata[off], sp->sh_size, 649 d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) { 650 dprintf("failed to read .plt\n"); 651 goto bad; 652 } 653 off += roundup(sp->sh_size, SH_ADDRALIGN); 654 sp++; 655 } 656 657 free(dp); 658 if ((elf = elf_memory(elfdata, size)) == NULL) { 659 free(elfdata); 660 return (NULL); 661 } 662 663 fptr->file_elfmem = elfdata; 664 665 return (elf); 666 667 bad: 668 if (dp != NULL) 669 free(dp); 670 if (elfdata != NULL) 671 free(elfdata); 672 return (NULL); 673 674 675 } 676