blob: d4a46fcc226b6529e26de326216cacb60e39ad66 [file] [log] [blame]
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +00001//===-- llvm-cfi-verify.cpp - CFI Verification tool for LLVM --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tool verifies Control Flow Integrity (CFI) instrumentation by static
11// binary anaylsis. See the design document in /docs/CFIVerify.rst for more
12// information.
13//
14// This tool is currently incomplete. It currently only does disassembly for
15// object files, and searches through the code for indirect control flow
16// instructions, printing them once found.
17//
18//===----------------------------------------------------------------------===//
19
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000020#include "lib/FileAnalysis.h"
Vlad Tsyrklevichb5488a22017-10-10 20:59:08 +000021
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000022#include "llvm/BinaryFormat/ELF.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/Error.h"
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000025#include "llvm/Support/FormatVariadic.h"
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000026
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000027#include <cstdlib>
28
29using namespace llvm;
30using namespace llvm::object;
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000031using namespace llvm::cfi_verify;
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000032
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000033cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"),
34 cl::Required);
35
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000036ExitOnError ExitOnErr;
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000037
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000038void printIndirectCFInstructions(FileAnalysis &Analysis) {
39 uint64_t ProtectedCount = 0;
40 uint64_t UnprotectedCount = 0;
41
42 for (uint64_t Address : Analysis.getIndirectInstructions()) {
43 const auto &InstrMeta = Analysis.getInstructionOrDie(Address);
44
45 if (Analysis.isIndirectInstructionCFIProtected(Address)) {
46 outs() << "P ";
47 ProtectedCount++;
48 } else {
49 outs() << "U ";
50 UnprotectedCount++;
51 }
52
53 outs() << format_hex(Address, 2) << " | "
54 << Analysis.getMCInstrInfo()->getName(
Vlad Tsyrklevich89c3c8c2017-10-11 20:35:01 +000055 InstrMeta.Instruction.getOpcode())
56 << " ";
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000057 outs() << "\n";
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000058
59 if (Analysis.hasLineTableInfo()) {
60 for (const auto &LineKV : Analysis.getLineInfoForAddressRange(Address)) {
61 outs() << " " << format_hex(LineKV.first, 2) << " = "
62 << LineKV.second.FileName << ":" << LineKV.second.Line << ":"
63 << LineKV.second.Column << " (" << LineKV.second.FunctionName
64 << ")\n";
65 }
66 }
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000067 }
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000068
69 if (ProtectedCount || UnprotectedCount)
70 outs() << formatv(
71 "Unprotected: {0} ({1:P}), Protected: {2} ({3:P})\n", UnprotectedCount,
72 (((double)UnprotectedCount) / (UnprotectedCount + ProtectedCount)),
73 ProtectedCount,
74 (((double)ProtectedCount) / (UnprotectedCount + ProtectedCount)));
75 else
76 outs() << "No indirect CF instructions found.\n";
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000077}
78
79int main(int argc, char **argv) {
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000080 cl::ParseCommandLineOptions(
81 argc, argv,
82 "Identifies whether Control Flow Integrity protects all indirect control "
83 "flow instructions in the provided object file, DSO or binary.\nNote: "
84 "Anything statically linked into the provided file *must* be compiled "
85 "with '-g'. This can be relaxed through the '--ignore-dwarf' flag.");
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000086
87 InitializeAllTargetInfos();
88 InitializeAllTargetMCs();
89 InitializeAllAsmParsers();
90 InitializeAllDisassemblers();
91
Mitch Phillips7db6f7a2017-10-31 23:20:05 +000092 FileAnalysis Analysis = ExitOnErr(FileAnalysis::Create(InputFilename));
93 printIndirectCFInstructions(Analysis);
Vlad Tsyrklevich31b45312017-09-20 20:38:14 +000094
95 return EXIT_SUCCESS;
96}