diff options
-rw-r--r-- | lib/Analysis/NaCl/PNaClABITypeChecker.cpp | 35 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABITypeChecker.h | 8 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp | 17 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 12 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types-function.ll | 6 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types.ll | 6 |
6 files changed, 69 insertions, 15 deletions
diff --git a/lib/Analysis/NaCl/PNaClABITypeChecker.cpp b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp index 3a18129588..dd319a3a9f 100644 --- a/lib/Analysis/NaCl/PNaClABITypeChecker.cpp +++ b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp @@ -15,6 +15,7 @@ #include "PNaClABITypeChecker.h" #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Metadata.h" using namespace llvm; @@ -74,13 +75,14 @@ bool PNaClABITypeChecker::isValidType(const Type *Ty) { return Valid; } -Type *PNaClABITypeChecker::checkTypesInValue(const Value *V) { - // TODO: Checking types in values probably belongs in its - // own value checker which also handles the various types of - // constexpr (in particular, blockaddr constexprs cause this code - // to assert rather than go off and try to verify the BBs of a function) - // But this code is in a good consistent checkpoint-able state. - assert(isa<Constant>(V)); +Type *PNaClABITypeChecker::checkTypesInConstant(const Constant *V) { + // TODO: blockaddr constexprs cause this code + // to assert rather than go off and try to verify the BBs of a function + // We may just ban blockaddr constexprs, or maybe just ban them in GVs, which + // is really the thing that's streaming-unfriendly. If we end up with more + // complex non-type-related rules for constexprs, maybe this could get its + // own file. + if (!V) return NULL; if (VisitedConstants.count(V)) return VisitedConstants[V]; @@ -95,7 +97,7 @@ Type *PNaClABITypeChecker::checkTypesInValue(const Value *V) { const User *U = cast<User>(V); for (Constant::const_op_iterator I = U->op_begin(), E = U->op_end(); I != E; ++I) { - Type *Invalid = checkTypesInValue(*I); + Type *Invalid = checkTypesInConstant(cast<Constant>(*I)); if (Invalid) { VisitedConstants[V] = Invalid; return Invalid; @@ -104,3 +106,20 @@ Type *PNaClABITypeChecker::checkTypesInValue(const Value *V) { VisitedConstants[V] = NULL; return NULL; } + + +// MDNodes don't support the same way of iterating over operands that Users do +Type *PNaClABITypeChecker::checkTypesInMDNode(const MDNode *N) { + if (VisitedConstants.count(N)) + return VisitedConstants[N]; + + for (unsigned i = 0, e = N->getNumOperands(); i != e; i++) { + if (Value *Op = N->getOperand(i)) { + if (Type *Invalid = checkTypesInConstant(dyn_cast<Constant>(Op))) { + VisitedConstants[N] = Invalid; + return Invalid; + } + } + } + return NULL; +} diff --git a/lib/Analysis/NaCl/PNaClABITypeChecker.h b/lib/Analysis/NaCl/PNaClABITypeChecker.h index 1249bf04cd..eed2dc76b6 100644 --- a/lib/Analysis/NaCl/PNaClABITypeChecker.h +++ b/lib/Analysis/NaCl/PNaClABITypeChecker.h @@ -20,6 +20,8 @@ #include "llvm/Support/raw_ostream.h" namespace llvm { +class Constant; +class MDNode; class Value; class PNaClABITypeChecker { @@ -29,7 +31,11 @@ class PNaClABITypeChecker { // If the value contains an invalid type, return a pointer to the type. // Return null if there are no invalid types. - Type *checkTypesInValue(const Value *V); + Type *checkTypesInConstant(const Constant *V); + + // If the Metadata node contains an invalid type, return a pointer to the + // type. Return null if there are no invalid types. + Type *checkTypesInMDNode(const MDNode *V); // There's no built-in way to get the name of a type, so use a // string ostream to print it. diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp index ef1c26e175..fa94733ef0 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/NaCl.h" @@ -138,15 +139,25 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { if (!isa<SwitchInst>(*BBI)) for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end(); OI != OE; OI++) { - if (isa<Constant>(OI) && !isa<GlobalValue>(OI) && - !isa<Instruction>(OI)) { - Type *T = TC.checkTypesInValue(*OI); + if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) { + Type *T = TC.checkTypesInConstant(cast<Constant>(*OI)); if (T) Errors << "Function " + F.getName() + " has instruction operand with disallowed type: " + PNaClABITypeChecker::getTypeName(T) + "\n"; } } + + // Get types hiding in metadata attached to the instruction + SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; + BBI->getAllMetadataOtherThanDebugLoc(MDForInst); + for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { + Type *T = TC.checkTypesInMDNode(MDForInst[i].second); + if (T) + Errors << "Function " + F.getName() + + " has instruction metadata containing disallowed type: " + + PNaClABITypeChecker::getTypeName(T) + "\n"; + } } } diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp index f2124e1d12..59addab087 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp @@ -80,7 +80,7 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { + "\n"; } else if (MI->hasInitializer()) { // If the type of the global is bad, no point in checking its initializer - Type *T = TC.checkTypesInValue(MI->getInitializer()); + Type *T = TC.checkTypesInConstant(MI->getInitializer()); if (T) Errors << "Initializer for " + MI->getName() + " has disallowed type: " + @@ -120,6 +120,16 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { } } + // 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))) + Errors << "Named metadata node " + I->getName() + + " refers to disallowed type: " + + PNaClABITypeChecker::getTypeName(T) + "\n"; + } + } Errors.flush(); return false; } diff --git a/test/NaCl/PNaClABI/types-function.ll b/test/NaCl/PNaClABI/types-function.ll index eb8aedcef5..d020c76499 100644 --- a/test/NaCl/PNaClABI/types-function.ll +++ b/test/NaCl/PNaClABI/types-function.ll @@ -6,6 +6,9 @@ @a2 = private global i17 zeroinitializer declare void @func(i15 %arg) +!llvm.foo = !{!0} +!0 = metadata !{ half 0.0} + define void @types() { ; CHECK: Function types has instruction with disallowed type: half %h1 = fptrunc double undef to half @@ -17,7 +20,8 @@ define void @types() { store i32 0, i32* bitcast (i17* @a2 to i32*), align 4 ; CHECK: Function types has instruction operand with disallowed type: i15 call void @func(i15 1) - ret void +; CHECK: Function types has instruction metadata containing disallowed type: half + ret void, !foo !0 } ; CHECK-NOT: disallowed diff --git a/test/NaCl/PNaClABI/types.ll b/test/NaCl/PNaClABI/types.ll index 0447ea07ee..05248bae06 100644 --- a/test/NaCl/PNaClABI/types.ll +++ b/test/NaCl/PNaClABI/types.ll @@ -96,4 +96,8 @@ declare half* @badReturn() ; CHECK: Function badArgType1 argument 1 has disallowed type declare void @badArgType1(half %a, i32 %b) ; CHECK: Function badArgType2 argument 2 has disallowed type -declare void @badArgType2(i32 %a, half %b)
\ No newline at end of file +declare void @badArgType2(i32 %a, half %b) + +; CHECK: Named metadata node namedmd refers to disallowed type +!0 = metadata !{ half 0.0} +!namedmd = !{!0} |