diff options
Diffstat (limited to 'include/llvm/Object/MachO.h')
-rw-r--r-- | include/llvm/Object/MachO.h | 197 |
1 files changed, 175 insertions, 22 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8c33ec8fd603..1ee571cce738 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -100,18 +100,58 @@ private: }; typedef content_iterator<ExportEntry> export_iterator; +// Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry +// can be checked and translated. Only the SegIndex/SegOffset pairs from +// checked entries are to be used with the segmentName(), sectionName() and +// address() methods below. +class BindRebaseSegInfo { +public: + BindRebaseSegInfo(const object::MachOObjectFile *Obj); + + // Used to check a Mach-O Bind or Rebase entry for errors when iterating. + const char *checkSegAndOffset(int32_t SegIndex, uint64_t SegOffset, + bool endInvalid); + const char *checkCountAndSkip(uint32_t Count, uint32_t Skip, + uint8_t PointerSize, int32_t SegIndex, + uint64_t SegOffset); + // Used with valid SegIndex/SegOffset values from checked entries. + StringRef segmentName(int32_t SegIndex); + StringRef sectionName(int32_t SegIndex, uint64_t SegOffset); + uint64_t address(uint32_t SegIndex, uint64_t SegOffset); + +private: + struct SectionInfo { + uint64_t Address; + uint64_t Size; + StringRef SectionName; + StringRef SegmentName; + uint64_t OffsetInSegment; + uint64_t SegmentStartAddress; + int32_t SegmentIndex; + }; + const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset); + SmallVector<SectionInfo, 32> Sections; + int32_t MaxSegIndex; +}; + /// MachORebaseEntry encapsulates the current state in the decompression of /// rebasing opcodes. This allows you to iterate through the compressed table of /// rebasing using: -/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { +/// Error Err; +/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) { /// } +/// if (Err) { report error ... class MachORebaseEntry { public: - MachORebaseEntry(ArrayRef<uint8_t> opcodes, bool is64Bit); + MachORebaseEntry(Error *Err, const MachOObjectFile *O, + ArrayRef<uint8_t> opcodes, bool is64Bit); - uint32_t segmentIndex() const; + int32_t segmentIndex() const; uint64_t segmentOffset() const; StringRef typeName() const; + StringRef segmentName() const; + StringRef sectionName() const; + uint64_t address() const; bool operator==(const MachORebaseEntry &) const; @@ -121,17 +161,18 @@ private: friend class MachOObjectFile; void moveToFirst(); void moveToEnd(); - uint64_t readULEB128(); + uint64_t readULEB128(const char **error); + Error *E; + const MachOObjectFile *O; ArrayRef<uint8_t> Opcodes; const uint8_t *Ptr; uint64_t SegmentOffset; - uint32_t SegmentIndex; + int32_t SegmentIndex; uint64_t RemainingLoopCount; uint64_t AdvanceAmount; uint8_t RebaseType; uint8_t PointerSize; - bool Malformed; bool Done; }; typedef content_iterator<MachORebaseEntry> rebase_iterator; @@ -139,15 +180,18 @@ typedef content_iterator<MachORebaseEntry> rebase_iterator; /// MachOBindEntry encapsulates the current state in the decompression of /// binding opcodes. This allows you to iterate through the compressed table of /// bindings using: -/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { +/// Error Err; +/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) { /// } +/// if (Err) { report error ... class MachOBindEntry { public: enum class Kind { Regular, Lazy, Weak }; - MachOBindEntry(ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); + MachOBindEntry(Error *Err, const MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind); - uint32_t segmentIndex() const; + int32_t segmentIndex() const; uint64_t segmentOffset() const; StringRef typeName() const; StringRef symbolName() const; @@ -155,6 +199,10 @@ public: int64_t addend() const; int ordinal() const; + StringRef segmentName() const; + StringRef sectionName() const; + uint64_t address() const; + bool operator==(const MachOBindEntry &) const; void moveNext(); @@ -163,14 +211,17 @@ private: friend class MachOObjectFile; void moveToFirst(); void moveToEnd(); - uint64_t readULEB128(); - int64_t readSLEB128(); + uint64_t readULEB128(const char **error); + int64_t readSLEB128(const char **error); + Error *E; + const MachOObjectFile *O; ArrayRef<uint8_t> Opcodes; const uint8_t *Ptr; uint64_t SegmentOffset; - uint32_t SegmentIndex; + int32_t SegmentIndex; StringRef SymbolName; + bool LibraryOrdinalSet; int Ordinal; uint32_t Flags; int64_t Addend; @@ -179,7 +230,6 @@ private: uint8_t BindType; uint8_t PointerSize; Kind TableKind; - bool Malformed; bool Done; }; typedef content_iterator<MachOBindEntry> bind_iterator; @@ -245,6 +295,7 @@ public: // MachO specific. std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; + uint32_t getLibraryCount() const; section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; @@ -285,26 +336,79 @@ public: static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie); /// For use iterating over all rebase table entries. - iterator_range<rebase_iterator> rebaseTable() const; + iterator_range<rebase_iterator> rebaseTable(Error &Err); - /// For use examining rebase opcodes not in a MachOObjectFile. - static iterator_range<rebase_iterator> rebaseTable(ArrayRef<uint8_t> Opcodes, + /// For use examining rebase opcodes in a MachOObjectFile. + static iterator_range<rebase_iterator> rebaseTable(Error &Err, + MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64); /// For use iterating over all bind table entries. - iterator_range<bind_iterator> bindTable() const; + iterator_range<bind_iterator> bindTable(Error &Err); /// For use iterating over all lazy bind table entries. - iterator_range<bind_iterator> lazyBindTable() const; + iterator_range<bind_iterator> lazyBindTable(Error &Err); - /// For use iterating over all lazy bind table entries. - iterator_range<bind_iterator> weakBindTable() const; + /// For use iterating over all weak bind table entries. + iterator_range<bind_iterator> weakBindTable(Error &Err); - /// For use examining bind opcodes not in a MachOObjectFile. - static iterator_range<bind_iterator> bindTable(ArrayRef<uint8_t> Opcodes, + /// For use examining bind opcodes in a MachOObjectFile. + static iterator_range<bind_iterator> bindTable(Error &Err, + MachOObjectFile *O, + ArrayRef<uint8_t> Opcodes, bool is64, MachOBindEntry::Kind); + /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to + /// validate a MachOBindEntry. + const char *BindEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset, + bool endInvalid) const { + return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset, + endInvalid); + } + /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for + /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode. + const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip, + uint8_t PointerSize, int32_t SegIndex, + uint64_t SegOffset) const { + return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize, + SegIndex, SegOffset); + } + + /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to + /// validate a MachORebaseEntry. + const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset, + bool endInvalid) const { + return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset, + endInvalid); + } + /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for + /// the REBASE_OPCODE_DO_*_TIMES* opcodes. + const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip, + uint8_t PointerSize, int32_t SegIndex, + uint64_t SegOffset) const { + return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize, + SegIndex, SegOffset); + } + + /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to + /// get the segment name. + StringRef BindRebaseSegmentName(int32_t SegIndex) const { + return BindRebaseSectionTable->segmentName(SegIndex); + } + + /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or + /// Rebase entry to get the section name. + StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const { + return BindRebaseSectionTable->sectionName(SegIndex, SegOffset); + } + + /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or + /// Rebase entry to get the address. + uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const { + return BindRebaseSectionTable->address(SegIndex, SegOffset); + } // 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 @@ -351,6 +455,12 @@ public: getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; + MachO::note_command + getNoteLoadCommand(const LoadCommandInfo &L) const; + MachO::build_version_command + getBuildVersionLoadCommand(const LoadCommandInfo &L) const; + MachO::build_tool_version + getBuildToolVersion(unsigned index) const; MachO::dylib_command getDylibIDLoadCommand(const LoadCommandInfo &L) const; MachO::dyld_info_command @@ -444,6 +554,46 @@ public: return VersionOrSDK & 0xff; } + static std::string getBuildPlatform(uint32_t platform) { + switch (platform) { + case MachO::PLATFORM_MACOS: return "macos"; + case MachO::PLATFORM_IOS: return "ios"; + case MachO::PLATFORM_TVOS: return "tvos"; + case MachO::PLATFORM_WATCHOS: return "watchos"; + case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; + default: + std::string ret; + llvm::raw_string_ostream ss(ret); + ss << format_hex(platform, 8, true); + return ss.str(); + } + } + + static std::string getBuildTool(uint32_t tools) { + switch (tools) { + case MachO::TOOL_CLANG: return "clang"; + case MachO::TOOL_SWIFT: return "swift"; + case MachO::TOOL_LD: return "ld"; + default: + std::string ret; + llvm::raw_string_ostream ss(ret); + ss << format_hex(tools, 8, true); + return ss.str(); + } + } + + static std::string getVersionString(uint32_t version) { + uint32_t major = (version >> 16) & 0xffff; + uint32_t minor = (version >> 8) & 0xff; + uint32_t update = version & 0xff; + + SmallString<32> Version; + Version = utostr(major) + "." + utostr(minor); + if (update != 0) + Version += "." + utostr(update); + return Version.str(); + } + private: MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, @@ -462,7 +612,10 @@ private: LibraryList Libraries; LoadCommandList LoadCommands; typedef SmallVector<StringRef, 1> LibraryShortName; + using BuildToolList = SmallVector<const char*, 1>; + BuildToolList BuildTools; mutable LibraryShortName LibrariesShortNames; + std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; |