diff options
-rw-r--r-- | include/llvm/Object/Binary.h | 3 | ||||
-rw-r--r-- | include/llvm/Object/MachO.h | 1645 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 1461 | ||||
-rw-r--r-- | test/tools/llvm-readobj/Inputs/trivial.obj.macho-arm | bin | 0 -> 908 bytes | |||
-rw-r--r-- | test/tools/llvm-readobj/relocations.test | 89 | ||||
-rw-r--r-- | test/tools/llvm-readobj/sections-ext.test | 277 | ||||
-rw-r--r-- | test/tools/llvm-readobj/sections.test | 121 | ||||
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 43 | ||||
-rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 20 | ||||
-rw-r--r-- | tools/llvm-readobj/MachODumper.cpp | 133 | ||||
-rw-r--r-- | tools/llvm-symbolizer/LLVMSymbolize.cpp | 2 |
11 files changed, 2039 insertions, 1755 deletions
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index ac5bfed4bf..78fcf6feb8 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -100,7 +100,8 @@ public: } bool isLittleEndian() const { - return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B); + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || + TypeID == ID_MachO32B || TypeID == ID_MachO64B); } }; diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8867068985..cec649e4b1 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MachOObjectFile class, which binds the MachOObject -// class to the generic ObjectFile wrapper. +// This file declares the MachOObjectFile class, which implement the ObjectFile +// interface for MachO files. // //===----------------------------------------------------------------------===// @@ -17,1607 +17,140 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Format.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { -using support::endianness; - -template<endianness E, bool B> -struct MachOType { - static const endianness TargetEndianness = E; - static const bool Is64Bits = B; -}; - -template<endianness TargetEndianness> -struct MachOInt24Impl; - -template<> -struct MachOInt24Impl<support::little> { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; - } -}; - -template<> -struct MachOInt24Impl<support::big> { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2]; - } -}; - -template<endianness TargetEndianness> -struct MachODataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - <uint16_t, TargetEndianness, support::unaligned> MachOInt16; - typedef support::detail::packed_endian_specific_integral - <uint32_t, TargetEndianness, support::unaligned> MachOInt32; - typedef support::detail::packed_endian_specific_integral - <uint64_t, TargetEndianness, support::unaligned> MachOInt64; - typedef MachOInt24Impl<TargetEndianness> MachOInt24; -}; - -#define LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \ -typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \ -typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \ -typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \ -typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24; - -#define LLVM_MACHOB_IMPORT_TYPES(E) \ -typedef MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \ -typedef MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \ -typedef MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \ -typedef MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24; - -template<class MachOT> -struct MachODataTypeTypedefHelper; - -template<endianness TargetEndianness> -struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, false> > { - typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base; - typedef typename Base::MachOInt32 MachOIntPtr; -}; - -template<endianness TargetEndianness> -struct MachODataTypeTypedefHelper<MachOType<TargetEndianness, true> > { - typedef MachODataTypeTypedefHelperCommon<TargetEndianness> Base; - typedef typename Base::MachOInt64 MachOIntPtr; -}; - -#define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \ -LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \ -typedef typename \ - MachODataTypeTypedefHelper <MachOT<E, B> >::MachOIntPtr MachOIntPtr; - -namespace MachOFormat { - struct SectionBase { - char Name[16]; - char SegmentName[16]; - }; - - template<class MachOT> - struct Section; - - template<endianness TargetEndianness> - struct Section<MachOType<TargetEndianness, false> > { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - char Name[16]; - char SegmentName[16]; - MachOInt32 Address; - MachOInt32 Size; - MachOInt32 Offset; - MachOInt32 Align; - MachOInt32 RelocationTableOffset; - MachOInt32 NumRelocationTableEntries; - MachOInt32 Flags; - MachOInt32 Reserved1; - MachOInt32 Reserved2; - }; - - template<endianness TargetEndianness> - struct Section<MachOType<TargetEndianness, true> > { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - char Name[16]; - char SegmentName[16]; - MachOInt64 Address; - MachOInt64 Size; - MachOInt32 Offset; - MachOInt32 Align; - MachOInt32 RelocationTableOffset; - MachOInt32 NumRelocationTableEntries; - MachOInt32 Flags; - MachOInt32 Reserved1; - MachOInt32 Reserved2; - MachOInt32 Reserved3; - }; - - struct MachOInt24 { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; - } - }; - - template<bool HostIsLittleEndian, endianness TargetEndianness> - struct RelocationEntry; - - template<> - struct RelocationEntry<true, support::little> { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned External : 1; - unsigned Type : 4; - }; - - template<> - struct RelocationEntry<false, support::little> { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned Type : 4; - unsigned External : 1; - unsigned Length : 2; - unsigned PCRel : 1; - }; - - template<> - struct RelocationEntry<true, support::big> { - LLVM_MACHOB_IMPORT_TYPES(support::big) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned Type : 4; - unsigned External : 1; - unsigned Length : 2; - unsigned PCRel : 1; - }; - - template<> - struct RelocationEntry<false, support::big> { - LLVM_MACHOB_IMPORT_TYPES(support::big) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned External : 1; - unsigned Type : 4; - }; - - template<bool HostIsLittleEndian, endianness TargetEndianness> - struct ScatteredRelocationEntry; - - template<> - struct ScatteredRelocationEntry<true, support::little> { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt24 Address; - unsigned Type : 4; - unsigned Length : 2; - unsigned PCRel : 1; - unsigned Scattered : 1; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry<false, support::little> { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt24 Address; - unsigned Scattered : 1; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned Type : 4; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry<true, support::big> { - LLVM_MACHOB_IMPORT_TYPES(support::big) - unsigned Type : 4; - unsigned Length : 2; - unsigned PCRel : 1; - unsigned Scattered : 1; - MachOInt24 Address; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry<false, support::big> { - LLVM_MACHOB_IMPORT_TYPES(support::big) - unsigned Scattered : 1; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned Type : 4; - MachOInt24 Address; - MachOInt32 Value; - }; - - template<endianness TargetEndianness> - struct SymbolTableEntryBase { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 StringIndex; - uint8_t Type; - uint8_t SectionIndex; - MachOInt16 Flags; - }; - - template<class MachOT> - struct SymbolTableEntry; - - template<endianness TargetEndianness, bool Is64Bits> - struct SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > { - LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) - MachOInt32 StringIndex; - uint8_t Type; - uint8_t SectionIndex; - MachOInt16 Flags; - MachOIntPtr Value; - }; - - template<endianness TargetEndianness> - struct LoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - }; - - template<endianness TargetEndianness> - struct SymtabLoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - MachOInt32 SymbolTableOffset; - MachOInt32 NumSymbolTableEntries; - MachOInt32 StringTableOffset; - MachOInt32 StringTableSize; - }; - - template<class MachOT> - struct SegmentLoadCommand; - - template<endianness TargetEndianness, bool Is64Bits> - struct SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > { - LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) - MachOInt32 Type; - MachOInt32 Size; - char Name[16]; - MachOIntPtr VMAddress; - MachOIntPtr VMSize; - MachOIntPtr FileOffset; - MachOIntPtr FileSize; - MachOInt32 MaxVMProtection; - MachOInt32 InitialVMProtection; - MachOInt32 NumSections; - MachOInt32 Flags; - }; - - template<endianness TargetEndianness> - struct LinkeditDataLoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - MachOInt32 DataOffset; - MachOInt32 DataSize; - }; - - template<endianness TargetEndianness> - struct Header { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Magic; - MachOInt32 CPUType; - MachOInt32 CPUSubtype; - MachOInt32 FileType; - MachOInt32 NumLoadCommands; - MachOInt32 SizeOfLoadCommands; - MachOInt32 Flags; - }; -} - -class MachOObjectFileBase : public ObjectFile { -public: - typedef MachOFormat::SectionBase SectionBase; - - MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &ec); - - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getLoadName() const; - - bool is64Bit() const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - unsigned getHeaderSize() const; - StringRef getData(size_t Offset, size_t Size) const; - - static inline bool classof(const Binary *v) { - return v->isMachO(); - } - -protected: - StringRef parseSegmentOrSectionName(const char *P) const; - - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; - virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - - std::size_t getSectionIndex(DataRefImpl Sec) const; - - typedef SmallVector<DataRefImpl, 1> SectionList; - SectionList Sections; -}; - -template<endianness TargetEndianness> -class MachOObjectFileMiddle : public MachOObjectFileBase { +class MachOObjectFile : public ObjectFile { public: + struct LoadCommandInfo { + const char *Ptr; // Where in memory the load command is. + macho::LoadCommand C; // The command itself. + }; - typedef MachOFormat::SymbolTableEntryBase<TargetEndianness> - SymbolTableEntryBase; - typedef MachOFormat::LinkeditDataLoadCommand<TargetEndianness> - LinkeditDataLoadCommand; - typedef MachOFormat::Header<TargetEndianness> Header; - typedef MachOFormat::SymtabLoadCommand<TargetEndianness> SymtabLoadCommand; - typedef MachOFormat::RelocationEntry<sys::IsLittleEndianHost, TargetEndianness> RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry<sys::IsLittleEndianHost, TargetEndianness> - ScatteredRelocationEntry; - typedef MachOFormat::LoadCommand<TargetEndianness> LoadCommand; - - MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec); - - const Header *getHeader() const; - const LoadCommand *getLoadCommandInfo(unsigned Index) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isRelocationScattered(const RelocationEntry *RE) const; - bool isRelocationPCRel(const RelocationEntry *RE) const; - unsigned getRelocationLength(const RelocationEntry *RE) const; - unsigned getRelocationTypeImpl(const RelocationEntry *RE) const; - - void moveToNextSymbol(DataRefImpl &DRI) const; - void printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const; - const SectionBase *getSectionBase(DataRefImpl DRI) const; - const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; - unsigned getCPUType() const; - - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. - StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - - // Names are stored as 16 bytes. These returns the raw 16 bytes without - // interpreting them as a C string. - ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; - ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; + MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual symbol_iterator begin_symbols() const; - virtual unsigned getArch() const; - virtual StringRef getFileFormatName() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator end_sections() const; - - static bool classof(const Binary *v); - -private: - // Helper to advance a section or symbol iterator multiple increments at a - // time. - template<class T> - static error_code advance(T &it, size_t Val); - - template<class T> - static void advanceTo(T &it, size_t Val); -}; - -template<class MachOT> -struct MachOObjectFileHelperCommon; - -template<endianness TargetEndianness, bool Is64Bits> -struct MachOObjectFileHelperCommon<MachOType<TargetEndianness, Is64Bits> > { - typedef - MachOFormat::SegmentLoadCommand<MachOType<TargetEndianness, Is64Bits> > - SegmentLoadCommand; - typedef MachOFormat::SymbolTableEntry<MachOType<TargetEndianness, Is64Bits> > - SymbolTableEntry; - typedef MachOFormat::Section<MachOType<TargetEndianness, Is64Bits> > Section; -}; - -template<class MachOT> -struct MachOObjectFileHelper; - -template<endianness TargetEndianness> -struct MachOObjectFileHelper<MachOType<TargetEndianness, false> > : - public MachOObjectFileHelperCommon<MachOType<TargetEndianness, false> > { - static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; -}; - -template<endianness TargetEndianness> -struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > : - public MachOObjectFileHelperCommon<MachOType<TargetEndianness, true> > { - static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; -}; - -template<class MachOT> -class MachOObjectFile : public MachOObjectFileMiddle<MachOT::TargetEndianness> { -public: - static const endianness TargetEndianness = MachOT::TargetEndianness; - static const bool Is64Bits = MachOT::Is64Bits; - - typedef MachOObjectFileMiddle<MachOT::TargetEndianness> Base; - typedef typename Base::RelocationEntry RelocationEntry; - typedef typename Base::SectionBase SectionBase; - typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase; - typedef typename Base::LoadCommand LoadCommand; - - typedef MachOObjectFileHelper<MachOT> Helper; - static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; - typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; - typedef typename Helper::SymbolTableEntry SymbolTableEntry; - typedef typename Helper::Section Section; - - MachOObjectFile(MemoryBuffer *Object, error_code &ec); - static bool classof(const Binary *v); - - const Section *getSection(DataRefImpl DRI) const; - const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual section_iterator begin_sections() const; - void moveToNextSection(DataRefImpl &DRI) const; -}; - -typedef MachOObjectFileMiddle<support::little> MachOObjectFileLE; -typedef MachOObjectFileMiddle<support::big> MachOObjectFileBE; - -typedef MachOObjectFile<MachOType<support::little, false> > - MachOObjectFileLE32; -typedef MachOObjectFile<MachOType<support::big, false> > - MachOObjectFileBE32; -typedef MachOObjectFile<MachOType<support::little, true> > - MachOObjectFileLE64; -typedef MachOObjectFile<MachOType<support::big, true> > - MachOObjectFileBE64; - -template<endianness TargetEndianness> -MachOObjectFileMiddle<TargetEndianness>::MachOObjectFileMiddle(MemoryBuffer *O, - bool Is64Bits, - error_code &ec) : - MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) { -} - -template<endianness E> -const typename MachOObjectFileMiddle<E>::SymbolTableEntryBase * -MachOObjectFileMiddle<E>::getSymbolTableEntryBase(DataRefImpl DRI) const { - const LoadCommand *L = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L); - - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFileLE64::SymbolTableEntry) : - sizeof(MachOObjectFileLE32::SymbolTableEntry); - - uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize; - StringRef Data = getData(Offset, SymbolTableEntrySize); - return reinterpret_cast<const SymbolTableEntryBase*>(Data.data()); -} - -template<endianness E> -const typename MachOObjectFileMiddle<E>::Header * -MachOObjectFileMiddle<E>::getHeader() const { - StringRef Data = getData(0, sizeof(Header)); - return reinterpret_cast<const Header*>(Data.data()); -} - -template<endianness E> -const typename MachOObjectFileMiddle<E>::LoadCommand * -MachOObjectFileMiddle<E>::getLoadCommandInfo(unsigned Index) const { - assert(Index < getHeader()->NumLoadCommands); - uint64_t Offset; - uint64_t NewOffset = getHeaderSize(); - const LoadCommand *Load; - unsigned I = 0; - do { - Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand)); - Load = reinterpret_cast<const LoadCommand*>(Data.data()); - NewOffset = Offset + Load->Size; - ++I; - } while (I != Index + 1); - - return reinterpret_cast<const LoadCommand*>(Load); -} - -template<endianness E> -const typename MachOObjectFileMiddle<E>::RelocationEntry * -MachOObjectFileMiddle<E>::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile<MachOType<E, true> > *O = - dyn_cast<MachOObjectFile<MachOType<E, true> > >(this)) - return O->getRelocation(Rel); - - const MachOObjectFile<MachOType<E, false> > *O = - cast<MachOObjectFile<MachOType<E, false> > >(this); - return O->getRelocation(Rel); -} - -template<endianness E> -bool -MachOObjectFileMiddle<E>::isRelocationScattered(const RelocationEntry *RE) - const { - if (this->getCPUType() == llvm::MachO::CPUTypeX86_64) - return false; - return RE->Address & macho::RF_Scattered; -} - -template<endianness E> -bool -MachOObjectFileMiddle<E>::isRelocationPCRel(const RelocationEntry *RE) const { - typedef MachOObjectFileMiddle<E> ObjType; - if (isRelocationScattered(RE)) { - const typename MachOObjectFileMiddle<E>::ScatteredRelocationEntry *SRE = - reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); - return SRE->PCRel; - } - return RE->PCRel; -} - -template<endianness E> -unsigned -MachOObjectFileMiddle<E>::getRelocationLength(const RelocationEntry *RE) const { - typedef MachOObjectFileMiddle<E> ObjType; - if (isRelocationScattered(RE)) { - const typename ObjType::ScatteredRelocationEntry *SRE = - reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); - return SRE->Length; - } - return RE->Length; -} - -template<endianness E> -unsigned -MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE) - const { - typedef MachOObjectFileMiddle<E> ObjType; - if (isRelocationScattered(RE)) { - const typename ObjType::ScatteredRelocationEntry *SRE = - reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); - return SRE->Type; - } - return RE->Type; -} - -// Helper to advance a section or symbol iterator multiple increments at a time. -template<endianness E> -template<class T> -error_code MachOObjectFileMiddle<E>::advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template<endianness E> -template<class T> -void MachOObjectFileMiddle<E>::advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); -} - -template<endianness E> -void -MachOObjectFileMiddle<E>::printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const { - bool IsScattered = isRelocationScattered(RE); - - // Target of a scattered relocation is an address. In the interest of - // generating pretty output, scan through the symbol table looking for a - // symbol that aligns with that address. If we find one, print it. - // Otherwise, we just print the hex address of the target. - if (IsScattered) { - uint32_t Val = RE->SymbolNum; - - error_code ec; - for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = RE->External; - uint64_t Val = RE->Address; - - if (isExtern) { - symbol_iterator SI = begin_symbols(); - advanceTo(SI, Val); - SI->getName(S); - } else { - section_iterator SI = begin_sections(); - advanceTo(SI, Val); - SI->getName(S); - } - - fmt << S; -} - -template<endianness E> -const typename MachOObjectFileMiddle<E>::SectionBase * -MachOObjectFileMiddle<E>::getSectionBase(DataRefImpl DRI) const { - uintptr_t CommandAddr = - reinterpret_cast<uintptr_t>(getLoadCommandInfo(DRI.d.a)); - - bool Is64 = is64Bit(); - unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) : - sizeof(MachOObjectFileLE32::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) : - sizeof(MachOObjectFileLE32::Section); - - uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast<const SectionBase*>(SectionAddr); -} - -template<endianness E> -unsigned MachOObjectFileMiddle<E>::getCPUType() const { - return getHeader()->CPUType; -} - -template<endianness E> -void MachOObjectFileMiddle<E>::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *L = getLoadCommandInfo(DRI.d.a); - if (L->Type == macho::LCT_Symtab) { - const SymtabLoadCommand *S = - reinterpret_cast<const SymtabLoadCommand *>(L); - if (DRI.d.b < S->NumSymbolTableEntries) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -template<endianness E> -StringRef -MachOObjectFileMiddle<E>::getSectionFinalSegmentName(DataRefImpl Sec) const { - ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); - return parseSegmentOrSectionName(Raw.data()); -} - -template<endianness E> -ArrayRef<char> -MachOObjectFileMiddle<E>::getSectionRawName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef<char>(Base->Name); -} - -template<endianness E> -ArrayRef<char> -MachOObjectFileMiddle<E>::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef<char>(Base->SegmentName); -} - -template<endianness E> -error_code MachOObjectFileMiddle<E>::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - - uint8_t MachOType = Entry->Type; - uint16_t MachOFlags = Entry->Flags; - - // TODO: Correctly set SF_ThreadLocal - Result = SymbolRef::SF_None; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Undefined; - - if (MachOFlags & macho::STF_StabsEntryMask) - Result |= SymbolRef::SF_FormatSpecific; - - if (MachOType & MachO::NlistMaskExternal) { - Result |= SymbolRef::SF_Global; - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Common; - } - - if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) - Result |= SymbolRef::SF_Weak; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) - Result |= SymbolRef::SF_Absolute; - - return object_error::success; -} - -template<endianness E> -error_code MachOObjectFileMiddle<E>::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t n_type = Entry->Type; - - Res = SymbolRef::ST_Other; - - // If this is a STAB debugging symbol, we can do nothing more. - if (n_type & MachO::NlistMaskStab) { - Res = SymbolRef::ST_Debug; - return object_error::success; - } - - switch (n_type & MachO::NlistMaskType) { - case MachO::NListTypeUndefined : - Res = SymbolRef::ST_Unknown; - break; - case MachO::NListTypeSection : - Res = SymbolRef::ST_Function; - break; - } - return object_error::success; -} - -template<endianness E> -error_code MachOObjectFileMiddle<E>::getSymbolName(DataRefImpl Symb, - StringRef &Res) const { - const LoadCommand *L = getLoadCommandInfo(Symb.d.a); - const SymtabLoadCommand *S = reinterpret_cast<const SymtabLoadCommand *>(L); - StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize); - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - const char *Start = &StringTable.data()[Entry->StringIndex]; - Res = StringRef(Start); - return object_error::success; -} - -template<endianness E> -error_code -MachOObjectFileMiddle<E>::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t index = Entry->SectionIndex; - - if (index == 0) - Res = end_sections(); - else - Res = section_iterator(SectionRef(Sections[index-1], this)); - - return object_error::success; -} - - -template<endianness E> -error_code MachOObjectFileMiddle<E>: |