aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/NaCl/PNaClABITypeChecker.cpp35
-rw-r--r--lib/Analysis/NaCl/PNaClABITypeChecker.h8
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp17
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyModule.cpp12
-rw-r--r--test/NaCl/PNaClABI/types-function.ll6
-rw-r--r--test/NaCl/PNaClABI/types.ll6
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}