Skip to content

Commit f8b761e

Browse files
author
Jan Voung
committed
Check for metadata in PNaCl ABI checker.
Disallow all metadata by default. There is a flag "-allow-debug-metadata", which will be used in pnacl-ld driver, to not change the debugging workflow. That flag will not be present in the pnacl-abicheck driver though. We'll also run -strip-metadata within pnacl-ld, after optimizations are run, so that at least that part is checked inside pnacl-ld. CL for driver changes: https://codereview.chromium.org/14358048/ BUG= http://code.google.com/p/nativeclient/issues/detail?id=3348 [email protected] Review URL: https://codereview.chromium.org/14329025
1 parent 7564114 commit f8b761e

File tree

6 files changed

+86
-19
lines changed

6 files changed

+86
-19
lines changed

include/llvm/Analysis/NaCl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef LLVM_ANALYSIS_NACL_H
1111
#define LLVM_ANALYSIS_NACL_H
1212

13+
#include "llvm/Support/CommandLine.h"
1314
#include "llvm/Support/ErrorHandling.h"
1415
#include "llvm/Support/raw_ostream.h"
1516
#include <string>
@@ -18,6 +19,7 @@ namespace llvm {
1819

1920
class FunctionPass;
2021
class ModulePass;
22+
extern cl::opt<bool> PNaClABIAllowDebugMetadata;
2123

2224
class PNaClABIErrorReporter {
2325
public:
@@ -58,8 +60,9 @@ class PNaClABIErrorReporter {
5860
bool UseFatalErrors;
5961
};
6062

61-
FunctionPass *createPNaClABIVerifyFunctionsPass(PNaClABIErrorReporter * Reporter);
62-
ModulePass *createPNaClABIVerifyModulePass(PNaClABIErrorReporter * Reporter);
63+
FunctionPass *createPNaClABIVerifyFunctionsPass(
64+
PNaClABIErrorReporter *Reporter);
65+
ModulePass *createPNaClABIVerifyModulePass(PNaClABIErrorReporter *Reporter);
6366

6467
}
6568

lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/Analysis/NaCl.h"
1818
#include "llvm/IR/Function.h"
1919
#include "llvm/IR/Instructions.h"
20+
#include "llvm/IR/LLVMContext.h"
2021
#include "llvm/IR/Metadata.h"
2122
#include "llvm/Support/raw_ostream.h"
2223

@@ -49,14 +50,36 @@ class PNaClABIVerifyFunctions : public FunctionPass {
4950
bool runOnFunction(Function &F);
5051
virtual void print(raw_ostream &O, const Module *M) const;
5152
private:
53+
bool IsWhitelistedMetadata(unsigned MDKind);
5254
PNaClABITypeChecker TC;
5355
PNaClABIErrorReporter *Reporter;
5456
bool ReporterIsOwned;
5557
};
5658

59+
// There's no built-in way to get the name of an MDNode, so use a
60+
// string ostream to print it.
61+
std::string getMDNodeString(unsigned Kind,
62+
const SmallVectorImpl<StringRef>& MDNames) {
63+
std::string MDName;
64+
raw_string_ostream N(MDName);
65+
if (Kind < MDNames.size()) {
66+
N << "!" << MDNames[Kind];
67+
} else {
68+
N << "!<unknown kind #" << Kind << ">";
69+
}
70+
return N.str();
71+
}
72+
5773
} // and anonymous namespace
5874

75+
bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) {
76+
return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata;
77+
}
78+
5979
bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
80+
SmallVector<StringRef, 8> MDNames;
81+
F.getContext().getMDKindNames(MDNames);
82+
6083
// TODO: only report one error per instruction?
6184
for (Function::const_iterator FI = F.begin(), FE = F.end();
6285
FI != FE; ++FI) {
@@ -181,15 +204,25 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
181204
}
182205
}
183206

184-
// Get types hiding in metadata attached to the instruction
207+
// Check instruction attachment metadata.
185208
SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
186-
BBI->getAllMetadataOtherThanDebugLoc(MDForInst);
209+
BBI->getAllMetadata(MDForInst);
210+
187211
for (unsigned i = 0, e = MDForInst.size(); i != e; i++) {
188-
Type *T = TC.checkTypesInMDNode(MDForInst[i].second);
189-
if (T) {
190-
Reporter->addError() << "Function " << F.getName() <<
191-
" has instruction metadata containing disallowed type: " <<
192-
PNaClABITypeChecker::getTypeName(T) << "\n";
212+
if (!IsWhitelistedMetadata(MDForInst[i].first)) {
213+
Reporter->addError()
214+
<< "Function " << F.getName()
215+
<< " has disallowed instruction metadata: "
216+
<< getMDNodeString(MDForInst[i].first, MDNames) << "\n";
217+
} else {
218+
// If allowed, check the types hiding in the metadata.
219+
Type *T = TC.checkTypesInMDNode(MDForInst[i].second);
220+
if (T) {
221+
Reporter->addError()
222+
<< "Function " << F.getName()
223+
<< " has instruction metadata containing disallowed type: "
224+
<< PNaClABITypeChecker::getTypeName(T) << "\n";
225+
}
193226
}
194227
}
195228
}

lib/Analysis/NaCl/PNaClABIVerifyModule.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@
2323
#include "PNaClABITypeChecker.h"
2424
using namespace llvm;
2525

