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:
parent
8e51f27003
commit
a0cefd153d
18
test/tools/llvm-cfi-verify/X86/dot-printing.s
Normal file
18
test/tools/llvm-cfi-verify/X86/dot-printing.s
Normal 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
|
@ -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 = "";
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user