aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Object/MachO.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Object/MachO.h')
-rw-r--r--include/llvm/Object/MachO.h197
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;