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/MemoryBuffer.h"
     19 
     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::isMachO, Object, ec),
     33       MachOObj(MOO),
     34       RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
     35   DataRefImpl DRI;
     36   DRI.d.a = DRI.d.b = 0;
     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::getSymbolOffset(DataRefImpl DRI,
    128                                              uint64_t &Result) const {
    129   uint64_t SectionOffset;
    130   uint8_t SectionIndex;
    131   if (MachOObj->is64Bit()) {
    132     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    133     getSymbol64TableEntry(DRI, Entry);
    134     Result = Entry->Value;
    135     SectionIndex = Entry->SectionIndex;
    136   } else {
    137     InMemoryStruct<macho::SymbolTableEntry> Entry;
    138     getSymbolTableEntry(DRI, Entry);
    139     Result = Entry->Value;
    140     SectionIndex = Entry->SectionIndex;
    141   }
    142   getSectionAddress(Sections[SectionIndex-1], SectionOffset);
    143   Result -= SectionOffset;
    144 
    145   return object_error::success;
    146 }
    147 
    148 error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
    149                                              uint64_t &Result) const {
    150   if (MachOObj->is64Bit()) {
    151     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    152     getSymbol64TableEntry(DRI, Entry);
    153     Result = Entry->Value;
    154   } else {
    155     InMemoryStruct<macho::SymbolTableEntry> Entry;
    156     getSymbolTableEntry(DRI, Entry);
    157     Result = Entry->Value;
    158   }
    159   return object_error::success;
    160 }
    161 
    162 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
    163                                           uint64_t &Result) const {
    164   Result = UnknownAddressOrSize;
    165   return object_error::success;
    166 }
    167 
    168 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
    169                                                 char &Result) const {
    170   uint8_t Type, Flags;
    171   if (MachOObj->is64Bit()) {
    172     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    173     getSymbol64TableEntry(DRI, Entry);
    174     Type = Entry->Type;
    175     Flags = Entry->Flags;
    176   } else {
    177     InMemoryStruct<macho::SymbolTableEntry> Entry;
    178     getSymbolTableEntry(DRI, Entry);
    179     Type = Entry->Type;
    180     Flags = Entry->Flags;
    181   }
    182 
    183   char Char;
    184   switch (Type & macho::STF_TypeMask) {
    185     case macho::STT_Undefined:
    186       Char = 'u';
    187       break;
    188     case macho::STT_Absolute:
    189     case macho::STT_Section:
    190       Char = 's';
    191       break;
    192     default:
    193       Char = '?';
    194       break;
    195   }
    196 
    197   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
    198     Char = toupper(Char);
    199   Result = Char;
    200   return object_error::success;
    201 }
    202 
    203 error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
    204                                              bool &Result) const {
    205   if (MachOObj->is64Bit()) {
    206     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    207     getSymbol64TableEntry(DRI, Entry);
    208     Result = Entry->Flags & macho::STF_StabsEntryMask;
    209   } else {
    210     InMemoryStruct<macho::SymbolTableEntry> Entry;
    211     getSymbolTableEntry(DRI, Entry);
    212     Result = Entry->Flags & macho::STF_StabsEntryMask;
    213   }
    214   return object_error::success;
    215 }
    216 
    217 error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
    218 
    219   if (MachOObj->is64Bit()) {
    220     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    221     getSymbol64TableEntry(Symb, Entry);
    222     Res = Entry->Type & MachO::NlistMaskExternal;
    223   } else {
    224     InMemoryStruct<macho::SymbolTableEntry> Entry;
    225     getSymbolTableEntry(Symb, Entry);
    226     Res = Entry->Type & MachO::NlistMaskExternal;
    227   }
    228   return object_error::success;
    229 }
    230 
    231 error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
    232 
    233   if (MachOObj->is64Bit()) {
    234     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    235     getSymbol64TableEntry(Symb, Entry);
    236     Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
    237   } else {
    238     InMemoryStruct<macho::SymbolTableEntry> Entry;
    239     getSymbolTableEntry(Symb, Entry);
    240     Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
    241   }
    242   return object_error::success;
    243 }
    244 
    245 error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
    246   uint8_t n_type;
    247   if (MachOObj->is64Bit()) {
    248     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    249     getSymbol64TableEntry(Symb, Entry);
    250     n_type = Entry->Type;
    251   } else {
    252     InMemoryStruct<macho::SymbolTableEntry> Entry;
    253     getSymbolTableEntry(Symb, Entry);
    254     n_type = Entry->Type;
    255   }
    256 
    257   Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
    258   return object_error::success;
    259 }
    260 
    261 error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
    262                                              section_iterator &Res) const {
    263   uint8_t index;
    264   if (MachOObj->is64Bit()) {
    265     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    266     getSymbol64TableEntry(Symb, Entry);
    267     index = Entry->SectionIndex;
    268   } else {
    269     InMemoryStruct<macho::SymbolTableEntry> Entry;
    270     getSymbolTableEntry(Symb, Entry);
    271     index = Entry->SectionIndex;
    272   }
    273 
    274   if (index == 0)
    275     Res = end_sections();
    276   else
    277     Res = section_iterator(SectionRef(Sections[index], this));
    278 
    279   return object_error::success;
    280 }
    281 
    282 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
    283                                           SymbolRef::Type &Res) const {
    284   uint8_t n_type;
    285   if (MachOObj->is64Bit()) {
    286     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    287     getSymbol64TableEntry(Symb, Entry);
    288     n_type = Entry->Type;
    289   } else {
    290     InMemoryStruct<macho::SymbolTableEntry> Entry;
    291     getSymbolTableEntry(Symb, Entry);
    292     n_type = Entry->Type;
    293   }
    294   Res = SymbolRef::ST_Other;
    295 
    296   // If this is a STAB debugging symbol, we can do nothing more.
    297   if (n_type & MachO::NlistMaskStab)
    298     return object_error::success;
    299 
    300   switch (n_type & MachO::NlistMaskType) {
    301     case MachO::NListTypeUndefined :
    302       Res = SymbolRef::ST_External;
    303       break;
    304     case MachO::NListTypeSection :
    305       Res = SymbolRef::ST_Function;
    306       break;
    307   }
    308   return object_error::success;
    309 }
    310 
    311 
    312 symbol_iterator MachOObjectFile::begin_symbols() const {
    313   // DRI.d.a = segment number; DRI.d.b = symbol index.
    314   DataRefImpl DRI;
    315   DRI.d.a = DRI.d.b = 0;
    316   moveToNextSymbol(DRI);
    317   return symbol_iterator(SymbolRef(DRI, this));
    318 }
    319 
    320 symbol_iterator MachOObjectFile::end_symbols() const {
    321   DataRefImpl DRI;
    322   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
    323   DRI.d.b = 0;
    324   return symbol_iterator(SymbolRef(DRI, this));
    325 }
    326 
    327 
    328 /*===-- Sections ----------------------------------------------------------===*/
    329 
    330 void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
    331   uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
    332   while (DRI.d.a < LoadCommandCount) {
    333     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    334     if (LCI.Command.Type == macho::LCT_Segment) {
    335       InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
    336       MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
    337       if (DRI.d.b < SegmentLoadCmd->NumSections)
    338         return;
    339     } else if (LCI.Command.Type == macho::LCT_Segment64) {
    340       InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
    341       MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
    342       if (DRI.d.b < Segment64LoadCmd->NumSections)
    343         return;
    344     }
    345 
    346     DRI.d.a++;
    347     DRI.d.b = 0;
    348   }
    349 }
    350 
    351 error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
    352                                            SectionRef &Result) const {
    353   DRI.d.b++;
    354   moveToNextSection(DRI);
    355   Result = SectionRef(DRI, this);
    356   return object_error::success;
    357 }
    358 
    359 void
    360 MachOObjectFile::getSection(DataRefImpl DRI,
    361                             InMemoryStruct<macho::Section> &Res) const {
    362   InMemoryStruct<macho::SegmentLoadCommand> SLC;
    363   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    364   MachOObj->ReadSegmentLoadCommand(LCI, SLC);
    365   MachOObj->ReadSection(LCI, DRI.d.b, Res);
    366 }
    367 
    368 std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
    369   SectionList::const_iterator loc =
    370     std::find(Sections.begin(), Sections.end(), Sec);
    371   assert(loc != Sections.end() && "Sec is not a valid section!");
    372   return std::distance(Sections.begin(), loc);
    373 }
    374 
    375 void
    376 MachOObjectFile::getSection64(DataRefImpl DRI,
    377                             InMemoryStruct<macho::Section64> &Res) const {
    378   InMemoryStruct<macho::Segment64LoadCommand> SLC;
    379   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    380   MachOObj->ReadSegment64LoadCommand(LCI, SLC);
    381   MachOObj->ReadSection64(LCI, DRI.d.b, Res);
    382 }
    383 
    384 static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
    385   LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    386   if (LCI.Command.Type == macho::LCT_Segment64)
    387     return true;
    388   assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
    389   return false;
    390 }
    391 
    392 error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
    393                                            StringRef &Result) const {
    394   // FIXME: thread safety.
    395   static char result[34];
    396   if (is64BitLoadCommand(MachOObj, DRI)) {
    397     InMemoryStruct<macho::Segment64LoadCommand> SLC;
    398     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    399     MachOObj->ReadSegment64LoadCommand(LCI, SLC);
    400     InMemoryStruct<macho::Section64> Sect;
    401     MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
    402 
    403     strcpy(result, Sect->SegmentName);
    404     strcat(result, ",");
    405     strcat(result, Sect->Name);
    406   } else {
    407     InMemoryStruct<macho::SegmentLoadCommand> SLC;
    408     LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
    409     MachOObj->ReadSegmentLoadCommand(LCI, SLC);
    410     InMemoryStruct<macho::Section> Sect;
    411     MachOObj->ReadSection(LCI, DRI.d.b, Sect);
    412 
    413     strcpy(result, Sect->SegmentName);
    414     strcat(result, ",");
    415     strcat(result, Sect->Name);
    416   }
    417   Result = StringRef(result);
    418   return object_error::success;
    419 }
    420 
    421 error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
    422                                               uint64_t &Result) const {
    423   if (is64BitLoadCommand(MachOObj, DRI)) {
    424     InMemoryStruct<macho::Section64> Sect;
    425     getSection64(DRI, Sect);
    426     Result = Sect->Address;
    427   } else {
    428     InMemoryStruct<macho::Section> Sect;
    429     getSection(DRI, Sect);
    430     Result = Sect->Address;
    431   }
    432   return object_error::success;
    433 }
    434 
    435 error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
    436                                            uint64_t &Result) const {
    437   if (is64BitLoadCommand(MachOObj, DRI)) {
    438     InMemoryStruct<macho::Section64> Sect;
    439     getSection64(DRI, Sect);
    440     Result = Sect->Size;
    441   } else {
    442     InMemoryStruct<macho::Section> Sect;
    443     getSection(DRI, Sect);
    444     Result = Sect->Size;
    445   }
    446   return object_error::success;
    447 }
    448 
    449 error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
    450                                                StringRef &Result) const {
    451   if (is64BitLoadCommand(MachOObj, DRI)) {
    452     InMemoryStruct<macho::Section64> Sect;
    453     getSection64(DRI, Sect);
    454     Result = MachOObj->getData(Sect->Offset, Sect->Size);
    455   } else {
    456     InMemoryStruct<macho::Section> Sect;
    457     getSection(DRI, Sect);
    458     Result = MachOObj->getData(Sect->Offset, Sect->Size);
    459   }
    460   return object_error::success;
    461 }
    462 
    463 error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
    464                                                 uint64_t &Result) const {
    465   if (is64BitLoadCommand(MachOObj, DRI)) {
    466     InMemoryStruct<macho::Section64> Sect;
    467     getSection64(DRI, Sect);
    468     Result = uint64_t(1) << Sect->Align;
    469   } else {
    470     InMemoryStruct<macho::Section> Sect;
    471     getSection(DRI, Sect);
    472     Result = uint64_t(1) << Sect->Align;
    473   }
    474   return object_error::success;
    475 }
    476 
    477 error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
    478                                           bool &Result) const {
    479   if (is64BitLoadCommand(MachOObj, DRI)) {
    480     InMemoryStruct<macho::Section64> Sect;
    481     getSection64(DRI, Sect);
    482     Result = !strcmp(Sect->Name, "__text");
    483   } else {
    484     InMemoryStruct<macho::Section> Sect;
    485     getSection(DRI, Sect);
    486     Result = !strcmp(Sect->Name, "__text");
    487   }
    488   return object_error::success;
    489 }
    490 
    491 error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
    492                                           bool &Result) const {
    493   // FIXME: Unimplemented.
    494   Result = false;
    495   return object_error::success;
    496 }
    497 
    498 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
    499                                          bool &Result) const {
    500   // FIXME: Unimplemented.
    501   Result = false;
    502   return object_error::success;
    503 }
    504 
    505 error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
    506                                                   DataRefImpl Symb,
    507                                                   bool &Result) const {
    508   SymbolRef::Type ST;
    509   getSymbolType(Symb, ST);
    510   if (ST == SymbolRef::ST_External) {
    511     Result = false;
    512     return object_error::success;
    513   }
    514 
    515   uint64_t SectBegin, SectEnd;
    516   getSectionAddress(Sec, SectBegin);
    517   getSectionSize(Sec, SectEnd);
    518   SectEnd += SectBegin;
    519 
    520   if (MachOObj->is64Bit()) {
    521     InMemoryStruct<macho::Symbol64TableEntry> Entry;
    522     getSymbol64TableEntry(Symb, Entry);
    523     uint64_t SymAddr= Entry->Value;
    524     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
    525   } else {
    526     InMemoryStruct<macho::SymbolTableEntry> Entry;
    527     getSymbolTableEntry(Symb, Entry);
    528     uint64_t SymAddr= Entry->Value;
    529     Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
    530   }
    531 
    532   return object_error::success;
    533 }
    534 
    535 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
    536   DataRefImpl ret;
    537   ret.d.a = 0;
    538   ret.d.b = getSectionIndex(Sec);
    539   return relocation_iterator(RelocationRef(ret, this));
    540 }
    541 relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
    542   uint32_t last_reloc;
    543   if (is64BitLoadCommand(MachOObj, Sec)) {
    544     InMemoryStruct<macho::Section64> Sect;
    545     getSection64(Sec, Sect);
    546     last_reloc = Sect->NumRelocationTableEntries;
    547   } else {
    548     InMemoryStruct<macho::Section> Sect;
    549     getSection(Sec, Sect);
    550     last_reloc = Sect->NumRelocationTableEntries;
    551   }
    552   DataRefImpl ret;
    553   ret.d.a = last_reloc;
    554   ret.d.b = getSectionIndex(Sec);
    555   return relocation_iterator(RelocationRef(ret, this));
    556 }
    557 
    558 section_iterator MachOObjectFile::begin_sections() const {
    559   DataRefImpl DRI;
    560   DRI.d.a = DRI.d.b = 0;
    561   moveToNextSection(DRI);
    562   return section_iterator(SectionRef(DRI, this));
    563 }
    564 
    565 section_iterator MachOObjectFile::end_sections() const {
    566   DataRefImpl DRI;
    567   DRI.d.a = MachOObj->getHeader().NumLoadCommands;
    568   DRI.d.b = 0;
    569   return section_iterator(SectionRef(DRI, this));
    570 }
    571 
    572 /*===-- Relocations -------------------------------------------------------===*/
    573 
    574 void MachOObjectFile::
    575 getRelocation(DataRefImpl Rel,
    576               InMemoryStruct<macho::RelocationEntry> &Res) const {
    577   uint32_t relOffset;
    578   if (MachOObj->is64Bit()) {
    579     InMemoryStruct<macho::Section64> Sect;
    580     getSection64(Sections[Rel.d.b], Sect);
    581     relOffset = Sect->RelocationTableOffset;
    582   } else {
    583     InMemoryStruct<macho::Section> Sect;
    584     getSection(Sections[Rel.d.b], Sect);
    585     relOffset = Sect->RelocationTableOffset;
    586   }
    587   MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
    588 }
    589 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
    590                                               RelocationRef &Res) const {
    591   ++Rel.d.a;
    592   Res = RelocationRef(Rel, this);
    593   return object_error::success;
    594 }
    595 error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
    596                                                  uint64_t &Res) const {
    597   const uint8_t* sectAddress = base();
    598   if (MachOObj->is64Bit()) {
    599     InMemoryStruct<macho::Section64> Sect;
    600     getSection64(Sections[Rel.d.b], Sect);
    601     sectAddress += Sect->Offset;
    602   } else {
    603     InMemoryStruct<macho::Section> Sect;
    604     getSection(Sections[Rel.d.b], Sect);
    605     sectAddress += Sect->Offset;
    606   }
    607   InMemoryStruct<macho::RelocationEntry> RE;
    608   getRelocation(Rel, RE);
    609   Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
    610   return object_error::success;
    611 }
    612 error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
    613                                                 SymbolRef &Res) const {
    614   InMemoryStruct<macho::RelocationEntry> RE;
    615   getRelocation(Rel, RE);
    616   uint32_t SymbolIdx = RE->Word1 & 0xffffff;
    617   bool isExtern = (RE->Word1 >> 27) & 1;
    618 
    619   DataRefImpl Sym;
    620   Sym.d.a = Sym.d.b = 0;
    621   moveToNextSymbol(Sym);
    622   if (isExtern) {
    623     for (unsigned i = 0; i < SymbolIdx; i++) {
    624       Sym.d.b++;
    625       moveToNextSymbol(Sym);
    626       assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
    627              "Relocation symbol index out of range!");
    628     }
    629   }
    630   Res = SymbolRef(Sym, this);
    631   return object_error::success;
    632 }
    633 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
    634                                               uint32_t &Res) const {
    635   InMemoryStruct<macho::RelocationEntry> RE;
    636   getRelocation(Rel, RE);
    637   Res = RE->Word1;
    638   return object_error::success;
    639 }
    640 error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
    641                                           SmallVectorImpl<char> &Result) const {
    642   return object_error::success;
    643 }
    644 error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
    645                                                         int64_t &Res) const {
    646   InMemoryStruct<macho::RelocationEntry> RE;
    647   getRelocation(Rel, RE);
    648   bool isExtern = (RE->Word1 >> 27) & 1;
    649   Res = 0;
    650   if (!isExtern) {
    651     const uint8_t* sectAddress = base();
    652     if (MachOObj->is64Bit()) {
    653       InMemoryStruct<macho::Section64> Sect;
    654       getSection64(Sections[Rel.d.b], Sect);
    655       sectAddress += Sect->Offset;
    656     } else {
    657       InMemoryStruct<macho::Section> Sect;
    658       getSection(Sections[Rel.d.b], Sect);
    659       sectAddress += Sect->Offset;
    660     }
    661     Res = reinterpret_cast<uintptr_t>(sectAddress);
    662   }
    663   return object_error::success;
    664 }
    665 error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
    666                                           SmallVectorImpl<char> &Result) const {
    667   return object_error::success;
    668 }
    669 
    670 /*===-- Miscellaneous -----------------------------------------------------===*/
    671 
    672 uint8_t MachOObjectFile::getBytesInAddress() const {
    673   return MachOObj->is64Bit() ? 8 : 4;
    674 }
    675 
    676 StringRef MachOObjectFile::getFileFormatName() const {
    677   if (!MachOObj->is64Bit()) {
    678     switch (MachOObj->getHeader().CPUType) {
    679     case llvm::MachO::CPUTypeI386:
    680       return "Mach-O 32-bit i386";
    681     case llvm::MachO::CPUTypeARM:
    682       return "Mach-O arm";
    683     case llvm::MachO::CPUTypePowerPC:
    684       return "Mach-O 32-bit ppc";
    685     default:
    686       assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
    687              "64-bit object file when we're not 64-bit?");
    688       return "Mach-O 32-bit unknown";
    689     }
    690   }
    691 
    692   switch (MachOObj->getHeader().CPUType) {
    693   case llvm::MachO::CPUTypeX86_64:
    694     return "Mach-O 64-bit x86-64";
    695   case llvm::MachO::CPUTypePowerPC64:
    696     return "Mach-O 64-bit ppc64";
    697   default:
    698     assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
    699            "32-bit object file when we're 64-bit?");
    700     return "Mach-O 64-bit unknown";
    701   }
    702 }
    703 
    704 unsigned MachOObjectFile::getArch() const {
    705   switch (MachOObj->getHeader().CPUType) {
    706   case llvm::MachO::CPUTypeI386:
    707     return Triple::x86;
    708   case llvm::MachO::CPUTypeX86_64:
    709     return Triple::x86_64;
    710   case llvm::MachO::CPUTypeARM:
    711     return Triple::arm;
    712   case llvm::MachO::CPUTypePowerPC:
    713     return Triple::ppc;
    714   case llvm::MachO::CPUTypePowerPC64:
    715     return Triple::ppc64;
    716   default:
    717     return Triple::UnknownArch;
    718   }
    719 }
    720 
    721 } // end namespace object
    722 } // end namespace llvm
    723