1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[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

llvm-svn: 318211
This commit is contained in:
Mitch Phillips 2017-11-14 22:43:13 +00:00
parent 8e51f27003
commit a0cefd153d
6 changed files with 64 additions and 4 deletions

View File

@ -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

View File

@ -273,6 +273,11 @@ FileAnalysis::validateCFIProtection(const GraphResult &Graph) const {
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 = "";

View File

@ -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

View File

@ -71,6 +71,30 @@ std::vector<uint64_t> GraphResult::flattenAddress(uint64_t Address) const {
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;

View File

@ -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 {

View File

@ -37,6 +37,10 @@ cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"),
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(FileAnalysis &Analysis,
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)