Analysis.Object = dyn_cast<object::ObjectFile>(Analysis.Binary.getBinary());
if (!Analysis.Object)
- return make_error<UnsupportedDisassembly>();
+ return make_error<UnsupportedDisassembly>("Failed to cast object");
Analysis.ObjectTriple = Analysis.Object->makeTriple();
Analysis.Features = Analysis.Object->getFeatures();
ObjectTarget =
TargetRegistry::lookupTarget(ArchName, ObjectTriple, ErrorString);
if (!ObjectTarget)
- return make_error<StringError>(Twine("Couldn't find target \"") +
- ObjectTriple.getTriple() +
- "\", failed with error: " + ErrorString,
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>(
+ (Twine("Couldn't find target \"") + ObjectTriple.getTriple() +
+ "\", failed with error: " + ErrorString).str());
RegisterInfo.reset(ObjectTarget->createMCRegInfo(TripleName));
if (!RegisterInfo)
- return make_error<StringError>("Failed to initialise RegisterInfo.",
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>(
+ "Failed to initialise RegisterInfo.");
AsmInfo.reset(ObjectTarget->createMCAsmInfo(*RegisterInfo, TripleName));
if (!AsmInfo)
- return make_error<StringError>("Failed to initialise AsmInfo.",
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>("Failed to initialise AsmInfo.");
SubtargetInfo.reset(ObjectTarget->createMCSubtargetInfo(
TripleName, MCPU, Features.getString()));
if (!SubtargetInfo)
- return make_error<StringError>("Failed to initialise SubtargetInfo.",
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>(
+ "Failed to initialise SubtargetInfo.");
MII.reset(ObjectTarget->createMCInstrInfo());
if (!MII)
- return make_error<StringError>("Failed to initialise MII.",
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>("Failed to initialise MII.");
Context.reset(new MCContext(AsmInfo.get(), RegisterInfo.get(), &MOFI));
ObjectTarget->createMCDisassembler(*SubtargetInfo, *Context));
if (!Disassembler)
- return make_error<StringError>("No disassembler available for target",
- inconvertibleErrorCode());
+ return make_error<UnsupportedDisassembly>(
+ "No disassembler available for target");
MIA.reset(ObjectTarget->createMCInstrAnalysis(MII.get()));
}
}
+UnsupportedDisassembly::UnsupportedDisassembly(StringRef Text) : Text(Text) {}
+
char UnsupportedDisassembly::ID;
void UnsupportedDisassembly::log(raw_ostream &OS) const {
- OS << "Dissassembling of non-objects not currently supported.\n";
+ OS << "Could not initialise disassembler: " << Text;
}
std::error_code UnsupportedDisassembly::convertToErrorCode() const {
class UnsupportedDisassembly : public ErrorInfo<UnsupportedDisassembly> {
public:
static char ID;
+ std::string Text;
+
+ UnsupportedDisassembly(StringRef Text);
void log(raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
Support
)
-list(FIND LLVM_TARGETS_TO_BUILD "X86" x86_idx)
-if (NOT x86_idx LESS 0)
- add_llvm_unittest(CFIVerifyTests
- FileAnalysis.cpp
- GraphBuilder.cpp)
-endif()
+add_llvm_unittest(CFIVerifyTests
+ FileAnalysis.cpp
+ GraphBuilder.cpp)
class BasicFileAnalysisTest : public ::testing::Test {
protected:
virtual void SetUp() {
- if (Analysis.initialiseDisassemblyMembers()) {
- FAIL() << "Failed to initialise FileAnalysis.";
+ SuccessfullyInitialised = true;
+ if (auto Err = Analysis.initialiseDisassemblyMembers()) {
+ handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
+ SuccessfullyInitialised = false;
+ outs()
+ << "Note: CFIVerifyTests are disabled due to lack of x86 support "
+ "on this build.\n";
+ });
}
}
+ bool SuccessfullyInitialised;
ELFx86TestFileAnalysis Analysis;
};
TEST_F(BasicFileAnalysisTest, BasicDisassemblyTraversalTest) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicFileAnalysisTest, PrevAndNextFromBadInst) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicFileAnalysisTest, CFITrapTest) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicFileAnalysisTest, FallThroughTest) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicFileAnalysisTest, DefiniteNextInstructionTest) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicFileAnalysisTest, ControlFlowXRefsTest) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
class BasicGraphBuilderTest : public ::testing::Test {
protected:
virtual void SetUp() {
- if (Analysis.initialiseDisassemblyMembers()) {
- FAIL() << "Failed to initialise FileAnalysis.";
+ SuccessfullyInitialised = true;
+ if (auto Err = Analysis.initialiseDisassemblyMembers()) {
+ handleAllErrors(std::move(Err), [&](const UnsupportedDisassembly &E) {
+ SuccessfullyInitialised = false;
+ outs()
+ << "Note: CFIVerifyTests are disabled due to lack of x86 support "
+ "on this build.\n";
+ });
}
}
+ bool SuccessfullyInitialised;
ELFx86TestFileAnalysis Analysis;
};
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathFallthroughUd2) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x02, // 0: jne 4 [+2]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestSinglePathJumpUd2) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x02, // 0: jne 4 [+2]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathDualUd2) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x03, // 0: jne 5 [+3]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphTestDualPathSingleUd2) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x05, // 0: jne 7 [+5]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphFailures) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x90, // 0: nop
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoXrefs) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0xeb, 0xfe, // 0: jmp 0 [-2]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphConditionalInfiniteLoop) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0xfe, // 0: jne 0 [-2]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphUnconditionalInfiniteLoop) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x02, // 0: jne 4 [+2]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphNoFlowsToIndirection) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x00, // 0: jne 2 [+0]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededUpwards) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x06, // 0: jne 8 [+6]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphLengthExceededDownwards) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x02, // 0: jne 4 [+2]
// paths correctly. We don't need to recalculate the flow from 0x2 -> 0x3 as it
// should only need to be generated once.
TEST_F(BasicGraphBuilderTest, BuildFlowGraphWithRepeatedWork) {
+ if (!SuccessfullyInitialised)
+ return;
Analysis.parseSectionContents(
{
0x75, 0x05, // 0: jne 7 [+5]
}
TEST_F(BasicGraphBuilderTest, BuildFlowGraphComplexExample) {
+ if (!SuccessfullyInitialised)
+ return;
// The following code has this graph:
// +----------+ +--------------+
// | 20 | <--- | 0 |