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