summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s2
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s2
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s2
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/dot-printing.s5
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s4
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s2
-rw-r--r--llvm/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s2
-rw-r--r--llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp152
8 files changed, 125 insertions, 46 deletions
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s
index c7a3daa0776..dccbd691812 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s
@@ -3,7 +3,7 @@
# RUN: echo "src:*tiny*" > %t.blacklist.txt
# RUN: llvm-cfi-verify %t.o %t.blacklist.txt | FileCheck %s
-# CHECK-LABEL: U
+# CHECK-LABEL: {{^Instruction: .* \(FAIL_BAD_CONDITIONAL_BRANCH\)}}
# CHECK-NEXT: tiny.cc:11
# CHECK-NEXT: {{^Blacklist Match:.*blacklist\.txt:1$}}
# CHECK-NEXT: ====> Expected Unprotected
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s
index f46fb926c5f..21e1ffe7c5c 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s
@@ -3,7 +3,7 @@
# RUN: echo "fun:*main*" > %t.blacklist.txt
# RUN: llvm-cfi-verify %t.o %t.blacklist.txt | FileCheck %s
-# CHECK-LABEL: U
+# CHECK-LABEL: {{^Instruction: .* \(FAIL_BAD_CONDITIONAL_BRANCH\)}}
# CHECK-NEXT: tiny.cc:11
# CHECK-NEXT: {{^Blacklist Match:.*blacklist\.txt:1$}}
# CHECK-NEXT: ====> Expected Unprotected
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s
index 0fd412416a9..2a32e78c8df 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s
@@ -3,7 +3,7 @@
# RUN: echo "src:*tiny*" > %t.blacklist.txt
# RUN: llvm-cfi-verify %t.o %t.blacklist.txt | FileCheck %s
-# CHECK-LABEL: P
+# CHECK-LABEL: {{^Instruction: .* \(PROTECTED\)}}
# CHECK-NEXT: tiny.cc:11
# CHECK-NEXT: {{^Blacklist Match:.*blacklist\.txt:1$}}
# CHECK-NEXT: ====> Unexpected Protected
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/dot-printing.s b/llvm/test/tools/llvm-cfi-verify/X86/dot-printing.s
index 5e0a2090d82..789f1727e89 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/dot-printing.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/dot-printing.s
@@ -3,14 +3,15 @@
# RUN: llvm-cfi-verify -print-graphs %t.o | FileCheck %s
# The expected output is as follows:
-# P 0x7b | callq *%rax
+# ----------------- Begin Instruction -----------------
+# PROTECTED 0x7b: callq *%rax
# digraph graph_0x7b {
# "0x77: jbe 2" -> "0x7b: callq *%rax"
# "0x77: jbe 2" -> "0x79: ud2"
# }
# 0x7b = tiny.cc:11:3 (main)
-# CHECK: {{^P.*callq +\*%rax.*$}}
+# CHECK-LABEL: {{^Instruction: .* \(PROTECTED\):.*callq +\*%rax}}
# CHECK-NEXT: digraph
# CHECK-NEXT: {{^.*jbe.*->.*callq \*%rax}}
# CHECK-NEXT: {{^.*jbe.*->.*ud2}}
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s b/llvm/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s
index e9b873471cb..be5217e02e8 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s
@@ -1,5 +1,5 @@
# RUN: llvm-mc %s -filetype obj -triple x86_64-linux-elf -o %t.o
-# RUN: llvm-cfi-verify %t.o 2>&1 | FileCheck %s
+# RUN: llvm-cfi-verify %t.o 2>&1 --summarize | FileCheck %s
# This is the same file as protected-lineinfo.s, however contains a hand-
# assembled function (fake_function) that has no line table information
@@ -10,6 +10,8 @@
# reporting of the cfi-verify program. It should only find a single indirect CF
# instruction at `tiny.cc:11` (see protected-lineinfo.s for the source).
+# CHECK-NOT: Begin Instruction
+
# CHECK: Expected Protected: 1 (100.00%)
# CHECK: Unexpected Protected: 0 (0.00%)
# CHECK: Expected Unprotected: 0 (0.00%)
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s b/llvm/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s
index 8eaf2e5e725..f1d0be1ed96 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s
@@ -2,7 +2,7 @@
# RUN: -triple x86_64-linux-elf -o %t.o
# RUN: llvm-cfi-verify %t.o | FileCheck %s
-# CHECK-LABEL: P
+# CHECK-LABEL: {{^Instruction: .* \(PROTECTED\)}}
# CHECK-NEXT: tiny.cc:11
# CHECK: Expected Protected: 1 (100.00%)
diff --git a/llvm/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s b/llvm/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s
index 65782cb5e42..687ceb558e5 100644
--- a/llvm/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s
+++ b/llvm/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s
@@ -2,7 +2,7 @@
# RUN: -triple x86_64-linux-elf -o %t.o
# RUN: llvm-cfi-verify %t.o | FileCheck %s
-# CHECK-LABEL: U
+# CHECK-LABEL: {{^Instruction: .* \(FAIL_BAD_CONDITIONAL_BRANCH\)}}
# CHECK-NEXT: tiny.cc:11
# CHECK: Expected Protected: 0 (0.00%)
diff --git a/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp b/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
index 245ce05a254..b221e5a8332 100644
--- a/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
+++ b/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
@@ -41,9 +41,87 @@ cl::opt<bool> PrintGraphs(
"print-graphs",
cl::desc("Print graphs around indirect CF instructions in DOT format."),
cl::init(false));
+cl::opt<unsigned> PrintBlameContext(
+ "blame-context",
+ cl::desc("Print the blame context (if possible) for BAD instructions. This "
+ "specifies the number of lines of context to include, where zero "
+ "disables this feature."),
+ cl::init(0));
+cl::opt<unsigned> PrintBlameContextAll(
+ "blame-context-all",
+ cl::desc("Prints the blame context (if possible) for ALL instructions. "
+ "This specifies the number of lines of context for non-BAD "
+ "instructions (see --blame-context). If --blame-context is "
+ "unspecified, it prints this number of contextual lines for BAD "
+ "instructions as well."),
+ cl::init(0));
+cl::opt<bool> Summarize("summarize", cl::desc("Print the summary only."),
+ cl::init(false));
ExitOnError ExitOnErr;
+void printBlameContext(const DILineInfo &LineInfo, unsigned Context) {
+ auto FileOrErr = MemoryBuffer::getFile(LineInfo.FileName);
+ if (!FileOrErr) {
+ errs() << "Could not open file: " << LineInfo.FileName << "\n";
+ return;
+ }
+
+ std::unique_ptr<MemoryBuffer> File = std::move(FileOrErr.get());
+ SmallVector<StringRef, 100> Lines;
+ File->getBuffer().split(Lines, '\n');
+
+ for (unsigned i = std::max(1l, (long)LineInfo.Line - Context);
+ i <
+ std::min(Lines.size() + 1, (unsigned long)LineInfo.Line + Context + 1);
+ ++i) {
+ if (i == LineInfo.Line)
+ outs() << ">";
+ else
+ outs() << " ";
+
+ outs() << i << ": " << Lines[i - 1] << "\n";
+ }
+}
+
+void printInstructionInformation(const FileAnalysis &Analysis,
+ const Instr &InstrMeta,
+ const GraphResult &Graph,
+ CFIProtectionStatus ProtectionStatus) {
+ outs() << "Instruction: " << format_hex(InstrMeta.VMAddress, 2) << " ("
+ << stringCFIProtectionStatus(ProtectionStatus) << "): ";
+ Analysis.printInstruction(InstrMeta, outs());
+ outs() << " \n";
+
+ if (PrintGraphs)
+ Graph.printToDOT(Analysis, outs());
+}
+
+void printInstructionStatus(unsigned BlameLine, bool CFIProtected,
+ const DILineInfo &LineInfo) {
+ if (BlameLine) {
+ outs() << "Blacklist Match: " << BlacklistFilename << ":" << BlameLine
+ << "\n";
+ if (CFIProtected)
+ outs() << "====> Unexpected Protected\n";
+ else
+ outs() << "====> Expected Unprotected\n";
+
+ if (PrintBlameContextAll)
+ printBlameContext(LineInfo, PrintBlameContextAll);
+ } else {
+ if (CFIProtected) {
+ outs() << "====> Expected Protected\n";
+ if (PrintBlameContextAll)
+ printBlameContext(LineInfo, PrintBlameContextAll);
+ } else {
+ outs() << "====> Unexpected Unprotected (BAD)\n";
+ if (PrintBlameContext)
+ printBlameContext(LineInfo, PrintBlameContext);
+ }
+ }
+}
+
void printIndirectCFInstructions(FileAnalysis &Analysis,
const SpecialCaseList *SpecialCaseList) {
uint64_t ExpectedProtected = 0;
@@ -61,17 +139,10 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
Analysis.validateCFIProtection(Graph);
bool CFIProtected = (ProtectionStatus == CFIProtectionStatus::PROTECTED);
- if (CFIProtected)
- outs() << "P ";
- else
- outs() << "U ";
-
- outs() << format_hex(Address, 2) << " | ";
- Analysis.printInstruction(InstrMeta, outs());
- outs() << " \n";
-
- if (PrintGraphs)
- Graph.printToDOT(Analysis, outs());
+ if (!Summarize) {
+ outs() << "-----------------------------------------------------\n";
+ printInstructionInformation(Analysis, InstrMeta, Graph, ProtectionStatus);
+ }
if (IgnoreDWARFFlag) {
if (CFIProtected)
@@ -88,22 +159,28 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
exit(EXIT_FAILURE);
}
- const auto &LineInfo =
- InliningInfo->getFrame(InliningInfo->getNumberOfFrames() - 1);
+ const auto &LineInfo = InliningInfo->getFrame(0);
// Print the inlining symbolisation of this instruction.
- for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) {
- const auto &Line = InliningInfo->getFrame(i);
- outs() << " " << format_hex(Address, 2) << " = " << Line.FileName << ":"
- << Line.Line << ":" << Line.Column << " (" << Line.FunctionName
- << ")\n";
+ if (!Summarize) {
+ for (uint32_t i = 0; i < InliningInfo->getNumberOfFrames(); ++i) {
+ const auto &Line = InliningInfo->getFrame(i);
+ outs() << " " << format_hex(Address, 2) << " = " << Line.FileName
+ << ":" << Line.Line << ":" << Line.Column << " ("
+ << Line.FunctionName << ")\n";
+ }
}
if (!SpecialCaseList) {
- if (CFIProtected)
+ if (CFIProtected) {
+ if (PrintBlameContextAll && !Summarize)
+ printBlameContext(LineInfo, PrintBlameContextAll);
ExpectedProtected++;
- else
+ } else {
+ if (PrintBlameContext && !Summarize)
+ printBlameContext(LineInfo, PrintBlameContext);
UnexpectedUnprotected++;
+ }
continue;
}
@@ -118,25 +195,20 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
}
if (BlameLine) {
- outs() << "Blacklist Match: " << BlacklistFilename << ":" << BlameLine
- << "\n";
BlameCounter[BlameLine]++;
- if (CFIProtected) {
+ if (CFIProtected)
UnexpectedProtected++;
- outs() << "====> Unexpected Protected\n";
- } else {
+ else
ExpectedUnprotected++;
- outs() << "====> Expected Unprotected\n";
- }
} else {
- if (CFIProtected) {
+ if (CFIProtected)
ExpectedProtected++;
- outs() << "====> Expected Protected\n";
- } else {
+ else
UnexpectedUnprotected++;
- outs() << "====> Unexpected Unprotected\n";
- }
}
+
+ if (!Summarize)
+ printInstructionStatus(BlameLine, CFIProtected, LineInfo);
}
uint64_t IndirectCFInstructions = ExpectedProtected + UnexpectedProtected +
@@ -147,11 +219,12 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
return;
}
- outs() << formatv("Expected Protected: {0} ({1:P})\n"
- "Unexpected Protected: {2} ({3:P})\n"
- "Expected Unprotected: {4} ({5:P})\n"
- "Unexpected Unprotected (BAD): {6} ({7:P})\n",
- ExpectedProtected,
+ outs() << formatv("\nTotal Indirect CF Instructions: {0}\n"
+ "Expected Protected: {1} ({2:P})\n"
+ "Unexpected Protected: {3} ({4:P})\n"
+ "Expected Unprotected: {5} ({6:P})\n"
+ "Unexpected Unprotected (BAD): {7} ({8:P})\n",
+ IndirectCFInstructions, ExpectedProtected,
((double)ExpectedProtected) / IndirectCFInstructions,
UnexpectedProtected,
((double)UnexpectedProtected) / IndirectCFInstructions,
@@ -163,7 +236,7 @@ void printIndirectCFInstructions(FileAnalysis &Analysis,
if (!SpecialCaseList)
return;
- outs() << "Blacklist Results:\n";
+ outs() << "\nBlacklist Results:\n";
for (const auto &KV : BlameCounter) {
outs() << " " << BlacklistFilename << ":" << KV.first << " affects "
<< KV.second << " indirect CF instructions.\n";
@@ -183,6 +256,9 @@ int main(int argc, char **argv) {
InitializeAllAsmParsers();
InitializeAllDisassemblers();
+ if (PrintBlameContextAll && !PrintBlameContext)
+ PrintBlameContext.setValue(PrintBlameContextAll);
+
std::unique_ptr<SpecialCaseList> SpecialCaseList;
if (BlacklistFilename != "-") {
std::string Error;
OpenPOWER on IntegriCloud