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 #ifdef _ELF64 190 Elf * 191 fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, 192 Ehdr *ehdr, uint_t phnum, Phdr *phdr) 193 #else 194 Elf * 195 fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr, 196 Ehdr *ehdr, uint_t phnum, Phdr *phdr) 197 #endif 198 { 199 enum { 200 DI_PLTGOT, 201 DI_JMPREL, 202 DI_PLTRELSZ, 203 DI_PLTREL, 204 DI_SYMTAB, 205 DI_HASH, 206 DI_SYMENT, 207 DI_STRTAB, 208 DI_STRSZ, 209 DI_SUNW_SYMTAB, 210 DI_SUNW_SYMSZ, 211 DI_NENT 212 }; 213 /* 214 * Mask of dynamic options that must be present in a well 215 * formed dynamic section. We need all of these in order to 216 * put together a complete set of elf sections. They are 217 * mandatory in both executables and shared objects so if one 218 * of them is missing, we're in some trouble and should abort. 219 * The PLT items are expected, but we will let them slide if 220 * need be. The DI_SUNW_SYM* items are completely optional, so 221 * we use them if they are present and ignore them otherwise. 222 */ 223 const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) | 224 (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ); 225 int di_mask = 0; 226 size_t size = 0; 227 caddr_t elfdata = NULL; 228 Elf *elf; 229 size_t dynsym_size, ldynsym_size; 230 int dynstr_shndx; 231 Ehdr *ep; 232 Shdr *sp; 233 Dyn *dp; 234 Dyn *d[DI_NENT] = { 0 }; 235 uint_t i; 236 Off off; 237 size_t pltsz = 0, pltentsz; 238 239 240 if (ehdr->e_type == ET_DYN) 241 phdr->p_vaddr += addr; 242 243 if ((dp = malloc(phdr->p_filesz)) == NULL) 244 goto bad; 245 246 if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) != phdr->p_filesz) 247 goto bad; 248 249 #ifndef _ELF64 250 /* 251 * Allow librtld_db the opportunity to "fix" the program 252 * headers, if it needs to, before we process them. 253 */ 254 if (P->rap != NULL && ehdr->e_type == ET_DYN) { 255 rd_fix_phdrs(P->rap, dp, phdr->p_filesz, addr); 256 } 257 #endif 258 259 /* 260 * Iterate over the items in the dynamic section, grabbing 261 * the address of items we want and saving them in dp[]. 262 */ 263 for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) { 264 switch (dp[i].d_tag) { 265 /* For the .plt section */ 266 case DT_PLTGOT: 267 d[DI_PLTGOT] = &dp[i]; 268 break; 269 case DT_JMPREL: 270 d[DI_JMPREL] = &dp[i]; 271 break; 272 case DT_PLTRELSZ: 273 d[DI_PLTRELSZ] = &dp[i]; 274 break; 275 case DT_PLTREL: 276 d[DI_PLTREL] = &dp[i]; 277 break; 278 279 /* For the .dynsym section */ 280 case DT_SYMTAB: 281 d[DI_SYMTAB] = &dp[i]; 282 di_mask |= (1 << DI_SYMTAB); 283 break; 284 case DT_HASH: 285 d[DI_HASH] = &dp[i]; 286 di_mask |= (1 << DI_HASH); 287 break; 288 case DT_SYMENT: 289 d[DI_SYMENT] = &dp[i]; 290 di_mask |= (1 << DI_SYMENT); 291 break; 292 case DT_SUNW_SYMTAB: 293 d[DI_SUNW_SYMTAB] = &dp[i]; 294 break; 295 case DT_SUNW_SYMSZ: 296 d[DI_SUNW_SYMSZ] = &dp[i]; 297 break; 298 299 /* For the .dynstr section */ 300 case DT_STRTAB: 301 d[DI_STRTAB] = &dp[i]; 302 di_mask |= (1 << DI_STRTAB); 303 break; 304 case DT_STRSZ: 305 d[DI_STRSZ] = &dp[i]; 306 di_mask |= (1 << DI_STRSZ); 307 break; 308 } 309 } 310 311 /* Ensure all required entries were collected */ 312 if ((di_mask & di_req_mask) != di_req_mask) { 313 dprintf("text section missing required dynamic entries\n"); 314 goto bad; 315 } 316 317 if (ehdr->e_type == ET_DYN) { 318 if (d[DI_PLTGOT] != NULL) 319 d[DI_PLTGOT]->d_un.d_ptr += addr; 320 if (d[DI_JMPREL] != NULL) 321 d[DI_JMPREL]->d_un.d_ptr += addr; 322 d[DI_SYMTAB]->d_un.d_ptr += addr; 323 d[DI_HASH]->d_un.d_ptr += addr; 324 d[DI_STRTAB]->d_un.d_ptr += addr; 325 if (d[DI_SUNW_SYMTAB] != NULL) 326 d[DI_SUNW_SYMTAB]->d_un.d_ptr += addr; 327 } 328 329 /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */ 330 if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) && 331 ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) || 332 (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr + 333 d[DI_SUNW_SYMSZ]->d_un.d_val)))) { 334 d[DI_SUNW_SYMTAB] = NULL; 335 d[DI_SUNW_SYMSZ] = NULL; 336 } 337 338 /* elf header */ 339 size = sizeof (Ehdr); 340 341 /* program headers from in-core elf fragment */ 342 size += phnum * ehdr->e_phentsize; 343 344 /* unused shdr, and .shstrtab section */ 345 size += sizeof (Shdr); 346 size += sizeof (Shdr); 347 size += roundup(sizeof (shstr), SH_ADDRALIGN); 348 349 /* 350 * .dynsym and .SUNW_ldynsym sections. 351 * 352 * The string table section used for the symbol table and 353 * dynamic sections lies immediately after the dynsym, so the 354 * presence of SUNW_ldynsym changes the dynstr section index. 355 */ 356 if (d[DI_SUNW_SYMTAB] != NULL) { 357 size += sizeof (Shdr); /* SUNW_ldynsym shdr */ 358 ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val; 359 dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr 360 - d[DI_SUNW_SYMTAB]->d_un.d_ptr); 361 ldynsym_size -= dynsym_size; 362 dynstr_shndx = 4; 363 } else { 364 Word nchain; 365 366 if (Pread(P, &nchain, sizeof (nchain), 367 d[DI_HASH]->d_un.d_ptr + sizeof (nchain)) != 368 sizeof (nchain)) { 369 dprintf("Pread of .dynsym at %lx failed\n", 370 (long)(d[DI_HASH]->d_un.d_val + sizeof (nchain))); 371 goto bad; 372 } 373 dynsym_size = sizeof (Sym) * nchain; 374 ldynsym_size = 0; 375 dynstr_shndx = 3; 376 } 377 size += sizeof (Shdr) + ldynsym_size + dynsym_size; 378 379 /* .dynstr section */ 380 size += sizeof (Shdr); 381 size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN); 382 383 /* .dynamic section */ 384 size += sizeof (Shdr); 385 size += roundup(phdr->p_filesz, SH_ADDRALIGN); 386 387 /* .plt section */ 388 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL && 389 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) { 390 uintptr_t penult, ult; 391 uintptr_t jmprel = d[DI_JMPREL]->d_un.d_ptr; 392 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val; 393 394 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) { 395 uint_t ndx = pltrelsz / sizeof (Rela) - 2; 396 Rela r[2]; 397 398 if (Pread(P, r, sizeof (r), jmprel + 399 sizeof (r[0]) * ndx) != sizeof (r)) { 400 dprintf("Pread of DT_RELA failed\n"); 401 goto bad; 402 } 403 404 penult = r[0].r_offset; 405 ult = r[1].r_offset; 406 407 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) { 408 uint_t ndx = pltrelsz / sizeof (Rel) - 2; 409 Rel r[2]; 410 411 if (Pread(P, r, sizeof (r), jmprel + 412 sizeof (r[0]) * ndx) != sizeof (r)) { 413 dprintf("Pread of DT_REL failed\n"); 414 goto bad; 415 } 416 417 penult = r[0].r_offset; 418 ult = r[1].r_offset; 419 } else { 420 dprintf(".plt: unknown jmprel value\n"); 421 goto bad; 422 } 423 424 pltentsz = ult - penult; 425 426 if (ehdr->e_type == ET_DYN) 427 ult += addr; 428 429 pltsz = ult - d[DI_PLTGOT]->d_un.d_ptr + pltentsz; 430 431 size += sizeof (Shdr); 432 size += roundup(pltsz, SH_ADDRALIGN); 433 } 434 435 if ((elfdata = calloc(1, size)) == NULL) 436 goto bad; 437 438 /* LINTED - alignment */ 439 ep = (Ehdr *)elfdata; 440 (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff)); 441 442 ep->e_ehsize = sizeof (Ehdr); 443 ep->e_phoff = sizeof (Ehdr); 444 ep->e_phentsize = ehdr->e_phentsize; 445 ep->e_phnum = phnum; 446 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize; 447 ep->e_shentsize = sizeof (Shdr); 448 /* 449 * Plt and SUNW_ldynsym sections are optional. C logical 450 * binary operators return a 0 or 1 value, so the following 451 * adds 1 for each optional section present. 452 */ 453 ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL); 454 ep->e_shstrndx = 1; 455 456 /* LINTED - alignment */ 457 sp = (Shdr *)(elfdata + ep->e_shoff); 458 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum; 459 460 /* 461 * Copying the program headers directly from the process's 462 * address space is a little suspect, but since we only 463 * use them for their address and size values, this is fine. 464 */ 465 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize, 466 addr + ehdr->e_phoff) != phnum * ep->e_phentsize) { 467 dprintf("failed to read program headers\n"); 468 goto bad; 469 } 470 471 /* 472 * The first elf section is always skipped. 473 */ 474 sp++; 475 476 /* 477 * Section Header: .shstrtab 478 */ 479 sp->sh_name = SHSTR_NDX_shstrtab; 480 sp->sh_type = SHT_STRTAB; 481 sp->sh_flags = SHF_STRINGS; 482 sp->sh_addr = 0; 483 sp->sh_offset = off; 484 sp->sh_size = sizeof (shstr); 485 sp->sh_link = 0; 486 sp->sh_info = 0; 487 sp->sh_addralign = 1; 488 sp->sh_entsize = 0; 489 490 (void) memcpy(&elfdata[off], shstr, sizeof (shstr)); 491 off += roundup(sp->sh_size, SH_ADDRALIGN); 492 sp++; 493 494 /* 495 * Section Header: .SUNW_ldynsym 496 */ 497 if (d[DI_SUNW_SYMTAB] != NULL) { 498 sp->sh_name = SHSTR_NDX_SUNW_ldynsym; 499 sp->sh_type = SHT_SUNW_LDYNSYM; 500 sp->sh_flags = SHF_ALLOC; 501 sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr; 502 if (ehdr->e_type == ET_DYN) 503 sp->sh_addr -= addr; 504 sp->sh_offset = off; 505 sp->sh_size = ldynsym_size; 506 sp->sh_link = dynstr_shndx; 507 /* Index of 1st global in table that has none == # items */ 508 sp->sh_info = sp->sh_size / sizeof (Sym); 509 sp->sh_addralign = SH_ADDRALIGN; 510 sp->sh_entsize = sizeof (Sym); 511 512 if (Pread(P, &elfdata[off], sp->sh_size, 513 d[DI_SUNW_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 514 dprintf("failed to read .SUNW_ldynsym at %lx\n", 515 (long)d[DI_SUNW_SYMTAB]->d_un.d_ptr); 516 goto bad; 517 } 518 off += sp->sh_size; 519 /* No need to round up ldynsym data. Dynsym data is same type */ 520 sp++; 521 } 522 523 /* 524 * Section Header: .dynsym 525 */ 526 sp->sh_name = SHSTR_NDX_dynsym; 527 sp->sh_type = SHT_DYNSYM; 528 sp->sh_flags = SHF_ALLOC; 529 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr; 530 if (ehdr->e_type == ET_DYN) 531 sp->sh_addr -= addr; 532 sp->sh_offset = off; 533 sp->sh_size = dynsym_size; 534 sp->sh_link = dynstr_shndx; 535 sp->sh_info = 1; /* Index of 1st global in table */ 536 sp->sh_addralign = SH_ADDRALIGN; 537 sp->sh_entsize = sizeof (Sym); 538 539 if (Pread(P, &elfdata[off], sp->sh_size, 540 d[DI_SYMTAB]->d_un.d_ptr) != sp->sh_size) { 541 dprintf("failed to read .dynsym at %lx\n", 542 (long)d[DI_SYMTAB]->d_un.d_ptr); 543 goto bad; 544 } 545 546 off += roundup(sp->sh_size, SH_ADDRALIGN); 547 sp++; 548 549 /* 550 * Section Header: .dynstr 551 */ 552 sp->sh_name = SHSTR_NDX_dynstr; 553 sp->sh_type = SHT_STRTAB; 554 sp->sh_flags = SHF_ALLOC | SHF_STRINGS; 555 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr; 556 if (ehdr->e_type == ET_DYN) 557 sp->sh_addr -= addr; 558 sp->sh_offset = off; 559 sp->sh_size = d[DI_STRSZ]->d_un.d_val; 560 sp->sh_link = 0; 561 sp->sh_info = 0; 562 sp->sh_addralign = 1; 563 sp->sh_entsize = 0; 564 565 if (Pread(P, &elfdata[off], sp->sh_size, 566 d[DI_STRTAB]->d_un.d_ptr) != sp->sh_size) { 567 dprintf("failed to read .dynstr\n"); 568 goto bad; 569 } 570 off += roundup(sp->sh_size, SH_ADDRALIGN); 571 sp++; 572 573 /* 574 * Section Header: .dynamic 575 */ 576 sp->sh_name = SHSTR_NDX_dynamic; 577 sp->sh_type = SHT_DYNAMIC; 578 sp->sh_flags = SHF_WRITE | SHF_ALLOC; 579 sp->sh_addr = phdr->p_vaddr; 580 if (ehdr->e_type == ET_DYN) 581 sp->sh_addr -= addr; 582 sp->sh_offset = off; 583 sp->sh_size = phdr->p_filesz; 584 sp->sh_link = dynstr_shndx; 585 sp->sh_info = 0; 586 sp->sh_addralign = SH_ADDRALIGN; 587 sp->sh_entsize = sizeof (Dyn); 588 589 (void) memcpy(&elfdata[off], dp, sp->sh_size); 590 off += roundup(sp->sh_size, SH_ADDRALIGN); 591 sp++; 592 593 /* 594 * Section Header: .plt 595 */ 596 if (pltsz != 0) { 597 sp->sh_name = SHSTR_NDX_plt; 598 sp->sh_type = SHT_PROGBITS; 599 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR; 600 sp->sh_addr = d[DI_PLTGOT]->d_un.d_ptr; 601 if (ehdr->e_type == ET_DYN) 602 sp->sh_addr -= addr; 603 sp->sh_offset = off; 604 sp->sh_size = pltsz; 605 sp->sh_link = 0; 606 sp->sh_info = 0; 607 sp->sh_addralign = SH_ADDRALIGN; 608 sp->sh_entsize = pltentsz; 609 610 if (Pread(P, &elfdata[off], sp->sh_size, 611 d[DI_PLTGOT]->d_un.d_ptr) != sp->sh_size) { 612 dprintf("failed to read .plt\n"); 613 goto bad; 614 } 615 off += roundup(sp->sh_size, SH_ADDRALIGN); 616 sp++; 617 } 618 619 free(dp); 620 if ((elf = elf_memory(elfdata, size)) == NULL) { 621 free(elfdata); 622 return (NULL); 623 } 624 625 fptr->file_elfmem = elfdata; 626 627 return (elf); 628 629 bad: 630 if (dp != NULL) 631 free(dp); 632 if (elfdata != NULL) 633 free(elfdata); 634 return (NULL); 635 636 637 } 638