Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Side by Side Diff: lib/Analysis/NaCl/PNaClABIVerifyModule.cpp

Issue 14670017: Start a whitelist of intrinsics for the PNaCl ABI checker. (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/NaCl/PNaClABI/intrinsics.ll » ('j') | test/NaCl/PNaClABI/intrinsics.ll » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===// 1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // Verify module-level PNaCl ABI requirements (specifically those that do not 10 // Verify module-level PNaCl ABI requirements (specifically those that do not
11 // require looking at the function bodies) 11 // require looking at the function bodies)
12 // 12 //
13 // 13 //
14 //===----------------------------------------------------------------------===// 14 //===----------------------------------------------------------------------===//
15 15
16 #include "llvm/Pass.h" 16 #include "llvm/Pass.h"
17 #include "llvm/ADT/Twine.h" 17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Analysis/NaCl.h" 18 #include "llvm/Analysis/NaCl.h"
19 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/Intrinsics.h"
20 #include "llvm/IR/Module.h" 21 #include "llvm/IR/Module.h"
22 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h" 23 #include "llvm/Support/raw_ostream.h"
22 24
23 #include "PNaClABITypeChecker.h" 25 #include "PNaClABITypeChecker.h"
24 using namespace llvm; 26 using namespace llvm;
25 27
26 namespace llvm { 28 namespace llvm {
27 cl::opt<bool> 29 cl::opt<bool>
28 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", 30 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata",
29 cl::desc("Allow debug metadata during PNaCl ABI verification."), 31 cl::desc("Allow debug metadata during PNaCl ABI verification."),
30 cl::init(false)); 32 cl::init(false));
33
31 } 34 }
32 35
36 static cl::opt<bool> PNaClABIAllowIntrinsics("pnaclabi-allow-intrinsics",
eliben 2013/05/07 15:27:40 Can we divide intrinsics into 3 groups: 1. Those
jvoung (off chromium) 2013/05/07 17:39:46 That sounds like a good breakdown. I'll rename t
jvoung (off chromium) 2013/05/07 21:24:41 At the Tues meeting (an hour ago), there was some
37 cl::desc("Allow all LLVM intrinsics duing PNaCl ABI verification."),
38 cl::init(true)); // TODO(jvoung): Make this false by default.
39
33 namespace { 40 namespace {
34 // This pass should not touch function bodies, to stay streaming-friendly 41 // This pass should not touch function bodies, to stay streaming-friendly
35 class PNaClABIVerifyModule : public ModulePass { 42 class PNaClABIVerifyModule : public ModulePass {
36 public: 43 public:
37 static char ID; 44 static char ID;
38 PNaClABIVerifyModule() : 45 PNaClABIVerifyModule() :
39 ModulePass(ID), 46 ModulePass(ID),
40 Reporter(new PNaClABIErrorReporter), 47 Reporter(new PNaClABIErrorReporter),
41 ReporterIsOwned(true) { 48 ReporterIsOwned(true) {
42 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); 49 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
43 } 50 }
44 explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) : 51 explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) :
45 ModulePass(ID), 52 ModulePass(ID),
46 Reporter(Reporter_), 53 Reporter(Reporter_),
47 ReporterIsOwned(false) { 54 ReporterIsOwned(false) {
48 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); 55 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
49 } 56 }
50 ~PNaClABIVerifyModule() { 57 ~PNaClABIVerifyModule() {
51 if (ReporterIsOwned) 58 if (ReporterIsOwned)
52 delete Reporter; 59 delete Reporter;
53 } 60 }
54 bool runOnModule(Module &M); 61 bool runOnModule(Module &M);
55 virtual void print(raw_ostream &O, const Module *M) const; 62 virtual void print(raw_ostream &O, const Module *M) const;
56 private: 63 private:
57 void CheckGlobalValueCommon(const GlobalValue *GV); 64 void CheckGlobalValueCommon(const GlobalValue *GV);
65 bool IsWhitelistedIntrinsic(const Function* F, unsigned ID);
58 bool IsWhitelistedMetadata(const NamedMDNode *MD); 66 bool IsWhitelistedMetadata(const NamedMDNode *MD);
59 PNaClABITypeChecker TC; 67 PNaClABITypeChecker TC;
60 PNaClABIErrorReporter *Reporter; 68 PNaClABIErrorReporter *Reporter;
61 bool ReporterIsOwned; 69 bool ReporterIsOwned;
62 }; 70 };
63 71
64 static const char *linkageName(GlobalValue::LinkageTypes LT) { 72 static const char *linkageName(GlobalValue::LinkageTypes LT) {
65 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp 73 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp
66 switch (LT) { 74 switch (LT) {
67 case GlobalValue::ExternalLinkage: return "external"; 75 case GlobalValue::ExternalLinkage: return "external";
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 Reporter->addError() << GVTypeName << GV->getName() 114 Reporter->addError() << GVTypeName << GV->getName()
107 << " has disallowed linkage type: " 115 << " has disallowed linkage type: "
108 << linkageName(GV->getLinkage()) << "\n"; 116 << linkageName(GV->getLinkage()) << "\n";
109 } 117 }
110 if (GV->hasSection()) { 118 if (GV->hasSection()) {
111 Reporter->addError() << GVTypeName << GV->getName() << 119 Reporter->addError() << GVTypeName << GV->getName() <<
112 " has disallowed \"section\" attribute\n"; 120 " has disallowed \"section\" attribute\n";
113 } 121 }
114 } 122 }
115 123
124 bool PNaClABIVerifyModule::IsWhitelistedIntrinsic(const Function* F,
125 unsigned ID) {
126 switch(ID) {
127 default:
128 DEBUG(dbgs() << "Unknown intrinsic: " << F->getName() << "\n");
129 return PNaClABIAllowIntrinsics;
130 case Intrinsic::not_intrinsic: return false;
131 case Intrinsic::dbg_declare:
132 case Intrinsic::dbg_value:
133 case Intrinsic::frameaddress: // Likely only used for debugging?
134 case Intrinsic::returnaddress: // Likely only used for debugging?
135 return PNaClABIAllowDebugMetadata;
136 case Intrinsic::invariant_end:
137 case Intrinsic::invariant_start:
138 case Intrinsic::lifetime_end:
139 case Intrinsic::lifetime_start:
140 case Intrinsic::memcpy:
141 case Intrinsic::memmove:
142 case Intrinsic::memset:
143 case Intrinsic::nacl_read_tp:
144 case Intrinsic::trap:
145 return true;
146 case Intrinsic::vacopy:
147 case Intrinsic::vaend:
148 case Intrinsic::vastart:
149 // Var-args code is expanded out, so we shouldn't need va_arg intrinsics.
150 // TODO(jvoung): Disallow this too. However, we need to strip
151 // dead prototypes before this will work.
152 return PNaClABIAllowDebugMetadata;
153 }
154 }
155
116 bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) { 156 bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) {
117 return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata; 157 return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata;
118 } 158 }
119 159
120 bool PNaClABIVerifyModule::runOnModule(Module &M) { 160 bool PNaClABIVerifyModule::runOnModule(Module &M) {
121 for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end(); 161 for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
122 MI != ME; ++MI) { 162 MI != ME; ++MI) {
123 // Check types of global variables and their initializers 163 // Check types of global variables and their initializers
124 if (!TC.isValidType(MI->getType())) { 164 if (!TC.isValidType(MI->getType())) {
125 // GVs are pointers, so print the pointed-to type for clarity 165 // GVs are pointers, so print the pointed-to type for clarity
(...skipping 20 matching lines...) Expand all
146 } 186 }
147 187
148 // No aliases allowed for now. 188 // No aliases allowed for now.
149 for (Module::alias_iterator MI = M.alias_begin(), 189 for (Module::alias_iterator MI = M.alias_begin(),
150 E = M.alias_end(); MI != E; ++MI) { 190 E = M.alias_end(); MI != E; ++MI) {
151 Reporter->addError() << "Variable " << MI->getName() << 191 Reporter->addError() << "Variable " << MI->getName() <<
152 " is an alias (disallowed)\n"; 192 " is an alias (disallowed)\n";
153 } 193 }
154 194
155 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { 195 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
196 // Check intrinsics.
197 if (MI->isIntrinsic()) {
eliben 2013/05/07 15:27:40 Can an intrinsic be called without a declaration?
jvoung (off chromium) 2013/05/07 17:39:46 I don't think you can call intrinsics without a de
jvoung (off chromium) 2013/05/07 22:32:18 Ah yes, you mean we'd do something like "llc -disa
jvoung (off chromium) 2013/05/07 22:33:08 Err... not that you can't generate bad binary bitc
198 if (!IsWhitelistedIntrinsic(MI, MI->getIntrinsicID())) {
199 Reporter->addError() << "Function " << MI->getName()
200 << " is a disallowed LLVM intrinsic\n";
201 }
202 }
203
156 // Check types of functions and their arguments 204 // Check types of functions and their arguments
157 FunctionType *FT = MI->getFunctionType(); 205 FunctionType *FT = MI->getFunctionType();
158 if (!TC.isValidType(FT->getReturnType())) { 206 if (!TC.isValidType(FT->getReturnType())) {
159 Reporter->addError() << "Function " << MI->getName() << 207 Reporter->addError() << "Function " << MI->getName() <<
160 " has disallowed return type: " << 208 " has disallowed return type: " <<
161 PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n"; 209 PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n";
162 } 210 }
163 for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) { 211 for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) {
164 Type *PT = FT->getParamType(I); 212 Type *PT = FT->getParamType(I);
165 if (!TC.isValidType(PT)) { 213 if (!TC.isValidType(PT)) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 } 263 }
216 264
217 char PNaClABIVerifyModule::ID = 0; 265 char PNaClABIVerifyModule::ID = 0;
218 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", 266 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module",
219 "Verify module for PNaCl", false, true) 267 "Verify module for PNaCl", false, true)
220 268
221 ModulePass *llvm::createPNaClABIVerifyModulePass( 269 ModulePass *llvm::createPNaClABIVerifyModulePass(
222 PNaClABIErrorReporter *Reporter) { 270 PNaClABIErrorReporter *Reporter) {
223 return new PNaClABIVerifyModule(Reporter); 271 return new PNaClABIVerifyModule(Reporter);
224 } 272 }
OLDNEW
« no previous file with comments | « no previous file | test/NaCl/PNaClABI/intrinsics.ll » ('j') | test/NaCl/PNaClABI/intrinsics.ll » ('J')

Powered by Google App Engine
This is Rietveld 408576698