26+
namespace llvm {
27+
cl::opt<bool>
28+
PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata",
29+
cl::desc("Allow debug metadata during PNaCl ABI verification."),
30+
cl::init(false));
31+
}
32+
2633
namespace {
2734
// This pass should not touch function bodies, to stay streaming-friendly
2835
class PNaClABIVerifyModule : public ModulePass {
@@ -48,6 +55,7 @@ class PNaClABIVerifyModule : public ModulePass {
4855
virtual void print(raw_ostream &O, const Module *M) const;
4956
private:
5057
void CheckGlobalValueCommon(const GlobalValue *GV);
58+
bool IsWhitelistedMetadata(const NamedMDNode *MD);
5159
PNaClABITypeChecker TC;
5260
PNaClABIErrorReporter *Reporter;
5361
bool ReporterIsOwned;
@@ -105,6 +113,10 @@ void PNaClABIVerifyModule::CheckGlobalValueCommon(const GlobalValue *GV) {
105113
}
106114
}
107115

116+
bool PNaClABIVerifyModule::IsWhitelistedMetadata(const NamedMDNode* MD) {
117+
return MD->getName().startswith("llvm.dbg.") && PNaClABIAllowDebugMetadata;
118+
}
119+
108120
bool PNaClABIVerifyModule::runOnModule(Module &M) {
109121
for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
110122
MI != ME; ++MI) {
@@ -174,11 +186,17 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
174186
// Check named metadata nodes
175187
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
176188
E = M.named_metadata_end(); I != E; ++I) {
177-
for (unsigned i = 0, e = I->getNumOperands(); i != e; i++) {
178-
if (Type *T = TC.checkTypesInMDNode(I->getOperand(i))) {
179-
Reporter->addError() << "Named metadata node " << I->getName() <<
180-
" refers to disallowed type: " <<
181-
PNaClABITypeChecker::getTypeName(T) << "\n";
189+
if (!IsWhitelistedMetadata(I)) {
190+
Reporter->addError() << "Named metadata node " << I->getName()
191+
<< " is disallowed\n";
192+
} else {
193+
// Check the types in the metadata.
194+
for (unsigned i = 0, e = I->getNumOperands(); i != e; i++) {
195+
if (Type *T = TC.checkTypesInMDNode(I->getOperand(i))) {
196+
Reporter->addError() << "Named metadata node " << I->getName()
197+
<< " refers to disallowed type: "
198+
<< PNaClABITypeChecker::getTypeName(T) << "\n";
199+
}
182200
}
183201
}
184202
}

test/NaCl/PNaClABI/types-function.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ define void @types() {
2424
; C;HECK: Function types has instruction operand with disallowed type: i15
2525
; call void @func(i15 1)
2626

27-
; CHECK: Function types has instruction metadata containing disallowed type: half
27+
; CHECK: Function types has disallowed instruction metadata: !foo
2828
ret void, !foo !0
2929
}
3030
; CHECK-NOT: disallowed

test/NaCl/PNaClABI/types.ll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: pnacl-abicheck < %s | FileCheck %s
2+
; RUN: pnacl-abicheck -pnaclabi-allow-debug-metadata < %s | FileCheck %s --check-prefix=DEBUG
23
; Test types allowed by PNaCl ABI
34

45
; Basic global types
@@ -112,6 +113,17 @@ declare void @badArgType1(half %a, i32 %b)
112113
; CHECK: Function badArgType2 argument 2 has disallowed type
113114
declare void @badArgType2(i32 %a, half %b)
114115

115-
; CHECK: Named metadata node namedmd refers to disallowed type
116+
; If the metadata is allowed we want to check for types.
117+
; We have a hacky way to test this. The -allow-debug-metadata whitelists debug
118+
; metadata. That allows us to check types within debug metadata, even though
119+
; debug metadata normally does not have illegal types.
120+
; DEBUG-NOT: Named metadata node llvm.dbg.cu is disallowed
121+
; DEBUG: Named metadata node llvm.dbg.cu refers to disallowed type: half
122+
; CHECK: Named metadata node llvm.dbg.cu is disallowed
123+
!llvm.dbg.cu = !{!0}
116124
!0 = metadata !{ half 0.0}
117-
!namedmd = !{!0}
125+
126+
; CHECK: Named metadata node madeup is disallowed
127+
; DEBUG: Named metadata node madeup is disallowed
128+
!madeup = !{!1}
129+
!1 = metadata !{ half 1.0}

tools/pnacl-abicheck/pnacl-abicheck.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ using namespace llvm;
2626
static cl::opt<std::string>
2727
InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
2828

29-
static cl::opt<bool, false>
29+
static cl::opt<bool>
3030
Quiet("q", cl::desc("Do not print error messages"));
3131

3232
// Print any errors collected by the error reporter. Return true if
@@ -59,7 +59,8 @@ int main(int argc, char **argv) {
5959
bool ErrorsFound = false;
6060
// Manually run the passes so we can tell the user which function had the
6161
// error. No need for a pass manager since it's just one pass.
62-
OwningPtr<ModulePass> ModuleChecker(createPNaClABIVerifyModulePass(&ABIErrorReporter));
62+
OwningPtr<ModulePass> ModuleChecker(
63+
createPNaClABIVerifyModulePass(&ABIErrorReporter));
6364
ModuleChecker->runOnModule(*Mod);
6465
ErrorsFound |= CheckABIVerifyErrors(ABIErrorReporter, "Module");
6566
OwningPtr<FunctionPass> FunctionChecker(

0 commit comments

Comments
 (0)