13b0f4066SDimitry Andric //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 23b0f4066SDimitry Andric // 33b0f4066SDimitry Andric // The LLVM Compiler Infrastructure 43b0f4066SDimitry Andric // 53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source 63b0f4066SDimitry Andric // License. See LICENSE.TXT for details. 73b0f4066SDimitry Andric // 83b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 93b0f4066SDimitry Andric // 103b0f4066SDimitry Andric // This file defines the MachOObjectFile class, which binds the MachOObject 113b0f4066SDimitry Andric // class to the generic ObjectFile wrapper. 123b0f4066SDimitry Andric // 133b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 143b0f4066SDimitry Andric 156122f3e6SDimitry Andric #include "llvm/Object/MachO.h" 1691bc56edSDimitry Andric #include "llvm/ADT/STLExtras.h" 17139f7f9bSDimitry Andric #include "llvm/ADT/Triple.h" 18284c1978SDimitry Andric #include "llvm/Support/DataExtractor.h" 19dff0c46cSDimitry Andric #include "llvm/Support/Format.h" 20284c1978SDimitry Andric #include "llvm/Support/Host.h" 213b0f4066SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 22f785676fSDimitry Andric #include "llvm/Support/raw_ostream.h" 233b0f4066SDimitry Andric #include <cctype> 243b0f4066SDimitry Andric #include <cstring> 253b0f4066SDimitry Andric #include <limits> 263b0f4066SDimitry Andric 273b0f4066SDimitry Andric using namespace llvm; 283b0f4066SDimitry Andric using namespace object; 293b0f4066SDimitry Andric 3091bc56edSDimitry Andric namespace { 31f785676fSDimitry Andric struct section_base { 32f785676fSDimitry Andric char sectname[16]; 33f785676fSDimitry Andric char segname[16]; 34284c1978SDimitry Andric }; 356122f3e6SDimitry Andric } 363b0f4066SDimitry Andric 37284c1978SDimitry Andric template<typename T> 3891bc56edSDimitry Andric static T getStruct(const MachOObjectFile *O, const char *P) { 39284c1978SDimitry Andric T Cmd; 40284c1978SDimitry Andric memcpy(&Cmd, P, sizeof(T)); 41284c1978SDimitry Andric if (O->isLittleEndian() != sys::IsLittleEndianHost) 4291bc56edSDimitry Andric MachO::swapStruct(Cmd); 43284c1978SDimitry Andric return Cmd; 44284c1978SDimitry Andric } 45284c1978SDimitry Andric 46284c1978SDimitry Andric static uint32_t 47284c1978SDimitry Andric getSegmentLoadCommandNumSections(const MachOObjectFile *O, 48284c1978SDimitry Andric const MachOObjectFile::LoadCommandInfo &L) { 49284c1978SDimitry Andric if (O->is64Bit()) { 50f785676fSDimitry Andric MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 51f785676fSDimitry Andric return S.nsects; 52284c1978SDimitry Andric } 53f785676fSDimitry Andric MachO::segment_command S = O->getSegmentLoadCommand(L); 54f785676fSDimitry Andric return S.nsects; 55284c1978SDimitry Andric } 56284c1978SDimitry Andric 57284c1978SDimitry Andric static const char * 58284c1978SDimitry Andric getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 59284c1978SDimitry Andric unsigned Sec) { 60284c1978SDimitry Andric uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 61284c1978SDimitry Andric 62284c1978SDimitry Andric bool Is64 = O->is64Bit(); 63f785676fSDimitry Andric unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 64f785676fSDimitry Andric sizeof(MachO::segment_command); 65f785676fSDimitry Andric unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 66f785676fSDimitry Andric sizeof(MachO::section); 67284c1978SDimitry Andric 68284c1978SDimitry Andric uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 69284c1978SDimitry Andric return reinterpret_cast<const char*>(SectionAddr); 70284c1978SDimitry Andric } 71284c1978SDimitry Andric 72284c1978SDimitry Andric static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 73284c1978SDimitry Andric return O->getData().substr(Offset, 1).data(); 74284c1978SDimitry Andric } 75284c1978SDimitry Andric 7691bc56edSDimitry Andric static MachO::nlist_base 77284c1978SDimitry Andric getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 78284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p); 7991bc56edSDimitry Andric return getStruct<MachO::nlist_base>(O, P); 80284c1978SDimitry Andric } 81284c1978SDimitry Andric 82284c1978SDimitry Andric static StringRef parseSegmentOrSectionName(const char *P) { 83284c1978SDimitry Andric if (P[15] == 0) 84284c1978SDimitry Andric // Null terminated. 85284c1978SDimitry Andric return P; 86284c1978SDimitry Andric // Not null terminated, so this is a 16 char string. 87284c1978SDimitry Andric return StringRef(P, 16); 88284c1978SDimitry Andric } 89284c1978SDimitry Andric 90284c1978SDimitry Andric // Helper to advance a section or symbol iterator multiple increments at a time. 91284c1978SDimitry Andric template<class T> 9291bc56edSDimitry Andric static void advance(T &it, size_t Val) { 9391bc56edSDimitry Andric while (Val--) 9491bc56edSDimitry Andric ++it; 95284c1978SDimitry Andric } 963b0f4066SDimitry Andric 97284c1978SDimitry Andric static unsigned getCPUType(const MachOObjectFile *O) { 98f785676fSDimitry Andric return O->getHeader().cputype; 99284c1978SDimitry Andric } 100284c1978SDimitry Andric 101284c1978SDimitry Andric static void printRelocationTargetName(const MachOObjectFile *O, 102f785676fSDimitry Andric const MachO::any_relocation_info &RE, 103284c1978SDimitry Andric raw_string_ostream &fmt) { 104284c1978SDimitry Andric bool IsScattered = O->isRelocationScattered(RE); 105284c1978SDimitry Andric 106284c1978SDimitry Andric // Target of a scattered relocation is an address. In the interest of 107284c1978SDimitry Andric // generating pretty output, scan through the symbol table looking for a 108284c1978SDimitry Andric // symbol that aligns with that address. If we find one, print it. 109284c1978SDimitry Andric // Otherwise, we just print the hex address of the target. 110284c1978SDimitry Andric if (IsScattered) { 111284c1978SDimitry Andric uint32_t Val = O->getPlainRelocationSymbolNum(RE); 112284c1978SDimitry Andric 11391bc56edSDimitry Andric for (const SymbolRef &Symbol : O->symbols()) { 11491bc56edSDimitry Andric std::error_code ec; 115284c1978SDimitry Andric uint64_t Addr; 116284c1978SDimitry Andric StringRef Name; 117284c1978SDimitry Andric 11891bc56edSDimitry Andric if ((ec = Symbol.getAddress(Addr))) 119284c1978SDimitry Andric report_fatal_error(ec.message()); 12091bc56edSDimitry Andric if (Addr != Val) 12191bc56edSDimitry Andric continue; 12291bc56edSDimitry Andric if ((ec = Symbol.getName(Name))) 123284c1978SDimitry Andric report_fatal_error(ec.message()); 124284c1978SDimitry Andric fmt << Name; 1253b0f4066SDimitry Andric return; 1263b0f4066SDimitry Andric } 1273b0f4066SDimitry Andric 128284c1978SDimitry Andric // If we couldn't find a symbol that this relocation refers to, try 129284c1978SDimitry Andric // to find a section beginning instead. 13091bc56edSDimitry Andric for (const SectionRef &Section : O->sections()) { 13191bc56edSDimitry Andric std::error_code ec; 132284c1978SDimitry Andric uint64_t Addr; 133284c1978SDimitry Andric StringRef Name; 134284c1978SDimitry Andric 13591bc56edSDimitry Andric if ((ec = Section.getAddress(Addr))) 136284c1978SDimitry Andric report_fatal_error(ec.message()); 13791bc56edSDimitry Andric if (Addr != Val) 13891bc56edSDimitry Andric continue; 13991bc56edSDimitry Andric if ((ec = Section.getName(Name))) 140284c1978SDimitry Andric report_fatal_error(ec.message()); 141284c1978SDimitry Andric fmt << Name; 142284c1978SDimitry Andric return; 143284c1978SDimitry Andric } 144284c1978SDimitry Andric 145284c1978SDimitry Andric fmt << format("0x%x", Val); 146284c1978SDimitry Andric return; 147284c1978SDimitry Andric } 148284c1978SDimitry Andric 149284c1978SDimitry Andric StringRef S; 150284c1978SDimitry Andric bool isExtern = O->getPlainRelocationExternal(RE); 151f785676fSDimitry Andric uint64_t Val = O->getPlainRelocationSymbolNum(RE); 152284c1978SDimitry Andric 153284c1978SDimitry Andric if (isExtern) { 15491bc56edSDimitry Andric symbol_iterator SI = O->symbol_begin(); 15591bc56edSDimitry Andric advance(SI, Val); 156284c1978SDimitry Andric SI->getName(S); 157284c1978SDimitry Andric } else { 15891bc56edSDimitry Andric section_iterator SI = O->section_begin(); 159f785676fSDimitry Andric // Adjust for the fact that sections are 1-indexed. 16091bc56edSDimitry Andric advance(SI, Val - 1); 161284c1978SDimitry Andric SI->getName(S); 162284c1978SDimitry Andric } 163284c1978SDimitry Andric 164284c1978SDimitry Andric fmt << S; 165284c1978SDimitry Andric } 166284c1978SDimitry Andric 167f785676fSDimitry Andric static uint32_t 168f785676fSDimitry Andric getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 169f785676fSDimitry Andric return RE.r_word0; 170284c1978SDimitry Andric } 171284c1978SDimitry Andric 172284c1978SDimitry Andric static unsigned 173f785676fSDimitry Andric getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 174f785676fSDimitry Andric return RE.r_word0 & 0xffffff; 175284c1978SDimitry Andric } 176284c1978SDimitry Andric 177284c1978SDimitry Andric static bool getPlainRelocationPCRel(const MachOObjectFile *O, 178f785676fSDimitry Andric const MachO::any_relocation_info &RE) { 179284c1978SDimitry Andric if (O->isLittleEndian()) 180f785676fSDimitry Andric return (RE.r_word1 >> 24) & 1; 181f785676fSDimitry Andric return (RE.r_word1 >> 7) & 1; 182284c1978SDimitry Andric } 183284c1978SDimitry Andric 184284c1978SDimitry Andric static bool 185284c1978SDimitry Andric getScatteredRelocationPCRel(const MachOObjectFile *O, 186f785676fSDimitry Andric const MachO::any_relocation_info &RE) { 187f785676fSDimitry Andric return (RE.r_word0 >> 30) & 1; 188284c1978SDimitry Andric } 189284c1978SDimitry Andric 190284c1978SDimitry Andric static unsigned getPlainRelocationLength(const MachOObjectFile *O, 191f785676fSDimitry Andric const MachO::any_relocation_info &RE) { 192284c1978SDimitry Andric if (O->isLittleEndian()) 193f785676fSDimitry Andric return (RE.r_word1 >> 25) & 3; 194f785676fSDimitry Andric return (RE.r_word1 >> 5) & 3; 195284c1978SDimitry Andric } 196284c1978SDimitry Andric 197284c1978SDimitry Andric static unsigned 198f785676fSDimitry Andric getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 199f785676fSDimitry Andric return (RE.r_word0 >> 28) & 3; 200284c1978SDimitry Andric } 201284c1978SDimitry Andric 202284c1978SDimitry Andric static unsigned getPlainRelocationType(const MachOObjectFile *O, 203f785676fSDimitry Andric const MachO::any_relocation_info &RE) { 204284c1978SDimitry Andric if (O->isLittleEndian()) 205f785676fSDimitry Andric return RE.r_word1 >> 28; 206f785676fSDimitry Andric return RE.r_word1 & 0xf; 207284c1978SDimitry Andric } 208284c1978SDimitry Andric 209f785676fSDimitry Andric static unsigned 210f785676fSDimitry Andric getScatteredRelocationType(const MachO::any_relocation_info &RE) { 211f785676fSDimitry Andric return (RE.r_word0 >> 24) & 0xf; 212284c1978SDimitry Andric } 213284c1978SDimitry Andric 214284c1978SDimitry Andric static uint32_t getSectionFlags(const MachOObjectFile *O, 215284c1978SDimitry Andric DataRefImpl Sec) { 216284c1978SDimitry Andric if (O->is64Bit()) { 217f785676fSDimitry Andric MachO::section_64 Sect = O->getSection64(Sec); 218f785676fSDimitry Andric return Sect.flags; 219284c1978SDimitry Andric } 220f785676fSDimitry Andric MachO::section Sect = O->getSection(Sec); 221f785676fSDimitry Andric return Sect.flags; 222284c1978SDimitry Andric } 223284c1978SDimitry Andric 22491bc56edSDimitry Andric MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, 225284c1978SDimitry Andric bool IsLittleEndian, bool Is64bits, 22691bc56edSDimitry Andric std::error_code &EC) 22791bc56edSDimitry Andric : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), 22891bc56edSDimitry Andric SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 22991bc56edSDimitry Andric DataInCodeLoadCmd(nullptr) { 230f785676fSDimitry Andric uint32_t LoadCommandCount = this->getHeader().ncmds; 231f785676fSDimitry Andric MachO::LoadCommandType SegmentLoadType = is64Bit() ? 232f785676fSDimitry Andric MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 233284c1978SDimitry Andric 234284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 235284c1978SDimitry Andric for (unsigned I = 0; ; ++I) { 236f785676fSDimitry Andric if (Load.C.cmd == MachO::LC_SYMTAB) { 237284c1978SDimitry Andric assert(!SymtabLoadCmd && "Multiple symbol tables"); 238284c1978SDimitry Andric SymtabLoadCmd = Load.Ptr; 239f785676fSDimitry Andric } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 240284c1978SDimitry Andric assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 241284c1978SDimitry Andric DysymtabLoadCmd = Load.Ptr; 242f785676fSDimitry Andric } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 243f785676fSDimitry Andric assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 244f785676fSDimitry Andric DataInCodeLoadCmd = Load.Ptr; 245f785676fSDimitry Andric } else if (Load.C.cmd == SegmentLoadType) { 246284c1978SDimitry Andric uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 247284c1978SDimitry Andric for (unsigned J = 0; J < NumSections; ++J) { 248284c1978SDimitry Andric const char *Sec = getSectionPtr(this, Load, J); 249284c1978SDimitry Andric Sections.push_back(Sec); 2503b0f4066SDimitry Andric } 25191bc56edSDimitry Andric } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 25291bc56edSDimitry Andric Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 25391bc56edSDimitry Andric Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 25491bc56edSDimitry Andric Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 25591bc56edSDimitry Andric Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 25691bc56edSDimitry Andric Libraries.push_back(Load.Ptr); 2573b0f4066SDimitry Andric } 2583b0f4066SDimitry Andric 259284c1978SDimitry Andric if (I == LoadCommandCount - 1) 260284c1978SDimitry Andric break; 261284c1978SDimitry Andric else 262284c1978SDimitry Andric Load = getNextLoadCommandInfo(Load); 263284c1978SDimitry Andric } 2643b0f4066SDimitry Andric } 2653b0f4066SDimitry Andric 26691bc56edSDimitry Andric void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 267284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ? 268f785676fSDimitry Andric sizeof(MachO::nlist_64) : 269f785676fSDimitry Andric sizeof(MachO::nlist); 270284c1978SDimitry Andric Symb.p += SymbolTableEntrySize; 2713b0f4066SDimitry Andric } 2723b0f4066SDimitry Andric 27391bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 274284c1978SDimitry Andric StringRef &Res) const { 275284c1978SDimitry Andric StringRef StringTable = getStringTableData(); 27691bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 277f785676fSDimitry Andric const char *Start = &StringTable.data()[Entry.n_strx]; 278284c1978SDimitry Andric Res = StringRef(Start); 279284c1978SDimitry Andric return object_error::success; 280284c1978SDimitry Andric } 281284c1978SDimitry Andric 28291bc56edSDimitry Andric // getIndirectName() returns the name of the alias'ed symbol who's string table 28391bc56edSDimitry Andric // index is in the n_value field. 28491bc56edSDimitry Andric std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 28591bc56edSDimitry Andric StringRef &Res) const { 28691bc56edSDimitry Andric StringRef StringTable = getStringTableData(); 28791bc56edSDimitry Andric uint64_t NValue; 28891bc56edSDimitry Andric if (is64Bit()) { 28991bc56edSDimitry Andric MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 29091bc56edSDimitry Andric NValue = Entry.n_value; 29191bc56edSDimitry Andric if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 29291bc56edSDimitry Andric return object_error::parse_failed; 29391bc56edSDimitry Andric } else { 29491bc56edSDimitry Andric MachO::nlist Entry = getSymbolTableEntry(Symb); 29591bc56edSDimitry Andric NValue = Entry.n_value; 29691bc56edSDimitry Andric if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 29791bc56edSDimitry Andric return object_error::parse_failed; 29891bc56edSDimitry Andric } 29991bc56edSDimitry Andric if (NValue >= StringTable.size()) 30091bc56edSDimitry Andric return object_error::parse_failed; 30191bc56edSDimitry Andric const char *Start = &StringTable.data()[NValue]; 30291bc56edSDimitry Andric Res = StringRef(Start); 30391bc56edSDimitry Andric return object_error::success; 30491bc56edSDimitry Andric } 30591bc56edSDimitry Andric 30691bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 307284c1978SDimitry Andric uint64_t &Res) const { 308284c1978SDimitry Andric if (is64Bit()) { 309f785676fSDimitry Andric MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 31091bc56edSDimitry Andric if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 31191bc56edSDimitry Andric Entry.n_value == 0) 31291bc56edSDimitry Andric Res = UnknownAddressOrSize; 31391bc56edSDimitry Andric else 314f785676fSDimitry Andric Res = Entry.n_value; 31517a519f9SDimitry Andric } else { 316f785676fSDimitry Andric MachO::nlist Entry = getSymbolTableEntry(Symb); 31791bc56edSDimitry Andric if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 31891bc56edSDimitry Andric Entry.n_value == 0) 31991bc56edSDimitry Andric Res = UnknownAddressOrSize; 32091bc56edSDimitry Andric else 321f785676fSDimitry Andric Res = Entry.n_value; 32217a519f9SDimitry Andric } 32317a519f9SDimitry Andric return object_error::success; 3243b0f4066SDimitry Andric } 3253b0f4066SDimitry Andric 32691bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 327284c1978SDimitry Andric uint32_t &Result) const { 32891bc56edSDimitry Andric uint32_t flags = getSymbolFlags(DRI); 329284c1978SDimitry Andric if (flags & SymbolRef::SF_Common) { 33091bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 331f785676fSDimitry Andric Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 33217a519f9SDimitry Andric } else { 333284c1978SDimitry Andric Result = 0; 33417a519f9SDimitry Andric } 33517a519f9SDimitry Andric return object_error::success; 3363b0f4066SDimitry Andric } 3373b0f4066SDimitry Andric 33891bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 33917a519f9SDimitry Andric uint64_t &Result) const { 340dff0c46cSDimitry Andric uint64_t BeginOffset; 341dff0c46cSDimitry Andric uint64_t EndOffset = 0; 342dff0c46cSDimitry Andric uint8_t SectionIndex; 343284c1978SDimitry Andric 34491bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 345284c1978SDimitry Andric uint64_t Value; 346284c1978SDimitry Andric getSymbolAddress(DRI, Value); 34791bc56edSDimitry Andric if (Value == UnknownAddressOrSize) { 34891bc56edSDimitry Andric Result = UnknownAddressOrSize; 34991bc56edSDimitry Andric return object_error::success; 35091bc56edSDimitry Andric } 351284c1978SDimitry Andric 352284c1978SDimitry Andric BeginOffset = Value; 353284c1978SDimitry Andric 354f785676fSDimitry Andric SectionIndex = Entry.n_sect; 355dff0c46cSDimitry Andric if (!SectionIndex) { 35691bc56edSDimitry Andric uint32_t flags = getSymbolFlags(DRI); 357dff0c46cSDimitry Andric if (flags & SymbolRef::SF_Common) 358284c1978SDimitry Andric Result = Value; 359dff0c46cSDimitry Andric else 36017a519f9SDimitry Andric Result = UnknownAddressOrSize; 36117a519f9SDimitry Andric return object_error::success; 3623b0f4066SDimitry Andric } 363dff0c46cSDimitry Andric // Unfortunately symbols are unsorted so we need to touch all 364dff0c46cSDimitry Andric // symbols from load command 36591bc56edSDimitry Andric for (const SymbolRef &Symbol : symbols()) { 36691bc56edSDimitry Andric DataRefImpl DRI = Symbol.getRawDataRefImpl(); 367284c1978SDimitry Andric Entry = getSymbolTableEntryBase(this, DRI); 368284c1978SDimitry Andric getSymbolAddress(DRI, Value); 36991bc56edSDimitry Andric if (Value == UnknownAddressOrSize) 37091bc56edSDimitry Andric continue; 371f785676fSDimitry Andric if (Entry.n_sect == SectionIndex && Value > BeginOffset) 372284c1978SDimitry Andric if (!EndOffset || Value < EndOffset) 373284c1978SDimitry Andric EndOffset = Value; 374dff0c46cSDimitry Andric } 375dff0c46cSDimitry Andric if (!EndOffset) { 376dff0c46cSDimitry Andric uint64_t Size; 377284c1978SDimitry Andric DataRefImpl Sec; 378284c1978SDimitry Andric Sec.d.a = SectionIndex-1; 379284c1978SDimitry Andric getSectionSize(Sec, Size); 380284c1978SDimitry Andric getSectionAddress(Sec, EndOffset); 381dff0c46cSDimitry Andric EndOffset += Size; 382dff0c46cSDimitry Andric } 383dff0c46cSDimitry Andric Result = EndOffset - BeginOffset; 384dff0c46cSDimitry Andric return object_error::success; 385dff0c46cSDimitry Andric } 3863b0f4066SDimitry Andric 38791bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 388dff0c46cSDimitry Andric SymbolRef::Type &Res) const { 38991bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 390f785676fSDimitry Andric uint8_t n_type = Entry.n_type; 391284c1978SDimitry Andric 3926122f3e6SDimitry Andric Res = SymbolRef::ST_Other; 3936122f3e6SDimitry Andric 3946122f3e6SDimitry Andric // If this is a STAB debugging symbol, we can do nothing more. 395f785676fSDimitry Andric if (n_type & MachO::N_STAB) { 396dff0c46cSDimitry Andric Res = SymbolRef::ST_Debug; 3976122f3e6SDimitry Andric return object_error::success; 398dff0c46cSDimitry Andric } 3996122f3e6SDimitry Andric 400f785676fSDimitry Andric switch (n_type & MachO::N_TYPE) { 401f785676fSDimitry Andric case MachO::N_UNDF : 402dff0c46cSDimitry Andric Res = SymbolRef::ST_Unknown; 4036122f3e6SDimitry Andric break; 404f785676fSDimitry Andric case MachO::N_SECT : 4056122f3e6SDimitry Andric Res = SymbolRef::ST_Function; 4066122f3e6SDimitry Andric break; 4076122f3e6SDimitry Andric } 4086122f3e6SDimitry Andric return object_error::success; 4096122f3e6SDimitry Andric } 4106122f3e6SDimitry Andric 41191bc56edSDimitry Andric uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 41291bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 413284c1978SDimitry Andric 414f785676fSDimitry Andric uint8_t MachOType = Entry.n_type; 415f785676fSDimitry Andric uint16_t MachOFlags = Entry.n_desc; 416284c1978SDimitry Andric 41791bc56edSDimitry Andric uint32_t Result = SymbolRef::SF_None; 418284c1978SDimitry Andric 419f785676fSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 420284c1978SDimitry Andric Result |= SymbolRef::SF_Undefined; 421284c1978SDimitry Andric 42291bc56edSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 42391bc56edSDimitry Andric Result |= SymbolRef::SF_Indirect; 42491bc56edSDimitry Andric 425f785676fSDimitry Andric if (MachOType & MachO::N_STAB) 426284c1978SDimitry Andric Result |= SymbolRef::SF_FormatSpecific; 427284c1978SDimitry Andric 428f785676fSDimitry Andric if (MachOType & MachO::N_EXT) { 429284c1978SDimitry Andric Result |= SymbolRef::SF_Global; 430f785676fSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 431284c1978SDimitry Andric uint64_t Value; 432284c1978SDimitry Andric getSymbolAddress(DRI, Value); 43391bc56edSDimitry Andric if (Value && Value != UnknownAddressOrSize) 434284c1978SDimitry Andric Result |= SymbolRef::SF_Common; 435284c1978SDimitry Andric } 436284c1978SDimitry Andric } 437284c1978SDimitry Andric 438f785676fSDimitry Andric if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 439284c1978SDimitry Andric Result |= SymbolRef::SF_Weak; 440284c1978SDimitry Andric 441f785676fSDimitry Andric if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 442284c1978SDimitry Andric Result |= SymbolRef::SF_Absolute; 443284c1978SDimitry Andric 44491bc56edSDimitry Andric return Result; 445284c1978SDimitry Andric } 446284c1978SDimitry Andric 44791bc56edSDimitry Andric std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 448284c1978SDimitry Andric section_iterator &Res) const { 44991bc56edSDimitry Andric MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 450f785676fSDimitry Andric uint8_t index = Entry.n_sect; 451284c1978SDimitry Andric 452284c1978SDimitry Andric if (index == 0) { 45391bc56edSDimitry Andric Res = section_end(); 454284c1978SDimitry Andric } else { 455284c1978SDimitry Andric DataRefImpl DRI; 456284c1978SDimitry Andric DRI.d.a = index - 1; 457284c1978SDimitry Andric Res = section_iterator(SectionRef(DRI, this)); 458284c1978SDimitry Andric } 459284c1978SDimitry Andric 460284c1978SDimitry Andric return object_error::success; 461284c1978SDimitry Andric } 462284c1978SDimitry Andric 46391bc56edSDimitry Andric void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 464284c1978SDimitry Andric Sec.d.a++; 4653b0f4066SDimitry Andric } 4663b0f4066SDimitry Andric 46791bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 46891bc56edSDimitry Andric StringRef &Result) const { 469284c1978SDimitry Andric ArrayRef<char> Raw = getSectionRawName(Sec); 470284c1978SDimitry Andric Result = parseSegmentOrSectionName(Raw.data()); 471284c1978SDimitry Andric return object_error::success; 4723b0f4066SDimitry Andric } 4733b0f4066SDimitry Andric 47491bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 47591bc56edSDimitry Andric uint64_t &Res) const { 476284c1978SDimitry Andric if (is64Bit()) { 477f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 478f785676fSDimitry Andric Res = Sect.addr; 47917a519f9SDimitry Andric } else { 480f785676fSDimitry Andric MachO::section Sect = getSection(Sec); 481f785676fSDimitry Andric Res = Sect.addr; 48217a519f9SDimitry Andric } 483139f7f9bSDimitry Andric return object_error::success; 484139f7f9bSDimitry Andric } 485139f7f9bSDimitry Andric 48691bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 48791bc56edSDimitry Andric uint64_t &Res) const { 488284c1978SDimitry Andric if (is64Bit()) { 489f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 490f785676fSDimitry Andric Res = Sect.size; 491139f7f9bSDimitry Andric } else { 492f785676fSDimitry Andric MachO::section Sect = getSection(Sec); 493f785676fSDimitry Andric Res = Sect.size; 494139f7f9bSDimitry Andric } 495284c1978SDimitry Andric 49617a519f9SDimitry Andric return object_error::success; 4973b0f4066SDimitry Andric } 4983b0f4066SDimitry Andric 49991bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 50091bc56edSDimitry Andric StringRef &Res) const { 501284c1978SDimitry Andric uint32_t Offset; 502284c1978SDimitry Andric uint64_t Size; 503284c1978SDimitry Andric 504284c1978SDimitry Andric if (is64Bit()) { 505f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 506f785676fSDimitry Andric Offset = Sect.offset; 507f785676fSDimitry Andric Size = Sect.size; 50817a519f9SDimitry Andric } else { 509f785676fSDimitry Andric MachO::section Sect = getSection(Sec); 510f785676fSDimitry Andric Offset = Sect.offset; 511f785676fSDimitry Andric Size = Sect.size; 51217a519f9SDimitry Andric } 513284c1978SDimitry Andric 514284c1978SDimitry Andric Res = this->getData().substr(Offset, Size); 51517a519f9SDimitry Andric return object_error::success; 5163b0f4066SDimitry Andric } 5173b0f4066SDimitry Andric 51891bc56edSDimitry Andric std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 51991bc56edSDimitry Andric uint64_t &Res) const { 520284c1978SDimitry Andric uint32_t Align; 521284c1978SDimitry Andric if (is64Bit()) { 522f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 523f785676fSDimitry Andric Align = Sect.align; 52417a519f9SDimitry Andric } else { 525f785676fSDimitry Andric MachO::section Sect = getSection(Sec); 526f785676fSDimitry Andric Align = Sect.align; 52717a519f9SDimitry Andric } 528284c1978SDimitry Andric 529284c1978SDimitry Andric Res = uint64_t(1) << Align; 53017a519f9SDimitry Andric return object_error::success; 5313b0f4066SDimitry Andric } 5323b0f4066SDimitry Andric 53391bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 53491bc56edSDimitry Andric bool &Res) const { 535284c1978SDimitry Andric uint32_t Flags = getSectionFlags(this, Sec); 536f785676fSDimitry Andric Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 53717a519f9SDimitry Andric return object_error::success; 5383b0f4066SDimitry Andric } 5393b0f4066SDimitry Andric 54091bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 54191bc56edSDimitry Andric bool &Result) const { 54291bc56edSDimitry Andric uint32_t Flags = getSectionFlags(this, Sec); 54391bc56edSDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE; 54491bc56edSDimitry Andric Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 54591bc56edSDimitry Andric !(SectionType == MachO::S_ZEROFILL || 54691bc56edSDimitry Andric SectionType == MachO::S_GB_ZEROFILL); 54717a519f9SDimitry Andric return object_error::success; 5483b0f4066SDimitry Andric } 5493b0f4066SDimitry Andric 55091bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 55191bc56edSDimitry Andric bool &Result) const { 55291bc56edSDimitry Andric uint32_t Flags = getSectionFlags(this, Sec); 55391bc56edSDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE; 55491bc56edSDimitry Andric Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 55591bc56edSDimitry Andric (SectionType == MachO::S_ZEROFILL || 55691bc56edSDimitry Andric SectionType == MachO::S_GB_ZEROFILL); 5576122f3e6SDimitry Andric return object_error::success; 5586122f3e6SDimitry Andric } 5596122f3e6SDimitry Andric 56091bc56edSDimitry Andric std::error_code 561284c1978SDimitry Andric MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 562dff0c46cSDimitry Andric bool &Result) const { 5633861d79fSDimitry Andric // FIXME: Unimplemented. 564dff0c46cSDimitry Andric Result = true; 565dff0c46cSDimitry Andric return object_error::success; 566dff0c46cSDimitry Andric } 567dff0c46cSDimitry Andric 56891bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 569dff0c46cSDimitry Andric bool &Result) const { 5703861d79fSDimitry Andric // FIXME: Unimplemented. 571dff0c46cSDimitry Andric Result = false; 572dff0c46cSDimitry Andric return object_error::success; 573dff0c46cSDimitry Andric } 574dff0c46cSDimitry Andric 57591bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 57691bc56edSDimitry Andric bool &Res) const { 577284c1978SDimitry Andric uint32_t Flags = getSectionFlags(this, Sec); 578f785676fSDimitry Andric unsigned SectionType = Flags & MachO::SECTION_TYPE; 579f785676fSDimitry Andric Res = SectionType == MachO::S_ZEROFILL || 580f785676fSDimitry Andric SectionType == MachO::S_GB_ZEROFILL; 581dff0c46cSDimitry Andric return object_error::success; 582dff0c46cSDimitry Andric } 583dff0c46cSDimitry Andric 58491bc56edSDimitry Andric std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 5853861d79fSDimitry Andric bool &Result) const { 5863861d79fSDimitry Andric // Consider using the code from isSectionText to look for __const sections. 5873861d79fSDimitry Andric // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 5883861d79fSDimitry Andric // to use section attributes to distinguish code from data. 5893861d79fSDimitry Andric 5903861d79fSDimitry Andric // FIXME: Unimplemented. 5913861d79fSDimitry Andric Result = false; 5923861d79fSDimitry Andric return object_error::success; 5933861d79fSDimitry Andric } 5943861d79fSDimitry Andric 59591bc56edSDimitry Andric std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 59691bc56edSDimitry Andric DataRefImpl Symb, 5976122f3e6SDimitry Andric bool &Result) const { 598dff0c46cSDimitry Andric SymbolRef::Type ST; 599284c1978SDimitry Andric this->getSymbolType(Symb, ST); 600dff0c46cSDimitry Andric if (ST == SymbolRef::ST_Unknown) { 6016122f3e6SDimitry Andric Result = false; 6026122f3e6SDimitry Andric return object_error::success; 6036122f3e6SDimitry Andric } 6046122f3e6SDimitry Andric 6056122f3e6SDimitry Andric uint64_t SectBegin, SectEnd; 6066122f3e6SDimitry Andric getSectionAddress(Sec, SectBegin); 6076122f3e6SDimitry Andric getSectionSize(Sec, SectEnd); 6086122f3e6SDimitry Andric SectEnd += SectBegin; 6096122f3e6SDimitry Andric 610284c1978SDimitry Andric uint64_t SymAddr; 611284c1978SDimitry Andric getSymbolAddress(Symb, SymAddr); 6126122f3e6SDimitry Andric Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 6136122f3e6SDimitry Andric 6146122f3e6SDimitry Andric return object_error::success; 6156122f3e6SDimitry Andric } 6166122f3e6SDimitry Andric 617f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 618284c1978SDimitry Andric DataRefImpl Ret; 61991bc56edSDimitry Andric Ret.d.a = Sec.d.a; 62091bc56edSDimitry Andric Ret.d.b = 0; 621284c1978SDimitry Andric return relocation_iterator(RelocationRef(Ret, this)); 6223b0f4066SDimitry Andric } 6233b0f4066SDimitry Andric 624284c1978SDimitry Andric relocation_iterator 625f785676fSDimitry Andric MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 626284c1978SDimitry Andric uint32_t Num; 627284c1978SDimitry Andric if (is64Bit()) { 628f785676fSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 629f785676fSDimitry Andric Num = Sect.nreloc; 6306122f3e6SDimitry Andric } else { 631f785676fSDimitry Andric MachO::section Sect = getSection(Sec); 632f785676fSDimitry Andric Num = Sect.nreloc; 6336122f3e6SDimitry Andric } 634284c1978SDimitry Andric 635284c1978SDimitry Andric DataRefImpl Ret; 63691bc56edSDimitry Andric Ret.d.a = Sec.d.a; 63791bc56edSDimitry Andric Ret.d.b = Num; 638284c1978SDimitry Andric return relocation_iterator(RelocationRef(Ret, this)); 6396122f3e6SDimitry Andric } 640284c1978SDimitry Andric 64191bc56edSDimitry Andric void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 64291bc56edSDimitry Andric ++Rel.d.b; 64391bc56edSDimitry Andric } 64491bc56edSDimitry Andric 64591bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 64691bc56edSDimitry Andric uint64_t &Res) const { 64791bc56edSDimitry Andric uint64_t Offset; 64891bc56edSDimitry Andric getRelocationOffset(Rel, Offset); 64991bc56edSDimitry Andric 65091bc56edSDimitry Andric DataRefImpl Sec; 65191bc56edSDimitry Andric Sec.d.a = Rel.d.a; 65291bc56edSDimitry Andric uint64_t SecAddress; 65391bc56edSDimitry Andric getSectionAddress(Sec, SecAddress); 65491bc56edSDimitry Andric Res = SecAddress + Offset; 6556122f3e6SDimitry Andric return object_error::success; 6566122f3e6SDimitry Andric } 657dff0c46cSDimitry Andric 65891bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 659dff0c46cSDimitry Andric uint64_t &Res) const { 66091bc56edSDimitry Andric assert(getHeader().filetype == MachO::MH_OBJECT && 66191bc56edSDimitry Andric "Only implemented for MH_OBJECT"); 662f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel); 663284c1978SDimitry Andric Res = getAnyRelocationAddress(RE); 6646122f3e6SDimitry Andric return object_error::success; 6656122f3e6SDimitry Andric } 6666122f3e6SDimitry Andric 667f785676fSDimitry Andric symbol_iterator 668f785676fSDimitry Andric MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 669f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel); 67091bc56edSDimitry Andric if (isRelocationScattered(RE)) 67191bc56edSDimitry Andric return symbol_end(); 67291bc56edSDimitry Andric 673284c1978SDimitry Andric uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 674284c1978SDimitry Andric bool isExtern = getPlainRelocationExternal(RE); 675f785676fSDimitry Andric if (!isExtern) 67691bc56edSDimitry Andric return symbol_end(); 677284c1978SDimitry Andric 678f785676fSDimitry Andric MachO::symtab_command S = getSymtabLoadCommand(); 679284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ? 680f785676fSDimitry Andric sizeof(MachO::nlist_64) : 681f785676fSDimitry Andric sizeof(MachO::nlist); 682f785676fSDimitry Andric uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 6836122f3e6SDimitry Andric DataRefImpl Sym; 684284c1978SDimitry Andric Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 685f785676fSDimitry Andric return symbol_iterator(SymbolRef(Sym, this)); 6866122f3e6SDimitry Andric } 687284c1978SDimitry Andric 68891bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 689dff0c46cSDimitry Andric uint64_t &Res) const { 690f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel); 691284c1978SDimitry Andric Res = getAnyRelocationType(RE); 6926122f3e6SDimitry Andric return object_error::success; 6936122f3e6SDimitry Andric } 694284c1978SDimitry Andric 69591bc56edSDimitry Andric std::error_code 696284c1978SDimitry Andric MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 6976122f3e6SDimitry Andric SmallVectorImpl<char> &Result) const { 698dff0c46cSDimitry Andric StringRef res; 699284c1978SDimitry Andric uint64_t RType; 700284c1978SDimitry Andric getRelocationType(Rel, RType); 701dff0c46cSDimitry Andric 702284c1978SDimitry Andric unsigned Arch = this->getArch(); 703dff0c46cSDimitry Andric 704dff0c46cSDimitry Andric switch (Arch) { 705dff0c46cSDimitry Andric case Triple::x86: { 7067ae0e2c9SDimitry Andric static const char *const Table[] = { 707dff0c46cSDimitry Andric "GENERIC_RELOC_VANILLA", 708dff0c46cSDimitry Andric "GENERIC_RELOC_PAIR", 709dff0c46cSDimitry Andric "GENERIC_RELOC_SECTDIFF", 710dff0c46cSDimitry Andric "GENERIC_RELOC_PB_LA_PTR", 711dff0c46cSDimitry Andric "GENERIC_RELOC_LOCAL_SECTDIFF", 712dff0c46cSDimitry Andric "GENERIC_RELOC_TLV" }; 713dff0c46cSDimitry Andric 71491bc56edSDimitry Andric if (RType > 5) 715dff0c46cSDimitry Andric res = "Unknown"; 716dff0c46cSDimitry Andric else 717284c1978SDimitry Andric res = Table[RType]; 718dff0c46cSDimitry Andric break; 719dff0c46cSDimitry Andric } 720dff0c46cSDimitry Andric case Triple::x86_64: { 7217ae0e2c9SDimitry Andric static const char *const Table[] = { 722dff0c46cSDimitry Andric "X86_64_RELOC_UNSIGNED", 723dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED", 724dff0c46cSDimitry Andric "X86_64_RELOC_BRANCH", 725dff0c46cSDimitry Andric "X86_64_RELOC_GOT_LOAD", 726dff0c46cSDimitry Andric "X86_64_RELOC_GOT", 727dff0c46cSDimitry Andric "X86_64_RELOC_SUBTRACTOR", 728dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_1", 729dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_2", 730dff0c46cSDimitry Andric "X86_64_RELOC_SIGNED_4", 731dff0c46cSDimitry Andric "X86_64_RELOC_TLV" }; 732dff0c46cSDimitry Andric 733284c1978SDimitry Andric if (RType > 9) 734dff0c46cSDimitry Andric res = "Unknown"; 735dff0c46cSDimitry Andric else 736284c1978SDimitry Andric res = Table[RType]; 737dff0c46cSDimitry Andric break; 738dff0c46cSDimitry Andric } 739dff0c46cSDimitry Andric case Triple::arm: { 7407ae0e2c9SDimitry Andric static const char *const Table[] = { 741dff0c46cSDimitry Andric "ARM_RELOC_VANILLA", 742dff0c46cSDimitry Andric "ARM_RELOC_PAIR", 743dff0c46cSDimitry Andric "ARM_RELOC_SECTDIFF", 744dff0c46cSDimitry Andric "ARM_RELOC_LOCAL_SECTDIFF", 745dff0c46cSDimitry Andric "ARM_RELOC_PB_LA_PTR", 746dff0c46cSDimitry Andric "ARM_RELOC_BR24", 747dff0c46cSDimitry Andric "ARM_THUMB_RELOC_BR22", 748dff0c46cSDimitry Andric "ARM_THUMB_32BIT_BRANCH", 749dff0c46cSDimitry Andric "ARM_RELOC_HALF", 750dff0c46cSDimitry Andric "ARM_RELOC_HALF_SECTDIFF" }; 751dff0c46cSDimitry Andric 752284c1978SDimitry Andric if (RType > 9) 753dff0c46cSDimitry Andric res = "Unknown"; 754dff0c46cSDimitry Andric else 755284c1978SDimitry Andric res = Table[RType]; 756dff0c46cSDimitry Andric break; 757dff0c46cSDimitry Andric } 75891bc56edSDimitry Andric case Triple::arm64: 75991bc56edSDimitry Andric case Triple::aarch64: { 76091bc56edSDimitry Andric static const char *const Table[] = { 76191bc56edSDimitry Andric "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 76291bc56edSDimitry Andric "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 76391bc56edSDimitry Andric "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 76491bc56edSDimitry Andric "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 76591bc56edSDimitry Andric "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 76691bc56edSDimitry Andric "ARM64_RELOC_ADDEND" 76791bc56edSDimitry Andric }; 76891bc56edSDimitry Andric 76991bc56edSDimitry Andric if (RType >= array_lengthof(Table)) 77091bc56edSDimitry Andric res = "Unknown"; 77191bc56edSDimitry Andric else 77291bc56edSDimitry Andric res = Table[RType]; 77391bc56edSDimitry Andric break; 77491bc56edSDimitry Andric } 775dff0c46cSDimitry Andric case Triple::ppc: { 7767ae0e2c9SDimitry Andric static const char *const Table[] = { 777dff0c46cSDimitry Andric "PPC_RELOC_VANILLA", 778dff0c46cSDimitry Andric "PPC_RELOC_PAIR", 779dff0c46cSDimitry Andric "PPC_RELOC_BR14", 780dff0c46cSDimitry Andric "PPC_RELOC_BR24", 781dff0c46cSDimitry Andric "PPC_RELOC_HI16", 782dff0c46cSDimitry Andric "PPC_RELOC_LO16", 783dff0c46cSDimitry Andric "PPC_RELOC_HA16", 784dff0c46cSDimitry Andric "PPC_RELOC_LO14", 785dff0c46cSDimitry Andric "PPC_RELOC_SECTDIFF", 786dff0c46cSDimitry Andric "PPC_RELOC_PB_LA_PTR", 787dff0c46cSDimitry Andric "PPC_RELOC_HI16_SECTDIFF", 788dff0c46cSDimitry Andric "PPC_RELOC_LO16_SECTDIFF", 789dff0c46cSDimitry Andric "PPC_RELOC_HA16_SECTDIFF", 790dff0c46cSDimitry Andric "PPC_RELOC_JBSR", 791dff0c46cSDimitry Andric "PPC_RELOC_LO14_SECTDIFF", 792dff0c46cSDimitry Andric "PPC_RELOC_LOCAL_SECTDIFF" }; 793dff0c46cSDimitry Andric 79491bc56edSDimitry Andric if (RType > 15) 79591bc56edSDimitry Andric res = "Unknown"; 79691bc56edSDimitry Andric else 797284c1978SDimitry Andric res = Table[RType]; 798dff0c46cSDimitry Andric break; 799dff0c46cSDimitry Andric } 800dff0c46cSDimitry Andric case Triple::UnknownArch: 801dff0c46cSDimitry Andric res = "Unknown"; 802dff0c46cSDimitry Andric break; 803dff0c46cSDimitry Andric } 804dff0c46cSDimitry Andric Result.append(res.begin(), res.end()); 8056122f3e6SDimitry Andric return object_error::success; 8066122f3e6SDimitry Andric } 807284c1978SDimitry Andric 80891bc56edSDimitry Andric std::error_code 809284c1978SDimitry Andric MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 8106122f3e6SDimitry Andric SmallVectorImpl<char> &Result) const { 811f785676fSDimitry Andric MachO::any_relocation_info RE = getRelocation(Rel); 812dff0c46cSDimitry Andric 813284c1978SDimitry Andric unsigned Arch = this->getArch(); 814dff0c46cSDimitry Andric 815dff0c46cSDimitry Andric std::string fmtbuf; 816dff0c46cSDimitry Andric raw_string_ostream fmt(fmtbuf); 817284c1978SDimitry Andric unsigned Type = this->getAnyRelocationType(RE); 818284c1978SDimitry Andric bool IsPCRel = this->getAnyRelocationPCRel(RE); 819dff0c46cSDimitry Andric 820dff0c46cSDimitry Andric // Determine any addends that should be displayed with the relocation. 821dff0c46cSDimitry Andric // These require decoding the relocation type, which is triple-specific. 822dff0c46cSDimitry Andric 823dff0c46cSDimitry Andric // X86_64 has entirely custom relocation types. 824dff0c46cSDimitry Andric if (Arch == Triple::x86_64) { 825284c1978SDimitry Andric bool isPCRel = getAnyRelocationPCRel(RE); 826dff0c46cSDimitry Andric 827dff0c46cSDimitry Andric switch (Type) { 828f785676fSDimitry Andric case MachO::X86_64_RELOC_GOT_LOAD: 829f785676fSDimitry Andric case MachO::X86_64_RELOC_GOT: { 830284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 831dff0c46cSDimitry Andric fmt << "@GOT"; 832dff0c46cSDimitry Andric if (isPCRel) fmt << "PCREL"; 833dff0c46cSDimitry Andric break; 834dff0c46cSDimitry Andric } 835f785676fSDimitry Andric case MachO::X86_64_RELOC_SUBTRACTOR: { 836dff0c46cSDimitry Andric DataRefImpl RelNext = Rel; 83791bc56edSDimitry Andric moveRelocationNext(RelNext); 838f785676fSDimitry Andric MachO::any_relocation_info RENext = getRelocation(RelNext); 839dff0c46cSDimitry Andric 840f785676fSDimitry Andric // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 841dff0c46cSDimitry Andric // X86_64_RELOC_UNSIGNED. 842dff0c46cSDimitry Andric // NOTE: Scattered relocations don't exist on x86_64. 843284c1978SDimitry Andric unsigned RType = getAnyRelocationType(RENext); 844f785676fSDimitry Andric if (RType != MachO::X86_64_RELOC_UNSIGNED) 845dff0c46cSDimitry Andric report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 846dff0c46cSDimitry Andric "X86_64_RELOC_SUBTRACTOR."); 847dff0c46cSDimitry Andric 848f785676fSDimitry Andric // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 849f785676fSDimitry Andric // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 850284c1978SDimitry Andric printRelocationTargetName(this, RENext, fmt); 851dff0c46cSDimitry Andric fmt << "-"; 852284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 853139f7f9bSDimitry Andric break; 854dff0c46cSDimitry Andric } 855f785676fSDimitry Andric case MachO::X86_64_RELOC_TLV: 856284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 857dff0c46cSDimitry Andric fmt << "@TLV"; 858dff0c46cSDimitry Andric if (isPCRel) fmt << "P"; 859dff0c46cSDimitry Andric break; 860f785676fSDimitry Andric case MachO::X86_64_RELOC_SIGNED_1: 861284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 862dff0c46cSDimitry Andric fmt << "-1"; 863dff0c46cSDimitry Andric break; 864f785676fSDimitry Andric case MachO::X86_64_RELOC_SIGNED_2: 865284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 866dff0c46cSDimitry Andric fmt << "-2"; 867dff0c46cSDimitry Andric break; 868f785676fSDimitry Andric case MachO::X86_64_RELOC_SIGNED_4: 869284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 870dff0c46cSDimitry Andric fmt << "-4"; 871dff0c46cSDimitry Andric break; 872dff0c46cSDimitry Andric default: 873284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 874dff0c46cSDimitry Andric break; 875dff0c46cSDimitry Andric } 876dff0c46cSDimitry Andric // X86 and ARM share some relocation types in common. 877f785676fSDimitry Andric } else if (Arch == Triple::x86 || Arch == Triple::arm || 878f785676fSDimitry Andric Arch == Triple::ppc) { 879dff0c46cSDimitry Andric // Generic relocation types... 880dff0c46cSDimitry Andric switch (Type) { 881f785676fSDimitry Andric case MachO::GENERIC_RELOC_PAIR: // prints no info 882dff0c46cSDimitry Andric return object_error::success; 883f785676fSDimitry Andric case MachO::GENERIC_RELOC_SECTDIFF: { 884dff0c46cSDimitry Andric DataRefImpl RelNext = Rel; 88591bc56edSDimitry Andric moveRelocationNext(RelNext); 886f785676fSDimitry Andric MachO::any_relocation_info RENext = getRelocation(RelNext); 887dff0c46cSDimitry Andric 888dff0c46cSDimitry Andric // X86 sect diff's must be followed by a relocation of type 889dff0c46cSDimitry Andric // GENERIC_RELOC_PAIR. 890284c1978SDimitry Andric unsigned RType = getAnyRelocationType(RENext); 891284c1978SDimitry Andric 892f785676fSDimitry Andric if (RType != MachO::GENERIC_RELOC_PAIR) 893dff0c46cSDimitry Andric report_fatal_error("Expected GENERIC_RELOC_PAIR after " 894dff0c46cSDimitry Andric "GENERIC_RELOC_SECTDIFF."); 895dff0c46cSDimitry Andric 896284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 897dff0c46cSDimitry Andric fmt << "-"; 898284c1978SDimitry Andric printRelocationTargetName(this, RENext, fmt); 899dff0c46cSDimitry Andric break; 900dff0c46cSDimitry Andric } 901dff0c46cSDimitry Andric } 902dff0c46cSDimitry Andric 903f785676fSDimitry Andric if (Arch == Triple::x86 || Arch == Triple::ppc) { 904dff0c46cSDimitry Andric switch (Type) { 905f785676fSDimitry Andric case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 906dff0c46cSDimitry Andric DataRefImpl RelNext = Rel; 90791bc56edSDimitry Andric moveRelocationNext(RelNext); 908f785676fSDimitry Andric MachO::any_relocation_info RENext = getRelocation(RelNext); 909dff0c46cSDimitry Andric 910dff0c46cSDimitry Andric // X86 sect diff's must be followed by a relocation of type 911dff0c46cSDimitry Andric // GENERIC_RELOC_PAIR. 912284c1978SDimitry Andric unsigned RType = getAnyRelocationType(RENext); 913f785676fSDimitry Andric if (RType != MachO::GENERIC_RELOC_PAIR) 914dff0c46cSDimitry Andric report_fatal_error("Expected GENERIC_RELOC_PAIR after " 915dff0c46cSDimitry Andric "GENERIC_RELOC_LOCAL_SECTDIFF."); 916dff0c46cSDimitry Andric 917284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 918dff0c46cSDimitry Andric fmt << "-"; 919284c1978SDimitry Andric printRelocationTargetName(this, RENext, fmt); 920dff0c46cSDimitry Andric break; 921dff0c46cSDimitry Andric } 922f785676fSDimitry Andric case MachO::GENERIC_RELOC_TLV: { 923284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 924dff0c46cSDimitry Andric fmt << "@TLV"; 925284c1978SDimitry Andric if (IsPCRel) fmt << "P"; 926dff0c46cSDimitry Andric break; 927dff0c46cSDimitry Andric } 928dff0c46cSDimitry Andric default: 929284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 930dff0c46cSDimitry Andric } 931dff0c46cSDimitry Andric } else { // ARM-specific relocations 932dff0c46cSDimitry Andric switch (Type) { 933f785676fSDimitry Andric case MachO::ARM_RELOC_HALF: 934f785676fSDimitry Andric case MachO::ARM_RELOC_HALF_SECTDIFF: { 935dff0c46cSDimitry Andric // Half relocations steal a bit from the length field to encode 936dff0c46cSDimitry Andric // whether this is an upper16 or a lower16 relocation. 937284c1978SDimitry Andric bool isUpper = getAnyRelocationLength(RE) >> 1; 938dff0c46cSDimitry Andric 939dff0c46cSDimitry Andric if (isUpper) 940dff0c46cSDimitry Andric fmt << ":upper16:("; 941dff0c46cSDimitry Andric else 942dff0c46cSDimitry Andric fmt << ":lower16:("; 943284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 944dff0c46cSDimitry Andric 945dff0c46cSDimitry Andric DataRefImpl RelNext = Rel; 94691bc56edSDimitry Andric moveRelocationNext(RelNext); 947f785676fSDimitry Andric MachO::any_relocation_info RENext = getRelocation(RelNext); 948dff0c46cSDimitry Andric 949dff0c46cSDimitry Andric // ARM half relocs must be followed by a relocation of type 950dff0c46cSDimitry Andric // ARM_RELOC_PAIR. 951284c1978SDimitry Andric unsigned RType = getAnyRelocationType(RENext); 952f785676fSDimitry Andric if (RType != MachO::ARM_RELOC_PAIR) 953dff0c46cSDimitry Andric report_fatal_error("Expected ARM_RELOC_PAIR after " 954f785676fSDimitry Andric "ARM_RELOC_HALF"); 955dff0c46cSDimitry Andric 956dff0c46cSDimitry Andric // NOTE: The half of the target virtual address is stashed in the 957dff0c46cSDimitry Andric // address field of the secondary relocation, but we can't reverse 958dff0c46cSDimitry Andric // engineer the constant offset from it without decoding the movw/movt 959dff0c46cSDimitry Andric // instruction to find the other half in its immediate field. 960dff0c46cSDimitry Andric 961dff0c46cSDimitry Andric // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 962dff0c46cSDimitry Andric // symbol/section pointer of the follow-on relocation. 963f785676fSDimitry Andric if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 964dff0c46cSDimitry Andric fmt << "-"; 965284c1978SDimitry Andric printRelocationTargetName(this, RENext, fmt); 966dff0c46cSDimitry Andric } 967dff0c46cSDimitry Andric 968dff0c46cSDimitry Andric fmt << ")"; 969dff0c46cSDimitry Andric break; 970dff0c46cSDimitry Andric } 971dff0c46cSDimitry Andric default: { 972284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 973dff0c46cSDimitry Andric } 974dff0c46cSDimitry Andric } 975dff0c46cSDimitry Andric } 976dff0c46cSDimitry Andric } else 977284c1978SDimitry Andric printRelocationTargetName(this, RE, fmt); 978dff0c46cSDimitry Andric 979dff0c46cSDimitry Andric fmt.flush(); 980dff0c46cSDimitry Andric Result.append(fmtbuf.begin(), fmtbuf.end()); 9816122f3e6SDimitry Andric return object_error::success; 9826122f3e6SDimitry Andric } 9836122f3e6SDimitry Andric 98491bc56edSDimitry Andric std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 98591bc56edSDimitry Andric bool &Result) const { 986dff0c46cSDimitry Andric unsigned Arch = getArch(); 987284c1978SDimitry Andric uint64_t Type; 988284c1978SDimitry Andric getRelocationType(Rel, Type); 989dff0c46cSDimitry Andric 990dff0c46cSDimitry Andric Result = false; 991dff0c46cSDimitry Andric 992dff0c46cSDimitry Andric // On arches that use the generic relocations, GENERIC_RELOC_PAIR 993dff0c46cSDimitry Andric // is always hidden. 994f785676fSDimitry Andric if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 995f785676fSDimitry Andric if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 996dff0c46cSDimitry Andric } else if (Arch == Triple::x86_64) { 997dff0c46cSDimitry Andric // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 998f785676fSDimitry Andric // an X86_64_RELOC_SUBTRACTOR. 999f785676fSDimitry Andric if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1000dff0c46cSDimitry Andric DataRefImpl RelPrev = Rel; 1001dff0c46cSDimitry Andric RelPrev.d.a--; 1002284c1978SDimitry Andric uint64_t PrevType; 1003284c1978SDimitry Andric getRelocationType(RelPrev, PrevType); 1004f785676fSDimitry Andric if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1005284c1978SDimitry Andric Result = true; 1006dff0c46cSDimitry Andric } 1007dff0c46cSDimitry Andric } 1008dff0c46cSDimitry Andric 1009dff0c46cSDimitry Andric return object_error::success; 1010dff0c46cSDimitry Andric } 1011dff0c46cSDimitry Andric 101291bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1013dff0c46cSDimitry Andric LibraryRef &Res) const { 1014dff0c46cSDimitry Andric report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1015dff0c46cSDimitry Andric } 1016dff0c46cSDimitry Andric 101791bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1018dff0c46cSDimitry Andric StringRef &Res) const { 1019dff0c46cSDimitry Andric report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1020dff0c46cSDimitry Andric } 1021dff0c46cSDimitry Andric 102291bc56edSDimitry Andric // 102391bc56edSDimitry Andric // guessLibraryShortName() is passed a name of a dynamic library and returns a 102491bc56edSDimitry Andric // guess on what the short name is. Then name is returned as a substring of the 102591bc56edSDimitry Andric // StringRef Name passed in. The name of the dynamic library is recognized as 102691bc56edSDimitry Andric // a framework if it has one of the two following forms: 102791bc56edSDimitry Andric // Foo.framework/Versions/A/Foo 102891bc56edSDimitry Andric // Foo.framework/Foo 102991bc56edSDimitry Andric // Where A and Foo can be any string. And may contain a trailing suffix 103091bc56edSDimitry Andric // starting with an underbar. If the Name is recognized as a framework then 103191bc56edSDimitry Andric // isFramework is set to true else it is set to false. If the Name has a 103291bc56edSDimitry Andric // suffix then Suffix is set to the substring in Name that contains the suffix 103391bc56edSDimitry Andric // else it is set to a NULL StringRef. 103491bc56edSDimitry Andric // 103591bc56edSDimitry Andric // The Name of the dynamic library is recognized as a library name if it has 103691bc56edSDimitry Andric // one of the two following forms: 103791bc56edSDimitry Andric // libFoo.A.dylib 103891bc56edSDimitry Andric // libFoo.dylib 103991bc56edSDimitry Andric // The library may have a suffix trailing the name Foo of the form: 104091bc56edSDimitry Andric // libFoo_profile.A.dylib 104191bc56edSDimitry Andric // libFoo_profile.dylib 104291bc56edSDimitry Andric // 104391bc56edSDimitry Andric // The Name of the dynamic library is also recognized as a library name if it 104491bc56edSDimitry Andric // has the following form: 104591bc56edSDimitry Andric // Foo.qtx 104691bc56edSDimitry Andric // 104791bc56edSDimitry Andric // If the Name of the dynamic library is none of the forms above then a NULL 104891bc56edSDimitry Andric // StringRef is returned. 104991bc56edSDimitry Andric // 105091bc56edSDimitry Andric StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 105191bc56edSDimitry Andric bool &isFramework, 105291bc56edSDimitry Andric StringRef &Suffix) { 105391bc56edSDimitry Andric StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 105491bc56edSDimitry Andric size_t a, b, c, d, Idx; 1055dff0c46cSDimitry Andric 105691bc56edSDimitry Andric isFramework = false; 105791bc56edSDimitry Andric Suffix = StringRef(); 105891bc56edSDimitry Andric 105991bc56edSDimitry Andric // Pull off the last component and make Foo point to it 106091bc56edSDimitry Andric a = Name.rfind('/'); 106191bc56edSDimitry Andric if (a == Name.npos || a == 0) 106291bc56edSDimitry Andric goto guess_library; 106391bc56edSDimitry Andric Foo = Name.slice(a+1, Name.npos); 106491bc56edSDimitry Andric 106591bc56edSDimitry Andric // Look for a suffix starting with a '_' 106691bc56edSDimitry Andric Idx = Foo.rfind('_'); 106791bc56edSDimitry Andric if (Idx != Foo.npos && Foo.size() >= 2) { 106891bc56edSDimitry Andric Suffix = Foo.slice(Idx, Foo.npos); 106991bc56edSDimitry Andric Foo = Foo.slice(0, Idx); 1070284c1978SDimitry Andric } 1071284c1978SDimitry Andric 107291bc56edSDimitry Andric // First look for the form Foo.framework/Foo 107391bc56edSDimitry Andric b = Name.rfind('/', a); 107491bc56edSDimitry Andric if (b == Name.npos) 107591bc56edSDimitry Andric Idx = 0; 107691bc56edSDimitry Andric else 107791bc56edSDimitry Andric Idx = b+1; 107891bc56edSDimitry Andric F = Name.slice(Idx, Idx + Foo.size()); 107991bc56edSDimitry Andric DotFramework = Name.slice(Idx + Foo.size(), 108091bc56edSDimitry Andric Idx + Foo.size() + sizeof(".framework/")-1); 108191bc56edSDimitry Andric if (F == Foo && DotFramework == ".framework/") { 108291bc56edSDimitry Andric isFramework = true; 108391bc56edSDimitry Andric return Foo; 108491bc56edSDimitry Andric } 108591bc56edSDimitry Andric 108691bc56edSDimitry Andric // Next look for the form Foo.framework/Versions/A/Foo 108791bc56edSDimitry Andric if (b == Name.npos) 108891bc56edSDimitry Andric goto guess_library; 108991bc56edSDimitry Andric c = Name.rfind('/', b); 109091bc56edSDimitry Andric if (c == Name.npos || c == 0) 109191bc56edSDimitry Andric goto guess_library; 109291bc56edSDimitry Andric V = Name.slice(c+1, Name.npos); 109391bc56edSDimitry Andric if (!V.startswith("Versions/")) 109491bc56edSDimitry Andric goto guess_library; 109591bc56edSDimitry Andric d = Name.rfind('/', c); 109691bc56edSDimitry Andric if (d == Name.npos) 109791bc56edSDimitry Andric Idx = 0; 109891bc56edSDimitry Andric else 109991bc56edSDimitry Andric Idx = d+1; 110091bc56edSDimitry Andric F = Name.slice(Idx, Idx + Foo.size()); 110191bc56edSDimitry Andric DotFramework = Name.slice(Idx + Foo.size(), 110291bc56edSDimitry Andric Idx + Foo.size() + sizeof(".framework/")-1); 110391bc56edSDimitry Andric if (F == Foo && DotFramework == ".framework/") { 110491bc56edSDimitry Andric isFramework = true; 110591bc56edSDimitry Andric return Foo; 110691bc56edSDimitry Andric } 110791bc56edSDimitry Andric 110891bc56edSDimitry Andric guess_library: 110991bc56edSDimitry Andric // pull off the suffix after the "." and make a point to it 111091bc56edSDimitry Andric a = Name.rfind('.'); 111191bc56edSDimitry Andric if (a == Name.npos || a == 0) 111291bc56edSDimitry Andric return StringRef(); 111391bc56edSDimitry Andric Dylib = Name.slice(a, Name.npos); 111491bc56edSDimitry Andric if (Dylib != ".dylib") 111591bc56edSDimitry Andric goto guess_qtx; 111691bc56edSDimitry Andric 111791bc56edSDimitry Andric // First pull off the version letter for the form Foo.A.dylib if any. 111891bc56edSDimitry Andric if (a >= 3) { 111991bc56edSDimitry Andric Dot = Name.slice(a-2, a-1); 112091bc56edSDimitry Andric if (Dot == ".") 112191bc56edSDimitry Andric a = a - 2; 112291bc56edSDimitry Andric } 112391bc56edSDimitry Andric 112491bc56edSDimitry Andric b = Name.rfind('/', a); 112591bc56edSDimitry Andric if (b == Name.npos) 112691bc56edSDimitry Andric b = 0; 112791bc56edSDimitry Andric else 112891bc56edSDimitry Andric b = b+1; 112991bc56edSDimitry Andric // ignore any suffix after an underbar like Foo_profile.A.dylib 113091bc56edSDimitry Andric Idx = Name.find('_', b); 113191bc56edSDimitry Andric if (Idx != Name.npos && Idx != b) { 113291bc56edSDimitry Andric Lib = Name.slice(b, Idx); 113391bc56edSDimitry Andric Suffix = Name.slice(Idx, a); 113491bc56edSDimitry Andric } 113591bc56edSDimitry Andric else 113691bc56edSDimitry Andric Lib = Name.slice(b, a); 113791bc56edSDimitry Andric // There are incorrect library names of the form: 113891bc56edSDimitry Andric // libATS.A_profile.dylib so check for these. 113991bc56edSDimitry Andric if (Lib.size() >= 3) { 114091bc56edSDimitry Andric Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 114191bc56edSDimitry Andric if (Dot == ".") 114291bc56edSDimitry Andric Lib = Lib.slice(0, Lib.size()-2); 114391bc56edSDimitry Andric } 114491bc56edSDimitry Andric return Lib; 114591bc56edSDimitry Andric 114691bc56edSDimitry Andric guess_qtx: 114791bc56edSDimitry Andric Qtx = Name.slice(a, Name.npos); 114891bc56edSDimitry Andric if (Qtx != ".qtx") 114991bc56edSDimitry Andric return StringRef(); 115091bc56edSDimitry Andric b = Name.rfind('/', a); 115191bc56edSDimitry Andric if (b == Name.npos) 115291bc56edSDimitry Andric Lib = Name.slice(0, a); 115391bc56edSDimitry Andric else 115491bc56edSDimitry Andric Lib = Name.slice(b+1, a); 115591bc56edSDimitry Andric // There are library names of the form: QT.A.qtx so check for these. 115691bc56edSDimitry Andric if (Lib.size() >= 3) { 115791bc56edSDimitry Andric Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 115891bc56edSDimitry Andric if (Dot == ".") 115991bc56edSDimitry Andric Lib = Lib.slice(0, Lib.size()-2); 116091bc56edSDimitry Andric } 116191bc56edSDimitry Andric return Lib; 116291bc56edSDimitry Andric } 116391bc56edSDimitry Andric 116491bc56edSDimitry Andric // getLibraryShortNameByIndex() is used to get the short name of the library 116591bc56edSDimitry Andric // for an undefined symbol in a linked Mach-O binary that was linked with the 116691bc56edSDimitry Andric // normal two-level namespace default (that is MH_TWOLEVEL in the header). 116791bc56edSDimitry Andric // It is passed the index (0 - based) of the library as translated from 116891bc56edSDimitry Andric // GET_LIBRARY_ORDINAL (1 - based). 116991bc56edSDimitry Andric std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 117091bc56edSDimitry Andric StringRef &Res) { 117191bc56edSDimitry Andric if (Index >= Libraries.size()) 117291bc56edSDimitry Andric return object_error::parse_failed; 117391bc56edSDimitry Andric 117491bc56edSDimitry Andric MachO::dylib_command D = 117591bc56edSDimitry Andric getStruct<MachO::dylib_command>(this, Libraries[Index]); 117691bc56edSDimitry Andric if (D.dylib.name >= D.cmdsize) 117791bc56edSDimitry Andric return object_error::parse_failed; 117891bc56edSDimitry Andric 117991bc56edSDimitry Andric // If the cache of LibrariesShortNames is not built up do that first for 118091bc56edSDimitry Andric // all the Libraries. 118191bc56edSDimitry Andric if (LibrariesShortNames.size() == 0) { 118291bc56edSDimitry Andric for (unsigned i = 0; i < Libraries.size(); i++) { 118391bc56edSDimitry Andric MachO::dylib_command D = 118491bc56edSDimitry Andric getStruct<MachO::dylib_command>(this, Libraries[i]); 118591bc56edSDimitry Andric if (D.dylib.name >= D.cmdsize) { 118691bc56edSDimitry Andric LibrariesShortNames.push_back(StringRef()); 118791bc56edSDimitry Andric continue; 118891bc56edSDimitry Andric } 118991bc56edSDimitry Andric const char *P = (const char *)(Libraries[i]) + D.dylib.name; 119091bc56edSDimitry Andric StringRef Name = StringRef(P); 119191bc56edSDimitry Andric StringRef Suffix; 119291bc56edSDimitry Andric bool isFramework; 119391bc56edSDimitry Andric StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 119491bc56edSDimitry Andric if (shortName == StringRef()) 119591bc56edSDimitry Andric LibrariesShortNames.push_back(Name); 119691bc56edSDimitry Andric else 119791bc56edSDimitry Andric LibrariesShortNames.push_back(shortName); 119891bc56edSDimitry Andric } 119991bc56edSDimitry Andric } 120091bc56edSDimitry Andric 120191bc56edSDimitry Andric Res = LibrariesShortNames[Index]; 120291bc56edSDimitry Andric return object_error::success; 120391bc56edSDimitry Andric } 120491bc56edSDimitry Andric 120591bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 120691bc56edSDimitry Andric return getSymbolByIndex(0); 120791bc56edSDimitry Andric } 120891bc56edSDimitry Andric 120991bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1210284c1978SDimitry Andric DataRefImpl DRI; 1211284c1978SDimitry Andric if (!SymtabLoadCmd) 121291bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this)); 1213284c1978SDimitry Andric 1214f785676fSDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand(); 1215284c1978SDimitry Andric unsigned SymbolTableEntrySize = is64Bit() ? 1216f785676fSDimitry Andric sizeof(MachO::nlist_64) : 1217f785676fSDimitry Andric sizeof(MachO::nlist); 1218f785676fSDimitry Andric unsigned Offset = Symtab.symoff + 1219f785676fSDimitry Andric Symtab.nsyms * SymbolTableEntrySize; 1220284c1978SDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 122191bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this)); 1222284c1978SDimitry Andric } 1223284c1978SDimitry Andric 122491bc56edSDimitry Andric basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 122591bc56edSDimitry Andric DataRefImpl DRI; 122691bc56edSDimitry Andric if (!SymtabLoadCmd) 122791bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this)); 122891bc56edSDimitry Andric 122991bc56edSDimitry Andric MachO::symtab_command Symtab = getSymtabLoadCommand(); 123091bc56edSDimitry Andric assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 123191bc56edSDimitry Andric unsigned SymbolTableEntrySize = 123291bc56edSDimitry Andric is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 123391bc56edSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 123491bc56edSDimitry Andric DRI.p += Index * SymbolTableEntrySize; 123591bc56edSDimitry Andric return basic_symbol_iterator(SymbolRef(DRI, this)); 1236284c1978SDimitry Andric } 1237284c1978SDimitry Andric 123891bc56edSDimitry Andric section_iterator MachOObjectFile::section_begin() const { 1239284c1978SDimitry Andric DataRefImpl DRI; 1240284c1978SDimitry Andric return section_iterator(SectionRef(DRI, this)); 1241284c1978SDimitry Andric } 1242284c1978SDimitry Andric 124391bc56edSDimitry Andric section_iterator MachOObjectFile::section_end() const { 1244284c1978SDimitry Andric DataRefImpl DRI; 1245284c1978SDimitry Andric DRI.d.a = Sections.size(); 1246284c1978SDimitry Andric return section_iterator(SectionRef(DRI, this)); 1247284c1978SDimitry Andric } 1248284c1978SDimitry Andric 124991bc56edSDimitry Andric library_iterator MachOObjectFile::needed_library_begin() const { 1250284c1978SDimitry Andric // TODO: implement 1251284c1978SDimitry Andric report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1252284c1978SDimitry Andric } 1253284c1978SDimitry Andric 125491bc56edSDimitry Andric library_iterator MachOObjectFile::needed_library_end() const { 1255284c1978SDimitry Andric // TODO: implement 1256284c1978SDimitry Andric report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1257284c1978SDimitry Andric } 12583b0f4066SDimitry Andric 12593b0f4066SDimitry Andric uint8_t MachOObjectFile::getBytesInAddress() const { 1260284c1978SDimitry Andric return is64Bit() ? 8 : 4; 12613b0f4066SDimitry Andric } 12623b0f4066SDimitry Andric 12633b0f4066SDimitry Andric StringRef MachOObjectFile::getFileFormatName() const { 1264284c1978SDimitry Andric unsigned CPUType = getCPUType(this); 1265284c1978SDimitry Andric if (!is64Bit()) { 1266284c1978SDimitry Andric switch (CPUType) { 1267f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_I386: 12683b0f4066SDimitry Andric return "Mach-O 32-bit i386"; 1269f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_ARM: 12703b0f4066SDimitry Andric return "Mach-O arm"; 1271f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_POWERPC: 12723b0f4066SDimitry Andric return "Mach-O 32-bit ppc"; 12733b0f4066SDimitry Andric default: 1274f785676fSDimitry Andric assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 12753b0f4066SDimitry Andric "64-bit object file when we're not 64-bit?"); 12763b0f4066SDimitry Andric return "Mach-O 32-bit unknown"; 12773b0f4066SDimitry Andric } 12783b0f4066SDimitry Andric } 12793b0f4066SDimitry Andric 1280139f7f9bSDimitry Andric // Make sure the cpu type has the correct mask. 1281f785676fSDimitry Andric assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1282f785676fSDimitry Andric == llvm::MachO::CPU_ARCH_ABI64 && 1283139f7f9bSDimitry Andric "32-bit object file when we're 64-bit?"); 1284139f7f9bSDimitry Andric 1285284c1978SDimitry Andric switch (CPUType) { 1286f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_X86_64: 12873b0f4066SDimitry Andric return "Mach-O 64-bit x86-64"; 128891bc56edSDimitry Andric case llvm::MachO::CPU_TYPE_ARM64: 128991bc56edSDimitry Andric return "Mach-O arm64"; 1290f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_POWERPC64: 12913b0f4066SDimitry Andric return "Mach-O 64-bit ppc64"; 12923b0f4066SDimitry Andric default: 12933b0f4066SDimitry Andric return "Mach-O 64-bit unknown"; 12943b0f4066SDimitry Andric } 12953b0f4066SDimitry Andric } 12963b0f4066SDimitry Andric 1297f785676fSDimitry Andric Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1298f785676fSDimitry Andric switch (CPUType) { 1299f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_I386: 13003b0f4066SDimitry Andric return Triple::x86; 1301f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_X86_64: 13023b0f4066SDimitry Andric return Triple::x86_64; 1303f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_ARM: 13043b0f4066SDimitry Andric return Triple::arm; 130591bc56edSDimitry Andric case llvm::MachO::CPU_TYPE_ARM64: 130691bc56edSDimitry Andric return Triple::arm64; 1307f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_POWERPC: 13083b0f4066SDimitry Andric return Triple::ppc; 1309f785676fSDimitry Andric case llvm::MachO::CPU_TYPE_POWERPC64: 13103b0f4066SDimitry Andric return Triple::ppc64; 13113b0f4066SDimitry Andric default: 13123b0f4066SDimitry Andric return Triple::UnknownArch; 13133b0f4066SDimitry Andric } 13143b0f4066SDimitry Andric } 13153b0f4066SDimitry Andric 131691bc56edSDimitry Andric Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { 131791bc56edSDimitry Andric switch (CPUType) { 131891bc56edSDimitry Andric case MachO::CPU_TYPE_I386: 131991bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 132091bc56edSDimitry Andric case MachO::CPU_SUBTYPE_I386_ALL: 132191bc56edSDimitry Andric return Triple("i386-apple-darwin"); 132291bc56edSDimitry Andric default: 132391bc56edSDimitry Andric return Triple(); 132491bc56edSDimitry Andric } 132591bc56edSDimitry Andric case MachO::CPU_TYPE_X86_64: 132691bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 132791bc56edSDimitry Andric case MachO::CPU_SUBTYPE_X86_64_ALL: 132891bc56edSDimitry Andric return Triple("x86_64-apple-darwin"); 132991bc56edSDimitry Andric case MachO::CPU_SUBTYPE_X86_64_H: 133091bc56edSDimitry Andric return Triple("x86_64h-apple-darwin"); 133191bc56edSDimitry Andric default: 133291bc56edSDimitry Andric return Triple(); 133391bc56edSDimitry Andric } 133491bc56edSDimitry Andric case MachO::CPU_TYPE_ARM: 133591bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 133691bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V4T: 133791bc56edSDimitry Andric return Triple("armv4t-apple-darwin"); 133891bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V5TEJ: 133991bc56edSDimitry Andric return Triple("armv5e-apple-darwin"); 134091bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V6: 134191bc56edSDimitry Andric return Triple("armv6-apple-darwin"); 134291bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V6M: 134391bc56edSDimitry Andric return Triple("armv6m-apple-darwin"); 134491bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7EM: 134591bc56edSDimitry Andric return Triple("armv7em-apple-darwin"); 134691bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7K: 134791bc56edSDimitry Andric return Triple("armv7k-apple-darwin"); 134891bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7M: 134991bc56edSDimitry Andric return Triple("armv7m-apple-darwin"); 135091bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM_V7S: 135191bc56edSDimitry Andric return Triple("armv7s-apple-darwin"); 135291bc56edSDimitry Andric default: 135391bc56edSDimitry Andric return Triple(); 135491bc56edSDimitry Andric } 135591bc56edSDimitry Andric case MachO::CPU_TYPE_ARM64: 135691bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 135791bc56edSDimitry Andric case MachO::CPU_SUBTYPE_ARM64_ALL: 135891bc56edSDimitry Andric return Triple("arm64-apple-darwin"); 135991bc56edSDimitry Andric default: 136091bc56edSDimitry Andric return Triple(); 136191bc56edSDimitry Andric } 136291bc56edSDimitry Andric case MachO::CPU_TYPE_POWERPC: 136391bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 136491bc56edSDimitry Andric case MachO::CPU_SUBTYPE_POWERPC_ALL: 136591bc56edSDimitry Andric return Triple("ppc-apple-darwin"); 136691bc56edSDimitry Andric default: 136791bc56edSDimitry Andric return Triple(); 136891bc56edSDimitry Andric } 136991bc56edSDimitry Andric case MachO::CPU_TYPE_POWERPC64: 137091bc56edSDimitry Andric switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 137191bc56edSDimitry Andric case MachO::CPU_SUBTYPE_POWERPC_ALL: 137291bc56edSDimitry Andric return Triple("ppc64-apple-darwin"); 137391bc56edSDimitry Andric default: 137491bc56edSDimitry Andric return Triple(); 137591bc56edSDimitry Andric } 137691bc56edSDimitry Andric default: 137791bc56edSDimitry Andric return Triple(); 137891bc56edSDimitry Andric } 137991bc56edSDimitry Andric } 138091bc56edSDimitry Andric 138191bc56edSDimitry Andric Triple MachOObjectFile::getHostArch() { 138291bc56edSDimitry Andric return Triple(sys::getDefaultTargetTriple()); 138391bc56edSDimitry Andric } 138491bc56edSDimitry Andric 138591bc56edSDimitry Andric Triple MachOObjectFile::getArch(StringRef ArchFlag) { 138691bc56edSDimitry Andric if (ArchFlag == "i386") 138791bc56edSDimitry Andric return Triple("i386-apple-darwin"); 138891bc56edSDimitry Andric else if (ArchFlag == "x86_64") 138991bc56edSDimitry Andric return Triple("x86_64-apple-darwin"); 139091bc56edSDimitry Andric else if (ArchFlag == "x86_64h") 139191bc56edSDimitry Andric return Triple("x86_64h-apple-darwin"); 139291bc56edSDimitry Andric else if (ArchFlag == "armv4t" || ArchFlag == "arm") 139391bc56edSDimitry Andric return Triple("armv4t-apple-darwin"); 139491bc56edSDimitry Andric else if (ArchFlag == "armv5e") 139591bc56edSDimitry Andric return Triple("armv5e-apple-darwin"); 139691bc56edSDimitry Andric else if (ArchFlag == "armv6") 139791bc56edSDimitry Andric return Triple("armv6-apple-darwin"); 139891bc56edSDimitry Andric else if (ArchFlag == "armv6m") 139991bc56edSDimitry Andric return Triple("armv6m-apple-darwin"); 140091bc56edSDimitry Andric else if (ArchFlag == "armv7em") 140191bc56edSDimitry Andric return Triple("armv7em-apple-darwin"); 140291bc56edSDimitry Andric else if (ArchFlag == "armv7k") 140391bc56edSDimitry Andric return Triple("armv7k-apple-darwin"); 140491bc56edSDimitry Andric else if (ArchFlag == "armv7k") 140591bc56edSDimitry Andric return Triple("armv7m-apple-darwin"); 140691bc56edSDimitry Andric else if (ArchFlag == "armv7s") 140791bc56edSDimitry Andric return Triple("armv7s-apple-darwin"); 140891bc56edSDimitry Andric else if (ArchFlag == "arm64") 140991bc56edSDimitry Andric return Triple("arm64-apple-darwin"); 141091bc56edSDimitry Andric else if (ArchFlag == "ppc") 141191bc56edSDimitry Andric return Triple("ppc-apple-darwin"); 141291bc56edSDimitry Andric else if (ArchFlag == "ppc64") 141391bc56edSDimitry Andric return Triple("ppc64-apple-darwin"); 141491bc56edSDimitry Andric else 141591bc56edSDimitry Andric return Triple(); 141691bc56edSDimitry Andric } 141791bc56edSDimitry Andric 1418f785676fSDimitry Andric unsigned MachOObjectFile::getArch() const { 1419f785676fSDimitry Andric return getArch(getCPUType(this)); 1420f785676fSDimitry Andric } 1421f785676fSDimitry Andric 1422284c1978SDimitry Andric StringRef MachOObjectFile::getLoadName() const { 1423284c1978SDimitry Andric // TODO: Implement 1424284c1978SDimitry Andric report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1425284c1978SDimitry Andric } 1426284c1978SDimitry Andric 1427f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1428284c1978SDimitry Andric DataRefImpl DRI; 1429284c1978SDimitry Andric DRI.d.a = Index; 1430f785676fSDimitry Andric return section_rel_begin(DRI); 1431284c1978SDimitry Andric } 1432284c1978SDimitry Andric 1433f785676fSDimitry Andric relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1434284c1978SDimitry Andric DataRefImpl DRI; 1435284c1978SDimitry Andric DRI.d.a = Index; 1436f785676fSDimitry Andric return section_rel_end(DRI); 1437f785676fSDimitry Andric } 1438f785676fSDimitry Andric 1439f785676fSDimitry Andric dice_iterator MachOObjectFile::begin_dices() const { 1440f785676fSDimitry Andric DataRefImpl DRI; 1441f785676fSDimitry Andric if (!DataInCodeLoadCmd) 1442f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this)); 1443f785676fSDimitry Andric 1444f785676fSDimitry Andric MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1445f785676fSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1446f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this)); 1447f785676fSDimitry Andric } 1448f785676fSDimitry Andric 1449f785676fSDimitry Andric dice_iterator MachOObjectFile::end_dices() const { 1450f785676fSDimitry Andric DataRefImpl DRI; 1451f785676fSDimitry Andric if (!DataInCodeLoadCmd) 1452f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this)); 1453f785676fSDimitry Andric 1454f785676fSDimitry Andric MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1455f785676fSDimitry Andric unsigned Offset = DicLC.dataoff + DicLC.datasize; 1456f785676fSDimitry Andric DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1457f785676fSDimitry Andric return dice_iterator(DiceRef(DRI, this)); 1458284c1978SDimitry Andric } 1459284c1978SDimitry Andric 1460284c1978SDimitry Andric StringRef 1461284c1978SDimitry Andric MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1462284c1978SDimitry Andric ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1463284c1978SDimitry Andric return parseSegmentOrSectionName(Raw.data()); 1464284c1978SDimitry Andric } 1465284c1978SDimitry Andric 1466284c1978SDimitry Andric ArrayRef<char> 1467284c1978SDimitry Andric MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1468f785676fSDimitry Andric const section_base *Base = 1469f785676fSDimitry Andric reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1470f785676fSDimitry Andric return ArrayRef<char>(Base->sectname); 1471284c1978SDimitry Andric } 1472284c1978SDimitry Andric 1473284c1978SDimitry Andric ArrayRef<char> 1474284c1978SDimitry Andric MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1475f785676fSDimitry Andric const section_base *Base = 1476f785676fSDimitry Andric reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1477f785676fSDimitry Andric return ArrayRef<char>(Base->segname); 1478284c1978SDimitry Andric } 1479284c1978SDimitry Andric 1480284c1978SDimitry Andric bool 1481f785676fSDimitry Andric MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1482284c1978SDimitry Andric const { 1483f785676fSDimitry Andric if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1484284c1978SDimitry Andric return false; 1485f785676fSDimitry Andric return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1486284c1978SDimitry Andric } 1487284c1978SDimitry Andric 1488f785676fSDimitry Andric unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1489f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1490284c1978SDimitry Andric if (isLittleEndian()) 1491f785676fSDimitry Andric return RE.r_word1 & 0xffffff; 1492f785676fSDimitry Andric return RE.r_word1 >> 8; 1493284c1978SDimitry Andric } 1494284c1978SDimitry Andric 1495f785676fSDimitry Andric bool MachOObjectFile::getPlainRelocationExternal( 1496f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1497284c1978SDimitry Andric if (isLittleEndian()) 1498f785676fSDimitry Andric return (RE.r_word1 >> 27) & 1; 1499f785676fSDimitry Andric return (RE.r_word1 >> 4) & 1; 1500284c1978SDimitry Andric } 1501284c1978SDimitry Andric 1502f785676fSDimitry Andric bool MachOObjectFile::getScatteredRelocationScattered( 1503f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1504f785676fSDimitry Andric return RE.r_word0 >> 31; 1505284c1978SDimitry Andric } 1506284c1978SDimitry Andric 1507f785676fSDimitry Andric uint32_t MachOObjectFile::getScatteredRelocationValue( 1508f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1509f785676fSDimitry Andric return RE.r_word1; 1510284c1978SDimitry Andric } 1511284c1978SDimitry Andric 1512f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationAddress( 1513f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1514284c1978SDimitry Andric if (isRelocationScattered(RE)) 1515284c1978SDimitry Andric return getScatteredRelocationAddress(RE); 1516284c1978SDimitry Andric return getPlainRelocationAddress(RE); 1517284c1978SDimitry Andric } 1518284c1978SDimitry Andric 1519f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationPCRel( 1520f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1521284c1978SDimitry Andric if (isRelocationScattered(RE)) 1522284c1978SDimitry Andric return getScatteredRelocationPCRel(this, RE); 1523284c1978SDimitry Andric return getPlainRelocationPCRel(this, RE); 1524284c1978SDimitry Andric } 1525284c1978SDimitry Andric 1526f785676fSDimitry Andric unsigned MachOObjectFile::getAnyRelocationLength( 1527f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1528284c1978SDimitry Andric if (isRelocationScattered(RE)) 1529284c1978SDimitry Andric return getScatteredRelocationLength(RE); 1530284c1978SDimitry Andric return getPlainRelocationLength(this, RE); 1531284c1978SDimitry Andric } 1532284c1978SDimitry Andric 1533284c1978SDimitry Andric unsigned 1534f785676fSDimitry Andric MachOObjectFile::getAnyRelocationType( 1535f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1536284c1978SDimitry Andric if (isRelocationScattered(RE)) 1537284c1978SDimitry Andric return getScatteredRelocationType(RE); 1538284c1978SDimitry Andric return getPlainRelocationType(this, RE); 1539284c1978SDimitry Andric } 1540284c1978SDimitry Andric 1541284c1978SDimitry Andric SectionRef 1542f785676fSDimitry Andric MachOObjectFile::getRelocationSection( 1543f785676fSDimitry Andric const MachO::any_relocation_info &RE) const { 1544284c1978SDimitry Andric if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 154591bc56edSDimitry Andric return *section_end(); 1546284c1978SDimitry Andric unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1547284c1978SDimitry Andric DataRefImpl DRI; 1548284c1978SDimitry Andric DRI.d.a = SecNum; 1549284c1978SDimitry Andric return SectionRef(DRI, this); 1550284c1978SDimitry Andric } 1551284c1978SDimitry Andric 1552284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo 1553284c1978SDimitry Andric MachOObjectFile::getFirstLoadCommandInfo() const { 1554284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo Load; 1555284c1978SDimitry Andric 1556f785676fSDimitry Andric unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1557f785676fSDimitry Andric sizeof(MachO::mach_header); 1558284c1978SDimitry Andric Load.Ptr = getPtr(this, HeaderSize); 1559f785676fSDimitry Andric Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1560284c1978SDimitry Andric return Load; 1561284c1978SDimitry Andric } 1562284c1978SDimitry Andric 1563284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo 1564284c1978SDimitry Andric MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1565284c1978SDimitry Andric MachOObjectFile::LoadCommandInfo Next; 1566f785676fSDimitry Andric Next.Ptr = L.Ptr + L.C.cmdsize; 1567f785676fSDimitry Andric Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1568284c1978SDimitry Andric return Next; 1569284c1978SDimitry Andric } 1570284c1978SDimitry Andric 1571f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1572f785676fSDimitry Andric return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1573284c1978SDimitry Andric } 1574284c1978SDimitry Andric 1575f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1576f785676fSDimitry Andric return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1577284c1978SDimitry Andric } 1578284c1978SDimitry Andric 1579f785676fSDimitry Andric MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1580284c1978SDimitry Andric unsigned Index) const { 1581284c1978SDimitry Andric const char *Sec = getSectionPtr(this, L, Index); 1582f785676fSDimitry Andric return getStruct<MachO::section>(this, Sec); 1583284c1978SDimitry Andric } 1584284c1978SDimitry Andric 1585f785676fSDimitry Andric MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1586284c1978SDimitry Andric unsigned Index) const { 1587284c1978SDimitry Andric const char *Sec = getSectionPtr(this, L, Index); 1588f785676fSDimitry Andric return getStruct<MachO::section_64>(this, Sec); 1589284c1978SDimitry Andric } 1590284c1978SDimitry Andric 1591f785676fSDimitry Andric MachO::nlist 1592284c1978SDimitry Andric MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1593284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p); 1594f785676fSDimitry Andric return getStruct<MachO::nlist>(this, P); 1595284c1978SDimitry Andric } 1596284c1978SDimitry Andric 1597f785676fSDimitry Andric MachO::nlist_64 1598284c1978SDimitry Andric MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1599284c1978SDimitry Andric const char *P = reinterpret_cast<const char *>(DRI.p); 1600f785676fSDimitry Andric return getStruct<MachO::nlist_64>(this, P); 1601284c1978SDimitry Andric } 1602284c1978SDimitry Andric 1603f785676fSDimitry Andric MachO::linkedit_data_command 1604f785676fSDimitry Andric MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1605f785676fSDimitry Andric return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1606284c1978SDimitry Andric } 1607284c1978SDimitry Andric 1608f785676fSDimitry Andric MachO::segment_command 1609284c1978SDimitry Andric MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1610f785676fSDimitry Andric return getStruct<MachO::segment_command>(this, L.Ptr); 1611284c1978SDimitry Andric } 1612284c1978SDimitry Andric 1613f785676fSDimitry Andric MachO::segment_command_64 1614284c1978SDimitry Andric MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1615f785676fSDimitry Andric return getStruct<MachO::segment_command_64>(this, L.Ptr); 1616284c1978SDimitry Andric } 1617284c1978SDimitry Andric 1618f785676fSDimitry Andric MachO::linker_options_command 1619284c1978SDimitry Andric MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1620f785676fSDimitry Andric return getStruct<MachO::linker_options_command>(this, L.Ptr); 1621284c1978SDimitry Andric } 1622284c1978SDimitry Andric 162391bc56edSDimitry Andric MachO::version_min_command 162491bc56edSDimitry Andric MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 162591bc56edSDimitry Andric return getStruct<MachO::version_min_command>(this, L.Ptr); 162691bc56edSDimitry Andric } 162791bc56edSDimitry Andric 162891bc56edSDimitry Andric MachO::dylib_command 162991bc56edSDimitry Andric MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 163091bc56edSDimitry Andric return getStruct<MachO::dylib_command>(this, L.Ptr); 163191bc56edSDimitry Andric } 163291bc56edSDimitry Andric 163391bc56edSDimitry Andric 1634f785676fSDimitry Andric MachO::any_relocation_info 1635284c1978SDimitry Andric MachOObjectFile::getRelocation(DataRefImpl Rel) const { 163691bc56edSDimitry Andric DataRefImpl Sec; 163791bc56edSDimitry Andric Sec.d.a = Rel.d.a; 163891bc56edSDimitry Andric uint32_t Offset; 163991bc56edSDimitry Andric if (is64Bit()) { 164091bc56edSDimitry Andric MachO::section_64 Sect = getSection64(Sec); 164191bc56edSDimitry Andric Offset = Sect.reloff; 164291bc56edSDimitry Andric } else { 164391bc56edSDimitry Andric MachO::section Sect = getSection(Sec); 164491bc56edSDimitry Andric Offset = Sect.reloff; 164591bc56edSDimitry Andric } 164691bc56edSDimitry Andric 164791bc56edSDimitry Andric auto P = reinterpret_cast<const MachO::any_relocation_info *>( 164891bc56edSDimitry Andric getPtr(this, Offset)) + Rel.d.b; 164991bc56edSDimitry Andric return getStruct<MachO::any_relocation_info>( 165091bc56edSDimitry Andric this, reinterpret_cast<const char *>(P)); 1651284c1978SDimitry Andric } 1652284c1978SDimitry Andric 1653f785676fSDimitry Andric MachO::data_in_code_entry 1654f785676fSDimitry Andric MachOObjectFile::getDice(DataRefImpl Rel) const { 1655f785676fSDimitry Andric const char *P = reinterpret_cast<const char *>(Rel.p); 1656f785676fSDimitry Andric return getStruct<MachO::data_in_code_entry>(this, P); 1657284c1978SDimitry Andric } 1658284c1978SDimitry Andric 1659f785676fSDimitry Andric MachO::mach_header MachOObjectFile::getHeader() const { 1660f785676fSDimitry Andric return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1661284c1978SDimitry Andric } 1662284c1978SDimitry Andric 1663f785676fSDimitry Andric MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1664f785676fSDimitry Andric return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1665f785676fSDimitry Andric } 1666f785676fSDimitry Andric 1667f785676fSDimitry Andric uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1668f785676fSDimitry Andric const MachO::dysymtab_command &DLC, 1669284c1978SDimitry Andric unsigned Index) const { 1670f785676fSDimitry Andric uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1671f785676fSDimitry Andric return getStruct<uint32_t>(this, getPtr(this, Offset)); 1672284c1978SDimitry Andric } 1673284c1978SDimitry Andric 1674f785676fSDimitry Andric MachO::data_in_code_entry 1675284c1978SDimitry Andric MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1676284c1978SDimitry Andric unsigned Index) const { 1677f785676fSDimitry Andric uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1678f785676fSDimitry Andric return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1679284c1978SDimitry Andric } 1680284c1978SDimitry Andric 1681f785676fSDimitry Andric MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1682f785676fSDimitry Andric return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1683284c1978SDimitry Andric } 1684284c1978SDimitry Andric 1685f785676fSDimitry Andric MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1686f785676fSDimitry Andric return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1687f785676fSDimitry Andric } 1688f785676fSDimitry Andric 1689f785676fSDimitry Andric MachO::linkedit_data_command 1690f785676fSDimitry Andric MachOObjectFile::getDataInCodeLoadCommand() const { 1691f785676fSDimitry Andric if (DataInCodeLoadCmd) 1692f785676fSDimitry Andric return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1693f785676fSDimitry Andric 1694f785676fSDimitry Andric // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1695f785676fSDimitry Andric MachO::linkedit_data_command Cmd; 1696f785676fSDimitry Andric Cmd.cmd = MachO::LC_DATA_IN_CODE; 1697f785676fSDimitry Andric Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1698f785676fSDimitry Andric Cmd.dataoff = 0; 1699f785676fSDimitry Andric Cmd.datasize = 0; 1700f785676fSDimitry Andric return Cmd; 1701284c1978SDimitry Andric } 1702284c1978SDimitry Andric 1703284c1978SDimitry Andric StringRef MachOObjectFile::getStringTableData() const { 1704f785676fSDimitry Andric MachO::symtab_command S = getSymtabLoadCommand(); 1705f785676fSDimitry Andric return getData().substr(S.stroff, S.strsize); 1706284c1978SDimitry Andric } 1707284c1978SDimitry Andric 1708284c1978SDimitry Andric bool MachOObjectFile::is64Bit() const { 1709284c1978SDimitry Andric return getType() == getMachOType(false, true) || 1710284c1978SDimitry Andric getType() == getMachOType(true, true); 1711284c1978SDimitry Andric } 1712284c1978SDimitry Andric 1713284c1978SDimitry Andric void MachOObjectFile::ReadULEB128s(uint64_t Index, 1714284c1978SDimitry Andric SmallVectorImpl<uint64_t> &Out) const { 1715284c1978SDimitry Andric DataExtractor extractor(ObjectFile::getData(), true, 0); 1716284c1978SDimitry Andric 1717284c1978SDimitry Andric uint32_t offset = Index; 1718284c1978SDimitry Andric uint64_t data = 0; 1719284c1978SDimitry Andric while (uint64_t delta = extractor.getULEB128(&offset)) { 1720284c1978SDimitry Andric data += delta; 1721284c1978SDimitry Andric Out.push_back(data); 1722284c1978SDimitry Andric } 1723284c1978SDimitry Andric } 1724284c1978SDimitry Andric 172591bc56edSDimitry Andric ErrorOr<ObjectFile *> 172691bc56edSDimitry Andric ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) { 1727284c1978SDimitry Andric StringRef Magic = Buffer->getBuffer().slice(0, 4); 172891bc56edSDimitry Andric std::error_code EC; 172991bc56edSDimitry Andric std::unique_ptr<MachOObjectFile> Ret; 1730284c1978SDimitry Andric if (Magic == "\xFE\xED\xFA\xCE") 173191bc56edSDimitry Andric Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); 1732284c1978SDimitry Andric else if (Magic == "\xCE\xFA\xED\xFE") 173391bc56edSDimitry Andric Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); 1734284c1978SDimitry Andric else if (Magic == "\xFE\xED\xFA\xCF") 173591bc56edSDimitry Andric Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); 1736284c1978SDimitry Andric else if (Magic == "\xCF\xFA\xED\xFE") 173791bc56edSDimitry Andric Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); 173891bc56edSDimitry Andric else 173991bc56edSDimitry Andric return object_error::parse_failed; 174091bc56edSDimitry Andric 174191bc56edSDimitry Andric if (EC) 174291bc56edSDimitry Andric return EC; 174391bc56edSDimitry Andric return Ret.release(); 1744f785676fSDimitry Andric } 1745284c1978SDimitry Andric 1746