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/* Copyright (c) 1988 AT&T */ 28/* All Rights Reserved */ 29 30#pragma ident "@(#)clscook.c 1.11 08/05/31 SMI" 31 32/* 33 * This stuff used to live in cook.c, but was moved out to 34 * facilitate dual (Elf32 and Elf64) compilation. See block 35 * comment in cook.c for more info. 36 */ 37 38#include <string.h> 39#include <ar.h> 40#include <stdlib.h> 41#include <errno.h> 42#include "decl.h" 43#include "member.h" 44#include "msg.h" 45 46#include <mach-o/fat.h> 47#include <mach-o/loader.h> 48#include <mach-o/nlist.h> 49#include <mach-o/stab.h> 50#include <sys/mman.h> 51 52static struct xSectName 53{ 54 const char *MachoName; 55 const char *PrimaryElfName; 56 const char *SecondaryElfName; 57} 58xTab[] = 59{ 60 {SECT_TEXT, ".text", "non-SEG_TEXT .text" }, 61 {SECT_DATA, ".data", "non-SEG_DATA .data" }, 62 {SECT_BSS, ".bss", "non-SEG_DATA .bss" }, 63 {SECT_CTF, ".SUNW_ctf", 0}, 64 {"__symbol_table", ".symtab", 0 }, 65 {"__debug_info", ".debug_info", 0 }, 66 {"__debug_abbrev", ".debug_abbrev", 0 }, 67 {"__debug_aranges", ".debug_aranges", 0 }, 68 {"__debug_ranges", ".debug_ranges", 0 }, 69 {"__debug_line", ".debug_line", 0 }, 70 {"__debug_frame", ".debug_frame", 0 }, 71 {"__debug_loc", ".debug_loc", 0 }, 72 {"__debug_pubnames", ".debug_pubnames", 0 }, 73 {"__debug_str", ".debug_str", 0 }, 74 {"__debug_funcnames", ".debug_funcnames", 0 }, 75 {"__debug_typenames", ".debug_typenames", 0 }, 76 {"__debug_pubtypes", ".debug_pubtypes", 0 }, 77 {"__debug_varnames", ".debug_varnames", 0 }, 78 {"__debug_weaknames", ".debug_weaknames", 0 }, 79 {"__debug_macinfo", ".debug_macinfo", 0 }, 80 {"__eh_frame", ".eh_frame", 0 }, 81 {"__dir_str_table", ".dir_str_table", 0 } /* Directly addressed Mach-o string table. */ 82}; 83#define SIZE_XTAB (sizeof(xTab)/sizeof(xTab[0])) 84#define LOADER_H_NAME_LENGTH 16 85 86static 87int elf_macho_str_cookie(const char *name, int primary) 88{ 89 int j; 90 int ret = SIZE_XTAB << 1; 91 92 for (j = 0; j < SIZE_XTAB && name; j++) { 93 if (0 == strncmp(name, xTab[j].MachoName, LOADER_H_NAME_LENGTH)) { 94 if (!primary && xTab[j].SecondaryElfName) 95 ret = (j << 1) + 1; 96 else 97 ret = j << 1; 98 break; 99 } 100 } 101 102 return ret; 103} 104 105#if defined(_ELF64) /* Want just one definition, so compile only under -D_ELF64 */ 106const char *elf_macho_str_off(size_t off) 107{ 108 if (off >= (SIZE_XTAB << 1)) 109 return ".unknown mach-o"; 110 else if (off & 1) 111 return xTab[off>>1].SecondaryElfName; 112 else 113 return xTab[off>>1].PrimaryElfName; 114} 115#endif 116 117static 118Elf32_Word STTSect(const char *sectname) 119{ 120 if (0 == strcmp(sectname, SECT_TEXT)) 121 return STT_FUNC; 122 else if (0 == strcmp(sectname, SECT_DATA)) 123 return STT_OBJECT; 124 else if (0 == strcmp(sectname, SECT_BSS)) 125 return STT_OBJECT; 126 else 127 return STT_OBJECT; 128} 129 130/* 131 * This module is compiled twice, the second time having 132 * -D_ELF64 defined. The following set of macros, along 133 * with machelf.h, represent the differences between the 134 * two compilations. Be careful *not* to add any class- 135 * dependent code (anything that has elf32 or elf64 in the 136 * name) to this code without hiding it behind a switch- 137 * able macro like these. 138 */ 139#if defined(_ELF64) 140#define Snode Snode64 141#define ELFCLASS ELFCLASS64 142#define ElfField Elf64 143#define _elf_snode_init _elf64_snode_init 144#define _elf_prepscan _elf64_prepscan 145#define _elf_cookscn _elf64_cookscn 146#define _elf_mtype _elf64_mtype 147#define _elf_msize _elf64_msize 148#define elf_fsize elf64_fsize 149#define _elf_snode _elf64_snode 150#define _elf_ehdr _elf64_ehdr 151#define elf_xlatetom elf64_xlatetom 152#define _elf_phdr _elf64_phdr 153#define _elf_shdr _elf64_shdr 154#define _elf_prepscn _elf64_prepscn 155 156#define _mach_header mach_header_64 157#define _MH_CIGAM MH_CIGAM_64 158#define _swap_mh __swap_mach_header_64 159#define _elf_word Elf64_Word 160#define _elf_addr Elf64_Addr 161#define _elf_off Elf64_Off 162#define _SHN_MACHO SHN_MACHO_64 163#define _nlist nlist_64 164#define _addralign 8 165#define _SWAPVAL SWAP64 166 167#define _LC_SEGMENT LC_SEGMENT_64 168#define _segcmd segment_command_64 169#define _sect section_64 170#define _swapsegcmd __swap_segment_command_64 171#define _swapsect __swap_section_64 172 173#else /* Elf32 */ 174#define Snode Snode32 175#define ELFCLASS ELFCLASS32 176#define ElfField Elf32 177#define _elf_snode_init _elf32_snode_init 178#define _elf_prepscan _elf32_prepscan 179#define _elf_cookscn _elf32_cookscn 180#define _elf_mtype _elf32_mtype 181#define _elf_msize _elf32_msize 182#define elf_fsize elf32_fsize 183#define _elf_snode _elf32_snode 184#define _elf_ehdr _elf32_ehdr 185#define elf_xlatetom elf32_xlatetom 186#define _elf_phdr _elf32_phdr 187#define _elf_shdr _elf32_shdr 188#define _elf_prepscn _elf32_prepscn 189 190#define _mach_header mach_header 191#define _MH_CIGAM MH_CIGAM 192#define _swap_mh __swap_mach_header 193#define _elf_word Elf32_Word 194#define _elf_addr Elf32_Addr 195#define _elf_off Elf32_Off 196#define _SHN_MACHO SHN_MACHO 197#define _nlist nlist 198#define _addralign 4 199#define _SWAPVAL SWAP32 200 201#define _LC_SEGMENT LC_SEGMENT 202#define _segcmd segment_command 203#define _sect section 204#define _swapsegcmd __swap_segment_command 205#define _swapsect __swap_section 206 207#endif /* _ELF64 */ 208 209 210static Okay 211_elf_prepscn(Elf *elf, size_t cnt) 212{ 213 NOTE(ASSUMING_PROTECTED(*elf)) 214 Elf_Scn * s; 215 Elf_Scn * end; 216 217 if (cnt == 0) 218 return (OK_YES); 219 220 if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) { 221 _elf_seterr(EMEM_SCN, errno); 222 return (OK_NO); 223 } 224 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s)) 225 elf->ed_scntabsz = cnt; 226 end = s + cnt; 227 elf->ed_hdscn = s; 228 do { 229 *s = _elf_snode_init.sb_scn; 230 s->s_elf = elf; 231 s->s_next = s + 1; 232 s->s_index = s - elf->ed_hdscn; 233 s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index; 234 ELFMUTEXINIT(&s->s_mutex); 235 236 /* 237 * Section has not yet been cooked! 238 * 239 * We don't cook a section until it's data is actually 240 * referenced. 241 */ 242 s->s_myflags = 0; 243 } while (++s < end); 244 245 elf->ed_tlscn = --s; 246 s->s_next = 0; 247 248 /* 249 * Section index SHN_UNDEF (0) does not and cannot 250 * have a data buffer. Fix it here. Also mark the 251 * initial section as being allocated for the block 252 */ 253 254 s = elf->ed_hdscn; 255 s->s_myflags = SF_ALLOC; 256 s->s_hdnode = 0; 257 s->s_tlnode = 0; 258 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s)) 259 return (OK_YES); 260} 261 262 263Okay 264_elf_cookscn(Elf_Scn * s) 265{ 266 NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf))) 267 Elf * elf; 268 Shdr * sh; 269 register Dnode * d = &s->s_dnode; 270 size_t fsz, msz; 271 unsigned work; 272 273 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d)) 274 s->s_hdnode = s->s_tlnode = d; 275 s->s_err = 0; 276 s->s_shflags = 0; 277 s->s_uflags = 0; 278 279 280 /* 281 * Prepare d_data for inspection, but don't actually 282 * translate data until needed. Leave the READY 283 * flag off. NOBITS sections see zero size. 284 */ 285 elf = s->s_elf; 286 sh = s->s_shdr; 287 288 d->db_scn = s; 289 d->db_off = sh->sh_offset; 290 d->db_data.d_align = sh->sh_addralign; 291 d->db_data.d_version = elf->ed_version; 292 ELFACCESSDATA(work, _elf_work) 293 d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work); 294 d->db_data.d_buf = 0; 295 d->db_data.d_off = 0; 296 fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version); 297 msz = _elf_msize(d->db_data.d_type, elf->ed_version); 298 d->db_data.d_size = (sh->sh_size / fsz) * msz; 299 d->db_shsz = sh->sh_size; 300 d->db_raw = 0; 301 d->db_buf = 0; 302 d->db_uflags = 0; 303 d->db_myflags = 0; 304 d->db_next = 0; 305 306 if (sh->sh_type != SHT_NOBITS) 307 d->db_fsz = sh->sh_size; 308 else 309 d->db_fsz = 0; 310 311 s->s_myflags |= SF_READY; 312 313 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d)) 314 return (OK_YES); 315} 316 317 318 319Snode * 320_elf_snode() 321{ 322 register Snode *s; 323 324 if ((s = malloc(sizeof (Snode))) == 0) { 325 _elf_seterr(EMEM_SNODE, errno); 326 return (0); 327 } 328 *s = _elf_snode_init; 329 ELFMUTEXINIT(&s->sb_scn.s_mutex); 330 s->sb_scn.s_myflags = SF_ALLOC | SF_READY; 331 s->sb_scn.s_shdr = &s->sb_shdr; 332 return (s); 333} 334 335 336 337int 338_elf_ehdr(Elf * elf, int inplace) 339{ 340 NOTE(ASSUMING_PROTECTED(*elf)) 341 register size_t fsz; /* field size */ 342 Elf_Data dst, src; 343 344 fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version); 345 if (fsz > elf->ed_fsz) { 346 _elf_seterr(EFMT_EHDRSZ, 0); 347 return (-1); 348 } 349 if (inplace && (fsz >= sizeof (Ehdr))) { 350 /* 351 * The translated Ehdr will fit over the original Ehdr. 352 */ 353 /* LINTED */ 354 elf->ed_ehdr = (Ehdr *)elf->ed_ident; 355 elf->ed_status = ES_COOKED; 356 } else { 357 elf->ed_ehdr = malloc(sizeof (Ehdr)); 358 if (elf->ed_ehdr == 0) { 359 _elf_seterr(EMEM_EHDR, errno); 360 return (-1); 361 } 362 elf->ed_myflags |= EDF_EHALLOC; 363 } 364 365 /* 366 * Memory size >= fsz, because otherwise the memory version 367 * loses information and cannot accurately implement the 368 * file. 369 */ 370 371 src.d_buf = (Elf_Void *)elf->ed_ident; 372 src.d_type = ELF_T_EHDR; 373 src.d_size = fsz; 374 src.d_version = elf->ed_version; 375 dst.d_buf = (Elf_Void *)elf->ed_ehdr; 376 dst.d_size = sizeof (Ehdr); 377 dst.d_version = EV_CURRENT; 378 379 if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) || 380 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 381 if (elf->ed_myflags & EDF_EHALLOC) { 382 elf->ed_myflags &= ~EDF_EHALLOC; 383 free(elf->ed_ehdr); 384 } 385 elf->ed_ehdr = 0; 386 return (-1); 387 } 388 389 if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) { 390 _elf_seterr(EREQ_CLASS, 0); 391 if (elf->ed_myflags & EDF_EHALLOC) { 392 elf->ed_myflags &= ~EDF_EHALLOC; 393 free(elf->ed_ehdr); 394 } 395 elf->ed_ehdr = 0; 396 return (-1); 397 } 398 399 if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) { 400 _elf_seterr(EFMT_VER2, 0); 401 if (elf->ed_myflags & EDF_EHALLOC) { 402 elf->ed_myflags &= ~EDF_EHALLOC; 403 free(elf->ed_ehdr); 404 } 405 elf->ed_ehdr = 0; 406 return (-1); 407 } 408 409 return (0); 410} 411 412 413 414int 415_elf_phdr(Elf * elf, int inplace) 416{ 417 NOTE(ASSUMING_PROTECTED(*elf)) 418 register size_t fsz, msz; 419 Elf_Data dst, src; 420 Ehdr * eh = elf->ed_ehdr; /* must be present */ 421 unsigned work; 422 423 if (eh->e_phnum == 0) 424 return (0); 425 426 fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version); 427 if (eh->e_phentsize != fsz) { 428 _elf_seterr(EFMT_PHDRSZ, 0); 429 return (-1); 430 } 431 432 fsz *= eh->e_phnum; 433 ELFACCESSDATA(work, _elf_work) 434 msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum; 435 if ((eh->e_phoff == 0) || 436 ((fsz + eh->e_phoff) > elf->ed_fsz)) { 437 _elf_seterr(EFMT_PHTAB, 0); 438 return (-1); 439 } 440 441 if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) { 442 elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 443 elf->ed_status = ES_COOKED; 444 } else { 445 if ((elf->ed_phdr = malloc(msz)) == 0) { 446 _elf_seterr(EMEM_PHDR, errno); 447 return (-1); 448 } 449 elf->ed_myflags |= EDF_PHALLOC; 450 } 451 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff); 452 src.d_type = ELF_T_PHDR; 453 src.d_size = fsz; 454 src.d_version = elf->ed_version; 455 dst.d_buf = elf->ed_phdr; 456 dst.d_size = msz; 457 dst.d_version = work; 458 if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) || 459 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 460 if (elf->ed_myflags & EDF_PHALLOC) { 461 elf->ed_myflags &= ~EDF_PHALLOC; 462 free(elf->ed_phdr); 463 } 464 elf->ed_phdr = 0; 465 return (-1); 466 } 467 elf->ed_phdrsz = msz; 468 return (0); 469} 470 471 472 473int 474_elf_shdr(Elf * elf, int inplace) 475{ 476 NOTE(ASSUMING_PROTECTED(*elf)) 477 register size_t fsz, msz; 478 size_t scncnt; 479 Elf_Data dst, src; 480 register Ehdr *eh = elf->ed_ehdr; /* must be present */ 481 482 if ((eh->e_shnum == 0) && (eh->e_shoff == 0)) 483 return (0); 484 485 fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version); 486 if (eh->e_shentsize != fsz) { 487 _elf_seterr(EFMT_SHDRSZ, 0); 488 return (-1); 489 } 490 /* 491 * If we are dealing with a file with 'extended section 492 * indexes' - then we need to load the first section 493 * header. The actual section count is stored in 494 * Shdr[0].sh_size. 495 */ 496 if ((scncnt = eh->e_shnum) == 0) { 497 Shdr sh; 498 if ((eh->e_shoff == 0) || 499 (elf->ed_fsz <= eh->e_shoff) || 500 (elf->ed_fsz - eh->e_shoff < fsz)) { 501 _elf_seterr(EFMT_SHTAB, 0); 502 return (-1); 503 } 504 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 505 src.d_type = ELF_T_SHDR; 506 src.d_size = fsz; 507 src.d_version = elf->ed_version; 508 dst.d_buf = (Elf_Void *)&sh; 509 dst.d_size = sizeof (Shdr); 510 dst.d_version = EV_CURRENT; 511 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 512 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) { 513 return (-1); 514 } 515 scncnt = sh.sh_size; 516 } 517 518 fsz *= scncnt; 519 msz = scncnt * sizeof (Shdr); 520 if ((eh->e_shoff == 0) || 521 (elf->ed_fsz <= eh->e_shoff) || 522 (elf->ed_fsz - eh->e_shoff < fsz)) { 523 _elf_seterr(EFMT_SHTAB, 0); 524 return (-1); 525 } 526 527 if (inplace && (fsz >= msz) && 528 ((eh->e_shoff % sizeof (ElfField)) == 0)) { 529 /* LINTED */ 530 elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff); 531 elf->ed_status = ES_COOKED; 532 } else { 533 if ((elf->ed_shdr = malloc(msz)) == 0) { 534 _elf_seterr(EMEM_SHDR, errno); 535 return (-1); 536 } 537 elf->ed_myflags |= EDF_SHALLOC; 538 } 539 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff); 540 src.d_type = ELF_T_SHDR; 541 src.d_size = fsz; 542 src.d_version = elf->ed_version; 543 dst.d_buf = (Elf_Void *)elf->ed_shdr; 544 dst.d_size = msz; 545 dst.d_version = EV_CURRENT; 546 547 if (elf->ed_kind == ELF_K_MACHO) { 548 struct _mach_header hdr, *mh = (struct _mach_header *)(elf->ed_image); 549 struct load_command *thisLC = (struct load_command *)(&(mh[1])); 550 int needSwap = (_MH_CIGAM == mh->magic); 551 int i,j; 552 553 Shdr *pShdr = (Shdr *)(elf->ed_shdr); 554 Shdr *SectionToShdrMap[scncnt]; /* small stack allocated array */ 555 Shdr **pMap = SectionToShdrMap; 556 Shdr *pSymTab = NULL; 557 558 bzero(pShdr, sizeof(Shdr)); 559 SectionToShdrMap[0] = pShdr; 560 pMap++; /* By Mach-o convention the n_sect ordinal index is one-based */ 561 pShdr++; /* By ELF convention the first section header is unused */ 562 563 if (needSwap) { 564 hdr = *mh; 565 mh = &hdr; 566 _swap_mh(mh); 567 } 568 569 for (i = 0; i < mh->ncmds; i++) { 570 int cmd = thisLC->cmd, cmdsize = thisLC->cmdsize; 571 572 if (needSwap) { 573 SWAP32(cmd); 574 SWAP32(cmdsize); 575 } 576 577 switch(cmd) { 578 case _LC_SEGMENT: 579 { 580 struct _segcmd seg, *thisSG = (struct _segcmd *)thisLC; 581 struct _sect sect, *section_ptr, *thisSect = (struct _sect *)(&(thisSG[1])); 582 583 if (needSwap) { 584 seg = *thisSG; 585 thisSG = &seg; 586 _swapsegcmd(thisSG); 587 } 588 589 for (j = 0; j < thisSG->nsects; ++j) { 590 int primary; 591 592 section_ptr = thisSect + j; 593 594 if (needSwap) { 595 sect = *section_ptr; 596 section_ptr = § 597 _swapsect(section_ptr); 598 } 599 600 primary = (0 == strcmp(thisSG->segname, SEG_TEXT)) || 601 (0 == strcmp(thisSG->segname, SEG_DATA)); 602 603 pShdr->sh_name = (_elf_word)elf_macho_str_cookie(section_ptr->sectname, primary); 604 pShdr->sh_type = SHT_UNKNOWN12; 605 pShdr->sh_flags = 0; 606 pShdr->sh_addr = (_elf_addr)section_ptr->addr; 607 pShdr->sh_offset = (_elf_off)section_ptr->offset; 608 pShdr->sh_size = section_ptr->size; 609 pShdr->sh_link = _SHN_MACHO; 610 pShdr->sh_info = STTSect(section_ptr->sectname); 611 pShdr->sh_addralign = section_ptr->align; 612 pShdr->sh_entsize = 0; 613 *pMap = pShdr; 614 pMap++; 615 pShdr++; 616 } 617 break; 618 } 619 620 case LC_SYMTAB: 621 { 622 struct symtab_command symt, *thisST = (struct symtab_command *)thisLC; 623 624 if (needSwap) { 625 symt = *thisST; 626 thisST = &symt; 627 __swap_symtab_command(thisST); 628 } 629 630 pShdr->sh_name = (_elf_word)elf_macho_str_cookie("__symbol_table", 1); 631 pShdr->sh_type = SHT_STRTAB; /* Must yield ELF_T_BYTE to allow the sh_entsize used below! */ 632 pShdr->sh_flags = 0; 633 pShdr->sh_addr = (_elf_addr)(thisST->symoff); 634 pShdr->sh_offset = (_elf_off)(thisST->symoff); 635 pShdr->sh_size = thisST->nsyms * sizeof (struct _nlist); 636 pShdr->sh_link = _SHN_MACHO; 637 pShdr->sh_info = 0; 638 pShdr->sh_addralign = _addralign; 639 pShdr->sh_entsize = sizeof(struct _nlist); 640 pSymTab = pShdr; 641 pShdr++; 642 643 pShdr->sh_name = (_elf_word)elf_macho_str_cookie("__dir_str_table", 1); 644 pShdr->sh_type = SHT_STRTAB; /* Must yield ELF_T_BYTE to allow the sh_entsize used below! */ 645 pShdr->sh_flags = 0; 646 pShdr->sh_addr = (_elf_addr)(thisST->stroff); 647 pShdr->sh_offset = (_elf_off)(thisST->stroff); 648 pShdr->sh_size = thisST->strsize; 649 pShdr->sh_link = _SHN_MACHO; 650 pShdr->sh_info = 0; 651 pShdr->sh_addralign = 1; 652 pShdr->sh_entsize = 0; 653 pShdr++; 654 break; 655 } 656 657 default: 658 break; 659 } 660 661 thisLC = (struct load_command *) ((caddr_t) thisLC + cmdsize); 662 } 663 664 src.d_buf = (Elf_Void *)elf->ed_shdr; 665 src.d_type = ELF_T_SHDR; 666 src.d_size = fsz; 667 668 if (NULL != pSymTab) { 669 struct _nlist *nsym = (struct _nlist *)(elf->ed_image + pSymTab->sh_addr); 670 struct _nlist *pEnd = nsym + (pSymTab->sh_size/pSymTab->sh_entsize); 671 pMap = SectionToShdrMap; 672 673 if (mprotect((char *)elf->ed_image, elf->ed_imagesz, 674 PROT_READ|PROT_WRITE) == -1) { 675 _elf_seterr(EIO_VM, errno); 676 return (-1); 677 } 678 679 while (nsym < pEnd) { 680 681 if (needSwap) { 682 SWAP32(nsym->n_un.n_strx); 683 SWAP16(nsym->n_desc); 684 _SWAPVAL(nsym->n_value); 685 } 686 687 if (nsym->n_type & N_STAB) { /* Detect C++ methods */ 688 689 switch(nsym->n_type) { 690 case N_FUN: 691 nsym->n_desc = STT_FUNC; 692 break; 693 case N_GSYM: 694 nsym->n_desc = STT_OBJECT; 695 break; 696 default: 697 break; 698 } 699 700 } else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) || 701 (N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) { 702 nsym->n_desc = SectionToShdrMap[nsym->n_sect]->sh_info; 703 } else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) && 704 nsym->n_sect == NO_SECT) { 705 nsym->n_desc = STT_OBJECT; /* Common symbol */ 706 } else { 707 /* NOTHING don't mess with other types of symbols */ 708 } 709 nsym++; 710 } 711 } 712 } 713 714 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) || 715 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) || 716 (_elf_prepscn(elf, scncnt) != OK_YES)) { 717 if (elf->ed_myflags & EDF_SHALLOC) { 718 elf->ed_myflags &= ~EDF_SHALLOC; 719 free(elf->ed_shdr); 720 } 721 elf->ed_shdr = 0; 722 return (-1); 723 } 724 return (0); 725} 726