#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/LEB128.h"
return S.nsects;
}
+static bool isPageZeroSegment(const MachOObjectFile *O,
+ const MachOObjectFile::LoadCommandInfo &L) {
+ if (O->is64Bit()) {
+ MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
+ return StringRef("__PAGEZERO").equals(S.segname);
+ }
+ MachO::segment_command S = O->getSegmentLoadCommand(L);
+ return StringRef("__PAGEZERO").equals(S.segname);
+}
+
+
static const char *
getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
unsigned Sec) {
// to find a section beginning instead.
for (const SectionRef &Section : O->sections()) {
std::error_code ec;
- uint64_t Addr;
- StringRef Name;
- if ((ec = Section.getAddress(Addr)))
- report_fatal_error(ec.message());
+ StringRef Name;
+ uint64_t Addr = Section.getAddress();
if (Addr != Val)
continue;
if ((ec = Section.getName(Name)))
bool Is64bits, std::error_code &EC)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
- DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr) {
+ DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr),
+ HasPageZeroSegment(false) {
uint32_t LoadCommandCount = this->getHeader().ncmds;
MachO::LoadCommandType SegmentLoadType = is64Bit() ?
MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
const char *Sec = getSectionPtr(this, Load, J);
Sections.push_back(Sec);
}
+ if (isPageZeroSegment(this, Load))
+ HasPageZeroSegment = true;
} else if (Load.C.cmd == MachO::LC_LOAD_DYLIB ||
Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
EndOffset = Value;
}
if (!EndOffset) {
- uint64_t Size;
DataRefImpl Sec;
Sec.d.a = SectionIndex-1;
- getSectionSize(Sec, Size);
- getSectionAddress(Sec, EndOffset);
+ uint64_t Size = getSectionSize(Sec);
+ EndOffset = getSectionAddress(Sec);
EndOffset += Size;
}
Result = EndOffset - BeginOffset;
return object_error::success;
}
-std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec,
- uint64_t &Res) const {
- if (is64Bit()) {
- MachO::section_64 Sect = getSection64(Sec);
- Res = Sect.addr;
- } else {
- MachO::section Sect = getSection(Sec);
- Res = Sect.addr;
- }
- return object_error::success;
+uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
+ if (is64Bit())
+ return getSection64(Sec).addr;
+ return getSection(Sec).addr;
}
-std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec,
- uint64_t &Res) const {
- if (is64Bit()) {
- MachO::section_64 Sect = getSection64(Sec);
- Res = Sect.size;
- } else {
- MachO::section Sect = getSection(Sec);
- Res = Sect.size;
- }
-
- return object_error::success;
+uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
+ if (is64Bit())
+ return getSection64(Sec).size;
+ return getSection(Sec).size;
}
std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
return object_error::success;
}
-std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec,
- uint64_t &Res) const {
+uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
uint32_t Align;
if (is64Bit()) {
MachO::section_64 Sect = getSection64(Sec);
Align = Sect.align;
}
- Res = uint64_t(1) << Align;
- return object_error::success;
+ return uint64_t(1) << Align;
}
-std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec,
- bool &Res) const {
+bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
- Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
- return object_error::success;
+ return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
}
-std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
- Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
- !(SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL);
- return object_error::success;
+ return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
+ !(SectionType == MachO::S_ZEROFILL ||
+ SectionType == MachO::S_GB_ZEROFILL);
}
-std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
- Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
- (SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL);
- return object_error::success;
+ return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
+ (SectionType == MachO::S_ZEROFILL ||
+ SectionType == MachO::S_GB_ZEROFILL);
}
-std::error_code
-MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sect) const {
// FIXME: Unimplemented.
- Result = true;
- return object_error::success;
+ return true;
}
-std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
// FIXME: Unimplemented.
- Result = false;
- return object_error::success;
+ return false;
}
-std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec,
- bool &Res) const {
+bool MachOObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
unsigned SectionType = Flags & MachO::SECTION_TYPE;
- Res = SectionType == MachO::S_ZEROFILL ||
- SectionType == MachO::S_GB_ZEROFILL;
- return object_error::success;
+ return SectionType == MachO::S_ZEROFILL ||
+ SectionType == MachO::S_GB_ZEROFILL;
}
-std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
- bool &Result) const {
+bool MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
// Consider using the code from isSectionText to look for __const sections.
// Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS
// to use section attributes to distinguish code from data.
// FIXME: Unimplemented.
- Result = false;
- return object_error::success;
+ return false;
}
-std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
- DataRefImpl Symb,
- bool &Result) const {
+bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
+ DataRefImpl Symb) const {
SymbolRef::Type ST;
this->getSymbolType(Symb, ST);
- if (ST == SymbolRef::ST_Unknown) {
- Result = false;
- return object_error::success;
- }
+ if (ST == SymbolRef::ST_Unknown)
+ return false;
- uint64_t SectBegin, SectEnd;
- getSectionAddress(Sec, SectBegin);
- getSectionSize(Sec, SectEnd);
+ uint64_t SectBegin = getSectionAddress(Sec);
+ uint64_t SectEnd = getSectionSize(Sec);
SectEnd += SectBegin;
uint64_t SymAddr;
getSymbolAddress(Symb, SymAddr);
- Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
-
- return object_error::success;
+ return (SymAddr >= SectBegin) && (SymAddr < SectEnd);
}
relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
DataRefImpl Sec;
Sec.d.a = Rel.d.a;
- uint64_t SecAddress;
- getSectionAddress(Sec, SecAddress);
+ uint64_t SecAddress = getSectionAddress(Sec);
Res = SecAddress + Offset;
return object_error::success;
}
if (Index >= Libraries.size())
return object_error::parse_failed;
- MachO::dylib_command D =
- getStruct<MachO::dylib_command>(this, Libraries[Index]);
- if (D.dylib.name >= D.cmdsize)
- return object_error::parse_failed;
-
// If the cache of LibrariesShortNames is not built up do that first for
// all the Libraries.
if (LibrariesShortNames.size() == 0) {
for (unsigned i = 0; i < Libraries.size(); i++) {
MachO::dylib_command D =
getStruct<MachO::dylib_command>(this, Libraries[i]);
- if (D.dylib.name >= D.cmdsize) {
- LibrariesShortNames.push_back(StringRef());
- continue;
- }
+ if (D.dylib.name >= D.cmdsize)
+ return object_error::parse_failed;
const char *P = (const char *)(Libraries[i]) + D.dylib.name;
StringRef Name = StringRef(P);
+ if (D.dylib.name+Name.size() >= D.cmdsize)
+ return object_error::parse_failed;
StringRef Suffix;
bool isFramework;
StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
- if (shortName == StringRef())
+ if (shortName.empty())
LibrariesShortNames.push_back(Name);
else
LibrariesShortNames.push_back(shortName);
return true;
}
-uint64_t ExportEntry::readULEB128(const uint8_t *&p) {
- unsigned count;
- uint64_t result = decodeULEB128(p, &count);
- p += count;
- if (p > Trie.end()) {
- p = Trie.end();
+uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
+ unsigned Count;
+ uint64_t Result = decodeULEB128(Ptr, &Count);
+ Ptr += Count;
+ if (Ptr > Trie.end()) {
+ Ptr = Trie.end();
Malformed = true;
}
- return result;
+ return Result;
}
StringRef ExportEntry::name() const {
NodeState &Top = Stack.back();
CumulativeString.resize(Top.ParentStringLength);
for (;*Top.Current != 0; Top.Current++) {
- char c = *Top.Current;
- CumulativeString.push_back(c);
+ char C = *Top.Current;
+ CumulativeString.push_back(C);
}
Top.Current += 1;
uint64_t childNodeIndex = readULEB128(Top.Current);
}
+MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
+ : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
+ RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
+ PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {}
+
+void MachORebaseEntry::moveToFirst() {
+ Ptr = Opcodes.begin();
+ moveNext();
+}
+
+void MachORebaseEntry::moveToEnd() {
+ Ptr = Opcodes.end();
+ RemainingLoopCount = 0;
+ Done = true;
+}
+
+void MachORebaseEntry::moveNext() {
+ // If in the middle of some loop, move to next rebasing in loop.
+ SegmentOffset += AdvanceAmount;
+ if (RemainingLoopCount) {
+ --RemainingLoopCount;
+ return;
+ }
+ if (Ptr == Opcodes.end()) {
+ Done = true;
+ return;
+ }
+ bool More = true;
+ while (More && !Malformed) {
+ // Parse next opcode and set up next loop.
+ uint8_t Byte = *Ptr++;
+ uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
+ uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
+ switch (Opcode) {
+ case MachO::REBASE_OPCODE_DONE:
+ More = false;
+ Done = true;
+ moveToEnd();
+ DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n");
+ break;
+ case MachO::REBASE_OPCODE_SET_TYPE_IMM:
+ RebaseType = ImmValue;
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
+ << "RebaseType=" << (int) RebaseType << "\n");
+ break;
+ case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+ SegmentIndex = ImmValue;
+ SegmentOffset = readULEB128();
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
+ << "SegmentIndex=" << SegmentIndex << ", "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << "\n");
+ break;
+ case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
+ SegmentOffset += readULEB128();
+ DEBUG_WITH_TYPE("mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
+ << format("SegmentOffset=0x%06X",
+ SegmentOffset) << "\n");
+ break;
+ case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
+ SegmentOffset += ImmValue * PointerSize;
+ DEBUG_WITH_TYPE("mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
+ << format("SegmentOffset=0x%06X",
+ SegmentOffset) << "\n");
+ break;
+ case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
+ AdvanceAmount = PointerSize;
+ RemainingLoopCount = ImmValue - 1;
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
+ AdvanceAmount = PointerSize;
+ RemainingLoopCount = readULEB128() - 1;
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
+ AdvanceAmount = readULEB128() + PointerSize;
+ RemainingLoopCount = 0;
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
+ RemainingLoopCount = readULEB128() - 1;
+ AdvanceAmount = readULEB128() + PointerSize;
+ DEBUG_WITH_TYPE(
+ "mach-o-rebase",
+ llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ default:
+ Malformed = true;
+ }
+ }
+}
+
+uint64_t MachORebaseEntry::readULEB128() {
+ unsigned Count;
+ uint64_t Result = decodeULEB128(Ptr, &Count);
+ Ptr += Count;
+ if (Ptr > Opcodes.end()) {
+ Ptr = Opcodes.end();
+ Malformed = true;
+ }
+ return Result;
+}
+
+uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
+
+uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
+
+StringRef MachORebaseEntry::typeName() const {
+ switch (RebaseType) {
+ case MachO::REBASE_TYPE_POINTER:
+ return "pointer";
+ case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
+ return "text abs32";
+ case MachO::REBASE_TYPE_TEXT_PCREL32:
+ return "text rel32";
+ }
+ return "unknown";
+}
+
+bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
+ assert(Opcodes == Other.Opcodes && "compare iterators of different files");
+ return (Ptr == Other.Ptr) &&
+ (RemainingLoopCount == Other.RemainingLoopCount) &&
+ (Done == Other.Done);
+}
+
+iterator_range<rebase_iterator>
+MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
+ MachORebaseEntry Start(Opcodes, is64);
+ Start.moveToFirst();
+
+ MachORebaseEntry Finish(Opcodes, is64);
+ Finish.moveToEnd();
+
+ return iterator_range<rebase_iterator>(rebase_iterator(Start),
+ rebase_iterator(Finish));
+}
+
+iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
+ return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
+}
+
+
+MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit,
+ Kind BK)
+ : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
+ Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0),
+ BindType(0), PointerSize(is64Bit ? 8 : 4),
+ TableKind(BK), Malformed(false), Done(false) {}
+
+void MachOBindEntry::moveToFirst() {
+ Ptr = Opcodes.begin();
+ moveNext();
+}
+
+void MachOBindEntry::moveToEnd() {
+ Ptr = Opcodes.end();
+ RemainingLoopCount = 0;
+ Done = true;
+}
+
+void MachOBindEntry::moveNext() {
+ // If in the middle of some loop, move to next binding in loop.
+ SegmentOffset += AdvanceAmount;
+ if (RemainingLoopCount) {
+ --RemainingLoopCount;
+ return;
+ }
+ if (Ptr == Opcodes.end()) {
+ Done = true;
+ return;
+ }
+ bool More = true;
+ while (More && !Malformed) {
+ // Parse next opcode and set up next loop.
+ uint8_t Byte = *Ptr++;
+ uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
+ uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
+ int8_t SignExtended;
+ const uint8_t *SymStart;
+ switch (Opcode) {
+ case MachO::BIND_OPCODE_DONE:
+ if (TableKind == Kind::Lazy) {
+ // Lazying bindings have a DONE opcode between entries. Need to ignore
+ // it to advance to next entry. But need not if this is last entry.
+ bool NotLastEntry = false;
+ for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
+ if (*P) {
+ NotLastEntry = true;
+ }
+ }
+ if (NotLastEntry)
+ break;
+ }
+ More = false;
+ Done = true;
+ moveToEnd();
+ DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n");
+ break;
+ case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
+ Ordinal = ImmValue;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
+ << "Ordinal=" << Ordinal << "\n");
+ break;
+ case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
+ Ordinal = readULEB128();
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
+ << "Ordinal=" << Ordinal << "\n");
+ break;
+ case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
+ if (ImmValue) {
+ SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
+ Ordinal = SignExtended;
+ } else
+ Ordinal = 0;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
+ << "Ordinal=" << Ordinal << "\n");
+ break;
+ case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
+ Flags = ImmValue;
+ SymStart = Ptr;
+ while (*Ptr) {
+ ++Ptr;
+ }
+ SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
+ Ptr-SymStart);
+ ++Ptr;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
+ << "SymbolName=" << SymbolName << "\n");
+ if (TableKind == Kind::Weak) {
+ if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
+ return;
+ }
+ break;
+ case MachO::BIND_OPCODE_SET_TYPE_IMM:
+ BindType = ImmValue;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
+ << "BindType=" << (int)BindType << "\n");
+ break;
+ case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
+ Addend = readSLEB128();
+ if (TableKind == Kind::Lazy)
+ Malformed = true;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
+ << "Addend=" << Addend << "\n");
+ break;
+ case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+ SegmentIndex = ImmValue;
+ SegmentOffset = readULEB128();
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
+ << "SegmentIndex=" << SegmentIndex << ", "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << "\n");
+ break;
+ case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
+ SegmentOffset += readULEB128();
+ DEBUG_WITH_TYPE("mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
+ << format("SegmentOffset=0x%06X",
+ SegmentOffset) << "\n");
+ break;
+ case MachO::BIND_OPCODE_DO_BIND:
+ AdvanceAmount = PointerSize;
+ RemainingLoopCount = 0;
+ DEBUG_WITH_TYPE("mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_DO_BIND: "
+ << format("SegmentOffset=0x%06X",
+ SegmentOffset) << "\n");
+ return;
+ case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
+ AdvanceAmount = readULEB128();
+ RemainingLoopCount = 0;
+ if (TableKind == Kind::Lazy)
+ Malformed = true;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
+ AdvanceAmount = ImmValue * PointerSize;
+ RemainingLoopCount = 0;
+ if (TableKind == Kind::Lazy)
+ Malformed = true;
+ DEBUG_WITH_TYPE("mach-o-bind",
+ llvm::dbgs()
+ << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
+ << format("SegmentOffset=0x%06X",
+ SegmentOffset) << "\n");
+ return;
+ case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
+ RemainingLoopCount = readULEB128() - 1;
+ AdvanceAmount = readULEB128() + PointerSize;
+ if (TableKind == Kind::Lazy)
+ Malformed = true;
+ DEBUG_WITH_TYPE(
+ "mach-o-bind",
+ llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
+ << format("SegmentOffset=0x%06X", SegmentOffset)
+ << ", AdvanceAmount=" << AdvanceAmount
+ << ", RemainingLoopCount=" << RemainingLoopCount
+ << "\n");
+ return;
+ default:
+ Malformed = true;
+ }
+ }
+}
+
+uint64_t MachOBindEntry::readULEB128() {
+ unsigned Count;
+ uint64_t Result = decodeULEB128(Ptr, &Count);
+ Ptr += Count;
+ if (Ptr > Opcodes.end()) {
+ Ptr = Opcodes.end();
+ Malformed = true;
+ }
+ return Result;
+}
+
+int64_t MachOBindEntry::readSLEB128() {
+ unsigned Count;
+ int64_t Result = decodeSLEB128(Ptr, &Count);
+ Ptr += Count;
+ if (Ptr > Opcodes.end()) {
+ Ptr = Opcodes.end();
+ Malformed = true;
+ }
+ return Result;
+}
+
+
+uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
+
+uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
+
+StringRef MachOBindEntry::typeName() const {
+ switch (BindType) {
+ case MachO::BIND_TYPE_POINTER:
+ return "pointer";
+ case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
+ return "text abs32";
+ case MachO::BIND_TYPE_TEXT_PCREL32:
+ return "text rel32";
+ }
+ return "unknown";
+}
+
+StringRef MachOBindEntry::symbolName() const { return SymbolName; }
+
+int64_t MachOBindEntry::addend() const { return Addend; }
+
+uint32_t MachOBindEntry::flags() const { return Flags; }
+
+int MachOBindEntry::ordinal() const { return Ordinal; }
+
+bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
+ assert(Opcodes == Other.Opcodes && "compare iterators of different files");
+ return (Ptr == Other.Ptr) &&
+ (RemainingLoopCount == Other.RemainingLoopCount) &&
+ (Done == Other.Done);
+}
+
+iterator_range<bind_iterator>
+MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64,
+ MachOBindEntry::Kind BKind) {
+ MachOBindEntry Start(Opcodes, is64, BKind);
+ Start.moveToFirst();
+
+ MachOBindEntry Finish(Opcodes, is64, BKind);
+ Finish.moveToEnd();
+
+ return iterator_range<bind_iterator>(bind_iterator(Start),
+ bind_iterator(Finish));
+}
+
+iterator_range<bind_iterator> MachOObjectFile::bindTable() const {
+ return bindTable(getDyldInfoBindOpcodes(), is64Bit(),
+ MachOBindEntry::Kind::Regular);
+}
+
+iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const {
+ return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(),
+ MachOBindEntry::Kind::Lazy);
+}
+
+iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const {
+ return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(),
+ MachOBindEntry::Kind::Weak);
+}
+
StringRef
MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
return getStruct<MachO::dylib_command>(this, L.Ptr);
}
+MachO::dyld_info_command
+MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::dyld_info_command>(this, L.Ptr);
+}
+
+MachO::dylinker_command
+MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::dylinker_command>(this, L.Ptr);
+}
+
+MachO::uuid_command
+MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::uuid_command>(this, L.Ptr);
+}
+
+MachO::source_version_command
+MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::source_version_command>(this, L.Ptr);
+}
+
+MachO::entry_point_command
+MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
+ return getStruct<MachO::entry_point_command>(this, L.Ptr);
+}
+
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {