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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
//===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Verify module-level PNaCl ABI requirements (specifically those that do not
// require looking at the function bodies)
//
//
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/NaCl.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
#include "PNaClABITypeChecker.h"
using namespace llvm;
namespace {
// This pass should not touch function bodies, to stay streaming-friendly
class PNaClABIVerifyModule : public ModulePass {
public:
static char ID;
PNaClABIVerifyModule() :
ModulePass(ID),
Reporter(new PNaClABIErrorReporter),
ReporterIsOwned(true) {
initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
}
explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) :
ModulePass(ID),
Reporter(Reporter_),
ReporterIsOwned(false) {
initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
}
~PNaClABIVerifyModule() {
if (ReporterIsOwned)
delete Reporter;
}
bool runOnModule(Module &M);
virtual void print(raw_ostream &O, const Module *M) const;
private:
PNaClABITypeChecker TC;
PNaClABIErrorReporter *Reporter;
bool ReporterIsOwned;
};
static const char *linkageName(GlobalValue::LinkageTypes LT) {
// This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp
switch (LT) {
case GlobalValue::ExternalLinkage: return "external";
case GlobalValue::PrivateLinkage: return "private ";
case GlobalValue::LinkerPrivateLinkage: return "linker_private ";
case GlobalValue::LinkerPrivateWeakLinkage: return "linker_private_weak ";
case GlobalValue::InternalLinkage: return "internal ";
case GlobalValue::LinkOnceAnyLinkage: return "linkonce ";
case GlobalValue::LinkOnceODRLinkage: return "linkonce_odr ";
case GlobalValue::LinkOnceODRAutoHideLinkage:
return "linkonce_odr_auto_hide ";
case GlobalValue::WeakAnyLinkage: return "weak ";
case GlobalValue::WeakODRLinkage: return "weak_odr ";
case GlobalValue::CommonLinkage: return "common ";
case GlobalValue::AppendingLinkage: return "appending ";
case GlobalValue::DLLImportLinkage: return "dllimport ";
case GlobalValue::DLLExportLinkage: return "dllexport ";
case GlobalValue::ExternalWeakLinkage: return "extern_weak ";
case GlobalValue::AvailableExternallyLinkage:
return "available_externally ";
default:
return "unknown";
}
}
} // end anonymous namespace
bool PNaClABIVerifyModule::runOnModule(Module &M) {
for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
MI != ME; ++MI) {
// Check types of global variables and their initializers
if (!TC.isValidType(MI->getType())) {
// GVs are pointers, so print the pointed-to type for clarity
Reporter->addError() << "Variable " << MI->getName() <<
" has disallowed type: " <<
PNaClABITypeChecker::getTypeName(MI->getType()->getContainedType(0))
+ "\n";
} else if (MI->hasInitializer()) {
// If the type of the global is bad, no point in checking its initializer
Type *T = TC.checkTypesInConstant(MI->getInitializer());
if (T) {
Reporter->addError() << "Initializer for " << MI->getName() <<
" has disallowed type: " <<
PNaClABITypeChecker::getTypeName(T) << "\n";
}
}
// Check GV linkage types
switch (MI->getLinkage()) {
case GlobalValue::ExternalLinkage:
case GlobalValue::AvailableExternallyLinkage:
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
break;
default:
Reporter->addError() << "Variable " << MI->getName() <<
" has disallowed linkage type: " <<
linkageName(MI->getLinkage()) << "\n";
}
if (MI->hasSection()) {
Reporter->addError() << "Variable " << MI->getName() <<
" has disallowed \"section\" attribute\n";
}
if (MI->isThreadLocal()) {
Reporter->addError() << "Variable " << MI->getName() <<
" has disallowed \"thread_local\" attribute\n";
}
}
// No aliases allowed for now.
for (Module::alias_iterator MI = M.alias_begin(),
E = M.alias_end(); MI != E; ++MI) {
Reporter->addError() << "Variable " << MI->getName() <<
" is an alias (disallowed)\n";
}
for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
// Check types of functions and their arguments
FunctionType *FT = MI->getFunctionType();
if (!TC.isValidType(FT->getReturnType())) {
Reporter->addError() << "Function " << MI->getName() <<
" has disallowed return type: " <<
PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n";
}
for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) {
Type *PT = FT->getParamType(I);
if (!TC.isValidType(PT)) {
Reporter->addError() << "Function " << MI->getName() << " argument " <<
I + 1 << " has disallowed type: " <<
PNaClABITypeChecker::getTypeName(PT) << "\n";
}
}
// Pointers to varargs function types are not yet disallowed, but
// we do disallow defining or calling functions of varargs types.
if (MI->isVarArg()) {
Reporter->addError() << "Function " << MI->getName() <<
" is a variable-argument function (disallowed)\n";
}
if (MI->hasSection()) {
Reporter->addError() << "Function " << MI->getName() <<
" has disallowed \"section\" attribute\n";
}
if (MI->hasGC()) {
Reporter->addError() << "Function " << MI->getName() <<
" has disallowed \"gc\" attribute\n";
}
}
// Check named metadata nodes
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
E = M.named_metadata_end(); I != E; ++I) {
for (unsigned i = 0, e = I->getNumOperands(); i != e; i++) {
if (Type *T = TC.checkTypesInMDNode(I->getOperand(i))) {
Reporter->addError() << "Named metadata node " << I->getName() <<
" refers to disallowed type: " <<
PNaClABITypeChecker::getTypeName(T) << "\n";
}
}
}
Reporter->checkForFatalErrors();
return false;
}
// This method exists so that the passes can easily be run with opt -analyze.
// In this case the default constructor is used and we want to reset the error
// messages after each print (this is more of an issue for the FunctionPass
// than the ModulePass)
void PNaClABIVerifyModule::print(llvm::raw_ostream &O, const Module *M) const {
Reporter->printErrors(O);
Reporter->reset();
}
char PNaClABIVerifyModule::ID = 0;
INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module",
"Verify module for PNaCl", false, true)
ModulePass *llvm::createPNaClABIVerifyModulePass(
PNaClABIErrorReporter *Reporter) {
return new PNaClABIVerifyModule(Reporter);
}
|