[llvm] r318211 - [cfi-verify] Add DOT graph printing for GraphResult objects.

Mitch Phillips via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 14 14:43:13 PST 2017


Author: hctim
Date: Tue Nov 14 14:43:13 2017
New Revision: 318211

URL: http://llvm.org/viewvc/llvm-project?rev=318211&view=rev
Log:
[cfi-verify] Add DOT graph printing for GraphResult objects.

Allows users to view GraphResult objects in a DOT directed-graph format. This feature can be turned on through the --print-graphs flag.

Also enabled pretty-printing of instructions in output. Together these features make analysis of unprotected CF instructions much easier by providing a visual control flow graph.

Reviewers: pcc

Subscribers: llvm-commits, kcc, vlad.tsyrklevich

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

Added:
    llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s
Modified:
    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
    llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
    llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.cpp
    llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.h
    llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp

Added: 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=318211&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s (added)
+++ llvm/trunk/test/tools/llvm-cfi-verify/X86/dot-printing.s Tue Nov 14 14:43:13 2017
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %S/Inputs/protected-lineinfo.s -filetype obj \
+# RUN:         -triple x86_64-linux-elf -o %t.o
+# RUN: llvm-cfi-verify -print-graphs %t.o | FileCheck %s
+
+# The expected output is as follows:
+#   P 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-NEXT: digraph
+# CHECK-NEXT: {{^.*jbe.*->.*callq \*%rax}}
+# CHECK-NEXT: {{^.*jbe.*->.*ud2}}
+# CHECK-NEXT: }
+# CHECK-NEXT: tiny.cc:11

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp?rev=318211&r1=318210&r2=318211&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.cpp Tue Nov 14 14:43:13 2017
@@ -273,6 +273,11 @@ FileAnalysis::validateCFIProtection(cons
   return CFIProtectionStatus::PROTECTED;
 }
 
+void FileAnalysis::printInstruction(const Instr &InstrMeta,
+                                    raw_ostream &OS) const {
+  Printer->printInst(&InstrMeta.Instruction, OS, "", *SubtargetInfo.get());
+}
+
 Error FileAnalysis::initialiseDisassemblyMembers() {
   std::string TripleName = ObjectTriple.getTriple();
   ArchName = "";

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h?rev=318211&r1=318210&r2=318211&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/FileAnalysis.h Tue Nov 14 14:43:13 2017
@@ -145,6 +145,10 @@ public:
   // flow instruction in this file.
   CFIProtectionStatus validateCFIProtection(const GraphResult &Graph) const;
 
+  // Prints an instruction to the provided stream using this object's pretty-
+  // printers.
+  void printInstruction(const Instr &InstrMeta, raw_ostream &OS) const;
+
 protected:
   // Construct a blank object with the provided triple and features. Used in
   // testing, where a sub class will dependency inject protected methods to

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.cpp?rev=318211&r1=318210&r2=318211&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.cpp Tue Nov 14 14:43:13 2017
@@ -71,6 +71,30 @@ std::vector<uint64_t> GraphResult::flatt
   return Addresses;
 }
 
+void printPairToDOT(const FileAnalysis &Analysis, raw_ostream &OS,
+                          uint64_t From, uint64_t To) {
+  OS << "  \"" << format_hex(From, 2) << ": ";
+  Analysis.printInstruction(Analysis.getInstructionOrDie(From), OS);
+  OS << "\" -> \"" << format_hex(To, 2) << ": ";
+  Analysis.printInstruction(Analysis.getInstructionOrDie(To), OS);
+  OS << "\"\n";
+}
+
+void GraphResult::printToDOT(const FileAnalysis &Analysis,
+                             raw_ostream &OS) const {
+  std::map<uint64_t, uint64_t> SortedIntermediateNodes(
+      IntermediateNodes.begin(), IntermediateNodes.end());
+  OS << "digraph graph_" << format_hex(BaseAddress, 2) << " {\n";
+  for (const auto &KV : SortedIntermediateNodes)
+    printPairToDOT(Analysis, OS, KV.first, KV.second);
+
+  for (auto &BranchNode : ConditionalBranchNodes) {
+    for (auto &V : {BranchNode.Target, BranchNode.Fallthrough})
+      printPairToDOT(Analysis, OS, BranchNode.Address, V);
+  }
+  OS << "}\n";
+}
+
 GraphResult GraphBuilder::buildFlowGraph(const FileAnalysis &Analysis,
                                          uint64_t Address) {
   GraphResult Result;

Modified: llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.h?rev=318211&r1=318210&r2=318211&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.h (original)
+++ llvm/trunk/tools/llvm-cfi-verify/lib/GraphBuilder.h Tue Nov 14 14:43:13 2017
@@ -89,6 +89,9 @@ struct GraphResult {
   // base. The provided address must be part of this graph, and must not be a
   // conditional branch.
   std::vector<uint64_t> flattenAddress(uint64_t Address) const;
+
+  // Print the DOT representation of this result.
+  void printToDOT(const FileAnalysis &Analysis, raw_ostream &OS) const;
 };
 
 class GraphBuilder {

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=318211&r1=318210&r2=318211&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp (original)
+++ llvm/trunk/tools/llvm-cfi-verify/llvm-cfi-verify.cpp Tue Nov 14 14:43:13 2017
@@ -37,6 +37,10 @@ cl::opt<std::string> InputFilename(cl::P
 cl::opt<std::string> BlacklistFilename(cl::Positional,
                                        cl::desc("[blacklist file]"),
                                        cl::init("-"));
+cl::opt<bool> PrintGraphs(
+    "print-graphs",
+    cl::desc("Print graphs around indirect CF instructions in DOT format."),
+    cl::init(false));
 
 ExitOnError ExitOnErr;
 
@@ -62,10 +66,12 @@ void printIndirectCFInstructions(FileAna
     else
       outs() << "U ";
 
-    outs() << format_hex(Address, 2) << " | "
-           << Analysis.getMCInstrInfo()->getName(
-                  InstrMeta.Instruction.getOpcode())
-           << " \n";
+    outs() << format_hex(Address, 2) << " | ";
+    Analysis.printInstruction(InstrMeta, outs());
+    outs() << " \n";
+
+    if (PrintGraphs)
+      Graph.printToDOT(Analysis, outs());
 
     if (IgnoreDWARFFlag) {
       if (CFIProtected)




More information about the llvm-commits mailing list