[llvm] r324035 - [cfi-verify] Add blame context printing, and improved print format.

Vlad Tsyrklevich via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 1 15:45:18 PST 2018


Author: vlad.tsyrklevich
Date: Thu Feb  1 15:45:18 2018
New Revision: 324035

URL: http://llvm.org/viewvc/llvm-project?rev=324035&view=rev
Log:
[cfi-verify] Add blame context printing, and improved print format.

Summary:
This update now allows users to specify `--blame-context` and `--blame-context-all` to print source file blame information for the source of the blame.

Also updates the inline printing to correctly identify the top of the inlining stack for blame information.

Patch by Mitch Phillips!

Reviewers: vlad.tsyrklevich

Subscribers: llvm-commits, kcc, pcc

Differential Revision: https://reviews.llvm.org/D40111

Modified:
    llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s
    llvm/trunk/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s
    llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-expected-unprotected.s Thu Feb  1 15:45:18 2018
@@ -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

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-match-fun.s Thu Feb  1 15:45:18 2018
@@ -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

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/blacklist-unexpected-protected.s Thu Feb  1 15:45:18 2018
@@ -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

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s Thu Feb  1 15:45:18 2018
@@ -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}}

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/indirect-cf-elimination.s Thu Feb  1 15:45:18 2018
@@ -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%)

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/protected-lineinfo.s Thu Feb  1 15:45:18 2018
@@ -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%)

Modified: llvm/trunk/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s (original)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/unprotected-lineinfo.s Thu Feb  1 15:45:18 2018
@@ -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%)

Modified: llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp?rev=324035&r1=324034&r2=324035&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp Thu Feb  1 15:45:18 2018
@@ -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(FileAna
         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(FileAna
       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(FileAna
     }
 
     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(FileAna
     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(FileAna
   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;




More information about the llvm-commits mailing list