1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Object/MachO.h" 16 #include "llvm/ADT/Triple.h" 17 #include "llvm/Support/DataExtractor.h" 18 #include "llvm/Support/Format.h" 19 #include "llvm/Support/Host.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cctype> 23 #include <cstring> 24 #include <limits> 25 26 using namespace llvm; 27 using namespace object; 28 29 namespace llvm { 30 namespace object { 31 32 struct nlist_base { 33 uint32_t n_strx; 34 uint8_t n_type; 35 uint8_t n_sect; 36 uint16_t n_desc; 37 }; 38 39 struct section_base { 40 char sectname[16]; 41 char segname[16]; 42 }; 43 44 template<typename T> 45 static void SwapValue(T &Value) { 46 Value = sys::SwapByteOrder(Value); 47 } 48 49 template<typename T> 50 static void SwapStruct(T &Value); 51 52 template<> 53 void SwapStruct(MachO::any_relocation_info &H) { 54 SwapValue(H.r_word0); 55 SwapValue(H.r_word1); 56 } 57 58 template<> 59 void SwapStruct(MachO::load_command &L) { 60 SwapValue(L.cmd); 61 SwapValue(L.cmdsize); 62 } 63 64 template<> 65 void SwapStruct(nlist_base &S) { 66 SwapValue(S.n_strx); 67 SwapValue(S.n_desc); 68 } 69 70 template<> 71 void SwapStruct(MachO::section &S) { 72 SwapValue(S.addr); 73 SwapValue(S.size); 74 SwapValue(S.offset); 75 SwapValue(S.align); 76 SwapValue(S.reloff); 77 SwapValue(S.nreloc); 78 SwapValue(S.flags); 79 SwapValue(S.reserved1); 80 SwapValue(S.reserved2); 81 } 82 83 template<> 84 void SwapStruct(MachO::section_64 &S) { 85 SwapValue(S.addr); 86 SwapValue(S.size); 87 SwapValue(S.offset); 88 SwapValue(S.align); 89 SwapValue(S.reloff); 90 SwapValue(S.nreloc); 91 SwapValue(S.flags); 92 SwapValue(S.reserved1); 93 SwapValue(S.reserved2); 94 SwapValue(S.reserved3); 95 } 96 97 template<> 98 void SwapStruct(MachO::nlist &S) { 99 SwapValue(S.n_strx); 100 SwapValue(S.n_desc); 101 SwapValue(S.n_value); 102 } 103 104 template<> 105 void SwapStruct(MachO::nlist_64 &S) { 106 SwapValue(S.n_strx); 107 SwapValue(S.n_desc); 108 SwapValue(S.n_value); 109 } 110 111 template<> 112 void SwapStruct(MachO::mach_header &H) { 113 SwapValue(H.magic); 114 SwapValue(H.cputype); 115 SwapValue(H.cpusubtype); 116 SwapValue(H.filetype); 117 SwapValue(H.ncmds); 118 SwapValue(H.sizeofcmds); 119 SwapValue(H.flags); 120 } 121 122 template<> 123 void SwapStruct(MachO::mach_header_64 &H) { 124 SwapValue(H.magic); 125 SwapValue(H.cputype); 126 SwapValue(H.cpusubtype); 127 SwapValue(H.filetype); 128 SwapValue(H.ncmds); 129 SwapValue(H.sizeofcmds); 130 SwapValue(H.flags); 131 SwapValue(H.reserved); 132 } 133 134 template<> 135 void SwapStruct(MachO::symtab_command &C) { 136 SwapValue(C.cmd); 137 SwapValue(C.cmdsize); 138 SwapValue(C.symoff); 139 SwapValue(C.nsyms); 140 SwapValue(C.stroff); 141 SwapValue(C.strsize); 142 } 143 144 template<> 145 void SwapStruct(MachO::dysymtab_command &C) { 146 SwapValue(C.cmd); 147 SwapValue(C.cmdsize); 148 SwapValue(C.ilocalsym); 149 SwapValue(C.nlocalsym); 150 SwapValue(C.iextdefsym); 151 SwapValue(C.nextdefsym); 152 SwapValue(C.iundefsym); 153 SwapValue(C.nundefsym); 154 SwapValue(C.tocoff); 155 SwapValue(C.ntoc); 156 SwapValue(C.modtaboff); 157 SwapValue(C.nmodtab); 158 SwapValue(C.extrefsymoff); 159 SwapValue(C.nextrefsyms); 160 SwapValue(C.indirectsymoff); 161 SwapValue(C.nindirectsyms); 162 SwapValue(C.extreloff); 163 SwapValue(C.nextrel); 164 SwapValue(C.locreloff); 165 SwapValue(C.nlocrel); 166 } 167 168 template<> 169 void SwapStruct(MachO::linkedit_data_command &C) { 170 SwapValue(C.cmd); 171 SwapValue(C.cmdsize); 172 SwapValue(C.dataoff); 173 SwapValue(C.datasize); 174 } 175 176 template<> 177 void SwapStruct(MachO::segment_command &C) { 178 SwapValue(C.cmd); 179 SwapValue(C.cmdsize); 180 SwapValue(C.vmaddr); 181 SwapValue(C.vmsize); 182 SwapValue(C.fileoff); 183 SwapValue(C.filesize); 184 SwapValue(C.maxprot); 185 SwapValue(C.initprot); 186 SwapValue(C.nsects); 187 SwapValue(C.flags); 188 } 189 190 template<> 191 void SwapStruct(MachO::segment_command_64 &C) { 192 SwapValue(C.cmd); 193 SwapValue(C.cmdsize); 194 SwapValue(C.vmaddr); 195 SwapValue(C.vmsize); 196 SwapValue(C.fileoff); 197 SwapValue(C.filesize); 198 SwapValue(C.maxprot); 199 SwapValue(C.initprot); 200 SwapValue(C.nsects); 201 SwapValue(C.flags); 202 } 203 204 template<> 205 void SwapStruct(uint32_t &C) { 206 SwapValue(C); 207 } 208 209 template<> 210 void SwapStruct(MachO::linker_options_command &C) { 211 SwapValue(C.cmd); 212 SwapValue(C.cmdsize); 213 SwapValue(C.count); 214 } 215 216 template<> 217 void SwapStruct(MachO::data_in_code_entry &C) { 218 SwapValue(C.offset); 219 SwapValue(C.length); 220 SwapValue(C.kind); 221 } 222 223 template<typename T> 224 T getStruct(const MachOObjectFile *O, const char *P) { 225 T Cmd; 226 memcpy(&Cmd, P, sizeof(T)); 227 if (O->isLittleEndian() != sys::IsLittleEndianHost) 228 SwapStruct(Cmd); 229 return Cmd; 230 } 231 232 static uint32_t 233 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 234 const MachOObjectFile::LoadCommandInfo &L) { 235 if (O->is64Bit()) { 236 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 237 return S.nsects; 238 } 239 MachO::segment_command S = O->getSegmentLoadCommand(L); 240 return S.nsects; 241 } 242 243 static const char * 244 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 245 unsigned Sec) { 246 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 247 248 bool Is64 = O->is64Bit(); 249 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 250 sizeof(MachO::segment_command); 251 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 252 sizeof(MachO::section); 253 254 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 255 return reinterpret_cast<const char*>(SectionAddr); 256 } 257 258 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 259 return O->getData().substr(Offset, 1).data(); 260 } 261 262 static nlist_base 263 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 264 const char *P = reinterpret_cast<const char *>(DRI.p); 265 return getStruct<nlist_base>(O, P); 266 } 267 268 static StringRef parseSegmentOrSectionName(const char *P) { 269 if (P[15] == 0) 270 // Null terminated. 271 return P; 272 // Not null terminated, so this is a 16 char string. 273 return StringRef(P, 16); 274 } 275 276 // Helper to advance a section or symbol iterator multiple increments at a time. 277 template<class T> 278 static error_code advance(T &it, size_t Val) { 279 error_code ec; 280 while (Val--) { 281 it.increment(ec); 282 } 283 return ec; 284 } 285 286 template<class T> 287 static void advanceTo(T &it, size_t Val) { 288 if (error_code ec = advance(it, Val)) 289 report_fatal_error(ec.message()); 290 } 291 292 static unsigned getCPUType(const MachOObjectFile *O) { 293 return O->getHeader().cputype; 294 } 295 296 static void printRelocationTargetName(const MachOObjectFile *O, 297 const MachO::any_relocation_info &RE, 298 raw_string_ostream &fmt) { 299 bool IsScattered = O->isRelocationScattered(RE); 300 301 // Target of a scattered relocation is an address. In the interest of 302 // generating pretty output, scan through the symbol table looking for a 303 // symbol that aligns with that address. If we find one, print it. 304 // Otherwise, we just print the hex address of the target. 305 if (IsScattered) { 306 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 307 308 error_code ec; 309 for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols(); 310 SI != SE; SI.increment(ec)) { 311 if (ec) report_fatal_error(ec.message()); 312 313 uint64_t Addr; 314 StringRef Name; 315 316 if ((ec = SI->getAddress(Addr))) 317 report_fatal_error(ec.message()); 318 if (Addr != Val) continue; 319 if ((ec = SI->getName(Name))) 320 report_fatal_error(ec.message()); 321 fmt << Name; 322 return; 323 } 324 325 // If we couldn't find a symbol that this relocation refers to, try 326 // to find a section beginning instead. 327 for (section_iterator SI = O->begin_sections(), SE = O->end_sections(); 328 SI != SE; SI.increment(ec)) { 329 if (ec) report_fatal_error(ec.message()); 330 331 uint64_t Addr; 332 StringRef Name; 333 334 if ((ec = SI->getAddress(Addr))) 335 report_fatal_error(ec.message()); 336 if (Addr != Val) continue; 337 if ((ec = SI->getName(Name))) 338 report_fatal_error(ec.message()); 339 fmt << Name; 340 return; 341 } 342 343 fmt << format("0x%x", Val); 344 return; 345 } 346 347 StringRef S; 348 bool isExtern = O->getPlainRelocationExternal(RE); 349 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 350 351 if (isExtern) { 352 symbol_iterator SI = O->begin_symbols(); 353 advanceTo(SI, Val); 354 SI->getName(S); 355 } else { 356 section_iterator SI = O->begin_sections(); 357 // Adjust for the fact that sections are 1-indexed. 358 advanceTo(SI, Val - 1); 359 SI->getName(S); 360 } 361 362 fmt << S; 363 } 364 365 static uint32_t 366 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 367 return RE.r_word0; 368 } 369 370 static unsigned 371 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 372 return RE.r_word0 & 0xffffff; 373 } 374 375 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 376 const MachO::any_relocation_info &RE) { 377 if (O->isLittleEndian()) 378 return (RE.r_word1 >> 24) & 1; 379 return (RE.r_word1 >> 7) & 1; 380 } 381 382 static bool 383 getScatteredRelocationPCRel(const MachOObjectFile *O, 384 const MachO::any_relocation_info &RE) { 385 return (RE.r_word0 >> 30) & 1; 386 } 387 388 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 389 const MachO::any_relocation_info &RE) { 390 if (O->isLittleEndian()) 391 return (RE.r_word1 >> 25) & 3; 392 return (RE.r_word1 >> 5) & 3; 393 } 394 395 static unsigned 396 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 397 return (RE.r_word0 >> 28) & 3; 398 } 399 400 static unsigned getPlainRelocationType(const MachOObjectFile *O, 401 const MachO::any_relocation_info &RE) { 402 if (O->isLittleEndian()) 403 return RE.r_word1 >> 28; 404 return RE.r_word1 & 0xf; 405 } 406 407 static unsigned 408 getScatteredRelocationType(const MachO::any_relocation_info &RE) { 409 return (RE.r_word0 >> 24) & 0xf; 410 } 411 412 static uint32_t getSectionFlags(const MachOObjectFile *O, 413 DataRefImpl Sec) { 414 if (O->is64Bit()) { 415 MachO::section_64 Sect = O->getSection64(Sec); 416 return Sect.flags; 417 } 418 MachO::section Sect = O->getSection(Sec); 419 return Sect.flags; 420 } 421 422 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, 423 bool IsLittleEndian, bool Is64bits, 424 error_code &ec) 425 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 426 SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { 427 uint32_t LoadCommandCount = this->getHeader().ncmds; 428 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 429 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 430 431 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 432 for (unsigned I = 0; ; ++I) { 433 if (Load.C.cmd == MachO::LC_SYMTAB) { 434 assert(!SymtabLoadCmd && "Multiple symbol tables"); 435 SymtabLoadCmd = Load.Ptr; 436 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 437 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 438 DysymtabLoadCmd = Load.Ptr; 439 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 440 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 441 DataInCodeLoadCmd = Load.Ptr; 442 } else if (Load.C.cmd == SegmentLoadType) { 443 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 444 for (unsigned J = 0; J < NumSections; ++J) { 445 const char *Sec = getSectionPtr(this, Load, J); 446 Sections.push_back(Sec); 447 } 448 } 449 450 if (I == LoadCommandCount - 1) 451 break; 452 else 453 Load = getNextLoadCommandInfo(Load); 454 } 455 } 456 457 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, 458 SymbolRef &Res) const { 459 unsigned SymbolTableEntrySize = is64Bit() ? 460 sizeof(MachO::nlist_64) : 461 sizeof(MachO::nlist); 462 Symb.p += SymbolTableEntrySize; 463 Res = SymbolRef(Symb, this); 464 return object_error::success; 465 } 466 467 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 468 StringRef &Res) const { 469 StringRef StringTable = getStringTableData(); 470 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 471 const char *Start = &StringTable.data()[Entry.n_strx]; 472 Res = StringRef(Start); 473 return object_error::success; 474 } 475 476 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 477 uint64_t &Res) const { 478 if (is64Bit()) { 479 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 480 Res = Entry.n_value; 481 } else { 482 MachO::nlist Entry = getSymbolTableEntry(Symb); 483 Res = Entry.n_value; 484 } 485 return object_error::success; 486 } 487 488 error_code 489 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, 490 uint64_t &Res) const { 491 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 492 getSymbolAddress(Symb, Res); 493 if (Entry.n_sect) { 494 uint64_t Delta; 495 DataRefImpl SecRel; 496 SecRel.d.a = Entry.n_sect-1; 497 if (is64Bit()) { 498 MachO::section_64 Sec = getSection64(SecRel); 499 Delta = Sec.offset - Sec.addr; 500 } else { 501 MachO::section Sec = getSection(SecRel); 502 Delta = Sec.offset - Sec.addr; 503 } 504 505 Res += Delta; 506 } 507 508 return object_error::success; 509 } 510 511 error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 512 uint32_t &Result) const { 513 uint32_t flags; 514 this->getSymbolFlags(DRI, flags); 515 if (flags & SymbolRef::SF_Common) { 516 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 517 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 518 } else { 519 Result = 0; 520 } 521 return object_error::success; 522 } 523 524 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 525 uint64_t &Result) const { 526 uint64_t BeginOffset; 527 uint64_t EndOffset = 0; 528 uint8_t SectionIndex; 529 530 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 531 uint64_t Value; 532 getSymbolAddress(DRI, Value); 533 534 BeginOffset = Value; 535 536 SectionIndex = Entry.n_sect; 537 if (!SectionIndex) { 538 uint32_t flags = SymbolRef::SF_None; 539 this->getSymbolFlags(DRI, flags); 540 if (flags & SymbolRef::SF_Common) 541 Result = Value; 542 else 543 Result = UnknownAddressOrSize; 544 return object_error::success; 545 } 546 // Unfortunately symbols are unsorted so we need to touch all 547 // symbols from load command 548 error_code ec; 549 for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E; 550 I.increment(ec)) { 551 DataRefImpl DRI = I->getRawDataRefImpl(); 552 Entry = getSymbolTableEntryBase(this, DRI); 553 getSymbolAddress(DRI, Value); 554 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 555 if (!EndOffset || Value < EndOffset) 556 EndOffset = Value; 557 } 558 if (!EndOffset) { 559 uint64_t Size; 560 DataRefImpl Sec; 561 Sec.d.a = SectionIndex-1; 562 getSectionSize(Sec, Size); 563 getSectionAddress(Sec, EndOffset); 564 EndOffset += Size; 565 } 566 Result = EndOffset - BeginOffset; 567 return object_error::success; 568 } 569 570 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 571 SymbolRef::Type &Res) const { 572 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 573 uint8_t n_type = Entry.n_type; 574 575 Res = SymbolRef::ST_Other; 576 577 // If this is a STAB debugging symbol, we can do nothing more. 578 if (n_type & MachO::N_STAB) { 579 Res = SymbolRef::ST_Debug; 580 return object_error::success; 581 } 582 583 switch (n_type & MachO::N_TYPE) { 584 case MachO::N_UNDF : 585 Res = SymbolRef::ST_Unknown; 586 break; 587 case MachO::N_SECT : 588 Res = SymbolRef::ST_Function; 589 break; 590 } 591 return object_error::success; 592 } 593 594 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, 595 char &Res) const { 596 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 597 uint8_t Type = Entry.n_type; 598 uint16_t Flags = Entry.n_desc; 599 600 char Char; 601 switch (Type & MachO::N_TYPE) { 602 case MachO::N_UNDF: 603 Char = 'u'; 604 break; 605 case MachO::N_ABS: 606 case MachO::N_SECT: 607 Char = 's'; 608 break; 609 default: 610 Char = '?'; 611 break; 612 } 613 614 if (Flags & (MachO::N_EXT | MachO::N_PEXT)) 615 Char = toupper(static_cast<unsigned char>(Char)); 616 Res = Char; 617 return object_error::success; 618 } 619 620 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, 621 uint32_t &Result) const { 622 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 623 624 uint8_t MachOType = Entry.n_type; 625 uint16_t MachOFlags = Entry.n_desc; 626 627 // TODO: Correctly set SF_ThreadLocal 628 Result = SymbolRef::SF_None; 629 630 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 631 Result |= SymbolRef::SF_Undefined; 632 633 if (MachOFlags & MachO::N_STAB) 634 Result |= SymbolRef::SF_FormatSpecific; 635 636 if (MachOType & MachO::N_EXT) { 637 Result |= SymbolRef::SF_Global; 638 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 639 uint64_t Value; 640 getSymbolAddress(DRI, Value); 641 if (Value) 642 Result |= SymbolRef::SF_Common; 643 } 644 } 645 646 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 647 Result |= SymbolRef::SF_Weak; 648 649 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 650 Result |= SymbolRef::SF_Absolute; 651 652 return object_error::success; 653 } 654 655 error_code 656 MachOObjectFile::getSymbolSection(DataRefImpl Symb, 657 section_iterator &Res) const { 658 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 659 uint8_t index = Entry.n_sect; 660 661 if (index == 0) { 662 Res = end_sections(); 663 } else { 664 DataRefImpl DRI; 665 DRI.d.a = index - 1; 666 Res = section_iterator(SectionRef(DRI, this)); 667 } 668 669 return object_error::success; 670 } 671 672 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, 673 uint64_t &Val) const { 674 report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); 675 } 676 677 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, 678 SectionRef &Res) const { 679 Sec.d.a++; 680 Res = SectionRef(Sec, this); 681 return object_error::success; 682 } 683 684 error_code 685 MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { 686 ArrayRef<char> Raw = getSectionRawName(Sec); 687 Result = parseSegmentOrSectionName(Raw.data()); 688 return object_error::success; 689 } 690 691 error_code 692 MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { 693 if (is64Bit()) { 694 MachO::section_64 Sect = getSection64(Sec); 695 Res = Sect.addr; 696 } else { 697 MachO::section Sect = getSection(Sec); 698 Res = Sect.addr; 699 } 700 return object_error::success; 701 } 702 703 error_code 704 MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { 705 if (is64Bit()) { 706 MachO::section_64 Sect = getSection64(Sec); 707 Res = Sect.size; 708 } else { 709 MachO::section Sect = getSection(Sec); 710 Res = Sect.size; 711 } 712 713 return object_error::success; 714 } 715 716 error_code 717 MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { 718 uint32_t Offset; 719 uint64_t Size; 720 721 if (is64Bit()) { 722 MachO::section_64 Sect = getSection64(Sec); 723 Offset = Sect.offset; 724 Size = Sect.size; 725 } else { 726 MachO::section Sect = getSection(Sec); 727 Offset = Sect.offset; 728 Size = Sect.size; 729 } 730 731 Res = this->getData().substr(Offset, Size); 732 return object_error::success; 733 } 734 735 error_code 736 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { 737 uint32_t Align; 738 if (is64Bit()) { 739 MachO::section_64 Sect = getSection64(Sec); 740 Align = Sect.align; 741 } else { 742 MachO::section Sect = getSection(Sec); 743 Align = Sect.align; 744 } 745 746 Res = uint64_t(1) << Align; 747 return object_error::success; 748 } 749 750 error_code 751 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { 752 uint32_t Flags = getSectionFlags(this, Sec); 753 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 754 return object_error::success; 755 } 756 757 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { 758 // FIXME: Unimplemented. 759 Result = false; 760 return object_error::success; 761 } 762 763 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { 764 // FIXME: Unimplemented. 765 Result = false; 766 return object_error::success; 767 } 768 769 error_code 770 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 771 bool &Result) const { 772 // FIXME: Unimplemented. 773 Result = true; 774 return object_error::success; 775 } 776 777 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 778 bool &Result) const { 779 // FIXME: Unimplemented. 780 Result = false; 781 return object_error::success; 782 } 783 784 error_code 785 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { 786 uint32_t Flags = getSectionFlags(this, Sec); 787 unsigned SectionType = Flags & MachO::SECTION_TYPE; 788 Res = SectionType == MachO::S_ZEROFILL || 789 SectionType == MachO::S_GB_ZEROFILL; 790 return object_error::success; 791 } 792 793 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 794 bool &Result) const { 795 // Consider using the code from isSectionText to look for __const sections. 796 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 797 // to use section attributes to distinguish code from data. 798 799 // FIXME: Unimplemented. 800 Result = false; 801 return object_error::success; 802 } 803 804 error_code 805 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, 806 bool &Result) const { 807 SymbolRef::Type ST; 808 this->getSymbolType(Symb, ST); 809 if (ST == SymbolRef::ST_Unknown) { 810 Result = false; 811 return object_error::success; 812 } 813 814 uint64_t SectBegin, SectEnd; 815 getSectionAddress(Sec, SectBegin); 816 getSectionSize(Sec, SectEnd); 817 SectEnd += SectBegin; 818 819 uint64_t SymAddr; 820 getSymbolAddress(Symb, SymAddr); 821 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 822 823 return object_error::success; 824 } 825 826 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { 827 uint32_t Offset; 828 if (is64Bit()) { 829 MachO::section_64 Sect = getSection64(Sec); 830 Offset = Sect.reloff; 831 } else { 832 MachO::section Sect = getSection(Sec); 833 Offset = Sect.reloff; 834 } 835 836 DataRefImpl Ret; 837 Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 838 return relocation_iterator(RelocationRef(Ret, this)); 839 } 840 841 relocation_iterator 842 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { 843 uint32_t Offset; 844 uint32_t Num; 845 if (is64Bit()) { 846 MachO::section_64 Sect = getSection64(Sec); 847 Offset = Sect.reloff; 848 Num = Sect.nreloc; 849 } else { 850 MachO::section Sect = getSection(Sec); 851 Offset = Sect.reloff; 852 Num = Sect.nreloc; 853 } 854 855 const MachO::any_relocation_info *P = 856 reinterpret_cast<const MachO::any_relocation_info *>(getPtr(this, Offset)); 857 858 DataRefImpl Ret; 859 Ret.p = reinterpret_cast<uintptr_t>(P + Num); 860 return relocation_iterator(RelocationRef(Ret, this)); 861 } 862 863 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, 864 RelocationRef &Res) const { 865 const MachO::any_relocation_info *P = 866 reinterpret_cast<const MachO::any_relocation_info *>(Rel.p); 867 Rel.p = reinterpret_cast<uintptr_t>(P + 1); 868 Res = RelocationRef(Rel, this); 869 return object_error::success; 870 } 871 872 error_code 873 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { 874 report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); 875 } 876 877 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 878 uint64_t &Res) const { 879 MachO::any_relocation_info RE = getRelocation(Rel); 880 Res = getAnyRelocationAddress(RE); 881 return object_error::success; 882 } 883 884 symbol_iterator 885 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 886 MachO::any_relocation_info RE = getRelocation(Rel); 887 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 888 bool isExtern = getPlainRelocationExternal(RE); 889 if (!isExtern) 890 return end_symbols(); 891 892 MachO::symtab_command S = getSymtabLoadCommand(); 893 unsigned SymbolTableEntrySize = is64Bit() ? 894 sizeof(MachO::nlist_64) : 895 sizeof(MachO::nlist); 896 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 897 DataRefImpl Sym; 898 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 899 return symbol_iterator(SymbolRef(Sym, this)); 900 } 901 902 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 903 uint64_t &Res) const { 904 MachO::any_relocation_info RE = getRelocation(Rel); 905 Res = getAnyRelocationType(RE); 906 return object_error::success; 907 } 908 909 error_code 910 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 911 SmallVectorImpl<char> &Result) const { 912 StringRef res; 913 uint64_t RType; 914 getRelocationType(Rel, RType); 915 916 unsigned Arch = this->getArch(); 917 918 switch (Arch) { 919 case Triple::x86: { 920 static const char *const Table[] = { 921 "GENERIC_RELOC_VANILLA", 922 "GENERIC_RELOC_PAIR", 923 "GENERIC_RELOC_SECTDIFF", 924 "GENERIC_RELOC_PB_LA_PTR", 925 "GENERIC_RELOC_LOCAL_SECTDIFF", 926 "GENERIC_RELOC_TLV" }; 927 928 if (RType > 6) 929 res = "Unknown"; 930 else 931 res = Table[RType]; 932 break; 933 } 934 case Triple::x86_64: { 935 static const char *const Table[] = { 936 "X86_64_RELOC_UNSIGNED", 937 "X86_64_RELOC_SIGNED", 938 "X86_64_RELOC_BRANCH", 939 "X86_64_RELOC_GOT_LOAD", 940 "X86_64_RELOC_GOT", 941 "X86_64_RELOC_SUBTRACTOR", 942 "X86_64_RELOC_SIGNED_1", 943 "X86_64_RELOC_SIGNED_2", 944 "X86_64_RELOC_SIGNED_4", 945 "X86_64_RELOC_TLV" }; 946 947 if (RType > 9) 948 res = "Unknown"; 949 else 950 res = Table[RType]; 951 break; 952 } 953 case Triple::arm: { 954 static const char *const Table[] = { 955 "ARM_RELOC_VANILLA", 956 "ARM_RELOC_PAIR", 957 "ARM_RELOC_SECTDIFF", 958 "ARM_RELOC_LOCAL_SECTDIFF", 959 "ARM_RELOC_PB_LA_PTR", 960 "ARM_RELOC_BR24", 961 "ARM_THUMB_RELOC_BR22", 962 "ARM_THUMB_32BIT_BRANCH", 963 "ARM_RELOC_HALF", 964 "ARM_RELOC_HALF_SECTDIFF" }; 965 966 if (RType > 9) 967 res = "Unknown"; 968 else 969 res = Table[RType]; 970 break; 971 } 972 case Triple::ppc: { 973 static const char *const Table[] = { 974 "PPC_RELOC_VANILLA", 975 "PPC_RELOC_PAIR", 976 "PPC_RELOC_BR14", 977 "PPC_RELOC_BR24", 978 "PPC_RELOC_HI16", 979 "PPC_RELOC_LO16", 980 "PPC_RELOC_HA16", 981 "PPC_RELOC_LO14", 982 "PPC_RELOC_SECTDIFF", 983 "PPC_RELOC_PB_LA_PTR", 984 "PPC_RELOC_HI16_SECTDIFF", 985 "PPC_RELOC_LO16_SECTDIFF", 986 "PPC_RELOC_HA16_SECTDIFF", 987 "PPC_RELOC_JBSR", 988 "PPC_RELOC_LO14_SECTDIFF", 989 "PPC_RELOC_LOCAL_SECTDIFF" }; 990 991 res = Table[RType]; 992 break; 993 } 994 case Triple::UnknownArch: 995 res = "Unknown"; 996 break; 997 } 998 Result.append(res.begin(), res.end()); 999 return object_error::success; 1000 } 1001 1002 error_code 1003 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 1004 SmallVectorImpl<char> &Result) const { 1005 MachO::any_relocation_info RE = getRelocation(Rel); 1006 1007 unsigned Arch = this->getArch(); 1008 1009 std::string fmtbuf; 1010 raw_string_ostream fmt(fmtbuf); 1011 unsigned Type = this->getAnyRelocationType(RE); 1012 bool IsPCRel = this->getAnyRelocationPCRel(RE); 1013 1014 // Determine any addends that should be displayed with the relocation. 1015 // These require decoding the relocation type, which is triple-specific. 1016 1017 // X86_64 has entirely custom relocation types. 1018 if (Arch == Triple::x86_64) { 1019 bool isPCRel = getAnyRelocationPCRel(RE); 1020 1021 switch (Type) { 1022 case MachO::X86_64_RELOC_GOT_LOAD: 1023 case MachO::X86_64_RELOC_GOT: { 1024 printRelocationTargetName(this, RE, fmt); 1025 fmt << "@GOT"; 1026 if (isPCRel) fmt << "PCREL"; 1027 break; 1028 } 1029 case MachO::X86_64_RELOC_SUBTRACTOR: { 1030 DataRefImpl RelNext = Rel; 1031 RelNext.d.a++; 1032 MachO::any_relocation_info RENext = getRelocation(RelNext); 1033 1034 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 1035 // X86_64_RELOC_UNSIGNED. 1036 // NOTE: Scattered relocations don't exist on x86_64. 1037 unsigned RType = getAnyRelocationType(RENext); 1038 if (RType != MachO::X86_64_RELOC_UNSIGNED) 1039 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1040 "X86_64_RELOC_SUBTRACTOR."); 1041 1042 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 1043 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 1044 printRelocationTargetName(this, RENext, fmt); 1045 fmt << "-"; 1046 printRelocationTargetName(this, RE, fmt); 1047 break; 1048 } 1049 case MachO::X86_64_RELOC_TLV: 1050 printRelocationTargetName(this, RE, fmt); 1051 fmt << "@TLV"; 1052 if (isPCRel) fmt << "P"; 1053 break; 1054 case MachO::X86_64_RELOC_SIGNED_1: 1055 printRelocationTargetName(this, RE, fmt); 1056 fmt << "-1"; 1057 break; 1058 case MachO::X86_64_RELOC_SIGNED_2: 1059 printRelocationTargetName(this, RE, fmt); 1060 fmt << "-2"; 1061 break; 1062 case MachO::X86_64_RELOC_SIGNED_4: 1063 printRelocationTargetName(this, RE, fmt); 1064 fmt << "-4"; 1065 break; 1066 default: 1067 printRelocationTargetName(this, RE, fmt); 1068 break; 1069 } 1070 // X86 and ARM share some relocation types in common. 1071 } else if (Arch == Triple::x86 || Arch == Triple::arm || 1072 Arch == Triple::ppc) { 1073 // Generic relocation types... 1074 switch (Type) { 1075 case MachO::GENERIC_RELOC_PAIR: // prints no info 1076 return object_error::success; 1077 case MachO::GENERIC_RELOC_SECTDIFF: { 1078 DataRefImpl RelNext = Rel; 1079 RelNext.d.a++; 1080 MachO::any_relocation_info RENext = getRelocation(RelNext); 1081 1082 // X86 sect diff's must be followed by a relocation of type 1083 // GENERIC_RELOC_PAIR. 1084 unsigned RType = getAnyRelocationType(RENext); 1085 1086 if (RType != MachO::GENERIC_RELOC_PAIR) 1087 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1088 "GENERIC_RELOC_SECTDIFF."); 1089 1090 printRelocationTargetName(this, RE, fmt); 1091 fmt << "-"; 1092 printRelocationTargetName(this, RENext, fmt); 1093 break; 1094 } 1095 } 1096 1097 if (Arch == Triple::x86 || Arch == Triple::ppc) { 1098 switch (Type) { 1099 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 1100 DataRefImpl RelNext = Rel; 1101 RelNext.d.a++; 1102 MachO::any_relocation_info RENext = getRelocation(RelNext); 1103 1104 // X86 sect diff's must be followed by a relocation of type 1105 // GENERIC_RELOC_PAIR. 1106 unsigned RType = getAnyRelocationType(RENext); 1107 if (RType != MachO::GENERIC_RELOC_PAIR) 1108 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1109 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1110 1111 printRelocationTargetName(this, RE, fmt); 1112 fmt << "-"; 1113 printRelocationTargetName(this, RENext, fmt); 1114 break; 1115 } 1116 case MachO::GENERIC_RELOC_TLV: { 1117 printRelocationTargetName(this, RE, fmt); 1118 fmt << "@TLV"; 1119 if (IsPCRel) fmt << "P"; 1120 break; 1121 } 1122 default: 1123 printRelocationTargetName(this, RE, fmt); 1124 } 1125 } else { // ARM-specific relocations 1126 switch (Type) { 1127 case MachO::ARM_RELOC_HALF: 1128 case MachO::ARM_RELOC_HALF_SECTDIFF: { 1129 // Half relocations steal a bit from the length field to encode 1130 // whether this is an upper16 or a lower16 relocation. 1131 bool isUpper = getAnyRelocationLength(RE) >> 1; 1132 1133 if (isUpper) 1134 fmt << ":upper16:("; 1135 else 1136 fmt << ":lower16:("; 1137 printRelocationTargetName(this, RE, fmt); 1138 1139 DataRefImpl RelNext = Rel; 1140 RelNext.d.a++; 1141 MachO::any_relocation_info RENext = getRelocation(RelNext); 1142 1143 // ARM half relocs must be followed by a relocation of type 1144 // ARM_RELOC_PAIR. 1145 unsigned RType = getAnyRelocationType(RENext); 1146 if (RType != MachO::ARM_RELOC_PAIR) 1147 report_fatal_error("Expected ARM_RELOC_PAIR after " 1148 "ARM_RELOC_HALF"); 1149 1150 // NOTE: The half of the target virtual address is stashed in the 1151 // address field of the secondary relocation, but we can't reverse 1152 // engineer the constant offset from it without decoding the movw/movt 1153 // instruction to find the other half in its immediate field. 1154 1155 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1156 // symbol/section pointer of the follow-on relocation. 1157 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1158 fmt << "-"; 1159 printRelocationTargetName(this, RENext, fmt); 1160 } 1161 1162 fmt << ")"; 1163 break; 1164 } 1165 default: { 1166 printRelocationTargetName(this, RE, fmt); 1167 } 1168 } 1169 } 1170 } else 1171 printRelocationTargetName(this, RE, fmt); 1172 1173 fmt.flush(); 1174 Result.append(fmtbuf.begin(), fmtbuf.end()); 1175 return object_error::success; 1176 } 1177 1178 error_code 1179 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { 1180 unsigned Arch = getArch(); 1181 uint64_t Type; 1182 getRelocationType(Rel, Type); 1183 1184 Result = false; 1185 1186 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1187 // is always hidden. 1188 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 1189 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 1190 } else if (Arch == Triple::x86_64) { 1191 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1192 // an X86_64_RELOC_SUBTRACTOR. 1193 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1194 DataRefImpl RelPrev = Rel; 1195 RelPrev.d.a--; 1196 uint64_t PrevType; 1197 getRelocationType(RelPrev, PrevType); 1198 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1199 Result = true; 1200 } 1201 } 1202 1203 return object_error::success; 1204 } 1205 1206 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1207 LibraryRef &Res) const { 1208 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1209 } 1210 1211 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1212 StringRef &Res) const { 1213 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1214 } 1215 1216 symbol_iterator MachOObjectFile::begin_symbols() const { 1217 DataRefImpl DRI; 1218 if (!SymtabLoadCmd) 1219 return symbol_iterator(SymbolRef(DRI, this)); 1220 1221 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1222 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1223 return symbol_iterator(SymbolRef(DRI, this)); 1224 } 1225 1226 symbol_iterator MachOObjectFile::end_symbols() const { 1227 DataRefImpl DRI; 1228 if (!SymtabLoadCmd) 1229 return symbol_iterator(SymbolRef(DRI, this)); 1230 1231 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1232 unsigned SymbolTableEntrySize = is64Bit() ? 1233 sizeof(MachO::nlist_64) : 1234 sizeof(MachO::nlist); 1235 unsigned Offset = Symtab.symoff + 1236 Symtab.nsyms * SymbolTableEntrySize; 1237 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1238 return symbol_iterator(SymbolRef(DRI, this)); 1239 } 1240 1241 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { 1242 // TODO: implement 1243 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 1244 } 1245 1246 symbol_iterator MachOObjectFile::end_dynamic_symbols() const { 1247 // TODO: implement 1248 report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); 1249 } 1250 1251 section_iterator MachOObjectFile::begin_sections() const { 1252 DataRefImpl DRI; 1253 return section_iterator(SectionRef(DRI, this)); 1254 } 1255 1256 section_iterator MachOObjectFile::end_sections() const { 1257 DataRefImpl DRI; 1258 DRI.d.a = Sections.size(); 1259 return section_iterator(SectionRef(DRI, this)); 1260 } 1261 1262 library_iterator MachOObjectFile::begin_libraries_needed() const { 1263 // TODO: implement 1264 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1265 } 1266 1267 library_iterator MachOObjectFile::end_libraries_needed() const { 1268 // TODO: implement 1269 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1270 } 1271 1272 uint8_t MachOObjectFile::getBytesInAddress() const { 1273 return is64Bit() ? 8 : 4; 1274 } 1275 1276 StringRef MachOObjectFile::getFileFormatName() const { 1277 unsigned CPUType = getCPUType(this); 1278 if (!is64Bit()) { 1279 switch (CPUType) { 1280 case llvm::MachO::CPU_TYPE_I386: 1281 return "Mach-O 32-bit i386"; 1282 case llvm::MachO::CPU_TYPE_ARM: 1283 return "Mach-O arm"; 1284 case llvm::MachO::CPU_TYPE_POWERPC: 1285 return "Mach-O 32-bit ppc"; 1286 default: 1287 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1288 "64-bit object file when we're not 64-bit?"); 1289 return "Mach-O 32-bit unknown"; 1290 } 1291 } 1292 1293 // Make sure the cpu type has the correct mask. 1294 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1295 == llvm::MachO::CPU_ARCH_ABI64 && 1296 "32-bit object file when we're 64-bit?"); 1297 1298 switch (CPUType) { 1299 case llvm::MachO::CPU_TYPE_X86_64: 1300 return "Mach-O 64-bit x86-64"; 1301 case llvm::MachO::CPU_TYPE_POWERPC64: 1302 return "Mach-O 64-bit ppc64"; 1303 default: 1304 return "Mach-O 64-bit unknown"; 1305 } 1306 } 1307 1308 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1309 switch (CPUType) { 1310 case llvm::MachO::CPU_TYPE_I386: 1311 return Triple::x86; 1312 case llvm::MachO::CPU_TYPE_X86_64: 1313 return Triple::x86_64; 1314 case llvm::MachO::CPU_TYPE_ARM: 1315 return Triple::arm; 1316 case llvm::MachO::CPU_TYPE_POWERPC: 1317 return Triple::ppc; 1318 case llvm::MachO::CPU_TYPE_POWERPC64: 1319 return Triple::ppc64; 1320 default: 1321 return Triple::UnknownArch; 1322 } 1323 } 1324 1325 unsigned MachOObjectFile::getArch() const { 1326 return getArch(getCPUType(this)); 1327 } 1328 1329 StringRef MachOObjectFile::getLoadName() const { 1330 // TODO: Implement 1331 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1332 } 1333 1334 relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const { 1335 DataRefImpl DRI; 1336 DRI.d.a = Index; 1337 return getSectionRelBegin(DRI); 1338 } 1339 1340 relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const { 1341 DataRefImpl DRI; 1342 DRI.d.a = Index; 1343 return getSectionRelEnd(DRI); 1344 } 1345 1346 dice_iterator MachOObjectFile::begin_dices() const { 1347 DataRefImpl DRI; 1348 if (!DataInCodeLoadCmd) 1349 return dice_iterator(DiceRef(DRI, this)); 1350 1351 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1352 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1353 return dice_iterator(DiceRef(DRI, this)); 1354 } 1355 1356 dice_iterator MachOObjectFile::end_dices() const { 1357 DataRefImpl DRI; 1358 if (!DataInCodeLoadCmd) 1359 return dice_iterator(DiceRef(DRI, this)); 1360 1361 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1362 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1363 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1364 return dice_iterator(DiceRef(DRI, this)); 1365 } 1366 1367 StringRef 1368 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1369 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1370 return parseSegmentOrSectionName(Raw.data()); 1371 } 1372 1373 ArrayRef<char> 1374 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1375 const section_base *Base = 1376 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1377 return ArrayRef<char>(Base->sectname); 1378 } 1379 1380 ArrayRef<char> 1381 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1382 const section_base *Base = 1383 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1384 return ArrayRef<char>(Base->segname); 1385 } 1386 1387 bool 1388 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1389 const { 1390 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1391 return false; 1392 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1393 } 1394 1395 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1396 const MachO::any_relocation_info &RE) const { 1397 if (isLittleEndian()) 1398 return RE.r_word1 & 0xffffff; 1399 return RE.r_word1 >> 8; 1400 } 1401 1402 bool MachOObjectFile::getPlainRelocationExternal( 1403 const MachO::any_relocation_info &RE) const { 1404 if (isLittleEndian()) 1405 return (RE.r_word1 >> 27) & 1; 1406 return (RE.r_word1 >> 4) & 1; 1407 } 1408 1409 bool MachOObjectFile::getScatteredRelocationScattered( 1410 const MachO::any_relocation_info &RE) const { 1411 return RE.r_word0 >> 31; 1412 } 1413 1414 uint32_t MachOObjectFile::getScatteredRelocationValue( 1415 const MachO::any_relocation_info &RE) const { 1416 return RE.r_word1; 1417 } 1418 1419 unsigned MachOObjectFile::getAnyRelocationAddress( 1420 const MachO::any_relocation_info &RE) const { 1421 if (isRelocationScattered(RE)) 1422 return getScatteredRelocationAddress(RE); 1423 return getPlainRelocationAddress(RE); 1424 } 1425 1426 unsigned MachOObjectFile::getAnyRelocationPCRel( 1427 const MachO::any_relocation_info &RE) const { 1428 if (isRelocationScattered(RE)) 1429 return getScatteredRelocationPCRel(this, RE); 1430 return getPlainRelocationPCRel(this, RE); 1431 } 1432 1433 unsigned MachOObjectFile::getAnyRelocationLength( 1434 const MachO::any_relocation_info &RE) const { 1435 if (isRelocationScattered(RE)) 1436 return getScatteredRelocationLength(RE); 1437 return getPlainRelocationLength(this, RE); 1438 } 1439 1440 unsigned 1441 MachOObjectFile::getAnyRelocationType( 1442 const MachO::any_relocation_info &RE) const { 1443 if (isRelocationScattered(RE)) 1444 return getScatteredRelocationType(RE); 1445 return getPlainRelocationType(this, RE); 1446 } 1447 1448 SectionRef 1449 MachOObjectFile::getRelocationSection( 1450 const MachO::any_relocation_info &RE) const { 1451 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1452 return *end_sections(); 1453 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1454 DataRefImpl DRI; 1455 DRI.d.a = SecNum; 1456 return SectionRef(DRI, this); 1457 } 1458 1459 MachOObjectFile::LoadCommandInfo 1460 MachOObjectFile::getFirstLoadCommandInfo() const { 1461 MachOObjectFile::LoadCommandInfo Load; 1462 1463 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1464 sizeof(MachO::mach_header); 1465 Load.Ptr = getPtr(this, HeaderSize); 1466 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1467 return Load; 1468 } 1469 1470 MachOObjectFile::LoadCommandInfo 1471 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1472 MachOObjectFile::LoadCommandInfo Next; 1473 Next.Ptr = L.Ptr + L.C.cmdsize; 1474 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1475 return Next; 1476 } 1477 1478 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1479 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1480 } 1481 1482 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1483 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1484 } 1485 1486 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1487 unsigned Index) const { 1488 const char *Sec = getSectionPtr(this, L, Index); 1489 return getStruct<MachO::section>(this, Sec); 1490 } 1491 1492 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1493 unsigned Index) const { 1494 const char *Sec = getSectionPtr(this, L, Index); 1495 return getStruct<MachO::section_64>(this, Sec); 1496 } 1497 1498 MachO::nlist 1499 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1500 const char *P = reinterpret_cast<const char *>(DRI.p); 1501 return getStruct<MachO::nlist>(this, P); 1502 } 1503 1504 MachO::nlist_64 1505 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1506 const char *P = reinterpret_cast<const char *>(DRI.p); 1507 return getStruct<MachO::nlist_64>(this, P); 1508 } 1509 1510 MachO::linkedit_data_command 1511 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1512 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1513 } 1514 1515 MachO::segment_command 1516 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1517 return getStruct<MachO::segment_command>(this, L.Ptr); 1518 } 1519 1520 MachO::segment_command_64 1521 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1522 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1523 } 1524 1525 MachO::linker_options_command 1526 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1527 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1528 } 1529 1530 MachO::any_relocation_info 1531 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1532 const char *P = reinterpret_cast<const char *>(Rel.p); 1533 return getStruct<MachO::any_relocation_info>(this, P); 1534 } 1535 1536 MachO::data_in_code_entry 1537 MachOObjectFile::getDice(DataRefImpl Rel) const { 1538 const char *P = reinterpret_cast<const char *>(Rel.p); 1539 return getStruct<MachO::data_in_code_entry>(this, P); 1540 } 1541 1542 MachO::mach_header MachOObjectFile::getHeader() const { 1543 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1544 } 1545 1546 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1547 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1548 } 1549 1550 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1551 const MachO::dysymtab_command &DLC, 1552 unsigned Index) const { 1553 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1554 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1555 } 1556 1557 MachO::data_in_code_entry 1558 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1559 unsigned Index) const { 1560 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1561 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1562 } 1563 1564 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1565 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1566 } 1567 1568 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1569 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1570 } 1571 1572 MachO::linkedit_data_command 1573 MachOObjectFile::getDataInCodeLoadCommand() const { 1574 if (DataInCodeLoadCmd) 1575 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1576 1577 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1578 MachO::linkedit_data_command Cmd; 1579 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1580 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1581 Cmd.dataoff = 0; 1582 Cmd.datasize = 0; 1583 return Cmd; 1584 } 1585 1586 StringRef MachOObjectFile::getStringTableData() const { 1587 MachO::symtab_command S = getSymtabLoadCommand(); 1588 return getData().substr(S.stroff, S.strsize); 1589 } 1590 1591 bool MachOObjectFile::is64Bit() const { 1592 return getType() == getMachOType(false, true) || 1593 getType() == getMachOType(true, true); 1594 } 1595 1596 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1597 SmallVectorImpl<uint64_t> &Out) const { 1598 DataExtractor extractor(ObjectFile::getData(), true, 0); 1599 1600 uint32_t offset = Index; 1601 uint64_t data = 0; 1602 while (uint64_t delta = extractor.getULEB128(&offset)) { 1603 data += delta; 1604 Out.push_back(data); 1605 } 1606 } 1607 1608 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { 1609 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1610 error_code ec; 1611 OwningPtr<ObjectFile> Ret; 1612 if (Magic == "\xFE\xED\xFA\xCE") 1613 Ret.reset(new MachOObjectFile(Buffer, false, false, ec)); 1614 else if (Magic == "\xCE\xFA\xED\xFE") 1615 Ret.reset(new MachOObjectFile(Buffer, true, false, ec)); 1616 else if (Magic == "\xFE\xED\xFA\xCF") 1617 Ret.reset(new MachOObjectFile(Buffer, false, true, ec)); 1618 else if (Magic == "\xCF\xFA\xED\xFE") 1619 Ret.reset(new MachOObjectFile(Buffer, true, true, ec)); 1620 else { 1621 delete Buffer; 1622 return NULL; 1623 } 1624 1625 if (ec) 1626 return NULL; 1627 return Ret.take(); 1628 } 1629 1630 } // end namespace object 1631 } // end namespace llvm 1632