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