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