LLVM API Documentation

MachOObjectFile.cpp
Go to the documentation of this file.
00001 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the MachOObjectFile class, which binds the MachOObject
00011 // class to the generic ObjectFile wrapper.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Object/MachO.h"
00016 #include "llvm/ADT/Triple.h"
00017 #include "llvm/Object/MachOFormat.h"
00018 #include "llvm/Support/DataExtractor.h"
00019 #include "llvm/Support/Format.h"
00020 #include "llvm/Support/Host.h"
00021 #include "llvm/Support/MemoryBuffer.h"
00022 #include <cctype>
00023 #include <cstring>
00024 #include <limits>
00025 
00026 using namespace llvm;
00027 using namespace object;
00028 
00029 namespace llvm {
00030 namespace object {
00031 
00032 struct SymbolTableEntryBase {
00033   uint32_t StringIndex;
00034   uint8_t Type;
00035   uint8_t SectionIndex;
00036   uint16_t Flags;
00037 };
00038 
00039 struct SectionBase {
00040   char Name[16];
00041   char SegmentName[16];
00042 };
00043 
00044 template<typename T>
00045 static void SwapValue(T &Value) {
00046   Value = sys::SwapByteOrder(Value);
00047 }
00048 
00049 template<typename T>
00050 static void SwapStruct(T &Value);
00051 
00052 template<>
00053 void SwapStruct(macho::RelocationEntry &H) {
00054   SwapValue(H.Word0);
00055   SwapValue(H.Word1);
00056 }
00057 
00058 template<>
00059 void SwapStruct(macho::LoadCommand &L) {
00060   SwapValue(L.Type);
00061   SwapValue(L.Size);
00062 }
00063 
00064 template<>
00065 void SwapStruct(SymbolTableEntryBase &S) {
00066   SwapValue(S.StringIndex);
00067   SwapValue(S.Flags);
00068 }
00069 
00070 template<>
00071 void SwapStruct(macho::Section &S) {
00072   SwapValue(S.Address);
00073   SwapValue(S.Size);
00074   SwapValue(S.Offset);
00075   SwapValue(S.Align);
00076   SwapValue(S.RelocationTableOffset);
00077   SwapValue(S.NumRelocationTableEntries);
00078   SwapValue(S.Flags);
00079   SwapValue(S.Reserved1);
00080   SwapValue(S.Reserved2);
00081 }
00082 
00083 template<>
00084 void SwapStruct(macho::Section64 &S) {
00085   SwapValue(S.Address);
00086   SwapValue(S.Size);
00087   SwapValue(S.Offset);
00088   SwapValue(S.Align);
00089   SwapValue(S.RelocationTableOffset);
00090   SwapValue(S.NumRelocationTableEntries);
00091   SwapValue(S.Flags);
00092   SwapValue(S.Reserved1);
00093   SwapValue(S.Reserved2);
00094   SwapValue(S.Reserved3);
00095 }
00096 
00097 template<>
00098 void SwapStruct(macho::SymbolTableEntry &S) {
00099   SwapValue(S.StringIndex);
00100   SwapValue(S.Flags);
00101   SwapValue(S.Value);
00102 }
00103 
00104 template<>
00105 void SwapStruct(macho::Symbol64TableEntry &S) {
00106   SwapValue(S.StringIndex);
00107   SwapValue(S.Flags);
00108   SwapValue(S.Value);
00109 }
00110 
00111 template<>
00112 void SwapStruct(macho::Header &H) {
00113   SwapValue(H.Magic);
00114   SwapValue(H.CPUType);
00115   SwapValue(H.CPUSubtype);
00116   SwapValue(H.FileType);
00117   SwapValue(H.NumLoadCommands);
00118   SwapValue(H.SizeOfLoadCommands);
00119   SwapValue(H.Flags);
00120 }
00121 
00122 template<>
00123 void SwapStruct(macho::Header64Ext &E) {
00124   SwapValue(E.Reserved);
00125 }
00126 
00127 template<>
00128 void SwapStruct(macho::SymtabLoadCommand &C) {
00129   SwapValue(C.Type);
00130   SwapValue(C.Size);
00131   SwapValue(C.SymbolTableOffset);
00132   SwapValue(C.NumSymbolTableEntries);
00133   SwapValue(C.StringTableOffset);
00134   SwapValue(C.StringTableSize);
00135 }
00136 
00137 template<>
00138 void SwapStruct(macho::DysymtabLoadCommand &C) {
00139   SwapValue(C.Type);
00140   SwapValue(C.Size);
00141   SwapValue(C.LocalSymbolsIndex);
00142   SwapValue(C.NumLocalSymbols);
00143   SwapValue(C.ExternalSymbolsIndex);
00144   SwapValue(C.NumExternalSymbols);
00145   SwapValue(C.UndefinedSymbolsIndex);
00146   SwapValue(C.NumUndefinedSymbols);
00147   SwapValue(C.TOCOffset);
00148   SwapValue(C.NumTOCEntries);
00149   SwapValue(C.ModuleTableOffset);
00150   SwapValue(C.NumModuleTableEntries);
00151   SwapValue(C.ReferenceSymbolTableOffset);
00152   SwapValue(C.NumReferencedSymbolTableEntries);
00153   SwapValue(C.IndirectSymbolTableOffset);
00154   SwapValue(C.NumIndirectSymbolTableEntries);
00155   SwapValue(C.ExternalRelocationTableOffset);
00156   SwapValue(C.NumExternalRelocationTableEntries);
00157   SwapValue(C.LocalRelocationTableOffset);
00158   SwapValue(C.NumLocalRelocationTableEntries);
00159 }
00160 
00161 template<>
00162 void SwapStruct(macho::LinkeditDataLoadCommand &C) {
00163   SwapValue(C.Type);
00164   SwapValue(C.Size);
00165   SwapValue(C.DataOffset);
00166   SwapValue(C.DataSize);
00167 }
00168 
00169 template<>
00170 void SwapStruct(macho::SegmentLoadCommand &C) {
00171   SwapValue(C.Type);
00172   SwapValue(C.Size);
00173   SwapValue(C.VMAddress);
00174   SwapValue(C.VMSize);
00175   SwapValue(C.FileOffset);
00176   SwapValue(C.FileSize);
00177   SwapValue(C.MaxVMProtection);
00178   SwapValue(C.InitialVMProtection);
00179   SwapValue(C.NumSections);
00180   SwapValue(C.Flags);
00181 }
00182 
00183 template<>
00184 void SwapStruct(macho::Segment64LoadCommand &C) {
00185   SwapValue(C.Type);
00186   SwapValue(C.Size);
00187   SwapValue(C.VMAddress);
00188   SwapValue(C.VMSize);
00189   SwapValue(C.FileOffset);
00190   SwapValue(C.FileSize);
00191   SwapValue(C.MaxVMProtection);
00192   SwapValue(C.InitialVMProtection);
00193   SwapValue(C.NumSections);
00194   SwapValue(C.Flags);
00195 }
00196 
00197 template<>
00198 void SwapStruct(macho::IndirectSymbolTableEntry &C) {
00199   SwapValue(C.Index);
00200 }
00201 
00202 template<>
00203 void SwapStruct(macho::LinkerOptionsLoadCommand &C) {
00204   SwapValue(C.Type);
00205   SwapValue(C.Size);
00206   SwapValue(C.Count);
00207 }
00208 
00209 template<>
00210 void SwapStruct(macho::DataInCodeTableEntry &C) {
00211   SwapValue(C.Offset);
00212   SwapValue(C.Length);
00213   SwapValue(C.Kind);
00214 }
00215 
00216 template<typename T>
00217 T getStruct(const MachOObjectFile *O, const char *P) {
00218   T Cmd;
00219   memcpy(&Cmd, P, sizeof(T));
00220   if (O->isLittleEndian() != sys::IsLittleEndianHost)
00221     SwapStruct(Cmd);
00222   return Cmd;
00223 }
00224 
00225 static uint32_t
00226 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
00227                                  const MachOObjectFile::LoadCommandInfo &L) {
00228   if (O->is64Bit()) {
00229     macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
00230     return S.NumSections;
00231   }
00232   macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
00233   return S.NumSections;
00234 }
00235 
00236 static const char *
00237 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
00238               unsigned Sec) {
00239   uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
00240 
00241   bool Is64 = O->is64Bit();
00242   unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) :
00243                                     sizeof(macho::SegmentLoadCommand);
00244   unsigned SectionSize = Is64 ? sizeof(macho::Section64) :
00245                                 sizeof(macho::Section);
00246 
00247   uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
00248   return reinterpret_cast<const char*>(SectionAddr);
00249 }
00250 
00251 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
00252   return O->getData().substr(Offset, 1).data();
00253 }
00254 
00255 static SymbolTableEntryBase
00256 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {
00257   const char *P = reinterpret_cast<const char *>(DRI.p);
00258   return getStruct<SymbolTableEntryBase>(O, P);
00259 }
00260 
00261 static StringRef parseSegmentOrSectionName(const char *P) {
00262   if (P[15] == 0)
00263     // Null terminated.
00264     return P;
00265   // Not null terminated, so this is a 16 char string.
00266   return StringRef(P, 16);
00267 }
00268 
00269 // Helper to advance a section or symbol iterator multiple increments at a time.
00270 template<class T>
00271 static error_code advance(T &it, size_t Val) {
00272   error_code ec;
00273   while (Val--) {
00274     it.increment(ec);
00275   }
00276   return ec;
00277 }
00278 
00279 template<class T>
00280 static void advanceTo(T &it, size_t Val) {
00281   if (error_code ec = advance(it, Val))
00282     report_fatal_error(ec.message());
00283 }
00284 
00285 static unsigned getCPUType(const MachOObjectFile *O) {
00286   return O->getHeader().CPUType;
00287 }
00288 
00289 static void printRelocationTargetName(const MachOObjectFile *O,
00290                                       const macho::RelocationEntry &RE,
00291                                       raw_string_ostream &fmt) {
00292   bool IsScattered = O->isRelocationScattered(RE);
00293 
00294   // Target of a scattered relocation is an address.  In the interest of
00295   // generating pretty output, scan through the symbol table looking for a
00296   // symbol that aligns with that address.  If we find one, print it.
00297   // Otherwise, we just print the hex address of the target.
00298   if (IsScattered) {
00299     uint32_t Val = O->getPlainRelocationSymbolNum(RE);
00300 
00301     error_code ec;
00302     for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols();
00303          SI != SE; SI.increment(ec)) {
00304       if (ec) report_fatal_error(ec.message());
00305 
00306       uint64_t Addr;
00307       StringRef Name;
00308 
00309       if ((ec = SI->getAddress(Addr)))
00310         report_fatal_error(ec.message());
00311       if (Addr != Val) continue;
00312       if ((ec = SI->getName(Name)))
00313         report_fatal_error(ec.message());
00314       fmt << Name;
00315       return;
00316     }
00317 
00318     // If we couldn't find a symbol that this relocation refers to, try
00319     // to find a section beginning instead.
00320     for (section_iterator SI = O->begin_sections(), SE = O->end_sections();
00321          SI != SE; SI.increment(ec)) {
00322       if (ec) report_fatal_error(ec.message());
00323 
00324       uint64_t Addr;
00325       StringRef Name;
00326 
00327       if ((ec = SI->getAddress(Addr)))
00328         report_fatal_error(ec.message());
00329       if (Addr != Val) continue;
00330       if ((ec = SI->getName(Name)))
00331         report_fatal_error(ec.message());
00332       fmt << Name;
00333       return;
00334     }
00335 
00336     fmt << format("0x%x", Val);
00337     return;
00338   }
00339 
00340   StringRef S;
00341   bool isExtern = O->getPlainRelocationExternal(RE);
00342   uint64_t Val = O->getPlainRelocationSymbolNum(RE);
00343 
00344   if (isExtern) {
00345     symbol_iterator SI = O->begin_symbols();
00346     advanceTo(SI, Val);
00347     SI->getName(S);
00348   } else {
00349     section_iterator SI = O->begin_sections();
00350     // Adjust for the fact that sections are 1-indexed.
00351     advanceTo(SI, Val - 1);
00352     SI->getName(S);
00353   }
00354 
00355   fmt << S;
00356 }
00357 
00358 static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) {
00359   return RE.Word0;
00360 }
00361 
00362 static unsigned
00363 getScatteredRelocationAddress(const macho::RelocationEntry &RE) {
00364   return RE.Word0 & 0xffffff;
00365 }
00366 
00367 static bool getPlainRelocationPCRel(const MachOObjectFile *O,
00368                                     const macho::RelocationEntry &RE) {
00369   if (O->isLittleEndian())
00370     return (RE.Word1 >> 24) & 1;
00371   return (RE.Word1 >> 7) & 1;
00372 }
00373 
00374 static bool
00375 getScatteredRelocationPCRel(const MachOObjectFile *O,
00376                             const macho::RelocationEntry &RE) {
00377   return (RE.Word0 >> 30) & 1;
00378 }
00379 
00380 static unsigned getPlainRelocationLength(const MachOObjectFile *O,
00381                                          const macho::RelocationEntry &RE) {
00382   if (O->isLittleEndian())
00383     return (RE.Word1 >> 25) & 3;
00384   return (RE.Word1 >> 5) & 3;
00385 }
00386 
00387 static unsigned
00388 getScatteredRelocationLength(const macho::RelocationEntry &RE) {
00389   return (RE.Word0 >> 28) & 3;
00390 }
00391 
00392 static unsigned getPlainRelocationType(const MachOObjectFile *O,
00393                                        const macho::RelocationEntry &RE) {
00394   if (O->isLittleEndian())
00395     return RE.Word1 >> 28;
00396   return RE.Word1 & 0xf;
00397 }
00398 
00399 static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) {
00400   return (RE.Word0 >> 24) & 0xf;
00401 }
00402 
00403 static uint32_t getSectionFlags(const MachOObjectFile *O,
00404                                 DataRefImpl Sec) {
00405   if (O->is64Bit()) {
00406     macho::Section64 Sect = O->getSection64(Sec);
00407     return Sect.Flags;
00408   }
00409   macho::Section Sect = O->getSection(Sec);
00410   return Sect.Flags;
00411 }
00412 
00413 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
00414                                  bool IsLittleEndian, bool Is64bits,
00415                                  error_code &ec)
00416     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
00417       SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
00418   uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
00419   macho::LoadCommandType SegmentLoadType = is64Bit() ?
00420     macho::LCT_Segment64 : macho::LCT_Segment;
00421 
00422   MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo();
00423   for (unsigned I = 0; ; ++I) {
00424     if (Load.C.Type == macho::LCT_Symtab) {
00425       assert(!SymtabLoadCmd && "Multiple symbol tables");
00426       SymtabLoadCmd = Load.Ptr;
00427     } else if (Load.C.Type == macho::LCT_Dysymtab) {
00428       assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
00429       DysymtabLoadCmd = Load.Ptr;
00430     } else if (Load.C.Type == macho::LCT_DataInCode) {
00431       assert(!DataInCodeLoadCmd && "Multiple data in code tables");
00432       DataInCodeLoadCmd = Load.Ptr;
00433     } else if (Load.C.Type == SegmentLoadType) {
00434       uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
00435       for (unsigned J = 0; J < NumSections; ++J) {
00436         const char *Sec = getSectionPtr(this, Load, J);
00437         Sections.push_back(Sec);
00438       }
00439     }
00440 
00441     if (I == LoadCommandCount - 1)
00442       break;
00443     else
00444       Load = getNextLoadCommandInfo(Load);
00445   }
00446 }
00447 
00448 error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb,
00449                                           SymbolRef &Res) const {
00450   unsigned SymbolTableEntrySize = is64Bit() ?
00451     sizeof(macho::Symbol64TableEntry) :
00452     sizeof(macho::SymbolTableEntry);
00453   Symb.p += SymbolTableEntrySize;
00454   Res = SymbolRef(Symb, this);
00455   return object_error::success;
00456 }
00457 
00458 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
00459                                           StringRef &Res) const {
00460   StringRef StringTable = getStringTableData();
00461   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
00462   const char *Start = &StringTable.data()[Entry.StringIndex];
00463   Res = StringRef(Start);
00464   return object_error::success;
00465 }
00466 
00467 error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb,
00468                                              uint64_t &Res) const {
00469   if (is64Bit()) {
00470     macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb);
00471     Res = Entry.Value;
00472   } else {
00473     macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb);
00474     Res = Entry.Value;
00475   }
00476   return object_error::success;
00477 }
00478 
00479 error_code
00480 MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb,
00481                                      uint64_t &Res) const {
00482   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
00483   getSymbolAddress(Symb, Res);
00484   if (Entry.SectionIndex) {
00485     uint64_t Delta;
00486     DataRefImpl SecRel;
00487     SecRel.d.a = Entry.SectionIndex-1;
00488     if (is64Bit()) {
00489       macho::Section64 Sec = getSection64(SecRel);
00490       Delta = Sec.Offset - Sec.Address;
00491     } else {
00492       macho::Section Sec = getSection(SecRel);
00493       Delta = Sec.Offset - Sec.Address;
00494     }
00495 
00496     Res += Delta;
00497   }
00498 
00499   return object_error::success;
00500 }
00501 
00502 error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,
00503                                                uint32_t &Result) const {
00504   uint32_t flags;
00505   this->getSymbolFlags(DRI, flags);
00506   if (flags & SymbolRef::SF_Common) {
00507     SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
00508     Result = 1 << MachO::GET_COMM_ALIGN(Entry.Flags);
00509   } else {
00510     Result = 0;
00511   }
00512   return object_error::success;
00513 }
00514 
00515 error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
00516                                           uint64_t &Result) const {
00517   uint64_t BeginOffset;
00518   uint64_t EndOffset = 0;
00519   uint8_t SectionIndex;
00520 
00521   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
00522   uint64_t Value;
00523   getSymbolAddress(DRI, Value);
00524 
00525   BeginOffset = Value;
00526 
00527   SectionIndex = Entry.SectionIndex;
00528   if (!SectionIndex) {
00529     uint32_t flags = SymbolRef::SF_None;
00530     this->getSymbolFlags(DRI, flags);
00531     if (flags & SymbolRef::SF_Common)
00532       Result = Value;
00533     else
00534       Result = UnknownAddressOrSize;
00535     return object_error::success;
00536   }
00537   // Unfortunately symbols are unsorted so we need to touch all
00538   // symbols from load command
00539   error_code ec;
00540   for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E;
00541        I.increment(ec)) {
00542     DataRefImpl DRI = I->getRawDataRefImpl();
00543     Entry = getSymbolTableEntryBase(this, DRI);
00544     getSymbolAddress(DRI, Value);
00545     if (Entry.SectionIndex == SectionIndex && Value > BeginOffset)
00546       if (!EndOffset || Value < EndOffset)
00547         EndOffset = Value;
00548   }
00549   if (!EndOffset) {
00550     uint64_t Size;
00551     DataRefImpl Sec;
00552     Sec.d.a = SectionIndex-1;
00553     getSectionSize(Sec, Size);
00554     getSectionAddress(Sec, EndOffset);
00555     EndOffset += Size;
00556   }
00557   Result = EndOffset - BeginOffset;
00558   return object_error::success;
00559 }
00560 
00561 error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
00562                                           SymbolRef::Type &Res) const {
00563   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
00564   uint8_t n_type = Entry.Type;
00565 
00566   Res = SymbolRef::ST_Other;
00567 
00568   // If this is a STAB debugging symbol, we can do nothing more.
00569   if (n_type & MachO::NlistMaskStab) {
00570     Res = SymbolRef::ST_Debug;
00571     return object_error::success;
00572   }
00573 
00574   switch (n_type & MachO::NlistMaskType) {
00575     case MachO::NListTypeUndefined :
00576       Res = SymbolRef::ST_Unknown;
00577       break;
00578     case MachO::NListTypeSection :
00579       Res = SymbolRef::ST_Function;
00580       break;
00581   }
00582   return object_error::success;
00583 }
00584 
00585 error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
00586                                                 char &Res) const {
00587   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
00588   uint8_t Type = Entry.Type;
00589   uint16_t Flags = Entry.Flags;
00590 
00591   char Char;
00592   switch (Type & macho::STF_TypeMask) {
00593     case macho::STT_Undefined:
00594       Char = 'u';
00595       break;
00596     case macho::STT_Absolute:
00597     case macho::STT_Section:
00598       Char = 's';
00599       break;
00600     default:
00601       Char = '?';
00602       break;
00603   }
00604 
00605   if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
00606     Char = toupper(static_cast<unsigned char>(Char));
00607   Res = Char;
00608   return object_error::success;
00609 }
00610 
00611 error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,
00612                                            uint32_t &Result) const {
00613   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI);
00614 
00615   uint8_t MachOType = Entry.Type;
00616   uint16_t MachOFlags = Entry.Flags;
00617 
00618   // TODO: Correctly set SF_ThreadLocal
00619   Result = SymbolRef::SF_None;
00620 
00621   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined)
00622     Result |= SymbolRef::SF_Undefined;
00623 
00624   if (MachOFlags & macho::STF_StabsEntryMask)
00625     Result |= SymbolRef::SF_FormatSpecific;
00626 
00627   if (MachOType & MachO::NlistMaskExternal) {
00628     Result |= SymbolRef::SF_Global;
00629     if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) {
00630       uint64_t Value;
00631       getSymbolAddress(DRI, Value);
00632       if (Value)
00633         Result |= SymbolRef::SF_Common;
00634     }
00635   }
00636 
00637   if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef))
00638     Result |= SymbolRef::SF_Weak;
00639 
00640   if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute)
00641     Result |= SymbolRef::SF_Absolute;
00642 
00643   return object_error::success;
00644 }
00645 
00646 error_code
00647 MachOObjectFile::getSymbolSection(DataRefImpl Symb,
00648                                   section_iterator &Res) const {
00649   SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
00650   uint8_t index = Entry.SectionIndex;
00651 
00652   if (index == 0) {
00653     Res = end_sections();
00654   } else {
00655     DataRefImpl DRI;
00656     DRI.d.a = index - 1;
00657     Res = section_iterator(SectionRef(DRI, this));
00658   }
00659 
00660   return object_error::success;
00661 }
00662 
00663 error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb,
00664                                            uint64_t &Val) const {
00665   report_fatal_error("getSymbolValue unimplemented in MachOObjectFile");
00666 }
00667 
00668 error_code MachOObjectFile::getSectionNext(DataRefImpl Sec,
00669                                            SectionRef &Res) const {
00670   Sec.d.a++;
00671   Res = SectionRef(Sec, this);
00672   return object_error::success;
00673 }
00674 
00675 error_code
00676 MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const {
00677   ArrayRef<char> Raw = getSectionRawName(Sec);
00678   Result = parseSegmentOrSectionName(Raw.data());
00679   return object_error::success;
00680 }
00681 
00682 error_code
00683 MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {
00684   if (is64Bit()) {
00685     macho::Section64 Sect = getSection64(Sec);
00686     Res = Sect.Address;
00687   } else {
00688     macho::Section Sect = getSection(Sec);
00689     Res = Sect.Address;
00690   }
00691   return object_error::success;
00692 }
00693 
00694 error_code
00695 MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {
00696   if (is64Bit()) {
00697     macho::Section64 Sect = getSection64(Sec);
00698     Res = Sect.Size;
00699   } else {
00700     macho::Section Sect = getSection(Sec);
00701     Res = Sect.Size;
00702   }
00703 
00704   return object_error::success;
00705 }
00706 
00707 error_code
00708 MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {
00709   uint32_t Offset;
00710   uint64_t Size;
00711 
00712   if (is64Bit()) {
00713     macho::Section64 Sect = getSection64(Sec);
00714     Offset = Sect.Offset;
00715     Size = Sect.Size;
00716   } else {
00717     macho::Section Sect =getSection(Sec);
00718     Offset = Sect.Offset;
00719     Size = Sect.Size;
00720   }
00721 
00722   Res = this->getData().substr(Offset, Size);
00723   return object_error::success;
00724 }
00725 
00726 error_code
00727 MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {
00728   uint32_t Align;
00729   if (is64Bit()) {
00730     macho::Section64 Sect = getSection64(Sec);
00731     Align = Sect.Align;
00732   } else {
00733     macho::Section Sect = getSection(Sec);
00734     Align = Sect.Align;
00735   }
00736 
00737   Res = uint64_t(1) << Align;
00738   return object_error::success;
00739 }
00740 
00741 error_code
00742 MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const {
00743   uint32_t Flags = getSectionFlags(this, Sec);
00744   Res = Flags & macho::SF_PureInstructions;
00745   return object_error::success;
00746 }
00747 
00748 error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const {
00749   // FIXME: Unimplemented.
00750   Result = false;
00751   return object_error::success;
00752 }
00753 
00754 error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const {
00755   // FIXME: Unimplemented.
00756   Result = false;
00757   return object_error::success;
00758 }
00759 
00760 error_code
00761 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
00762                                                bool &Result) const {
00763   // FIXME: Unimplemented.
00764   Result = true;
00765   return object_error::success;
00766 }
00767 
00768 error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
00769                                              bool &Result) const {
00770   // FIXME: Unimplemented.
00771   Result = false;
00772   return object_error::success;
00773 }
00774 
00775 error_code
00776 MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {
00777   uint32_t Flags = getSectionFlags(this, Sec);
00778   unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType;
00779   Res = SectionType == MachO::SectionTypeZeroFill ||
00780     SectionType == MachO::SectionTypeZeroFillLarge;
00781   return object_error::success;
00782 }
00783 
00784 error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
00785                                                   bool &Result) const {
00786   // Consider using the code from isSectionText to look for __const sections.
00787   // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
00788   // to use section attributes to distinguish code from data.
00789 
00790   // FIXME: Unimplemented.
00791   Result = false;
00792   return object_error::success;
00793 }
00794 
00795 error_code
00796 MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
00797                                        bool &Result) const {
00798   SymbolRef::Type ST;
00799   this->getSymbolType(Symb, ST);
00800   if (ST == SymbolRef::ST_Unknown) {
00801     Result = false;
00802     return object_error::success;
00803   }
00804 
00805   uint64_t SectBegin, SectEnd;
00806   getSectionAddress(Sec, SectBegin);
00807   getSectionSize(Sec, SectEnd);
00808   SectEnd += SectBegin;
00809 
00810   uint64_t SymAddr;
00811   getSymbolAddress(Symb, SymAddr);
00812   Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
00813 
00814   return object_error::success;
00815 }
00816 
00817 relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
00818   uint32_t Offset;
00819   if (is64Bit()) {
00820     macho::Section64 Sect = getSection64(Sec);
00821     Offset = Sect.RelocationTableOffset;
00822   } else {
00823     macho::Section Sect = getSection(Sec);
00824     Offset = Sect.RelocationTableOffset;
00825   }
00826 
00827   DataRefImpl Ret;
00828   Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
00829   return relocation_iterator(RelocationRef(Ret, this));
00830 }
00831 
00832 relocation_iterator
00833 MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
00834   uint32_t Offset;
00835   uint32_t Num;
00836   if (is64Bit()) {
00837     macho::Section64 Sect = getSection64(Sec);
00838     Offset = Sect.RelocationTableOffset;
00839     Num = Sect.NumRelocationTableEntries;
00840   } else {
00841     macho::Section Sect = getSection(Sec);
00842     Offset = Sect.RelocationTableOffset;
00843     Num = Sect.NumRelocationTableEntries;
00844   }
00845 
00846   const macho::RelocationEntry *P =
00847     reinterpret_cast<const macho::RelocationEntry*>(getPtr(this, Offset));
00848 
00849   DataRefImpl Ret;
00850   Ret.p = reinterpret_cast<uintptr_t>(P + Num);
00851   return relocation_iterator(RelocationRef(Ret, this));
00852 }
00853 
00854 error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
00855                                               RelocationRef &Res) const {
00856   const macho::RelocationEntry *P =
00857     reinterpret_cast<const macho::RelocationEntry *>(Rel.p);
00858   Rel.p = reinterpret_cast<uintptr_t>(P + 1);
00859   Res = RelocationRef(Rel, this);
00860   return object_error::success;
00861 }
00862 
00863 error_code
00864 MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const {
00865   report_fatal_error("getRelocationAddress not implemented in MachOObjectFile");
00866 }
00867 
00868 error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,
00869                                                 uint64_t &Res) const {
00870   macho::RelocationEntry RE = getRelocation(Rel);
00871   Res = getAnyRelocationAddress(RE);
00872   return object_error::success;
00873 }
00874 
00875 symbol_iterator
00876 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
00877   macho::RelocationEntry RE = getRelocation(Rel);
00878   uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
00879   bool isExtern = getPlainRelocationExternal(RE);
00880   if (!isExtern)
00881     return end_symbols();
00882 
00883   macho::SymtabLoadCommand S = getSymtabLoadCommand();
00884   unsigned SymbolTableEntrySize = is64Bit() ?
00885     sizeof(macho::Symbol64TableEntry) :
00886     sizeof(macho::SymbolTableEntry);
00887   uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize;
00888   DataRefImpl Sym;
00889   Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
00890   return symbol_iterator(SymbolRef(Sym, this));
00891 }
00892 
00893 error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
00894                                               uint64_t &Res) const {
00895   macho::RelocationEntry RE = getRelocation(Rel);
00896   Res = getAnyRelocationType(RE);
00897   return object_error::success;
00898 }
00899 
00900 error_code
00901 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
00902                                        SmallVectorImpl<char> &Result) const {
00903   StringRef res;
00904   uint64_t RType;
00905   getRelocationType(Rel, RType);
00906 
00907   unsigned Arch = this->getArch();
00908 
00909   switch (Arch) {
00910     case Triple::x86: {
00911       static const char *const Table[] =  {
00912         "GENERIC_RELOC_VANILLA",
00913         "GENERIC_RELOC_PAIR",
00914         "GENERIC_RELOC_SECTDIFF",
00915         "GENERIC_RELOC_PB_LA_PTR",
00916         "GENERIC_RELOC_LOCAL_SECTDIFF",
00917         "GENERIC_RELOC_TLV" };
00918 
00919       if (RType > 6)
00920         res = "Unknown";
00921       else
00922         res = Table[RType];
00923       break;
00924     }
00925     case Triple::x86_64: {
00926       static const char *const Table[] =  {
00927         "X86_64_RELOC_UNSIGNED",
00928         "X86_64_RELOC_SIGNED",
00929         "X86_64_RELOC_BRANCH",
00930         "X86_64_RELOC_GOT_LOAD",
00931         "X86_64_RELOC_GOT",
00932         "X86_64_RELOC_SUBTRACTOR",
00933         "X86_64_RELOC_SIGNED_1",
00934         "X86_64_RELOC_SIGNED_2",
00935         "X86_64_RELOC_SIGNED_4",
00936         "X86_64_RELOC_TLV" };
00937 
00938       if (RType > 9)
00939         res = "Unknown";
00940       else
00941         res = Table[RType];
00942       break;
00943     }
00944     case Triple::arm: {
00945       static const char *const Table[] =  {
00946         "ARM_RELOC_VANILLA",
00947         "ARM_RELOC_PAIR",
00948         "ARM_RELOC_SECTDIFF",
00949         "ARM_RELOC_LOCAL_SECTDIFF",
00950         "ARM_RELOC_PB_LA_PTR",
00951         "ARM_RELOC_BR24",
00952         "ARM_THUMB_RELOC_BR22",
00953         "ARM_THUMB_32BIT_BRANCH",
00954         "ARM_RELOC_HALF",
00955         "ARM_RELOC_HALF_SECTDIFF" };
00956 
00957       if (RType > 9)
00958         res = "Unknown";
00959       else
00960         res = Table[RType];
00961       break;
00962     }
00963     case Triple::ppc: {
00964       static const char *const Table[] =  {
00965         "PPC_RELOC_VANILLA",
00966         "PPC_RELOC_PAIR",
00967         "PPC_RELOC_BR14",
00968         "PPC_RELOC_BR24",
00969         "PPC_RELOC_HI16",
00970         "PPC_RELOC_LO16",
00971         "PPC_RELOC_HA16",
00972         "PPC_RELOC_LO14",
00973         "PPC_RELOC_SECTDIFF",
00974         "PPC_RELOC_PB_LA_PTR",
00975         "PPC_RELOC_HI16_SECTDIFF",
00976         "PPC_RELOC_LO16_SECTDIFF",
00977         "PPC_RELOC_HA16_SECTDIFF",
00978         "PPC_RELOC_JBSR",
00979         "PPC_RELOC_LO14_SECTDIFF",
00980         "PPC_RELOC_LOCAL_SECTDIFF" };
00981 
00982       res = Table[RType];
00983       break;
00984     }
00985     case Triple::UnknownArch:
00986       res = "Unknown";
00987       break;
00988   }
00989   Result.append(res.begin(), res.end());
00990   return object_error::success;
00991 }
00992 
00993 error_code
00994 MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
00995                                           SmallVectorImpl<char> &Result) const {
00996   macho::RelocationEntry RE = getRelocation(Rel);
00997 
00998   unsigned Arch = this->getArch();
00999 
01000   std::string fmtbuf;
01001   raw_string_ostream fmt(fmtbuf);
01002   unsigned Type = this->getAnyRelocationType(RE);
01003   bool IsPCRel = this->getAnyRelocationPCRel(RE);
01004 
01005   // Determine any addends that should be displayed with the relocation.
01006   // These require decoding the relocation type, which is triple-specific.
01007 
01008   // X86_64 has entirely custom relocation types.
01009   if (Arch == Triple::x86_64) {
01010     bool isPCRel = getAnyRelocationPCRel(RE);
01011 
01012     switch (Type) {
01013       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
01014       case macho::RIT_X86_64_GOT: {     // X86_64_RELOC_GOT
01015         printRelocationTargetName(this, RE, fmt);
01016         fmt << "@GOT";
01017         if (isPCRel) fmt << "PCREL";
01018         break;
01019       }
01020       case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR
01021         DataRefImpl RelNext = Rel;
01022         RelNext.d.a++;
01023         macho::RelocationEntry RENext = getRelocation(RelNext);
01024 
01025         // X86_64_SUBTRACTOR must be followed by a relocation of type
01026         // X86_64_RELOC_UNSIGNED.
01027         // NOTE: Scattered relocations don't exist on x86_64.
01028         unsigned RType = getAnyRelocationType(RENext);
01029         if (RType != 0)
01030           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
01031                              "X86_64_RELOC_SUBTRACTOR.");
01032 
01033         // The X86_64_RELOC_UNSIGNED contains the minuend symbol,
01034         // X86_64_SUBTRACTOR contains to the subtrahend.
01035         printRelocationTargetName(this, RENext, fmt);
01036         fmt << "-";
01037         printRelocationTargetName(this, RE, fmt);
01038         break;
01039       }
01040       case macho::RIT_X86_64_TLV:
01041         printRelocationTargetName(this, RE, fmt);
01042         fmt << "@TLV";
01043         if (isPCRel) fmt << "P";
01044         break;
01045       case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1
01046         printRelocationTargetName(this, RE, fmt);
01047         fmt << "-1";
01048         break;
01049       case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2
01050         printRelocationTargetName(this, RE, fmt);
01051         fmt << "-2";
01052         break;
01053       case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4
01054         printRelocationTargetName(this, RE, fmt);
01055         fmt << "-4";
01056         break;
01057       default:
01058         printRelocationTargetName(this, RE, fmt);
01059         break;
01060     }
01061   // X86 and ARM share some relocation types in common.
01062   } else if (Arch == Triple::x86 || Arch == Triple::arm) {
01063     // Generic relocation types...
01064     switch (Type) {
01065       case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info
01066         return object_error::success;
01067       case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF
01068         DataRefImpl RelNext = Rel;
01069         RelNext.d.a++;
01070         macho::RelocationEntry RENext = getRelocation(RelNext);
01071 
01072         // X86 sect diff's must be followed by a relocation of type
01073         // GENERIC_RELOC_PAIR.
01074         unsigned RType = getAnyRelocationType(RENext);
01075 
01076         if (RType != 1)
01077           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
01078                              "GENERIC_RELOC_SECTDIFF.");
01079 
01080         printRelocationTargetName(this, RE, fmt);
01081         fmt << "-";
01082         printRelocationTargetName(this, RENext, fmt);
01083         break;
01084       }
01085     }
01086 
01087     if (Arch == Triple::x86) {
01088       // All X86 relocations that need special printing were already
01089       // handled in the generic code.
01090       switch (Type) {
01091         case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF
01092           DataRefImpl RelNext = Rel;
01093           RelNext.d.a++;
01094           macho::RelocationEntry RENext = getRelocation(RelNext);
01095 
01096           // X86 sect diff's must be followed by a relocation of type
01097           // GENERIC_RELOC_PAIR.
01098           unsigned RType = getAnyRelocationType(RENext);
01099           if (RType != 1)
01100             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
01101                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
01102 
01103           printRelocationTargetName(this, RE, fmt);
01104           fmt << "-";
01105           printRelocationTargetName(this, RENext, fmt);
01106           break;
01107         }
01108         case macho::RIT_Generic_TLV: {
01109           printRelocationTargetName(this, RE, fmt);
01110           fmt << "@TLV";
01111           if (IsPCRel) fmt << "P";
01112           break;
01113         }
01114         default:
01115           printRelocationTargetName(this, RE, fmt);
01116       }
01117     } else { // ARM-specific relocations
01118       switch (Type) {
01119         case macho::RIT_ARM_Half:             // ARM_RELOC_HALF
01120         case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF
01121           // Half relocations steal a bit from the length field to encode
01122           // whether this is an upper16 or a lower16 relocation.
01123           bool isUpper = getAnyRelocationLength(RE) >> 1;
01124 
01125           if (isUpper)
01126             fmt << ":upper16:(";
01127           else
01128             fmt << ":lower16:(";
01129           printRelocationTargetName(this, RE, fmt);
01130 
01131           DataRefImpl RelNext = Rel;
01132           RelNext.d.a++;
01133           macho::RelocationEntry RENext = getRelocation(RelNext);
01134 
01135           // ARM half relocs must be followed by a relocation of type
01136           // ARM_RELOC_PAIR.
01137           unsigned RType = getAnyRelocationType(RENext);
01138           if (RType != 1)
01139             report_fatal_error("Expected ARM_RELOC_PAIR after "
01140                                "GENERIC_RELOC_HALF");
01141 
01142           // NOTE: The half of the target virtual address is stashed in the
01143           // address field of the secondary relocation, but we can't reverse
01144           // engineer the constant offset from it without decoding the movw/movt
01145           // instruction to find the other half in its immediate field.
01146 
01147           // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
01148           // symbol/section pointer of the follow-on relocation.
01149           if (Type == macho::RIT_ARM_HalfDifference) {
01150             fmt << "-";
01151             printRelocationTargetName(this, RENext, fmt);
01152           }
01153 
01154           fmt << ")";
01155           break;
01156         }
01157         default: {
01158           printRelocationTargetName(this, RE, fmt);
01159         }
01160       }
01161     }
01162   } else
01163     printRelocationTargetName(this, RE, fmt);
01164 
01165   fmt.flush();
01166   Result.append(fmtbuf.begin(), fmtbuf.end());
01167   return object_error::success;
01168 }
01169 
01170 error_code
01171 MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {
01172   unsigned Arch = getArch();
01173   uint64_t Type;
01174   getRelocationType(Rel, Type);
01175 
01176   Result = false;
01177 
01178   // On arches that use the generic relocations, GENERIC_RELOC_PAIR
01179   // is always hidden.
01180   if (Arch == Triple::x86 || Arch == Triple::arm) {
01181     if (Type == macho::RIT_Pair) Result = true;
01182   } else if (Arch == Triple::x86_64) {
01183     // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
01184     // an X864_64_RELOC_SUBTRACTOR.
01185     if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) {
01186       DataRefImpl RelPrev = Rel;
01187       RelPrev.d.a--;
01188       uint64_t PrevType;
01189       getRelocationType(RelPrev, PrevType);
01190       if (PrevType == macho::RIT_X86_64_Subtractor)
01191         Result = true;
01192     }
01193   }
01194 
01195   return object_error::success;
01196 }
01197 
01198 error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData,
01199                                            LibraryRef &Res) const {
01200   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
01201 }
01202 
01203 error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData,
01204                                            StringRef &Res) const {
01205   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
01206 }
01207 
01208 symbol_iterator MachOObjectFile::begin_symbols() const {
01209   DataRefImpl DRI;
01210   if (!SymtabLoadCmd)
01211     return symbol_iterator(SymbolRef(DRI, this));
01212 
01213   macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
01214   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.SymbolTableOffset));
01215   return symbol_iterator(SymbolRef(DRI, this));
01216 }
01217 
01218 symbol_iterator MachOObjectFile::end_symbols() const {
01219   DataRefImpl DRI;
01220   if (!SymtabLoadCmd)
01221     return symbol_iterator(SymbolRef(DRI, this));
01222 
01223   macho::SymtabLoadCommand Symtab = getSymtabLoadCommand();
01224   unsigned SymbolTableEntrySize = is64Bit() ?
01225     sizeof(macho::Symbol64TableEntry) :
01226     sizeof(macho::SymbolTableEntry);
01227   unsigned Offset = Symtab.SymbolTableOffset +
01228     Symtab.NumSymbolTableEntries * SymbolTableEntrySize;
01229   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
01230   return symbol_iterator(SymbolRef(DRI, this));
01231 }
01232 
01233 symbol_iterator MachOObjectFile::begin_dynamic_symbols() const {
01234   // TODO: implement
01235   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
01236 }
01237 
01238 symbol_iterator MachOObjectFile::end_dynamic_symbols() const {
01239   // TODO: implement
01240   report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile");
01241 }
01242 
01243 section_iterator MachOObjectFile::begin_sections() const {
01244   DataRefImpl DRI;
01245   return section_iterator(SectionRef(DRI, this));
01246 }
01247 
01248 section_iterator MachOObjectFile::end_sections() const {
01249   DataRefImpl DRI;
01250   DRI.d.a = Sections.size();
01251   return section_iterator(SectionRef(DRI, this));
01252 }
01253 
01254 library_iterator MachOObjectFile::begin_libraries_needed() const {
01255   // TODO: implement
01256   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
01257 }
01258 
01259 library_iterator MachOObjectFile::end_libraries_needed() const {
01260   // TODO: implement
01261   report_fatal_error("Needed libraries unimplemented in MachOObjectFile");
01262 }
01263 
01264 uint8_t MachOObjectFile::getBytesInAddress() const {
01265   return is64Bit() ? 8 : 4;
01266 }
01267 
01268 StringRef MachOObjectFile::getFileFormatName() const {
01269   unsigned CPUType = getCPUType(this);
01270   if (!is64Bit()) {
01271     switch (CPUType) {
01272     case llvm::MachO::CPUTypeI386:
01273       return "Mach-O 32-bit i386";
01274     case llvm::MachO::CPUTypeARM:
01275       return "Mach-O arm";
01276     case llvm::MachO::CPUTypePowerPC:
01277       return "Mach-O 32-bit ppc";
01278     default:
01279       assert((CPUType & llvm::MachO::CPUArchABI64) == 0 &&
01280              "64-bit object file when we're not 64-bit?");
01281       return "Mach-O 32-bit unknown";
01282     }
01283   }
01284 
01285   // Make sure the cpu type has the correct mask.
01286   assert((CPUType & llvm::MachO::CPUArchABI64)
01287    == llvm::MachO::CPUArchABI64 &&
01288    "32-bit object file when we're 64-bit?");
01289 
01290   switch (CPUType) {
01291   case llvm::MachO::CPUTypeX86_64:
01292     return "Mach-O 64-bit x86-64";
01293   case llvm::MachO::CPUTypePowerPC64:
01294     return "Mach-O 64-bit ppc64";
01295   default:
01296     return "Mach-O 64-bit unknown";
01297   }
01298 }
01299 
01300 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
01301   switch (CPUType) {
01302   case llvm::MachO::CPUTypeI386:
01303     return Triple::x86;
01304   case llvm::MachO::CPUTypeX86_64:
01305     return Triple::x86_64;
01306   case llvm::MachO::CPUTypeARM:
01307     return Triple::arm;
01308   case llvm::MachO::CPUTypePowerPC:
01309     return Triple::ppc;
01310   case llvm::MachO::CPUTypePowerPC64:
01311     return Triple::ppc64;
01312   default:
01313     return Triple::UnknownArch;
01314   }
01315 }
01316 
01317 unsigned MachOObjectFile::getArch() const {
01318   return getArch(getCPUType(this));
01319 }
01320 
01321 StringRef MachOObjectFile::getLoadName() const {
01322   // TODO: Implement
01323   report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
01324 }
01325 
01326 relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const {
01327   DataRefImpl DRI;
01328   DRI.d.a = Index;
01329   return getSectionRelBegin(DRI);
01330 }
01331 
01332 relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const {
01333   DataRefImpl DRI;
01334   DRI.d.a = Index;
01335   return getSectionRelEnd(DRI);
01336 }
01337 
01338 dice_iterator MachOObjectFile::begin_dices() const {
01339   DataRefImpl DRI;
01340   if (!DataInCodeLoadCmd)
01341     return dice_iterator(DiceRef(DRI, this));
01342 
01343   macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
01344   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.DataOffset));
01345   return dice_iterator(DiceRef(DRI, this));
01346 }
01347 
01348 dice_iterator MachOObjectFile::end_dices() const {
01349   DataRefImpl DRI;
01350   if (!DataInCodeLoadCmd)
01351     return dice_iterator(DiceRef(DRI, this));
01352 
01353   macho::LinkeditDataLoadCommand DicLC = getDataInCodeLoadCommand();
01354   unsigned Offset = DicLC.DataOffset + DicLC.DataSize;
01355   DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
01356   return dice_iterator(DiceRef(DRI, this));
01357 }
01358 
01359 StringRef
01360 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
01361   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
01362   return parseSegmentOrSectionName(Raw.data());
01363 }
01364 
01365 ArrayRef<char>
01366 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
01367   const SectionBase *Base =
01368     reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
01369   return ArrayRef<char>(Base->Name);
01370 }
01371 
01372 ArrayRef<char>
01373 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
01374   const SectionBase *Base =
01375     reinterpret_cast<const SectionBase*>(Sections[Sec.d.a]);
01376   return ArrayRef<char>(Base->SegmentName);
01377 }
01378 
01379 bool
01380 MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE)
01381   const {
01382   if (getCPUType(this) == llvm::MachO::CPUTypeX86_64)
01383     return false;
01384   return getPlainRelocationAddress(RE) & macho::RF_Scattered;
01385 }
01386 
01387 unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const {
01388   if (isLittleEndian())
01389     return RE.Word1 & 0xffffff;
01390   return RE.Word1 >> 8;
01391 }
01392 
01393 bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const {
01394   if (isLittleEndian())
01395     return (RE.Word1 >> 27) & 1;
01396   return (RE.Word1 >> 4) & 1;
01397 }
01398 
01399 bool
01400 MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const {
01401   return RE.Word0 >> 31;
01402 }
01403 
01404 uint32_t
01405 MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const {
01406   return RE.Word1;
01407 }
01408 
01409 unsigned
01410 MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const {
01411   if (isRelocationScattered(RE))
01412     return getScatteredRelocationAddress(RE);
01413   return getPlainRelocationAddress(RE);
01414 }
01415 
01416 unsigned
01417 MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const {
01418   if (isRelocationScattered(RE))
01419     return getScatteredRelocationPCRel(this, RE);
01420   return getPlainRelocationPCRel(this, RE);
01421 }
01422 
01423 unsigned
01424 MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const {
01425   if (isRelocationScattered(RE))
01426     return getScatteredRelocationLength(RE);
01427   return getPlainRelocationLength(this, RE);
01428 }
01429 
01430 unsigned
01431 MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const {
01432   if (isRelocationScattered(RE))
01433     return getScatteredRelocationType(RE);
01434   return getPlainRelocationType(this, RE);
01435 }
01436 
01437 SectionRef
01438 MachOObjectFile::getRelocationSection(const macho::RelocationEntry &RE) const {
01439   if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
01440     return *end_sections();
01441   unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;
01442   DataRefImpl DRI;
01443   DRI.d.a = SecNum;
01444   return SectionRef(DRI, this);
01445 }
01446 
01447 MachOObjectFile::LoadCommandInfo
01448 MachOObjectFile::getFirstLoadCommandInfo() const {
01449   MachOObjectFile::LoadCommandInfo Load;
01450 
01451   unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size;
01452   Load.Ptr = getPtr(this, HeaderSize);
01453   Load.C = getStruct<macho::LoadCommand>(this, Load.Ptr);
01454   return Load;
01455 }
01456 
01457 MachOObjectFile::LoadCommandInfo
01458 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
01459   MachOObjectFile::LoadCommandInfo Next;
01460   Next.Ptr = L.Ptr + L.C.Size;
01461   Next.C = getStruct<macho::LoadCommand>(this, Next.Ptr);
01462   return Next;
01463 }
01464 
01465 macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const {
01466   return getStruct<macho::Section>(this, Sections[DRI.d.a]);
01467 }
01468 
01469 macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
01470   return getStruct<macho::Section64>(this, Sections[DRI.d.a]);
01471 }
01472 
01473 macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L,
01474                                            unsigned Index) const {
01475   const char *Sec = getSectionPtr(this, L, Index);
01476   return getStruct<macho::Section>(this, Sec);
01477 }
01478 
01479 macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
01480                                                unsigned Index) const {
01481   const char *Sec = getSectionPtr(this, L, Index);
01482   return getStruct<macho::Section64>(this, Sec);
01483 }
01484 
01485 macho::SymbolTableEntry
01486 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
01487   const char *P = reinterpret_cast<const char *>(DRI.p);
01488   return getStruct<macho::SymbolTableEntry>(this, P);
01489 }
01490 
01491 macho::Symbol64TableEntry
01492 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
01493   const char *P = reinterpret_cast<const char *>(DRI.p);
01494   return getStruct<macho::Symbol64TableEntry>(this, P);
01495 }
01496 
01497 macho::LinkeditDataLoadCommand
01498 MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const {
01499   return getStruct<macho::LinkeditDataLoadCommand>(this, L.Ptr);
01500 }
01501 
01502 macho::SegmentLoadCommand
01503 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
01504   return getStruct<macho::SegmentLoadCommand>(this, L.Ptr);
01505 }
01506 
01507 macho::Segment64LoadCommand
01508 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
01509   return getStruct<macho::Segment64LoadCommand>(this, L.Ptr);
01510 }
01511 
01512 macho::LinkerOptionsLoadCommand
01513 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
01514   return getStruct<macho::LinkerOptionsLoadCommand>(this, L.Ptr);
01515 }
01516 
01517 macho::RelocationEntry
01518 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
01519   const char *P = reinterpret_cast<const char *>(Rel.p);
01520   return getStruct<macho::RelocationEntry>(this, P);
01521 }
01522 
01523 macho::DataInCodeTableEntry
01524 MachOObjectFile::getDice(DataRefImpl Rel) const {
01525   const char *P = reinterpret_cast<const char *>(Rel.p);
01526   return getStruct<macho::DataInCodeTableEntry>(this, P);
01527 }
01528 
01529 macho::Header MachOObjectFile::getHeader() const {
01530   return getStruct<macho::Header>(this, getPtr(this, 0));
01531 }
01532 
01533 macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
01534   return
01535     getStruct<macho::Header64Ext>(this, getPtr(this, sizeof(macho::Header)));
01536 }
01537 
01538 macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry(
01539                                           const macho::DysymtabLoadCommand &DLC,
01540                                           unsigned Index) const {
01541   uint64_t Offset = DLC.IndirectSymbolTableOffset +
01542     Index * sizeof(macho::IndirectSymbolTableEntry);
01543   return getStruct<macho::IndirectSymbolTableEntry>(this, getPtr(this, Offset));
01544 }
01545 
01546 macho::DataInCodeTableEntry
01547 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
01548                                          unsigned Index) const {
01549   uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry);
01550   return getStruct<macho::DataInCodeTableEntry>(this, getPtr(this, Offset));
01551 }
01552 
01553 macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const {
01554   return getStruct<macho::SymtabLoadCommand>(this, SymtabLoadCmd);
01555 }
01556 
01557 macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const {
01558   return getStruct<macho::DysymtabLoadCommand>(this, DysymtabLoadCmd);
01559 }
01560 
01561 macho::LinkeditDataLoadCommand
01562 MachOObjectFile::getDataInCodeLoadCommand() const {
01563   if (DataInCodeLoadCmd)
01564     return getStruct<macho::LinkeditDataLoadCommand>(this, DataInCodeLoadCmd);
01565 
01566   // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
01567   macho::LinkeditDataLoadCommand Cmd;
01568   Cmd.Type = macho::LCT_DataInCode;
01569   Cmd.Size = macho::LinkeditLoadCommandSize;
01570   Cmd.DataOffset = 0;
01571   Cmd.DataSize = 0;
01572   return Cmd;
01573 }
01574 
01575 StringRef MachOObjectFile::getStringTableData() const {
01576   macho::SymtabLoadCommand S = getSymtabLoadCommand();
01577   return getData().substr(S.StringTableOffset, S.StringTableSize);
01578 }
01579 
01580 bool MachOObjectFile::is64Bit() const {
01581   return getType() == getMachOType(false, true) ||
01582     getType() == getMachOType(true, true);
01583 }
01584 
01585 void MachOObjectFile::ReadULEB128s(uint64_t Index,
01586                                    SmallVectorImpl<uint64_t> &Out) const {
01587   DataExtractor extractor(ObjectFile::getData(), true, 0);
01588 
01589   uint32_t offset = Index;
01590   uint64_t data = 0;
01591   while (uint64_t delta = extractor.getULEB128(&offset)) {
01592     data += delta;
01593     Out.push_back(data);
01594   }
01595 }
01596 
01597 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
01598   StringRef Magic = Buffer->getBuffer().slice(0, 4);
01599   error_code ec;
01600   ObjectFile *Ret;
01601   if (Magic == "\xFE\xED\xFA\xCE")
01602     Ret = new MachOObjectFile(Buffer, false, false, ec);
01603   else if (Magic == "\xCE\xFA\xED\xFE")
01604     Ret = new MachOObjectFile(Buffer, true, false, ec);
01605   else if (Magic == "\xFE\xED\xFA\xCF")
01606     Ret = new MachOObjectFile(Buffer, false, true, ec);
01607   else if (Magic == "\xCF\xFA\xED\xFE")
01608     Ret = new MachOObjectFile(Buffer, true, true, ec);
01609   else
01610     return NULL;
01611 
01612   if (ec)
01613     return NULL;
01614   return Ret;
01615 }
01616 
01617 } // end namespace object
01618 } // end namespace llvm