diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp | 47 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 28 |
2 files changed, 63 insertions, 12 deletions
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp index cd3ede4b58..2c9a6a17b9 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp @@ -17,6 +17,7 @@ #include "llvm/Analysis/NaCl.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/raw_ostream.h" @@ -49,14 +50,36 @@ class PNaClABIVerifyFunctions : public FunctionPass { bool runOnFunction(Function &F); virtual void print(raw_ostream &O, const Module *M) const; private: + bool IsWhitelistedMetadata(unsigned MDKind); PNaClABITypeChecker TC; PNaClABIErrorReporter *Reporter; bool ReporterIsOwned; }; +// There's no built-in way to get the name of an MDNode, so use a +// string ostream to print it. +std::string getMDNodeString(unsigned Kind, + const SmallVectorImpl<StringRef>& MDNames) { + std::string MDName; + raw_string_ostream N(MDName); + if (Kind < MDNames.size()) { + N << "!" << MDNames[Kind]; + } else { + N << "!<unknown kind #" << Kind << ">"; + } + return N.str(); +} + } // and anonymous namespace +bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) { + return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata; +} + bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { + SmallVector<StringRef, 8> MDNames; + F.getContext().getMDKindNames(MDNames); + // TODO: only report one error per instruction? for (Function::const_iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) { @@ -181,15 +204,25 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { } } - // Get types hiding in metadata attached to the instruction + // Check instruction attachment metadata. SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; - BBI->getAllMetadataOtherThanDebugLoc(MDForInst); + BBI->getAllMetadata(MDForInst); + for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { - Type *T = TC.checkTypesInMDNode(MDForInst[i].second); - if (T) { - Reporter->addError() << "Function " << F.getName() << - " has instruction metadata containing disallowed type: " << - PNaClABITypeChecker::getTypeName(T) << "\n"; + if (!IsWhitelistedMetadata(MDForInst[i].first)) { + Reporter->addError() + << "Function " << F.getName() + << " has disallowed instruction metadata: " + << getMDNodeString(MDForInst[i].first, MDNames) << "\n"; + } else { + // If allowed, check the types hiding in the metadata. + Type *T = TC.checkTypesInMDNode(MDForInst[i].second); + if (T) { + Reporter->addError() + << "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 88914c85a8..efb40cf43a 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp @@ -23,6 +23,13 @@ #include "PNaClABITypeChecker.h" using namespace llvm; +namespace llvm { +cl::opt<bool> +PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", + cl::desc("Allow debug metadata during PNaCl ABI verification."), + cl::init(false)); +} + namespace { // This pass should not touch function bodies, to stay streaming-friendly class PNaClABIVerifyModule : public ModulePass { @@ -48,6 +55,7 @@ class PNaClABIVerifyModule : public ModulePass { virtual void print(raw_ostream &O, const Module *M) const; private: void CheckGlobalValueCommon(const GlobalValue *GV); + bool IsWhitelistedMetadata(const NamedMDNode *MD); PNaClABITypeChecker TC; PNaClABIErrorReporter *Reporter; bool ReporterIsOwned; @@ -105,6 +113,10 @@ void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) { } } +bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) { + return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata; +} + bool PNaClABIVerifyModule::runOnModule(Module &M) { for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end(); MI != ME; ++MI) { @@ -174,11 +186,17 @@ 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))) { - Reporter->addError() << "Named metadata node " << I->getName() << - " refers to disallowed type: " << - PNaClABITypeChecker::getTypeName(T) << "\n"; + if (!IsWhitelistedMetadata(I)) { + Reporter->addError() << "Named metadata node " << I->getName() + << " is disallowed\n"; + } else { + // Check the types in the metadata. + 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"; + } } } } |