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