Add the rest of the error checking for Mach-O dyld compact bind entry errors

and test cases for each of the error checks.

To do this more plumbing was needed so that the segment indexes and
segment offsets can be checked.  Basically what was done was the SegInfo
from llvm-objdump’s MachODump.cpp was moved into libObject for Mach-O
objects as BindRebaseSegInfo and it is only created when an iterator for
bind or rebase entries are created.

This commit really only adds the error checking and test cases for the
bind table entires and the checking for the lazy bind and weak bind entries
are still to be fully done as well as the rebase entires.  Though some of
the plumbing for those are added with this commit.  Those other error
checks and test cases will be added in follow on commits.

Note, the two llvm_unreachable() calls should now actually be unreachable
with the error checks in place and would take a logic bug in the error
checking code to be reached if the segment indexes and segment
offsets are used from a checked bind entry.  Comments have been added
to the methods that require the arguments to have been checked
prior to calling.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298292 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kevin Enderby 2017-03-20 19:46:55 +00:00
parent d3ffac83c0
commit 1ae32f1960
25 changed files with 623 additions and 203 deletions

View File

@ -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;
uint64_t segmentOffset() const;
StringRef typeName() const;
StringRef segmentName() const;
StringRef sectionName() const;
uint64_t address() const;
bool operator==(const MachORebaseEntry &) const;
@ -123,6 +163,8 @@ private:
void moveToEnd();
uint64_t readULEB128();
Error *E;
const MachOObjectFile *O;
ArrayRef<uint8_t> Opcodes;
const uint8_t *Ptr;
uint64_t SegmentOffset;
@ -150,7 +192,7 @@ public:
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;
@ -158,6 +200,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();
@ -166,16 +212,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;
@ -291,28 +338,63 @@ 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(Error &Err) const;
iterator_range<bind_iterator> bindTable(Error &Err);
/// For use iterating over all lazy bind table entries.
iterator_range<bind_iterator> lazyBindTable(Error &Err) const;
iterator_range<bind_iterator> lazyBindTable(Error &Err);
/// For use iterating over all weak bind table entries.
iterator_range<bind_iterator> weakBindTable(Error &Err) const;
iterator_range<bind_iterator> weakBindTable(Error &Err);
/// For use examining bind opcodes not in a MachOObjectFile.
/// For use examining bind opcodes in a MachOObjectFile.
static iterator_range<bind_iterator> bindTable(Error &Err,
const MachOObjectFile *O,
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 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
@ -519,6 +601,7 @@ private:
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;

View File

@ -113,11 +113,30 @@ inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
/// Utility function to decode a ULEB128 value.
inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
const uint8_t *end = nullptr,
const char **error = nullptr) {
const uint8_t *orig_p = p;
uint64_t Value = 0;
unsigned Shift = 0;
if(error)
*error = nullptr;
do {
if(end && p == end){
if(error)
*error = "malformed uleb128, extends past end";
if (n)
*n = (unsigned)(p - orig_p);
return 0;
}
uint64_t Slice = *p & 0x7f;
if(Shift >= 64 || Slice << Shift >> Shift != Slice){
if(error)
*error = "uleb128 too big for uint64";
if (n)
*n = (unsigned)(p - orig_p);
return 0;
}
Value += uint64_t(*p & 0x7f) << Shift;
Shift += 7;
} while (*p++ >= 128);
@ -127,12 +146,21 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
}
/// Utility function to decode a SLEB128 value.
inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) {
inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
const uint8_t *end = nullptr,
const char **error = nullptr) {
const uint8_t *orig_p = p;
int64_t Value = 0;
unsigned Shift = 0;
uint8_t Byte;
do {
if(end && p == end){
if(error)
*error = "malformed sleb128, extends past end";
if (n)
*n = (unsigned)(p - orig_p);
return 0;
}
Byte = *p++;
Value |= ((Byte & 0x7f) << Shift);
Shift += 7;

View File

@ -2755,9 +2755,10 @@ iterator_range<export_iterator> MachOObjectFile::exports() const {
return exports(getDyldInfoExportsTrie());
}
MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit)
: Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0),
RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
ArrayRef<uint8_t> Bytes, bool is64Bit)
: E(E), O(O), 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() {
@ -2903,6 +2904,24 @@ StringRef MachORebaseEntry::typeName() const {
return "unknown";
}
// For use with the SegIndex of a checked Mach-O Rebase entry
// to get the segment name.
StringRef MachORebaseEntry::segmentName() const {
return O->BindRebaseSegmentName(SegmentIndex);
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
// to get the section name.
StringRef MachORebaseEntry::sectionName() const {
return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
// to get the address.
uint64_t MachORebaseEntry::address() const {
return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
}
bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
#ifdef EXPENSIVE_CHECKS
assert(Opcodes == Other.Opcodes && "compare iterators of different files");
@ -2915,26 +2934,30 @@ bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
}
iterator_range<rebase_iterator>
MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) {
MachORebaseEntry Start(Opcodes, is64);
MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
ArrayRef<uint8_t> Opcodes, bool is64) {
if (O->BindRebaseSectionTable == nullptr)
O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
MachORebaseEntry Start(&Err, O, Opcodes, is64);
Start.moveToFirst();
MachORebaseEntry Finish(Opcodes, is64);
MachORebaseEntry Finish(&Err, O, Opcodes, is64);
Finish.moveToEnd();
return make_range(rebase_iterator(Start), rebase_iterator(Finish));
}
iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const {
return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit());
iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
}
MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
: E(E), O(O), 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) {}
: E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0),
SegmentIndex(-1), LibraryOrdinalSet(false), 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();
@ -2968,6 +2991,8 @@ void MachOBindEntry::moveNext() {
uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
int8_t SignExtended;
const uint8_t *SymStart;
uint32_t Count, Skip;
const char *error = nullptr;
switch (Opcode) {
case MachO::BIND_OPCODE_DONE:
if (TableKind == Kind::Lazy) {
@ -2989,6 +3014,7 @@ void MachOBindEntry::moveNext() {
break;
case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
Ordinal = ImmValue;
LibraryOrdinalSet = true;
if (ImmValue > O->getLibraryCount()) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
"library ordinal: " + Twine((int)ImmValue) + " (max " +
@ -3003,7 +3029,23 @@ void MachOBindEntry::moveNext() {
<< "Ordinal=" << Ordinal << "\n");
break;
case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
Ordinal = readULEB128();
Ordinal = readULEB128(&error);
LibraryOrdinalSet = true;
if (error) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (Ordinal > (int)O->getLibraryCount()) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
"library ordinal: " + Twine((int)Ordinal) + " (max " +
Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
@ -3013,6 +3055,14 @@ void MachOBindEntry::moveNext() {
if (ImmValue) {
SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
Ordinal = SignExtended;
LibraryOrdinalSet = true;
if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
"special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
"0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
} else
Ordinal = 0;
DEBUG_WITH_TYPE(
@ -3023,9 +3073,16 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
Flags = ImmValue;
SymStart = Ptr;
while (*Ptr) {
while (*Ptr && (Ptr < Opcodes.end())) {
++Ptr;
}
if (Ptr == Opcodes.end()) {
*E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
"symbol name extends past opcodes for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
Ptr-SymStart);
++Ptr;
@ -3040,13 +3097,27 @@ void MachOBindEntry::moveNext() {
break;
case MachO::BIND_OPCODE_SET_TYPE_IMM:
BindType = ImmValue;
if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
*E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
Twine((int)ImmValue) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
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();
Addend = readSLEB128(&error);
if (error) {
*E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (TableKind == Kind::Lazy)
Malformed = true;
DEBUG_WITH_TYPE(
@ -3056,7 +3127,22 @@ void MachOBindEntry::moveNext() {
break;
case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
SegmentIndex = ImmValue;
SegmentOffset = readULEB128();
SegmentOffset = readULEB128(&error);
if (error) {
*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
@ -3065,7 +3151,22 @@ void MachOBindEntry::moveNext() {
<< "\n");
break;
case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
SegmentOffset += readULEB128();
SegmentOffset += readULEB128(&error);
if (error) {
*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
DEBUG_WITH_TYPE("mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
<< format("SegmentOffset=0x%06X",
@ -3074,13 +3175,75 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_DO_BIND:
AdvanceAmount = PointerSize;
RemainingLoopCount = 0;
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
" for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
*E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
"BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
*E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
"BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
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() + PointerSize;
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
"preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
"at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
"preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
AdvanceAmount = readULEB128(&error) + PointerSize;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
// Note, this is not really an error until the next bind but make no sense
// for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
// bind operation.
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
AdvanceAmount, false);
if (error) {
*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
"ULEB) " + Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
RemainingLoopCount = 0;
if (TableKind == Kind::Lazy)
Malformed = true;
@ -3093,8 +3256,40 @@ void MachOBindEntry::moveNext() {
<< "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
"missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
"opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
"missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
"at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
AdvanceAmount = ImmValue * PointerSize + PointerSize;
RemainingLoopCount = 0;
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
AdvanceAmount, false);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
" (after adding immediate times the pointer size) " +
Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (TableKind == Kind::Lazy)
Malformed = true;
DEBUG_WITH_TYPE("mach-o-bind",
@ -3104,8 +3299,58 @@ void MachOBindEntry::moveNext() {
SegmentOffset) << "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
RemainingLoopCount = readULEB128() - 1;
AdvanceAmount = readULEB128() + PointerSize;
Count = readULEB128(&error);
if (Count != 0)
RemainingLoopCount = Count - 1;
else
RemainingLoopCount = 0;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
" (count value) " + Twine(error) + " for opcode at"
": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
Skip = readULEB128(&error);
AdvanceAmount = Skip + PointerSize;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
" (skip value) " + Twine(error) + " for opcode at"
": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
+ Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
"missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
"opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
"missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
"at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
SegmentIndex, SegmentOffset);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
+ Twine(error) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (TableKind == Kind::Lazy)
Malformed = true;
DEBUG_WITH_TYPE(
@ -3118,13 +3363,18 @@ void MachOBindEntry::moveNext() {
return;
default:
Malformed = true;
*E = malformedError("bad bind info (bad opcode value 0x" +
utohexstr(Opcode) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
}
}
uint64_t MachOBindEntry::readULEB128() {
uint64_t MachOBindEntry::readULEB128(const char **error) {
unsigned Count;
uint64_t Result = decodeULEB128(Ptr, &Count);
uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Ptr += Count;
if (Ptr > Opcodes.end()) {
Ptr = Opcodes.end();
@ -3133,9 +3383,9 @@ uint64_t MachOBindEntry::readULEB128() {
return Result;
}
int64_t MachOBindEntry::readSLEB128() {
int64_t MachOBindEntry::readSLEB128(const char **error) {
unsigned Count;
int64_t Result = decodeSLEB128(Ptr, &Count);
int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Ptr += Count;
if (Ptr > Opcodes.end()) {
Ptr = Opcodes.end();
@ -3144,7 +3394,7 @@ int64_t MachOBindEntry::readSLEB128() {
return Result;
}
uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
@ -3168,6 +3418,24 @@ uint32_t MachOBindEntry::flags() const { return Flags; }
int MachOBindEntry::ordinal() const { return Ordinal; }
// For use with the SegIndex of a checked Mach-O Bind entry
// to get the segment name.
StringRef MachOBindEntry::segmentName() const {
return O->BindRebaseSegmentName(SegmentIndex);
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
// to get the section name.
StringRef MachOBindEntry::sectionName() const {
return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
// to get the address.
uint64_t MachOBindEntry::address() const {
return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
}
bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
#ifdef EXPENSIVE_CHECKS
assert(Opcodes == Other.Opcodes && "compare iterators of different files");
@ -3179,10 +3447,119 @@ bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
(Done == Other.Done);
}
// Build table of sections so SegIndex/SegOffset pairs can be translated.
BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
StringRef CurSegName;
uint64_t CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
SectionInfo Info;
Section.getName(Info.SectionName);
Info.Address = Section.getAddress();
Info.Size = Section.getSize();
Info.SegmentName =
Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
if (!Info.SegmentName.equals(CurSegName)) {
++CurSegIndex;
CurSegName = Info.SegmentName;
CurSegAddress = Info.Address;
}
Info.SegmentIndex = CurSegIndex - 1;
Info.OffsetInSegment = Info.Address - CurSegAddress;
Info.SegmentStartAddress = CurSegAddress;
Sections.push_back(Info);
}
MaxSegIndex = CurSegIndex;
}
// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
// validate a MachOBindEntry.
const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
uint64_t SegOffset,
bool endInvalid) {
if (SegIndex == -1)
return "missing preceding BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
if (SegIndex >= MaxSegIndex)
return "bad segIndex (too large)";
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
continue;
if (SI.OffsetInSegment > SegOffset)
continue;
if (SegOffset > (SI.OffsetInSegment + SI.Size))
continue;
if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size))
continue;
return nullptr;
}
return "bad segOffset, too large";
}
// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for
// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode. The SegIndex
// and SegOffset must have been already checked.
const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
uint8_t PointerSize,
int32_t SegIndex,
uint64_t SegOffset) {
const SectionInfo &SI = findSection(SegIndex, SegOffset);
uint64_t addr = SI.SegmentStartAddress + SegOffset;
if (addr >= SI.Address + SI.Size)
return "bad segOffset, too large";
uint64_t i = 0;
if (Count > 1)
i = (Skip + PointerSize) * (Count - 1);
if (addr + i >= SI.Address + SI.Size)
return "bad count and skip, too large";
return nullptr;
}
// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
// to get the segment name.
StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex == SegIndex)
return SI.SegmentName;
}
llvm_unreachable("invalid SegIndex");
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
// to get the SectionInfo.
const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
int32_t SegIndex, uint64_t SegOffset) {
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
continue;
if (SI.OffsetInSegment > SegOffset)
continue;
if (SegOffset >= (SI.OffsetInSegment + SI.Size))
continue;
return SI;
}
llvm_unreachable("SegIndex and SegOffset not in any section");
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
// entry to get the section name.
StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
uint64_t SegOffset) {
return findSection(SegIndex, SegOffset).SectionName;
}
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
// entry to get the address.
uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
return SI.SegmentStartAddress + OffsetInSeg;
}
iterator_range<bind_iterator>
MachOObjectFile::bindTable(Error &Err, const MachOObjectFile *O,
MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
ArrayRef<uint8_t> Opcodes, bool is64,
MachOBindEntry::Kind BKind) {
if (O->BindRebaseSectionTable == nullptr)
O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
Start.moveToFirst();
@ -3192,17 +3569,17 @@ MachOObjectFile::bindTable(Error &Err, const MachOObjectFile *O,
return make_range(bind_iterator(Start), bind_iterator(Finish));
}
iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) const {
iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
MachOBindEntry::Kind::Regular);
}
iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) const {
iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
MachOBindEntry::Kind::Lazy);
}
iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) const {
iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
MachOBindEntry::Kind::Weak);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -64,5 +64,5 @@ INVALID-SYMBOL-STRX-UNIVERSAL: macho-invalid-symbol-strx-universal' (for archite
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-lib_ordinal 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-LIB_ORDINAL %s
INVALID-SYMBOL-LIB_ORDINAL: macho-invalid-symbol-lib_ordinal': truncated or malformed object (bad library ordinal: 7 for symbol at index 2)
RUN: llvm-objdump -macho -objc-meta-data %p/Inputs/macho-invalid-bind-entry | FileCheck -check-prefix INVALID-BIND-ENTRY %s
INVALID-BIND-ENTRY: 0000000100020c90 0x2d0409887202e473
RUN: not llvm-objdump -macho -objc-meta-data %p/Inputs/macho-invalid-bind-entry 2>&1 | FileCheck -check-prefix INVALID-BIND-ENTRY %s
INVALID-BIND-ENTRY: macho-invalid-bind-entry': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad library ordinal: 83 (max 0) for opcode at: 0x0)

View File

@ -0,0 +1,50 @@
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-dylib-ordinal-uleb 2>&1 | FileCheck -check-prefix DYLIB-ORDINAL-ULEB %s
DYLIB-ORDINAL-ULEB: macho-bind-dylib-ordinal-uleb': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad library ordinal: 355 (max 1) for opcode at: 0x0)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-dylib-ordinal-uleb-malformed-uleb128 2>&1 | FileCheck -check-prefix DYLIB-ORDINAL-ULEB-MALFORMED-ULEB128 %s
DYLIB-ORDINAL-ULEB-MALFORMED-ULEB128: macho-bind-dylib-ordinal-uleb-malformed-uleb128': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB malformed uleb128, extends past end for opcode at: 0x0)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-dylib-ordinal-uleb-too-big 2>&1 | FileCheck -check-prefix DYLIB-ORDINAL-ULEB-TOO-BIG %s
DYLIB-ORDINAL-ULEB-TOO-BIG: macho-bind-dylib-ordinal-uleb-too-big': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB uleb128 too big for uint64 for opcode at: 0x0)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-dylib-special-imm 2>&1 | FileCheck -check-prefix DYLIB-SPECIAL-IMM %s
DYLIB-SPECIAL-IMM: macho-bind-dylib-special-imm': truncated or malformed object (for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown special ordinal: -5 for opcode at: 0x0)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-set-symbol 2>&1 | FileCheck -check-prefix BIND-SET-SYMBOL %s
BIND-SET-SYMBOL: macho-bind-set-symbol': truncated or malformed object (for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM symbol name extends past opcodes for opcode at: 0x2)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-set-type-imm 2>&1 | FileCheck -check-prefix SET-TYPE-IMM %s
SET-TYPE-IMM: macho-bind-set-type-imm': truncated or malformed object (for BIND_OPCODE_SET_TYPE_IMM bad bind type: 5 for opcode at: 0x14)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-set-addend-sleb 2>&1 | FileCheck -check-prefix SET-ADDEND-SLEB %s
SET-ADDEND-SLEB: macho-bind-set-addend-sleb': truncated or malformed object (for BIND_OPCODE_SET_ADDEND_SLEB malformed sleb128, extends past end for opcode at: 0x14)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-seg-too-big 2>&1 | FileCheck -check-prefix SEG-TOO-BIG %s
SEG-TOO-BIG: macho-bind-seg-too-big': truncated or malformed object (for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segIndex (too large) for opcode at: 0x15)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-segoff-too-big 2>&1 | FileCheck -check-prefix SEGOFF-TOO-BIG %s
SEGOFF-TOO-BIG: macho-bind-segoff-too-big': truncated or malformed object (for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segOffset, too large for opcode at: 0x15)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-add_addr_uleb 2>&1 | FileCheck -check-prefix ADD_ADDR_ULEB %s
ADD_ADDR_ULEB: macho-bind-add_addr_uleb': truncated or malformed object (for BIND_OPCODE_ADD_ADDR_ULEB bad segOffset, too large for opcode at: 0x17)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-do-bind-no-segIndex 2>&1 | FileCheck -check-prefix BIND-NO-SEGINDEX %s
BIND-NO-SEGINDEX: macho-bind-do-bind-no-segIndex': truncated or malformed object (for BIND_OPCODE_DO_BIND missing preceding BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB for opcode at: 0x15)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-bind-add-addr-uleb 2>&1 | FileCheck -check-prefix ADD-ADDR-ULEB %s
ADD-ADDR-ULEB: macho-bind-bind-add-addr-uleb': truncated or malformed object (for BIND_OPCODE_ADD_ADDR_ULEB (after adding ULEB) bad segOffset, too large for opcode at: 0x18)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-add-addr-imm-scaled 2>&1 | FileCheck -check-prefix ADD-ADDR-IMM-SCALED %s
ADD-ADDR-IMM-SCALED: macho-bind-add-addr-imm-scaled': truncated or malformed object (for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED (after adding immediate times the pointer size) bad segOffset, too large for opcode at: 0x17)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-uleb-times-skipping-uleb 2>&1 | FileCheck -check-prefix ULEB-TIMES-SKIPPING-ULEB %s
ULEB-TIMES-SKIPPING-ULEB: macho-bind-uleb-times-skipping-uleb': truncated or malformed object (for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB bad count and skip, too large for opcode at: 0x17)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-do-bind-no-symbol 2>&1 | FileCheck -check-prefix DO-BIND-NO-SYMBOL %s
DO-BIND-NO-SYMBOL: macho-do-bind-no-symbol': truncated or malformed object (for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x5)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-do-bind-no-dylib-ordinal 2>&1 | FileCheck -check-prefix DO-BIND-NO-DYLIB-ORDINAL %s
DO-BIND-NO-DYLIB-ORDINAL: macho-do-bind-no-dylib-ordinal': truncated or malformed object (for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x15)
RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-bad-opcode-value 2>&1 | FileCheck -check-prefix BAD-OPCODE-VALUE %s
BAD-OPCODE-VALUE: macho-bind-bad-opcode-value': truncated or malformed object (bad bind info (bad opcode value 0xD0 for opcode at: 0x18)

View File

@ -9391,117 +9391,21 @@ void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
// rebase table dumping
//===----------------------------------------------------------------------===//
namespace {
class SegInfo {
public:
SegInfo(const object::MachOObjectFile *Obj);
StringRef segmentName(uint32_t SegIndex);
StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
bool isValidSegIndexAndOffset(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;
uint32_t SegmentIndex;
};
const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset);
SmallVector<SectionInfo, 32> Sections;
};
}
SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
// Build table of sections so segIndex/offset pairs can be translated.
uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
StringRef CurSegName;
uint64_t CurSegAddress;
for (const SectionRef &Section : Obj->sections()) {
SectionInfo Info;
error(Section.getName(Info.SectionName));
Info.Address = Section.getAddress();
Info.Size = Section.getSize();
Info.SegmentName =
Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
if (!Info.SegmentName.equals(CurSegName)) {
++CurSegIndex;
CurSegName = Info.SegmentName;
CurSegAddress = Info.Address;
}
Info.SegmentIndex = CurSegIndex - 1;
Info.OffsetInSegment = Info.Address - CurSegAddress;
Info.SegmentStartAddress = CurSegAddress;
Sections.push_back(Info);
}
}
StringRef SegInfo::segmentName(uint32_t SegIndex) {
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex == SegIndex)
return SI.SegmentName;
}
llvm_unreachable("invalid segIndex");
}
bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
uint64_t OffsetInSeg) {
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
continue;
if (SI.OffsetInSegment > OffsetInSeg)
continue;
if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
continue;
return true;
}
return false;
}
const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
uint64_t OffsetInSeg) {
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
continue;
if (SI.OffsetInSegment > OffsetInSeg)
continue;
if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
continue;
return SI;
}
llvm_unreachable("segIndex and offset not in any section");
}
StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) {
return findSection(SegIndex, OffsetInSeg).SectionName;
}
uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
return SI.SegmentStartAddress + OffsetInSeg;
}
void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) {
// Build table of sections so names can used in final output.
SegInfo sectionTable(Obj);
void llvm::printMachORebaseTable(object::MachOObjectFile *Obj) {
outs() << "segment section address type\n";
for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
StringRef SegmentName = sectionTable.segmentName(SegIndex);
StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
Error Err = Error::success();
for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(Err)) {
StringRef SegmentName = Entry.segmentName();
StringRef SectionName = Entry.sectionName();
uint64_t Address = Entry.address();
// Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer
outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n",
SegmentName.str().c_str(), SectionName.str().c_str(),
Address, Entry.typeName().str().c_str());
}
if (Err)
report_error(Obj->getFileName(), std::move(Err));
}
static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
@ -9529,19 +9433,15 @@ static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
// bind table dumping
//===----------------------------------------------------------------------===//
void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
void llvm::printMachOBindTable(object::MachOObjectFile *Obj) {
// Build table of sections so names can used in final output.
SegInfo sectionTable(Obj);
outs() << "segment section address type "
"addend dylib symbol\n";
Error Err = Error::success();
for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(Err)) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
StringRef SegmentName = sectionTable.segmentName(SegIndex);
StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
StringRef SegmentName = Entry.segmentName();
StringRef SectionName = Entry.sectionName();
uint64_t Address = Entry.address();
// Table lines look like:
// __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
@ -9564,19 +9464,14 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
// lazy bind table dumping
//===----------------------------------------------------------------------===//
void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
// Build table of sections so names can used in final output.
SegInfo sectionTable(Obj);
void llvm::printMachOLazyBindTable(object::MachOObjectFile *Obj) {
outs() << "segment section address "
"dylib symbol\n";
Error Err = Error::success();
for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable(Err)) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
StringRef SegmentName = sectionTable.segmentName(SegIndex);
StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
StringRef SegmentName = Entry.segmentName();
StringRef SectionName = Entry.sectionName();
uint64_t Address = Entry.address();
// Table lines look like:
// __DATA __got 0x00012010 libSystem ___stack_chk_guard
@ -9594,10 +9489,7 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
// weak bind table dumping
//===----------------------------------------------------------------------===//
void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
// Build table of sections so names can used in final output.
SegInfo sectionTable(Obj);
void llvm::printMachOWeakBindTable(object::MachOObjectFile *Obj) {
outs() << "segment section address "
"type addend symbol\n";
Error Err = Error::success();
@ -9608,11 +9500,9 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
<< Entry.symbolName() << "\n";
continue;
}
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
StringRef SegmentName = sectionTable.segmentName(SegIndex);
StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
StringRef SegmentName = Entry.segmentName();
StringRef SectionName = Entry.sectionName();
uint64_t Address = Entry.address();
// Table lines look like:
// __DATA __data 0x00001000 pointer 0 _foo
@ -9635,17 +9525,9 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
struct DisassembleInfo *info) {
if (info->bindtable == nullptr) {
info->bindtable = llvm::make_unique<SymbolAddressMap>();
SegInfo sectionTable(info->O);
Error Err = Error::success();
for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable(Err)) {
uint32_t SegIndex = Entry.segmentIndex();
uint64_t OffsetInSeg = Entry.segmentOffset();
if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg)) {
if (Err)
report_error(info->O->getFileName(), std::move(Err));
return nullptr;
}
uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
uint64_t Address = Entry.address();
StringRef name = Entry.symbolName();
if (!name.empty())
(*info->bindtable)[Address] = name;

