1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
//===----------- CFIInfoVerifier.cpp - CFI Information Verifier -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass verifies incoming and outgoing CFI information of basic blocks. CFI
// information is information about offset and register set by CFI directives,
// valid at the start and end of a basic block. This pass checks that outgoing
// information of predecessors matches incoming information of their successors.
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
namespace {
class CFIInfoVerifier : public MachineFunctionPass {
public:
static char ID;
CFIInfoVerifier() : MachineFunctionPass(ID) {
initializeCFIInfoVerifierPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
bool runOnMachineFunction(MachineFunction &MF) override {
bool NeedsDwarfCFI = (MF.getMMI().hasDebugInfo() ||
MF.getFunction()->needsUnwindTableEntry()) &&
(!MF.getTarget().getTargetTriple().isOSDarwin() &&
!MF.getTarget().getTargetTriple().isOSWindows());
if (!NeedsDwarfCFI) return false;
verify(MF);
return false;
}
private:
// Go through each MBB in a function and check that outgoing offset and
// register of its predecessors match incoming offset and register of that
// MBB, as well as that incoming offset and register of its successors match
// outgoing offset and register of the MBB.
void verify(MachineFunction &MF);
void report(const char *msg, MachineBasicBlock &MBB);
};
}
char CFIInfoVerifier::ID = 0;
INITIALIZE_PASS(CFIInfoVerifier, "cfiinfoverifier",
"Verify that corresponding in/out CFI info matches", false,
false)
FunctionPass *llvm::createCFIInfoVerifier() { return new CFIInfoVerifier(); }
void CFIInfoVerifier::verify(MachineFunction &MF) {
for (auto &CurrMBB : MF) {
for (auto Pred : CurrMBB.predecessors()) {
// Check that outgoing offset values of predecessors match the incoming
// offset value of CurrMBB
if (Pred->getOutgoingCFAOffset() != CurrMBB.getIncomingCFAOffset()) {
report("The outgoing offset of a predecessor is inconsistent.",
CurrMBB);
errs() << "Predecessor BB#" << Pred->getNumber()
<< " has outgoing offset (" << Pred->getOutgoingCFAOffset()
<< "), while BB#" << CurrMBB.getNumber()
<< " has incoming offset (" << CurrMBB.getIncomingCFAOffset()
<< ").\n";
}
// Check that outgoing register values of predecessors match the incoming
// register value of CurrMBB
if (Pred->getOutgoingCFARegister() != CurrMBB.getIncomingCFARegister()) {
report("The outgoing register of a predecessor is inconsistent.",
CurrMBB);
errs() << "Predecessor BB#" << Pred->getNumber()
<< " has outgoing register (" << Pred->getOutgoingCFARegister()
<< "), while BB#" << CurrMBB.getNumber()
<< " has incoming register (" << CurrMBB.getIncomingCFARegister()
<< ").\n";
}
}
for (auto Succ : CurrMBB.successors()) {
// Check that incoming offset values of successors match the outgoing
// offset value of CurrMBB
if (Succ->getIncomingCFAOffset() != CurrMBB.getOutgoingCFAOffset()) {
report("The incoming offset of a successor is inconsistent.", CurrMBB);
errs() << "Successor BB#" << Succ->getNumber()
<< " has incoming offset (" << Succ->getIncomingCFAOffset()
<< "), while BB#" << CurrMBB.getNumber()
<< " has outgoing offset (" << CurrMBB.getOutgoingCFAOffset()
<< ").\n";
}
// Check that incoming register values of successors match the outgoing
// register value of CurrMBB
if (Succ->getIncomingCFARegister() != CurrMBB.getOutgoingCFARegister()) {
report("The incoming register of a successor is inconsistent.",
CurrMBB);
errs() << "Successor BB#" << Succ->getNumber()
<< " has incoming register (" << Succ->getIncomingCFARegister()
<< "), while BB#" << CurrMBB.getNumber()
<< " has outgoing register (" << CurrMBB.getOutgoingCFARegister()
<< ").\n";
}
}
}
}
void CFIInfoVerifier::report(const char *msg, MachineBasicBlock &MBB) {
assert(&MBB);
errs() << '\n';
errs() << "*** " << msg << " ***\n"
<< "- function: " << MBB.getParent()->getName() << "\n";
errs() << "- basic block: BB#" << MBB.getNumber() << ' ' << MBB.getName()
<< " (" << (const void *)&MBB << ')';
errs() << '\n';
}
|