summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Object/MachO.h24
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp320
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-bind-missing-donebin0 -> 8432 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-add-addr-imm-scaledbin0 -> 8448 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-uleb-times-skipping-ulebbin0 -> 8448 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-lazy-do_bind_add_addr_ulebbin0 -> 8448 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-imm-scaledbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-ulebbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb-too-bigbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-bad-opcode-valuebin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-imm-timesbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-missing-donebin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-seg-too-bigbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-segoff-too-bigbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-set-type-immbin0 -> 8432 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-malformed-uleb128bin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-timesbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times-skipping-ulebbin0 -> 8456 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-immbin0 -> 8464 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-ulebbin0 -> 8464 bytes
-rwxr-xr-xllvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-special-immbin0 -> 8464 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/macho-bad-bind.test59
22 files changed, 351 insertions, 52 deletions
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index 019f777ed65..1ee571cce73 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -146,7 +146,7 @@ public:
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;
@@ -161,19 +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;
@@ -231,7 +230,6 @@ private:
uint8_t BindType;
uint8_t PointerSize;
Kind TableKind;
- bool Malformed;
bool Done;
};
typedef content_iterator<MachOBindEntry> bind_iterator;
@@ -378,6 +376,22 @@ public:
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 {
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 0ca1fea6179..8124c18f30e 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -2758,8 +2758,8 @@ iterator_range<export_iterator> MachOObjectFile::exports() const {
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) {}
+ SegmentIndex(-1), RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0),
+ PointerSize(is64Bit ? 8 : 4), Done(false) {}
void MachORebaseEntry::moveToFirst() {
Ptr = Opcodes.begin();
@@ -2773,22 +2773,31 @@ void MachORebaseEntry::moveToEnd() {
}
void MachORebaseEntry::moveNext() {
+ ErrorAsOutParameter ErrAsOutParam(E);
// If in the middle of some loop, move to next rebasing in loop.
SegmentOffset += AdvanceAmount;
if (RemainingLoopCount) {
--RemainingLoopCount;
return;
}
- if (Ptr == Opcodes.end()) {
+ if (Ptr >= Opcodes.end()) {
+ if (Opcodes.begin() != Opcodes.end() && Done != true) {
+ *E = malformedError("missing REBASE_OPCODE_DONE at end of opcodes");
+ moveToEnd();
+ return;
+ }
Done = true;
return;
}
bool More = true;
- while (More && !Malformed) {
+ while (More) {
// Parse next opcode and set up next loop.
+ const uint8_t *OpcodeStart = Ptr;
uint8_t Byte = *Ptr++;
uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
+ uint32_t Count, Skip;
+ const char *error = nullptr;
switch (Opcode) {
case MachO::REBASE_OPCODE_DONE:
More = false;
@@ -2798,6 +2807,13 @@ void MachORebaseEntry::moveNext() {
break;
case MachO::REBASE_OPCODE_SET_TYPE_IMM:
RebaseType = ImmValue;
+ if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
+ *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
+ Twine((int)RebaseType) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
@@ -2805,7 +2821,23 @@ void MachORebaseEntry::moveNext() {
break;
case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
SegmentIndex = ImmValue;
- SegmentOffset = readULEB128();
+ SegmentOffset = readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
@@ -2814,22 +2846,80 @@ void MachORebaseEntry::moveNext() {
<< "\n");
break;
case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
- SegmentOffset += readULEB128();
+ SegmentOffset += readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
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:
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
SegmentOffset += ImmValue * PointerSize;
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ false);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
+ " (after adding immediate times the pointer size) " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
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:
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
AdvanceAmount = PointerSize;
- RemainingLoopCount = ImmValue - 1;
+ Skip = 0;
+ Count = ImmValue;
+ if (ImmValue != 0)
+ RemainingLoopCount = ImmValue - 1;
+ else
+ RemainingLoopCount = 0;
+ error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
+ SegmentIndex, SegmentOffset);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
+ + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
@@ -2839,8 +2929,38 @@ void MachORebaseEntry::moveNext() {
<< "\n");
return;
case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
AdvanceAmount = PointerSize;
- RemainingLoopCount = readULEB128() - 1;
+ Skip = 0;
+ Count = readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ if (Count != 0)
+ RemainingLoopCount = Count - 1;
+ else
+ RemainingLoopCount = 0;
+ error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
+ SegmentIndex, SegmentOffset);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
+ + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
@@ -2850,8 +2970,35 @@ void MachORebaseEntry::moveNext() {
<< "\n");
return;
case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
- AdvanceAmount = readULEB128() + PointerSize;
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ Skip = readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ AdvanceAmount = Skip + PointerSize;
+ Count = 1;
RemainingLoopCount = 0;
+ error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
+ SegmentIndex, SegmentOffset);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
+ + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
@@ -2861,8 +3008,46 @@ void MachORebaseEntry::moveNext() {
<< "\n");
return;
case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
- RemainingLoopCount = readULEB128() - 1;
- AdvanceAmount = readULEB128() + PointerSize;
+ error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
+ true);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
+ "ULEB " + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ Count = readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
+ "ULEB " + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ if (Count != 0)
+ RemainingLoopCount = Count - 1;
+ else
+ RemainingLoopCount = 0;
+ Skip = readULEB128(&error);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
+ "ULEB " + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
+ AdvanceAmount = Skip + PointerSize;
+
+ error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
+ SegmentIndex, SegmentOffset);
+ if (error) {
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
+ "ULEB " + Twine(error) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
DEBUG_WITH_TYPE(
"mach-o-rebase",
llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
@@ -2872,23 +3057,25 @@ void MachORebaseEntry::moveNext() {
<< "\n");
return;
default:
- Malformed = true;
+ *E = malformedError("bad rebase info (bad opcode value 0x" +
+ utohexstr(Opcode) + " for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
}
}
}
-uint64_t MachORebaseEntry::readULEB128() {
+uint64_t MachORebaseEntry::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()) {
+ if (Ptr > Opcodes.end())
Ptr = Opcodes.end();
- Malformed = true;
- }
return Result;
}
-uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
+int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
@@ -2956,8 +3143,7 @@ MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
: 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) {}
+ PointerSize(is64Bit ? 8 : 4), TableKind(BK), Done(false) {}
void MachOBindEntry::moveToFirst() {
Ptr = Opcodes.begin();
@@ -2978,12 +3164,17 @@ void MachOBindEntry::moveNext() {
--RemainingLoopCount;
return;
}
- if (Ptr == Opcodes.end()) {
+ if (Ptr >= Opcodes.end()) {
+ if (Opcodes.begin() != Opcodes.end() && Done != true) {
+ *E = malformedError("missing BIND_OPCODE_DONE at end of opcodes");
+ moveToEnd();
+ return;
+ }
Done = true;
return;
}
bool More = true;
- while (More && !Malformed) {
+ while (More) {
// Parse next opcode and set up next loop.
const uint8_t *OpcodeStart = Ptr;
uint8_t Byte = *Ptr++;
@@ -3008,11 +3199,17 @@ void MachOBindEntry::moveNext() {
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:
+ if (TableKind == Kind::Weak) {
+ *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
+ "weak bind table for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
Ordinal = ImmValue;
LibraryOrdinalSet = true;
if (ImmValue > O->getLibraryCount()) {
@@ -3029,6 +3226,13 @@ void MachOBindEntry::moveNext() {
<< "Ordinal=" << Ordinal << "\n");
break;
case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
+ if (TableKind == Kind::Weak) {
+ *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
+ "weak bind table for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
Ordinal = readULEB128(&error);
LibraryOrdinalSet = true;
if (error) {
@@ -3052,6 +3256,13 @@ void MachOBindEntry::moveNext() {
<< "Ordinal=" << Ordinal << "\n");
break;
case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
+ if (TableKind == Kind::Weak) {
+ *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
+ "weak bind table for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
if (ImmValue) {
SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
Ordinal = SignExtended;
@@ -3118,8 +3329,6 @@ void MachOBindEntry::moveNext() {
moveToEnd();
return;
}
- if (TableKind == Kind::Lazy)
- Malformed = true;
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
@@ -3202,6 +3411,13 @@ void MachOBindEntry::moveNext() {
SegmentOffset) << "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
+ if (TableKind == Kind::Lazy) {
+ *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
+ "lazy bind table 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_ADD_ADDR_ULEB " +
@@ -3245,8 +3461,6 @@ void MachOBindEntry::moveNext() {
return;
}
RemainingLoopCount = 0;
- if (TableKind == Kind::Lazy)
- Malformed = true;
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
@@ -3256,6 +3470,13 @@ void MachOBindEntry::moveNext() {
<< "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
+ if (TableKind == Kind::Lazy) {
+ *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
+ "allowed in lazy bind table 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_ADD_ADDR_IMM_SCALED " +
@@ -3290,8 +3511,6 @@ void MachOBindEntry::moveNext() {
moveToEnd();
return;
}
- if (TableKind == Kind::Lazy)
- Malformed = true;
DEBUG_WITH_TYPE("mach-o-bind",
llvm::dbgs()
<< "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
@@ -3299,6 +3518,13 @@ void MachOBindEntry::moveNext() {
SegmentOffset) << "\n");
return;
case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
+ if (TableKind == Kind::Lazy) {
+ *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
+ "allowed in lazy bind table for opcode at: 0x" +
+ utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
+ }
Count = readULEB128(&error);
if (Count != 0)
RemainingLoopCount = Count - 1;
@@ -3351,8 +3577,6 @@ void MachOBindEntry::moveNext() {
moveToEnd();
return;
}
- if (TableKind == Kind::Lazy)
- Malformed = true;
DEBUG_WITH_TYPE(
"mach-o-bind",
llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
@@ -3362,7 +3586,6 @@ void MachOBindEntry::moveNext() {
<< "\n");
return;
default:
- Malformed = true;
*E = malformedError("bad bind info (bad opcode value 0x" +
utohexstr(Opcode) + " for opcode at: 0x" +
utohexstr(OpcodeStart - Opcodes.begin()));
@@ -3376,10 +3599,8 @@ uint64_t MachOBindEntry::readULEB128(const char **error) {
unsigned Count;
uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
Ptr += Count;
- if (Ptr > Opcodes.end()) {
+ if (Ptr > Opcodes.end())
Ptr = Opcodes.end();
- Malformed = true;
- }
return Result;
}
@@ -3387,10 +3608,8 @@ int64_t MachOBindEntry::readSLEB128(const char **error) {
unsigned Count;
int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
Ptr += Count;
- if (Ptr > Opcodes.end()) {
+ if (Ptr > Opcodes.end())
Ptr = Opcodes.end();
- Malformed = true;
- }
return Result;
}
@@ -3473,12 +3692,12 @@ BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
}
// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to
-// validate a MachOBindEntry.
+// validate a MachOBindEntry or MachORebaseEntry.
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";
+ return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
if (SegIndex >= MaxSegIndex)
return "bad segIndex (too large)";
for (const SectionInfo &SI : Sections) {
@@ -3496,12 +3715,14 @@ const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex,
}
// 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.
+// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in
+// MachORebaseEntry::moveNext() to validate a MachORebaseEntry for
+// REBASE_OPCODE_DO_*_TIMES* opcodes. 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) {
+ int32_t SegIndex,
+ uint64_t SegOffset) {
const SectionInfo &SI = findSection(SegIndex, SegOffset);
uint64_t addr = SI.SegmentStartAddress + SegOffset;
if (addr >= SI.Address + SI.Size)
@@ -3509,8 +3730,15 @@ const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip,
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";
+ else if (Count == 1)
+ i = Skip + PointerSize;
+ if (addr + i >= SI.Address + SI.Size) {
+ // For rebase opcodes they can step from one section to another.
+ uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress;
+ const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false);
+ if (error)
+ return "bad count and skip, too large";
+ }
return nullptr;
}
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-bind-missing-done b/llvm/test/tools/llvm-objdump/Inputs/macho-bind-missing-done
new file mode 100755
index 00000000000..ced8840ea83
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-bind-missing-done
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-add-addr-imm-scaled b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-add-addr-imm-scaled
new file mode 100755
index 00000000000..a7d5abeef74
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-add-addr-imm-scaled
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-uleb-times-skipping-uleb b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-uleb-times-skipping-uleb
new file mode 100755
index 00000000000..1f0288342c4
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do-bind-uleb-times-skipping-uleb
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do_bind_add_addr_uleb b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do_bind_add_addr_uleb
new file mode 100755
index 00000000000..63f034688ff
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-lazy-do_bind_add_addr_uleb
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-imm-scaled b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-imm-scaled
new file mode 100755
index 00000000000..6b0c1bd4566
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-imm-scaled
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb
new file mode 100755
index 00000000000..e409590dc2d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb-too-big b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb-too-big
new file mode 100755
index 00000000000..68b72ec6a3b
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-add-addr-uleb-too-big
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-bad-opcode-value b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-bad-opcode-value
new file mode 100755
index 00000000000..59e0d4fe619
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-bad-opcode-value
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-imm-times b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-imm-times
new file mode 100755
index 00000000000..be2286baf6b
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-imm-times
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-missing-done b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-missing-done
new file mode 100755
index 00000000000..633a1175607
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-missing-done
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-seg-too-big b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-seg-too-big
new file mode 100755
index 00000000000..12b52328a96
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-seg-too-big
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-segoff-too-big b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-segoff-too-big
new file mode 100755
index 00000000000..4dfb19dea80
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-segoff-too-big
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-set-type-imm b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-set-type-imm
new file mode 100755
index 00000000000..947db0ee915
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-set-type-imm
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-malformed-uleb128 b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-malformed-uleb128
new file mode 100755
index 00000000000..045f425b223
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-malformed-uleb128
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times
new file mode 100755
index 00000000000..c12f256f660
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times-skipping-uleb b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times-skipping-uleb
new file mode 100755
index 00000000000..5bec8ca1157
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-rebase-uleb-times-skipping-uleb
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-imm b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-imm
new file mode 100755
index 00000000000..1d8785c55d0
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-imm
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-uleb b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-uleb
new file mode 100755
index 00000000000..bf7babc09e6
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-ordinal-uleb
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-special-imm b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-special-imm
new file mode 100755
index 00000000000..d13f6ec981e
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/Inputs/macho-weak-bind-set-dylib-special-imm
Binary files differ
diff --git a/llvm/test/tools/llvm-objdump/macho-bad-bind.test b/llvm/test/tools/llvm-objdump/macho-bad-bind.test
index dea86bb6514..baf8dee3234 100644
--- a/llvm/test/tools/llvm-objdump/macho-bad-bind.test
+++ b/llvm/test/tools/llvm-objdump/macho-bad-bind.test
@@ -29,7 +29,7 @@ RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-add_addr_uleb 2>&1 | Fil
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)
+BIND-NO-SEGINDEX: macho-bind-do-bind-no-segIndex': truncated or malformed object (for BIND_OPCODE_DO_BIND missing preceding *_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)
@@ -48,3 +48,60 @@ DO-BIND-NO-DYLIB-ORDINAL: macho-do-bind-no-dylib-ordinal': truncated or malforme
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)
+
+RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do_bind_add_addr_uleb 2>&1 | FileCheck -check-prefix LAZY_DO_BIND_ADD_ADDR_ULEB %s
+LAZY_DO_BIND_ADD_ADDR_ULEB: macho-lazy-do_bind_add_addr_uleb': truncated or malformed object (BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in lazy bind table for opcode at: 0xC)
+
+RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do-bind-add-addr-imm-scaled 2>&1 | FileCheck -check-prefix LAZY-DO-BIND-ADD-ADDR-IMM-SCALED %s
+LAZY-DO-BIND-ADD-ADDR-IMM-SCALED: macho-lazy-do-bind-add-addr-imm-scaled': truncated or malformed object (BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not allowed in lazy bind table for opcode at: 0xC)
+
+RUN: not llvm-objdump -macho -lazy-bind %p/Inputs/macho-lazy-do-bind-uleb-times-skipping-uleb 2>&1 | FileCheck -check-prefix LAZY-DO-BIND-ULEB-TIMES-SKIPPING-ULEB %s
+LAZY-DO-BIND-ULEB-TIMES-SKIPPING-ULEB: macho-lazy-do-bind-uleb-times-skipping-uleb': truncated or malformed object (BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not allowed in lazy bind table for opcode at: 0xC)
+
+RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-ordinal-imm 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-ORDINAL-IMM %s
+WEAK-BIND-SET-DYLIB-ORDINAL-IMM: macho-weak-bind-set-dylib-ordinal-imm': truncated or malformed object (BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in weak bind table for opcode at: 0x2)
+
+RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-ordinal-uleb 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-ORDINAL-ULEB %s
+WEAK-BIND-SET-DYLIB-ORDINAL-ULEB: macho-weak-bind-set-dylib-ordinal-uleb': truncated or malformed object (BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in weak bind table for opcode at: 0x2)
+
+RUN: not llvm-objdump -macho -weak-bind %p/Inputs/macho-weak-bind-set-dylib-special-imm 2>&1 | FileCheck -check-prefix WEAK-BIND-SET-DYLIB-SPECIAL-IMM %s
+WEAK-BIND-SET-DYLIB-SPECIAL-IMM: macho-weak-bind-set-dylib-special-imm': truncated or malformed object (BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in weak bind table for opcode at: 0x2)
+
+RUN: not llvm-objdump -macho -bind %p/Inputs/macho-bind-missing-done 2>&1 | FileCheck -check-prefix BIND-MISSING-DONE %s
+BIND-MISSING-DONE: macho-bind-missing-done': truncated or malformed object (missing BIND_OPCODE_DONE at end of opcodes)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-set-type-imm 2>&1 | FileCheck -check-prefix REBASE-SET-TYPE-IMM %s
+REBASE-SET-TYPE-IMM: macho-rebase-set-type-imm': truncated or malformed object (for REBASE_OPCODE_SET_TYPE_IMM bad bind type: 5 for opcode at: 0x0)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-malformed-uleb128 2>&1 | FileCheck -check-prefix REBASE-ULEB-MALFORMED-ULEB128 %s
+REBASE-ULEB-MALFORMED-ULEB128: macho-rebase-uleb-malformed-uleb128': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB malformed uleb128, extends past end for opcode at: 0x1)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-seg-too-big 2>&1 | FileCheck -check-prefix REBASE-SEG-TOO-BIG %s
+REBASE-SEG-TOO-BIG: macho-rebase-seg-too-big': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segIndex (too large) for opcode at: 0x1)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-segoff-too-big 2>&1 | FileCheck -check-prefix REBASE-SEGOFF-TOO-BIG %s
+REBASE-SEGOFF-TOO-BIG: macho-rebase-segoff-too-big': truncated or malformed object (for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB bad segOffset, too large for opcode at: 0x1)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-uleb 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-ULEB %s
+REBASE-ADD-ADDR-ULEB: macho-rebase-add-addr-uleb': truncated or malformed object (for REBASE_OPCODE_ADD_ADDR_ULEB bad segOffset, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-imm-scaled 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-IMM-SCALED %s
+REBASE-ADD-ADDR-IMM-SCALED: macho-rebase-add-addr-imm-scaled': truncated or malformed object (for REBASE_OPCODE_ADD_ADDR_IMM_SCALED (after adding immediate times the pointer size) bad segOffset, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-imm-times 2>&1 | FileCheck -check-prefix REBASE-IMM-TIMES %s
+REBASE-IMM-TIMES: macho-rebase-imm-times': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_IMM_TIMES bad count and skip, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-times 2>&1 | FileCheck -check-prefix REBASE-ULEB-TIMES %s
+REBASE-ULEB-TIMES: macho-rebase-uleb-times': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ULEB_TIMES bad count and skip, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-add-addr-uleb-too-big 2>&1 | FileCheck -check-prefix REBASE-ADD-ADDR-ULEB-TOO-BIG %s
+REBASE-ADD-ADDR-ULEB-TOO-BIG: macho-rebase-add-addr-uleb-too-big': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB bad count and skip, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-uleb-times-skipping-uleb 2>&1 | FileCheck -check-prefix REBASE-ULEB-TIMES-SKIPPING-ULEB %s
+REBASE-ULEB-TIMES-SKIPPING-ULEB: macho-rebase-uleb-times-skipping-uleb': truncated or malformed object (for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB bad count and skip, too large for opcode at: 0x3)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-bad-opcode-value 2>&1 | FileCheck -check-prefix REBASE-BAD-OPCODE-VALUE %s
+REBASE-BAD-OPCODE-VALUE: macho-rebase-bad-opcode-value': truncated or malformed object (bad rebase info (bad opcode value 0xD0 for opcode at: 0x4)
+
+RUN: not llvm-objdump -macho -rebase %p/Inputs/macho-rebase-missing-done 2>&1 | FileCheck -check-prefix REBASE-MISSING-DONE %s
+REBASE-MISSING-DONE: macho-rebase-missing-done': truncated or malformed object (missing REBASE_OPCODE_DONE at end of opcodes)
OpenPOWER on IntegriCloud