View File

@ -1885,9 +1885,9 @@ void llvm::printExportsTrie(const ObjectFile *o) {
}
}
void llvm::printRebaseTable(const ObjectFile *o) {
void llvm::printRebaseTable(ObjectFile *o) {
outs() << "Rebase table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachORebaseTable(MachO);
else {
errs() << "This operation is only currently supported "
@ -1896,9 +1896,9 @@ void llvm::printRebaseTable(const ObjectFile *o) {
}
}
void llvm::printBindTable(const ObjectFile *o) {
void llvm::printBindTable(ObjectFile *o) {
outs() << "Bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOBindTable(MachO);
else {
errs() << "This operation is only currently supported "
@ -1907,9 +1907,9 @@ void llvm::printBindTable(const ObjectFile *o) {
}
}
void llvm::printLazyBindTable(const ObjectFile *o) {
void llvm::printLazyBindTable(ObjectFile *o) {
outs() << "Lazy bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOLazyBindTable(MachO);
else {
errs() << "This operation is only currently supported "
@ -1918,9 +1918,9 @@ void llvm::printLazyBindTable(const ObjectFile *o) {
}
}
void llvm::printWeakBindTable(const ObjectFile *o) {
void llvm::printWeakBindTable(ObjectFile *o) {
outs() << "Weak bind table:\n";
if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
printMachOWeakBindTable(MachO);
else {
errs() << "This operation is only currently supported "
@ -2018,7 +2018,7 @@ static void printPrivateFileHeaders(const ObjectFile *o, bool onlyFirst) {
report_error(o->getFileName(), "Invalid/Unsupported object file format");
}
static void DumpObject(const ObjectFile *o, const Archive *a = nullptr) {
static void DumpObject(ObjectFile *o, const Archive *a = nullptr) {
StringRef ArchiveName = a != nullptr ? a->getFileName() : "";
// Avoid other output when using a raw option.
if (!RawClangAST) {

View File

@ -70,10 +70,10 @@ void ParseInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printMachOUnwindInfo(const object::MachOObjectFile* o);
void printMachOExportsTrie(const object::MachOObjectFile* o);
void printMachORebaseTable(const object::MachOObjectFile* o);
void printMachOBindTable(const object::MachOObjectFile* o);
void printMachOLazyBindTable(const object::MachOObjectFile* o);
void printMachOWeakBindTable(const object::MachOObjectFile* o);
void printMachORebaseTable(object::MachOObjectFile* o);
void printMachOBindTable(object::MachOObjectFile* o);
void printMachOLazyBindTable(object::MachOObjectFile* o);
void printMachOWeakBindTable(object::MachOObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
void printCOFFFileHeader(const object::ObjectFile *o);
void printCOFFSymbolTable(const object::COFFImportFile *i);
@ -82,10 +82,10 @@ void printMachOFileHeader(const object::ObjectFile *o);
void printMachOLoadCommands(const object::ObjectFile *o);
void printWasmFileHeader(const object::ObjectFile *o);
void printExportsTrie(const object::ObjectFile *o);
void printRebaseTable(const object::ObjectFile *o);
void printBindTable(const object::ObjectFile *o);
void printLazyBindTable(const object::ObjectFile *o);
void printWeakBindTable(const object::ObjectFile *o);
void printRebaseTable(object::ObjectFile *o);
void printBindTable(object::ObjectFile *o);
void printLazyBindTable(object::ObjectFile *o);
void printWeakBindTable(object::ObjectFile *o);
void printRawClangAST(const object::ObjectFile *o);
void PrintRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);