diff options
-rw-r--r-- | include/llvm/Object/MachO.h | 783 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 432 | ||||
-rw-r--r-- | test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc | bin | 0 -> 844 bytes | |||
-rw-r--r-- | test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 | bin | 0 -> 956 bytes | |||
-rw-r--r-- | test/tools/llvm-readobj/relocations.test | 42 | ||||
-rw-r--r-- | test/tools/llvm-readobj/sections-ext.test | 313 | ||||
-rw-r--r-- | test/tools/llvm-readobj/sections.test | 178 | ||||
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 48 | ||||
-rw-r--r-- | tools/llvm-objdump/llvm-objdump.cpp | 18 | ||||
-rw-r--r-- | tools/llvm-readobj/MachODumper.cpp | 132 |
10 files changed, 1353 insertions, 593 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 9b7a073..33e10ff 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -20,7 +20,9 @@ #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" @@ -36,6 +38,25 @@ struct MachOType { }; 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; @@ -43,12 +64,14 @@ struct MachODataTypeTypedefHelperCommon { <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(E) \ typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt16 MachOInt16; \ typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt32 MachOInt32; \ -typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; +typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt64 MachOInt64; \ +typedef typename MachODataTypeTypedefHelperCommon<E>::MachOInt24 MachOInt24; template<class MachOT> struct MachODataTypeTypedefHelper; @@ -120,8 +143,11 @@ namespace MachOFormat { }; template<endianness TargetEndianness> - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct RelocationEntry; + + template<> + struct RelocationEntry<support::little> { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt32 Address; MachOInt24 SymbolNum; uint8_t Bits; @@ -140,9 +166,33 @@ namespace MachOFormat { } }; + template<> + struct RelocationEntry<support::big> { + LLVM_MACHOB_IMPORT_TYPES(support::big) + MachOInt32 Address; + MachOInt24 SymbolNum; + uint8_t Bits; + + unsigned getType() const { + return Bits &0xf; + } + unsigned getExternal() const { + return (Bits >> 4) & 0x1; + } + unsigned getLength() const { + return (Bits >> 5) & 0x3; + } + unsigned getPCRel() const { + return Bits >> 7; + } + }; + template<endianness TargetEndianness> - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct ScatteredRelocationEntry; + + template<> + struct ScatteredRelocationEntry<support::little> { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt24 Address; uint8_t Bits; MachOInt32 Value; @@ -161,6 +211,26 @@ namespace MachOFormat { } }; + template<> + struct ScatteredRelocationEntry<support::big> { + LLVM_MACHOB_IMPORT_TYPES(support::big) + uint8_t Bits; + unsigned getType() const { + return Bits & 0xf; + } + unsigned getLength() const { + return (Bits >> 4) & 0x3; + } + unsigned getPCRel() const { + return (Bits >> 6) & 0x1; + } + unsigned getScattered() const { + return Bits >> 7; + } + MachOInt24 Address; + MachOInt32 Value; + }; + template<endianness TargetEndianness> struct SymbolTableEntryBase { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) @@ -244,69 +314,32 @@ namespace MachOFormat { class MachOObjectFileBase : public ObjectFile { public: - typedef MachOFormat::SymbolTableEntryBase<support::little> - SymbolTableEntryBase; - typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand; - typedef MachOFormat::RelocationEntry<support::little> RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry<support::little> - ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; - typedef MachOFormat::LoadCommand<support::little> LoadCommand; - typedef MachOFormat::Header<support::little> Header; - typedef MachOFormat::LinkeditDataLoadCommand<support::little> - LinkeditDataLoadCommand; - MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); + MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; 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 section_iterator end_sections() const; virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; virtual StringRef getLoadName() 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; - bool is64Bit() const; - const LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isScattered(const RelocationEntry *RE) const; - bool isPCRel(const RelocationEntry *RE) const; - unsigned getLength(const RelocationEntry *RE) const; - unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); } protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &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 getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; + StringRef parseSegmentOrSectionName(const char *P) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &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, @@ -327,17 +360,75 @@ protected: typedef SmallVector<DataRefImpl, 1> SectionList; SectionList Sections; +}; + +template<endianness TargetEndianness> +class MachOObjectFileMiddle : public MachOObjectFileBase { +public: + + typedef MachOFormat::SymbolTableEntryBase<TargetEndianness> + SymbolTableEntryBase; + typedef MachOFormat::LinkeditDataLoadCommand<TargetEndianness> + LinkeditDataLoadCommand; + typedef MachOFormat::Header<TargetEndianness> Header; + typedef MachOFormat::SymtabLoadCommand<TargetEndianness> SymtabLoadCommand; + typedef MachOFormat::RelocationEntry<TargetEndianness> RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry<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; + + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &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); - const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const; + template<class T> + static void advanceTo(T &it, size_t Val); }; template<class MachOT> @@ -369,11 +460,17 @@ struct MachOObjectFileHelper<MachOType<TargetEndianness, true> > : }; template<class MachOT> -class MachOObjectFile : public MachOObjectFileBase { +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; @@ -413,15 +510,491 @@ public: 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 ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); + return SRE->getPCRel(); + } + return RE->getPCRel(); +} + +template<endianness E> +unsigned +MachOObjectFileMiddle<E>::getRelocationLength(const RelocationEntry *RE) const { + typedef MachOObjectFileMiddle<E> ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); + return SRE->getLength(); + } + return RE->getLength(); +} + +template<endianness E> +unsigned +MachOObjectFileMiddle<E>::getRelocationTypeImpl(const RelocationEntry *RE) + const { + typedef MachOObjectFileMiddle<E> ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast<const typename ObjType::ScatteredRelocationEntry *>(RE); + return SRE->getType(); + } + return RE->getType(); +} + +// 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->getExternal(); + 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>::getSymbolNMTypeChar(DataRefImpl Symb, + char &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + uint8_t Type = Entry->Type; + uint16_t Flags = Entry->Flags; + + char Char; + switch (Type & macho::STF_TypeMask) { + case macho::STT_Undefined: + Char = 'u'; + break; + case macho::STT_Absolute: + case macho::STT_Section: + Char = 's'; + break; + default: + Char = '?'; + break; + } + + if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) + Char = toupper(static_cast<unsigned char>(Char)); + Res = Char; + return object_error::success; +} + +template<endianness E> +error_code +MachOObjectFileMiddle<E>::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ArrayRef<char> Raw = getSectionRawName(Sec); + Result = parseSegmentOrSectionName(Raw.data()); + return object_error::success; +} + +template<endianness E> +error_code MachOObjectFileMiddle<E>::getSymbolNext(DataRefImpl Symb, + SymbolRef &Res) const { + Symb.d.b++; + moveToNextSymbol(Symb); + Res = SymbolRef(Symb, this); + return object_error::success; +} + +template<endianness E> +symbol_iterator MachOObjectFileMiddle<E>::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + moveToNextSymbol(DRI); + return symbol_iterator(SymbolRef(DRI, this)); +} + +template<endianness E> +unsigned MachOObjectFileMiddle<E>::getArch() const { + switch (getCPUType()) { + case llvm::MachO::CPUTypeI386: + return Triple::x86; + case llvm::MachO::CPUTypeX86_64: + return Triple::x86_64; + case llvm::MachO::CPUTypeARM: + return Triple::arm; + case llvm::MachO::CPUTypePowerPC: + return Triple::ppc; + case llvm::MachO::CPUTypePowerPC64: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +template<endianness E> +StringRef MachOObjectFileMiddle<E>::getFileFormatName() const { + unsigned CPUType = getCPUType(); + if (!is64Bit()) { + switch (CPUType) { + case llvm::MachO::CPUTypeI386: + return "Mach-O 32-bit i386"; + case llvm::MachO::CPUTypeARM: + return "Mach-O arm"; + case llvm::MachO::CPUTypePowerPC: + return "Mach-O 32-bit ppc"; + default: + assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; + } + } + + // Make sure the cpu type has the correct mask. + assert((CPUType & llvm::MachO::CPUArchABI64) + == llvm::MachO::CPUArchABI64 && + "32-bit object file when we're 64-bit?"); + + switch (CPUType) { + case llvm::MachO::CPUTypeX86_64: + return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPUTypePowerPC64: + return "Mach-O 64-bit ppc64"; + default: + return "Mach-O 64-bit unknown"; + } +} + +template<endianness E> +symbol_iterator MachOObjectFileMiddle<E>::end_symbols() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return symbol_iterator(SymbolRef(DRI, this)); +} + +template<endianness E> +section_iterator MachOObjectFileMiddle<E>::end_sections() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return section_iterator(SectionRef(DRI, this)); +} + +template<endianness E> +bool MachOObjectFileMiddle<E>::classof(const Binary *v) { + return isa<MachOObjectFile<MachOType<E, false> > >(v) || + isa<MachOObjectFile<MachOType<E, true> > >(v); +} + template<class MachOT> MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object, error_code &ec) : - MachOObjectFileBase(Object, Is64Bits, ec) { + MachOObjectFileMiddle<TargetEndianness>(Object, Is64Bits, ec) { DataRefImpl DRI; moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - Sections.push_back(DRI); + this->Sections.push_back(DRI); DRI.d.b++; moveToNextSection(DRI); } @@ -429,30 +1002,31 @@ MachOObjectFile<MachOT>::MachOObjectFile(MemoryBuffer *Object, template<class MachOT> bool MachOObjectFile<MachOT>::classof(const Binary *v) { - return v->getType() == getMachOType(true, Is64Bits); + return v->getType() == + Base::getMachOType(TargetEndianness == support::little, Is64Bits); } template<class MachOT> const typename MachOObjectFile<MachOT>::Section * MachOObjectFile<MachOT>::getSection(DataRefImpl DRI) const { - const SectionBase *Addr = getSectionBase(DRI); + const SectionBase *Addr = this->getSectionBase(DRI); return reinterpret_cast<const Section*>(Addr); } template<class MachOT> const typename MachOObjectFile<MachOT>::SymbolTableEntry * MachOObjectFile<MachOT>::getSymbolTableEntry(DataRefImpl DRI) const { - const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI); return reinterpret_cast<const SymbolTableEntry*>(Base); } template<class MachOT> const typename MachOObjectFile<MachOT>::RelocationEntry * MachOObjectFile<MachOT>::getRelocation(DataRefImpl Rel) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint32_t RelOffset = Sect->RelocationTableOffset; uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); - StringRef Data = getData(Offset, sizeof(RelocationEntry)); + StringRef Data = this->getData(Offset, sizeof(RelocationEntry)); return reinterpret_cast<const RelocationEntry*>(Data.data()); } @@ -479,7 +1053,7 @@ error_code MachOObjectFile<MachOT>::getSectionContents(DataRefImpl Sec, StringRef &Res) const { const Section *Sect = getSection(Sec); - Res = getData(Sect->Offset, Sect->Size); + Res = this->getData(Sect->Offset, Sect->Size); return object_error::success; } @@ -517,7 +1091,7 @@ MachOObjectFile<MachOT>::getSectionRelEnd(DataRefImpl Sec) const { uint32_t LastReloc = Sect->NumRelocationTableEntries; DataRefImpl Ret; Ret.d.a = LastReloc; - Ret.d.b = getSectionIndex(Sec); + Ret.d.b = this->getSectionIndex(Sec); return relocation_iterator(RelocationRef(Ret, this)); } @@ -525,12 +1099,12 @@ template<class MachOT> error_code MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); uint64_t RelAddr; - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) RelAddr = RE->Address & 0xFFFFFF; else RelAddr = RE->Address; @@ -544,7 +1118,7 @@ error_code MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) Res = RE->Address & 0xFFFFFF; else Res = RE->Address; @@ -560,12 +1134,12 @@ MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel, bool isExtern = RE->getExternal(); DataRefImpl Sym; - moveToNextSymbol(Sym); + this->moveToNextSymbol(Sym); if (isExtern) { for (unsigned i = 0; i < SymbolIdx; i++) { Sym.d.b++; - moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader()->NumLoadCommands && + this->moveToNextSymbol(Sym); + assert(Sym.d.a < this->getHeader()->NumLoadCommands && "Relocation symbol index out of range!"); } } @@ -577,7 +1151,7 @@ template<class MachOT> error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = getType(RE); + Res = this->getRelocationTypeImpl(RE); return object_error::success; } @@ -589,9 +1163,9 @@ MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel, StringRef res; const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); + unsigned Arch = this->getArch(); - unsigned r_type = getType(RE); + unsigned r_type = this->getRelocationTypeImpl(RE); switch (Arch) { case Triple::x86: { @@ -683,14 +1257,14 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool IsScattered = isScattered(RE); + unsigned Arch = this->getArch(); + bool IsScattered = this->isRelocationScattered(RE); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type = getType(RE); - bool IsPCRel = isPCRel(RE); + unsigned Type = this->getRelocationTypeImpl(RE); + bool IsPCRel = this->isRelocationPCRel(RE); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. @@ -702,7 +1276,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@GOT"; if (isPCRel) fmt << "PCREL"; break; @@ -722,30 +1296,30 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // The X86_64_RELOC_UNSIGNED contains the minuend symbol, // X86_64_SUBTRACTOR contains to the subtrahend. - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); fmt << "-"; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } case macho::RIT_X86_64_TLV: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (isPCRel) fmt << "P"; break; case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-1"; break; case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-2"; break; case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-4"; break; default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } // X86 and ARM share some relocation types in common. @@ -772,9 +1346,9 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } } @@ -801,19 +1375,19 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } case macho::RIT_Generic_TLV: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (IsPCRel) fmt << "P"; break; } default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } else { // ARM-specific relocations switch (Type) { @@ -831,7 +1405,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, fmt << ":upper16:("; else fmt << ":lower16:("; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); DataRefImpl RelNext = Rel; RelNext.d.a++; @@ -860,19 +1434,19 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel, // symbol/section pointer of the follow-on relocation. if (Type == macho::RIT_ARM_HalfDifference) { fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); } fmt << ")"; break; } default: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } } } else - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); @@ -884,8 +1458,8 @@ error_code MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - unsigned Type = getType(RE); + unsigned Arch = this->getArch(); + unsigned Type = this->getRelocationTypeImpl(RE); Result = false; @@ -899,7 +1473,7 @@ MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel, if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { DataRefImpl RelPrev = Rel; RelPrev.d.a--; - const RelocationEntry *REPrev = getRelocation(RelPrev); + const RelocationEntry *REPrev = this->getRelocation(RelPrev); unsigned PrevType = REPrev->getType(); @@ -917,7 +1491,8 @@ MachOObjectFile<MachOT>::getSymbolFileOffset(DataRefImpl Symb, const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); Res = Entry->Value; if (Entry->SectionIndex) { - const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); + const Section *Sec = + this->getSection(this->Sections[Entry->SectionIndex-1]); Res += Sec->Offset - Sec->Address; } @@ -930,7 +1505,7 @@ MachOObjectFile<MachOT>::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { SymbolRef::Type ST; - getSymbolType(Symb, ST); + this->getSymbolType(Symb, ST); if (ST == SymbolRef::ST_Unknown) { Result = false; return object_error::success; @@ -959,7 +1534,7 @@ error_code MachOObjectFile<MachOT>::getSymbolAddress(DataRefImpl Symb, template<class MachOT> error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; @@ -969,7 +1544,7 @@ error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI, SectionIndex = Entry->SectionIndex; if (!SectionIndex) { uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); + this->getSymbolFlags(DRI, flags); if (flags & SymbolRef::SF_Common) Result = Entry->Value; else @@ -981,7 +1556,7 @@ error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI, DRI.d.b = 0; uint32_t Command = DRI.d.a; while (Command == DRI.d.a) { - moveToNextSymbol(DRI); + this->moveToNextSymbol(DRI); if (DRI.d.a < LoadCommandCount) { Entry = getSymbolTableEntry(DRI); if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) @@ -992,8 +1567,8 @@ error_code MachOObjectFile<MachOT>::getSymbolSize(DataRefImpl DRI, } if (!EndOffset) { uint64_t Size; - getSectionSize(Sections[SectionIndex-1], Size); - getSectionAddress(Sections[SectionIndex-1], EndOffset); + this->getSectionSize(this->Sections[SectionIndex-1], Size); + this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset); EndOffset += Size; } Result = EndOffset - BeginOffset; @@ -1018,9 +1593,9 @@ section_iterator MachOObjectFile<MachOT>::begin_sections() const { template<class MachOT> void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a); if (Command->Type == SegmentLoadType) { const SegmentLoadCommand *SegmentLoadCmd = reinterpret_cast<const SegmentLoadCommand*>(Command); @@ -1033,10 +1608,6 @@ void MachOObjectFile<MachOT>::moveToNextSection(DataRefImpl &DRI) const { } } - typedef MachOObjectFile<MachOType<support::little, false> > - MachOObjectFile32Le; - typedef MachOObjectFile<MachOType<support::little, true> > - MachOObjectFile64Le; } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 627e748..192e755 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -29,30 +29,14 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, +MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, + bool IsLittleEndian, bool Is64bits, error_code &ec) - : ObjectFile(getMachOType(true, Is64bits), Object) { + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) { } bool MachOObjectFileBase::is64Bit() const { - return isa<MachOObjectFile64Le>(this); -} - -const MachOObjectFileBase::LoadCommand * -MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const { - uint64_t Offset; - uint64_t NewOffset = getHeaderSize(); - const LoadCommand *Load; - unsigned I = 0; - do { - Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(LoadCommand)); - Load = reinterpret_cast<const LoadCommand*>(Data.data()); - NewOffset = Offset + Load->Size; - ++I; - } while (I != Index + 1); - - return Load; + return isa<MachOObjectFileLE64>(this) || isa<MachOObjectFileBE64>(this); } void MachOObjectFileBase::ReadULEB128s(uint64_t Index, @@ -67,11 +51,6 @@ void MachOObjectFileBase::ReadULEB128s(uint64_t Index, } } -const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const { - StringRef Data = getData(0, sizeof(Header)); - return reinterpret_cast<const Header*>(Data.data()); -} - unsigned MachOObjectFileBase::getHeaderSize() const { return is64Bit() ? macho::Header64Size : macho::Header32Size; } @@ -80,55 +59,21 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } -const MachOObjectFileBase::RelocationEntry * -MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile32Le *O = dyn_cast<MachOObjectFile32Le>(this)) - return O->getRelocation(Rel); - const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(this); - return O->getRelocation(Rel); -} - -bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { - unsigned Arch = getArch(); - return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); -} - -bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast<const ScatteredRelocationEntry *>(RE); - return SRE->getPCRel(); - } - return RE->getPCRel(); -} - -unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast<const ScatteredRelocationEntry *>(RE); - return SRE->getLength(); - } - return RE->getLength(); -} - -unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast<const ScatteredRelocationEntry *>(RE); - return SRE->getType(); - } - return RE->getType(); -} - ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; - bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; ObjectFile *Ret; - if (Is64Bits) - Ret = new MachOObjectFile64Le(Buffer, ec); + if (Magic == "\xFE\xED\xFA\xCE") + Ret = new MachOObjectFileBE32(Buffer, ec); + else if (Magic == "\xCE\xFA\xED\xFE") + Ret = new MachOObjectFileLE32(Buffer, ec); + else if (Magic == "\xFE\xED\xFA\xCF") + Ret = new MachOObjectFileBE64(Buffer, ec); + else if (Magic == "\xCF\xFA\xED\xFE") + Ret = new MachOObjectFileLE64(Buffer, ec); else - Ret = new MachOObjectFile32Le(Buffer, ec); + return NULL; + if (ec) return NULL; return Ret; @@ -136,183 +81,11 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Symtab) { - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const SymtabLoadCommand*>(Command); - if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const SymtabLoadCommand*>(Command); - return getSymbolTableEntryBase(DRI, SymtabLoadCmd); -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const { - uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFile64Le::SymbolTableEntry) : - sizeof(MachOObjectFile32Le::SymbolTableEntry); - - uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; - StringRef Data = getData(Offset, SymbolTableEntrySize); - return reinterpret_cast<const SymbolTableEntryBase*>(Data.data()); -} - -error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI, - SymbolRef &Result) const { - DRI.d.b++; - moveToNextSymbol(DRI); - Result = SymbolRef(DRI, this); - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI, - StringRef &Result) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast<const SymtabLoadCommand*>(Command); - - StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, - SymtabLoadCmd->StringTableSize); - - const SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(DRI, SymtabLoadCmd); - uint32_t StringIndex = Entry->StringIndex; - - const char *Start = &StringTable.data()[StringIndex]; - Result = StringRef(Start); - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI, - char &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - uint8_t Type = Entry->Type; - uint16_t Flags = Entry->Flags; - - char Char; - switch (Type & macho::STF_TypeMask) { - case macho::STT_Undefined: - Char = 'u'; - break; - case macho::STT_Absolute: - case macho::STT_Section: - Char = 's'; - break; - default: - Char = '?'; - break; - } - - if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) - Char = toupper(static_cast<unsigned char>(Char)); - Result = Char; - return object_error::success; -} - -error_code MachOObjectFileBase::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; -} - -error_code MachOObjectFileBase::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; -} - -error_code MachOObjectFileBase::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; -} - error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, uint64_t &Val) const { report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFileBase::begin_symbols() const { - // DRI.d.a = segment number; DRI.d.b = symbol index. - DataRefImpl DRI; - moveToNextSymbol(DRI); - return symbol_iterator(SymbolRef(DRI, this)); -} - -symbol_iterator MachOObjectFileBase::end_symbols() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return symbol_iterator(SymbolRef(DRI, this)); -} - symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { // TODO: implement report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); @@ -347,23 +120,7 @@ std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -const MachOObjectFileBase::SectionBase* -MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(Command); - - bool Is64 = is64Bit(); - unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) : - sizeof(MachOObjectFile32Le::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) : - sizeof(MachOObjectFile32Le::Section); - - uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast<const SectionBase*>(SectionAddr); -} - -static StringRef parseSegmentOrSectionName(const char *P) { +StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const { if (P[15] == 0) // Null terminated. return P; @@ -371,30 +128,6 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -ArrayRef<char> MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const { - const SectionBase *Base = getSectionBase(DRI); - return ArrayRef<char>(Base->Name); -} - -error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI, - StringRef &Result) const { - ArrayRef<char> Raw = getSectionRawName(DRI); - Result = parseSegmentOrSectionName(Raw.data()); - return object_error::success; -} - -ArrayRef<char> -MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef<char>(Base->SegmentName); -} - -StringRef -MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const { - ArrayRef<char> Raw = getSectionRawFinalSegmentName(DRI); - return parseSegmentOrSectionName(Raw.data()); -} - error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. @@ -441,11 +174,6 @@ relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) con return relocation_iterator(RelocationRef(ret, this)); } -section_iterator MachOObjectFileBase::end_sections() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return section_iterator(SectionRef(DRI, this)); -} /*===-- Relocations -------------------------------------------------------===*/ @@ -456,88 +184,6 @@ error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, return object_error::success; } -// Helper to advance a section or symbol iterator multiple increments at a time. -template<class T> -error_code advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template<class T> -void advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); -} - -void -MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const { - // 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(RE)) { - 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->getExternal(); - uint32_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; -} - error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); @@ -561,53 +207,5 @@ uint8_t MachOObjectFileBase::getBytesInAddress() const { return is64Bit() ? 8 : 4; } -StringRef MachOObjectFileBase::getFileFormatName() const { - if (!is64Bit()) { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return "Mach-O 32-bit i386"; - case llvm::MachO::CPUTypeARM: - return "Mach-O arm"; - case llvm::MachO::CPUTypePowerPC: - return "Mach-O 32-bit ppc"; - default: - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 && - "64-bit object file when we're not 64-bit?"); - return "Mach-O 32-bit unknown"; - } - } - - // Make sure the cpu type has the correct mask. - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) - == llvm::MachO::CPUArchABI64 && - "32-bit object file when we're 64-bit?"); - - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeX86_64: - return "Mach-O 64-bit x86-64"; - case llvm::MachO::CPUTypePowerPC64: - return "Mach-O 64-bit ppc64"; - default: - return "Mach-O 64-bit unknown"; - } -} - -unsigned MachOObjectFileBase::getArch() const { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return Triple::x86; - case llvm::MachO::CPUTypeX86_64: - return Triple::x86_64; - case llvm::MachO::CPUTypeARM: - return Triple::arm; - case llvm::MachO::CPUTypePowerPC: - return Triple::ppc; - case llvm::MachO::CPUTypePowerPC64: - return Triple::ppc64; - default: - return Triple::UnknownArch; - } -} - } // end namespace object } // end namespace llvm diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc Binary files differnew file mode 100644 index 0000000..dd2e956 --- /dev/null +++ b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 Binary files differnew file mode 100644 index 0000000..20ec8ef --- /dev/null +++ b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index 96aac23..6dc08ee 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Relocations [ COFF-NEXT: Section (1) .text { @@ -40,3 +44,41 @@ MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Relocations [ +MACHO-PPC-NEXT: Section __text { +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section __picsymbolstub1 { +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section __la_symbol_ptr { +MACHO-PPC-NEXT: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + +MACHO-PPC64: Relocations [ +MACHO-PPC64-NEXT: Section __text { +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section __picsymbolstub1 { +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section __la_symbol_ptr { +MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a12d9e4..3e42ab9 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Sections [ COFF-NEXT: Section { @@ -249,3 +253,312 @@ MACHO-X86-64-NEXT: 0000: 48656C6C 6F20576F 726C640A 00 |Hello World. MACHO-X86-64-NEXT: ) MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Sections [ +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 0 +MACHO-PPC-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x0 +MACHO-PPC-NEXT: Size: 0x3C +MACHO-PPC-NEXT: Offset: 528 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x27C +MACHO-PPC-NEXT: RelocationCount: 5 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: Symbol { +MACHO-PPC-NEXT: Name: _f (4) +MACHO-PPC-NEXT: Type: 0xF +MACHO-PPC-NEXT: Section: __text (0x1) +MACHO-PPC-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC-NEXT: Flags [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Value: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 7C0802A6 93E1FFFC 429F0005 7FE802A6 ||.......B.......| +MACHO-PPC-NEXT: 0010: 90010008 9421FFB0 48000029 3C5F0000 |.....!..H..)<_..| +MACHO-PPC-NEXT: 0020: 38210050 80420058 80010008 83E1FFFC |8!.P.B.X........| +MACHO-PPC-NEXT: 0030: 7C0803A6 80620000 4E800020 ||....b..N.. | +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 1 +MACHO-PPC-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x40 +MACHO-PPC-NEXT: Size: 0x20 +MACHO-PPC-NEXT: Offset: 592 +MACHO-PPC-NEXT: Alignment: 5 +MACHO-PPC-NEXT: RelocationOffset: 0x2A4 +MACHO-PPC-NEXT: RelocationCount: 4 +MACHO-PPC-NEXT: Type: 0x8 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x20 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 7C0802A6 429F0005 7D6802A6 3D6B0000 ||...B...}h..=k..| +MACHO-PPC-NEXT: 0010: 7C0803A6 858B0020 7D8903A6 4E800420 ||...... }...N.. | +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 2 +MACHO-PPC-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x60 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 624 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: Symbol { +MACHO-PPC-NEXT: Name: _b (1) +MACHO-PPC-NEXT: Type: 0xF +MACHO-PPC-NEXT: Section: __data (0x3) +MACHO-PPC-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC-NEXT: Flags [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Value: 0x60 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 0000002A |...*| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 3 +MACHO-PPC-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x64 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 628 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x6 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x1 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 00000000 |....| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 4 +MACHO-PPC-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x68 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 632 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x2C4 +MACHO-PPC-NEXT: RelocationCount: 1 +MACHO-PPC-NEXT: Type: 0x7 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x2 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 00000000 |....| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + + +MACHO-PPC64: Sections [ +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 0 +MACHO-PPC64-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x0 +MACHO-PPC64-NEXT: Size: 0x3C +MACHO-PPC64-NEXT: Offset: 608 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x2D4 +MACHO-PPC64-NEXT: RelocationCount: 5 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: Symbol { +MACHO-PPC64-NEXT: Name: _f (4) +MACHO-PPC64-NEXT: Type: 0xF +MACHO-PPC64-NEXT: Section: __text (0x1) +MACHO-PPC64-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC64-NEXT: Flags [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Value: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 7C0802A6 FBE1FFF8 429F0005 7FE802A6 ||.......B.......| +MACHO-PPC64-NEXT: 0010: F8010010 F821FF81 48000029 3C5F0000 |.....!..H..)<_..| +MACHO-PPC64-NEXT: 0020: 38210080 E8420058 E8010010 EBE1FFF8 |8!...B.X........| +MACHO-PPC64-NEXT: 0030: 7C0803A6 E8620002 4E800020 ||....b..N.. | +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 1 +MACHO-PPC64-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x40 +MACHO-PPC64-NEXT: Size: 0x20 +MACHO-PPC64-NEXT: Offset: 672 +MACHO-PPC64-NEXT: Alignment: 5 +MACHO-PPC64-NEXT: RelocationOffset: 0x2FC +MACHO-PPC64-NEXT: RelocationCount: 4 +MACHO-PPC64-NEXT: Type: 0x8 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x20 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 7C0802A6 429F0005 7D6802A6 3D6B0000 ||...B...}h..=k..| +MACHO-PPC64-NEXT: 0010: 7C0803A6 E98B0025 7D8903A6 4E800420 ||......%}...N.. | +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 2 +MACHO-PPC64-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x60 +MACHO-PPC64-NEXT: Size: 0x4 +MACHO-PPC64-NEXT: Offset: 704 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: Symbol { +MACHO-PPC64-NEXT: Name: _b (1) +MACHO-PPC64-NEXT: Type: 0xF +MACHO-PPC64-NEXT: Section: __data (0x3) +MACHO-PPC64-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC64-NEXT: Flags [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Value: 0x60 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 0000002A |...*| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 3 +MACHO-PPC64-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x64 +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 708 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x6 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x1 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 00000000 00000000 |........| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 4 +MACHO-PPC64-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x6C +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 716 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x31C +MACHO-PPC64-NEXT: RelocationCount: 1 +MACHO-PPC64-NEXT: Type: 0x7 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x2 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 00000000 00000000 |........| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/test/tools/llvm-readobj/sections.test b/test/tools/llvm-readobj/sections.test index f4da9e3..b569682 100644 --- a/test/tools/llvm-readobj/sections.test +++ b/test/tools/llvm-readobj/sections.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Sections [ COFF-NEXT: Section { @@ -151,3 +155,177 @@ MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Sections [ +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 0 +MACHO-PPC-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x0 +MACHO-PPC-NEXT: Size: 0x3C +MACHO-PPC-NEXT: Offset: 528 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x27C +MACHO-PPC-NEXT: RelocationCount: 5 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 1 +MACHO-PPC-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x40 +MACHO-PPC-NEXT: Size: 0x20 +MACHO-PPC-NEXT: Offset: 592 +MACHO-PPC-NEXT: Alignment: 5 +MACHO-PPC-NEXT: RelocationOffset: 0x2A4 +MACHO-PPC-NEXT: RelocationCount: 4 +MACHO-PPC-NEXT: Type: 0x8 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x20 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 2 +MACHO-PPC-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x60 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 624 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 3 +MACHO-PPC-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x64 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 628 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x6 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x1 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 4 +MACHO-PPC-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x68 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 632 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x2C4 +MACHO-PPC-NEXT: RelocationCount: 1 +MACHO-PPC-NEXT: Type: 0x7 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x2 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + +MACHO-PPC64: Sections [ +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 0 +MACHO-PPC64-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x0 +MACHO-PPC64-NEXT: Size: 0x3C +MACHO-PPC64-NEXT: Offset: 608 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x2D4 +MACHO-PPC64-NEXT: RelocationCount: 5 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 1 +MACHO-PPC64-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x40 +MACHO-PPC64-NEXT: Size: 0x20 +MACHO-PPC64-NEXT: Offset: 672 +MACHO-PPC64-NEXT: Alignment: 5 +MACHO-PPC64-NEXT: RelocationOffset: 0x2FC +MACHO-PPC64-NEXT: RelocationCount: 4 +MACHO-PPC64-NEXT: Type: 0x8 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x20 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 2 +MACHO-PPC64-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x60 +MACHO-PPC64-NEXT: Size: 0x4 +MACHO-PPC64-NEXT: Offset: 704 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 3 +MACHO-PPC64-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x64 +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 708 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x6 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x1 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 4 +MACHO-PPC64-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x6C +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 716 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x31C +MACHO-PPC64-NEXT: RelocationCount: 1 +MACHO-PPC64-NEXT: Type: 0x7 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x2 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 89847d0..4b6cb5f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/MachO.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -183,11 +184,14 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -static void getSectionsAndSymbols(const MachOObjectFileBase::Header *Header, - MachOObjectFileBase *MachOObj, - std::vector<SectionRef> &Sections, - std::vector<SymbolRef> &Symbols, - SmallVectorImpl<uint64_t> &FoundFns) { +template<endianness E> +static void +getSectionsAndSymbols(const typename MachOObjectFileMiddle<E>::Header *Header, + const MachOObjectFileMiddle<E> *MachOObj, + std::vector<SectionRef> &Sections, + std::vector<SymbolRef> &Symbols, + SmallVectorImpl<uint64_t> &FoundFns) { + typedef MachOObjectFileMiddle<E> ObjType; error_code ec; for (symbol_iterator SI = MachOObj->begin_symbols(), SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) @@ -202,19 +206,23 @@ static void getSectionsAndSymbols(const MachOObjectFileBase::Header *Header, } for (unsigned i = 0; i != Header->NumLoadCommands; ++i) { - const MachOObjectFileBase::LoadCommand *Command = + const typename ObjType::LoadCommand *Command = MachOObj->getLoadCommandInfo(i); if (Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - const MachOObjectFileBase::LinkeditDataLoadCommand *LLC = - reinterpret_cast<const MachOObjectFileBase::LinkeditDataLoadCommand*>(Command); + const typename ObjType::LinkeditDataLoadCommand *LLC = + reinterpret_cast<const typename ObjType::LinkeditDataLoadCommand*>(Command); MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); } } } +template<endianness E> +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFileMiddle<E> *MachOOF); + void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<MemoryBuffer> Buff; @@ -226,7 +234,18 @@ void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr<MachOObjectFileBase> MachOOF(static_cast<MachOObjectFileBase*>( ObjectFile::createMachOObjectFile(Buff.take()))); - const Target *TheTarget = GetTarget(MachOOF.get()); + if (MachOObjectFileLE *O = dyn_cast<MachOObjectFileLE>(MachOOF.get())) { + DisassembleInputMachO2(Filename, O); + return; + } + MachOObjectFileBE *O = cast<MachOObjectFileBE>(MachOOF.get()); + DisassembleInputMachO2(Filename, O); +} + +template<endianness E> +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFileMiddle<E> *MachOOF) { + const Target *TheTarget = GetTarget(MachOOF); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -254,13 +273,14 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const MachOObjectFileBase::Header *Header = MachOOF->getHeader(); + const typename MachOObjectFileMiddle<E>::Header *Header = + MachOOF->getHeader(); std::vector<SectionRef> Sections; std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; - getSectionsAndSymbols(Header, MachOOF.get(), Sections, Symbols, FoundFns); + getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns); // Make a copy of the unsorted symbol list. FIXME: duplication std::vector<SymbolRef> UnsortedSymbols(Symbols); @@ -274,7 +294,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { #endif OwningPtr<DIContext> diContext; - ObjectFile *DbgObj = MachOOF.get(); + ObjectFile *DbgObj = MachOOF; // Try to find debug info and set up the DIContext for it. if (UseDbg) { // A separate DSym file path was specified, parse it as a macho file, @@ -563,7 +583,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Relocs[j].second.getName(SymName); outs() << "\t# " << SymName << ' '; - DumpAddress(Addr, Sections, MachOOF.get(), outs()); + DumpAddress(Addr, Sections, MachOOF, outs()); } // If this instructions contains an address, see if we can evaluate @@ -572,7 +592,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Inst.Address, Inst.Size); if (targ != -1ULL) - DumpAddress(targ, Sections, MachOOF.get(), outs()); + DumpAddress(targ, Sections, MachOOF, outs()); // Print debug info. if (diContext) { diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 4790d7a..5a0519d 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -191,6 +191,14 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { return a_addr < b_addr; } +StringRef +getSectionFinalSegmentName(const MachOObjectFileBase *MachO, DataRefImpl DR) { + if (const MachOObjectFileLE *O = dyn_cast<MachOObjectFileLE>(MachO)) + return O->getSectionFinalSegmentName(DR); + const MachOObjectFileBE *O = dyn_cast<MachOObjectFileBE>(MachO); + return O->getSectionFinalSegmentName(DR); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); // getTarget() will have already issued a diagnostic if necessary, so @@ -255,9 +263,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFileBase *MachO = dyn_cast<const MachOObjectFileBase>(Obj)) { + if (const MachOObjectFileBase *MachO = + dyn_cast<const MachOObjectFileBase>(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); - SegmentName = MachO->getSectionFinalSegmentName(DR); + SegmentName = getSectionFinalSegmentName(MachO, DR); } StringRef name; if (error(i->getName(name))) break; @@ -591,9 +600,10 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFileBase *MachO = dyn_cast<const MachOObjectFileBase>(o)) { + if (const MachOObjectFileBase *MachO = + dyn_cast<const MachOObjectFileBase>(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); - StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); + StringRef SegmentName = getSectionFinalSegmentName(MachO, DR); outs() << SegmentName << ","; } StringRef SectionName; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 69f1d63..d207eab 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const llvm::object::MachOObjectFileBase *Obj, StreamWriter& Writer) + MachODumper(const MachOObjectFileBase *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,7 +43,14 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - const llvm::object::MachOObjectFileBase *Obj; + template<support::endianness E> + void printRelocation(const MachOObjectFileMiddle<E> *Obj, + section_iterator SecI, relocation_iterator RelI); + + template<support::endianness E> + void printSections(const MachOObjectFileMiddle<E> *Obj); + + const MachOObjectFileBase *Obj; }; } // namespace @@ -157,58 +164,59 @@ namespace { }; } +template<class MachOT> +static void getSection(const MachOObjectFile<MachOT> *Obj, + DataRefImpl DRI, + MachOSection &Section) { + const typename MachOObjectFile<MachOT>::Section *Sect = Obj->getSection(DRI); + Section.Address = Sect->Address; + Section.Size = Sect->Size; + Section.Offset = Sect->Offset; + Section.Alignment = Sect->Align; + Section.RelocationTableOffset = Sect->RelocationTableOffset; + Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; + Section.Flags = Sect->Flags; + Section.Reserved1 = Sect->Reserved1; + Section.Reserved2 = Sect->Reserved2; +} + static void getSection(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSection &Section) { - if (const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(Obj)) { - const MachOObjectFile64Le::Section *Sect = O->getSection(DRI); - - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; - } else { - const MachOObjectFile32Le *O2 = cast<MachOObjectFile32Le>(Obj); - const MachOObjectFile32Le::Section *Sect = O2->getSection(DRI); - - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; - } + if (const MachOObjectFileLE32 *O = dyn_cast<MachOObjectFileLE32>(Obj)) + return getSection(O, DRI, Section); + if (const MachOObjectFileLE64 *O = dyn_cast<MachOObjectFileLE64>(Obj)) + return getSection(O, DRI, Section); + if (const MachOObjectFileBE32 *O = dyn_cast<MachOObjectFileBE32>(Obj)) + return getSection(O, DRI, Section); + const MachOObjectFileBE64 *O = cast<MachOObjectFileBE64>(Obj); + getSection(O, DRI, Section); +} + +template<class MachOT> +static void getSymbol(const MachOObjectFile<MachOT> *Obj, + DataRefImpl DRI, + MachOSymbol &Symbol) { + const typename MachOObjectFile<MachOT>::SymbolTableEntry *Entry = + Obj->getSymbolTableEntry(DRI); + Symbol.StringIndex = Entry->StringIndex; + Symbol.Type = Entry->Type; + Symbol.SectionIndex = Entry->SectionIndex; + Symbol.Flags = Entry->Flags; + Symbol.Value = Entry->Value; } static void getSymbol(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(Obj)) { - const MachOObjectFile64Le::SymbolTableEntry *Entry = - O->getSymbolTableEntry(DRI); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; - } else { - const MachOObjectFile32Le *O2 = cast<MachOObjectFile32Le>(Obj); - const MachOObjectFile32Le::SymbolTableEntry *Entry = - O2->getSymbolTableEntry(DRI); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; - } + if (const MachOObjectFileLE32 *O = dyn_cast<MachOObjectFileLE32>(Obj)) + return getSymbol(O, DRI, Symbol); + if (const MachOObjectFileLE64 *O = dyn_cast<MachOObjectFileLE64>(Obj)) + return getSymbol(O, DRI, Symbol); + if (const MachOObjectFileBE32 *O = dyn_cast<MachOObjectFileBE32>(Obj)) + return getSymbol(O, DRI, Symbol); + const MachOObjectFileBE64 *O = cast<MachOObjectFileBE64>(Obj); + getSymbol(O, DRI, Symbol); } void MachODumper::printFileHeaders() { @@ -216,6 +224,14 @@ void MachODumper::printFileHeaders() { } void MachODumper::printSections() { + if (const MachOObjectFileLE *O = dyn_cast<MachOObjectFileLE>(Obj)) + return printSections(O); + const MachOObjectFileBE *O = cast<MachOObjectFileBE>(Obj); + return printSections(O); +} + +template<support::endianness E> +void MachODumper::printSections(const MachOObjectFileMiddle<E> *Obj) { ListScope Group(W, "Sections"); int SectionIndex = -1; @@ -328,6 +344,16 @@ void MachODumper::printRelocations() { void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { + if (const MachOObjectFileLE *O = dyn_cast<MachOObjectFileLE>(Obj)) + return printRelocation(O, SecI, RelI); + const MachOObjectFileBE *O = cast<MachOObjectFileBE>(Obj); + return printRelocation(O, SecI, RelI); +} + +template<support::endianness E> +void MachODumper::printRelocation(const MachOObjectFileMiddle<E> *Obj, + section_iterator SecI, + relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; StringRef SymbolName; @@ -338,14 +364,15 @@ void MachODumper::printRelocation(section_iterator SecI, if (error(Symbol.getName(SymbolName))) return; DataRefImpl DR = RelI->getRawDataRefImpl(); - const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); - bool IsScattered = Obj->isScattered(RE); + const typename MachOObjectFileMiddle<E>::RelocationEntry *RE = + Obj->getRelocation(DR); + bool IsScattered = Obj->isRelocationScattered(RE); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); - W.printNumber("PCRel", Obj->isPCRel(RE)); - W.printNumber("Length", Obj->getLength(RE)); + W.printNumber("PCRel", Obj->isRelocationPCRel(RE)); + W.printNumber("Length", Obj->getRelocationLength(RE)); if (IsScattered) W.printString("Extern", StringRef("N/A")); else @@ -356,8 +383,8 @@ void MachODumper::printRelocation(section_iterator SecI, } else { raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << Obj->isPCRel(RE) - << " " << Obj->getLength(RE); + << " " << Obj->isRelocationPCRel(RE) + << " " << Obj->getRelocationLength(RE); if (IsScattered) OS << " n/a"; else @@ -399,6 +426,7 @@ void MachODumper::printSymbol(symbol_iterator SymI) { StringRef SectionName; section_iterator SecI(Obj->end_sections()); if (error(SymI->getSection(SecI)) || + SecI == Obj->end_sections() || error(SecI->getName(SectionName))) SectionName = ""; |