Index: lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp |
diff --git a/lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp b/lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp |
index 3f84857feae7e2e8337affef7f6fffabdc09d02b..3906bfd269f0abc71455b6ab598235ed2e0b9a79 100644 |
--- a/lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp |
+++ b/lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp |
@@ -39,6 +39,12 @@ ReportWarningsAsErrors( |
cl::desc("Report warnings as errors."), |
cl::init(false)); |
+static cl::opt<bool> |
+IgnorePNaClABIChecks( |
+ "ignore-pnaclabi-checks", |
+ cl::desc("Ignore checking bitcode for PNaCl ABI violations"), |
+ cl::init(false)); |
+ |
/// Class to handle sign rotations in a human readable form. That is, |
/// the sign is in the low bit. The two special cases are: |
/// 1) -1 is true for i1. |
@@ -933,7 +939,8 @@ public: |
/// Verifies the given integer operator has the right type. Returns |
/// the operator. |
const char *VerifyIntArithmeticOp(const char *Op, Type *OpTy) { |
- if (!PNaClABITypeChecker::isValidIntArithmeticType(OpTy)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidIntArithmeticType(OpTy)) { |
Errors() << Op << ": Invalid integer arithmetic type: " << *OpTy; |
} |
return Op; |
@@ -942,7 +949,8 @@ public: |
// Checks the Alignment for loading/storing a value of type Ty. If |
// invalid, generates an appropriate error message. |
void VerifyMemoryAccessAlignment(const char *Op, Type *Ty, |
- uint64_t Alignment) { |
+ unsigned Alignment) { |
+ if (IgnorePNaClABIChecks) return; |
if (!PNaClABIProps::isAllowedAlignment(&DL, Alignment, Ty)) { |
if (unsigned Expected = NaClGetExpectedLoadStoreAlignment(DL, Ty)) { |
Errors() << Op << ": Illegal alignment for " << *Ty |
@@ -1797,12 +1805,14 @@ void NaClDisTypesParser::ProcessRecord() { |
case 16: |
case 32: |
case 64: { |
- break; |
- } |
+ break; |
+ } |
default: |
- Errors() << "Integer record contains bad integer size: " |
- << Size << "\n"; |
- Size = 32; |
+ if (!IgnorePNaClABIChecks) { |
+ Errors() << "Integer record contains bad integer size: " |
+ << Size << "\n"; |
+ Size = 32; |
+ } |
break; |
} |
Type *IntType = GetIntegerType(Size); |
@@ -1832,7 +1842,8 @@ void NaClDisTypesParser::ProcessRecord() { |
} |
uint64_t NumElements = Values[0]; |
Type *VecType = VectorType::get(BaseType, NumElements); |
- if (!PNaClABITypeChecker::isValidVectorType(VecType)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidVectorType(VecType)) { |
Errors() << "Vector type " << *VecType << " not allowed.\n"; |
} |
Tokens() << NextTypeId() << Space() << "=" << Space() |
@@ -2207,7 +2218,7 @@ void NaClDisValueSymtabParser::ProcessRecord() { |
<< "\n"; |
break; |
} |
- if (!PNaClABITypeChecker::IsPointerEquivType( |
+ if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType( |
IntrinTy->getReturnType(), FcnTy->getReturnType())) { |
Errors() << "Intrinsic " << Name |
<< " expects return type " << *IntrinTy->getReturnType() |
@@ -2215,7 +2226,7 @@ void NaClDisValueSymtabParser::ProcessRecord() { |
break; |
} |
for (size_t i = 0; i < FcnTy->getNumParams(); ++i) { |
- if (!PNaClABITypeChecker::IsPointerEquivType( |
+ if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType( |
IntrinTy->getParamType(i), |
FcnTy->getParamType(i))) { |
Errors() << "Intrinsic " << Name |
@@ -2463,14 +2474,18 @@ private: |
const char *VerifyIntegerOrVectorOp(const char *Op, Type *OpTy) { |
Type *BaseTy = OpTy; |
if (OpTy->isVectorTy()) { |
- if (!PNaClABITypeChecker::isValidVectorType(OpTy)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidVectorType(OpTy)) { |
Errors() << Op << ": invalid vector type: " << *OpTy << "\n"; |
return Op; |
} |
BaseTy = OpTy->getVectorElementType(); |
} |
if (BaseTy->isIntegerTy()) { |
- if (PNaClABITypeChecker::isValidScalarType(BaseTy)) return Op; |
+ if (IgnorePNaClABIChecks || |
+ PNaClABITypeChecker::isValidScalarType(BaseTy)) { |
+ return Op; |
+ } |
Errors() << Op << ": Invalid integer type: " << *OpTy << "\n"; |
} else { |
Errors() << Op << ": Expects integer type. Found: " << *OpTy << "\n"; |
@@ -2484,7 +2499,8 @@ private: |
const char *VerifyFloatingOrVectorOp(const char *Op, Type *OpTy) { |
Type *BaseTy = OpTy; |
if (OpTy->isVectorTy()) { |
- if (!PNaClABITypeChecker::isValidVectorType(OpTy)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidVectorType(OpTy)) { |
Errors() << Op << ": invalid vector type: " << *OpTy << "\n"; |
return Op; |
} |
@@ -2495,7 +2511,8 @@ private: |
<< OpTy << "\n"; |
return Op; |
} |
- if (!PNaClABITypeChecker::isValidScalarType(BaseTy)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidScalarType(BaseTy)) { |
Errors() << Op << ": type not allowed: " << OpTy << "\n"; |
} |
return Op; |
@@ -2505,6 +2522,7 @@ private: |
/// OpTy is either a (non-void) scalar, or a vector of scalars. If |
/// not, generates an appropriate error message. Always returns Op. |
const char *VerifyScalarOrVectorOp(const char *Op, Type *OpTy) { |
+ if (IgnorePNaClABIChecks) return Op; |
if (PNaClABITypeChecker::isValidScalarType(OpTy)) { |
if (OpTy->isVoidTy()) |
Errors() << Op << ": Type void not allowed\n"; |
@@ -2519,7 +2537,8 @@ private: |
uint32_t IdxValue) { |
Type *VecType = GetValueType(VecValue); |
Type *IdxType = GetValueType(IdxValue); |
- if (!PNaClABITypeChecker::isValidVectorType(VecType)){ |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidVectorType(VecType)){ |
if (VecType->isVectorTy()) |
Errors() << Op << ": Vector type " << *VecType << " not allowed\n"; |
else |
@@ -2546,6 +2565,11 @@ private: |
<< " out of range. Not in [1," << ExpectedNumBbs << "]\n"; |
} |
} |
+ |
+ /// Convert alignment exponent (i.e. power of two (or zero)) to the |
+ /// corresponding alignment to use. If alignment is too large, it generates |
+ /// an error message and returns 0. |
+ unsigned getAlignmentValue(uint64_t Exponent); |
}; |
NaClDisFunctionParser::NaClDisFunctionParser( |
@@ -2578,8 +2602,14 @@ NaClDisFunctionParser::NaClDisFunctionParser( |
void NaClDisFunctionParser::PrintBlockHeader() { |
Tokens() << "function" << Space(); |
BitcodeId FunctionId('f', FcnId); |
- if (!(Context->IsFunctionIntrinsic(FcnId) |
- || PNaClABITypeChecker::isValidFunctionType(FcnTy))) { |
+ bool InvalidSignature = true; // until proven otherwise. |
+ if (Context->IsFunctionIntrinsic(FcnId)) |
+ InvalidSignature = false; |
+ else if (IgnorePNaClABIChecks || |
+ PNaClABITypeChecker::isValidFunctionType(FcnTy)) { |
+ InvalidSignature = false; |
+ } |
+ if (InvalidSignature) { |
Errors() << "Invalid type signature for " |
<< BitcodeId('f', FcnId) << ": " << *FcnTy << "\n"; |
} |
@@ -2766,6 +2796,23 @@ const char *NaClDisFunctionParser::GetFcmpPredicate(uint32_t Opcode) { |
} |
} |
+namespace { |
+ |
+static const unsigned MaxAlignmentExponent = 29; |
+static_assert( |
+ (1u << MaxAlignmentExponent) == Value::MaximumAlignment, |
+ "Inconsistency between Value.MaxAlignment and PNaCl alignment limit"); |
+} |
+ |
+unsigned NaClDisFunctionParser::getAlignmentValue(uint64_t Exponent) { |
+ if (Exponent > MaxAlignmentExponent + 1) { |
+ Errors() << "Alignment can't be greater than 2**" << MaxAlignmentExponent |
+ << ". Found: 2**" << (Exponent - 1) << "\n"; |
+ return 0; |
+ } |
+ return (1 << static_cast<unsigned>(Exponent)) >> 1; |
+} |
+ |
bool NaClDisFunctionParser::ParseBlock(unsigned BlockID) { |
ObjDumpSetRecordBitAddress(GetBlock().GetStartBit()); |
switch (BlockID) { |
@@ -2914,9 +2961,11 @@ void NaClDisFunctionParser::ProcessRecord() { |
if (OpType != CondType) |
Errors() << "Specified select type " << *OpType << " but found: " |
<< *CondType << "\n"; |
- if (!PNaClABITypeChecker::isValidSwitchConditionType(CondType)) |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidSwitchConditionType(CondType)) { |
Errors() << PNaClABITypeChecker::ExpectedSwitchConditionType(CondType) |
<< "\n"; |
+ } |
uint32_t DefaultBb = Values[2]; |
unsigned NumCases = Values[3]; |
VerifyBranchRange(DefaultBb); |
@@ -2995,8 +3044,8 @@ void NaClDisFunctionParser::ProcessRecord() { |
uint32_t SizeOp = RelativeToAbsId(Values[0]); |
Type* SizeType = GetValueType(SizeOp); |
BitcodeId SizeId(GetBitcodeId(SizeOp)); |
- uint64_t Alignment = (1 << Values[1]) >> 1; |
- if (!PNaClABIProps::isAllocaSizeType(SizeType)) |
+ unsigned Alignment = getAlignmentValue(Values[1]); |
+ if (!IgnorePNaClABIChecks && !PNaClABIProps::isAllocaSizeType(SizeType)) |
Errors() << PNaClABIProps::ExpectedAllocaSizeType() << "\n"; |
// TODO(kschimpf) Are there any constraints on alignment? |
Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster() |
@@ -3015,7 +3064,7 @@ void NaClDisFunctionParser::ProcessRecord() { |
<< Values.size() << "\n"; |
break; |
} |
- uint64_t Alignment = (1 << Values[1]) >> 1; |
+ unsigned Alignment = getAlignmentValue(Values[1]); |
Type *LoadType = GetType(Values[2]); |
VerifyScalarOrVectorOp("load", LoadType); |
Context->VerifyMemoryAccessAlignment("load", LoadType, Alignment); |
@@ -3035,7 +3084,7 @@ void NaClDisFunctionParser::ProcessRecord() { |
<< Values.size() << "\n"; |
break; |
} |
- uint64_t Alignment = (1 << Values[2]) >> 1; |
+ unsigned Alignment = getAlignmentValue(Values[2]); |
uint32_t Val = RelativeToAbsId(Values[1]); |
Type *ValType = GetValueType(Val); |
VerifyScalarOrVectorOp("store", ValType); |
@@ -3186,7 +3235,8 @@ void NaClDisFunctionParser::ProcessRecord() { |
uint32_t FcnId = RelativeToAbsId(Values[1]); |
if (!naclbitc::DecodeCallingConv(Values[0]>>1, CallingConv)) |
Errors() << "Call unknown calling convention:" << (Values[0]>>1) << "\n"; |
- if (!PNaClABIProps::isValidCallingConv(CallingConv)) { |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABIProps::isValidCallingConv(CallingConv)) { |
Errors() << "Call uses disallowed calling convention: " |
<< PNaClABIProps::CallingConvName(CallingConv) << "(" |
<< CallingConv << ")\n"; |
@@ -3220,8 +3270,11 @@ void NaClDisFunctionParser::ProcessRecord() { |
if (IsTailCall) { |
Tokens() << "tail" << Space(); |
} |
- if (CheckArgRetTypes && !PNaClABITypeChecker::isValidParamType(ReturnType)) |
+ if (CheckArgRetTypes && |
+ !IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidParamType(ReturnType)) { |
Errors() << "Invalid return type: " << *ReturnType << "\n"; |
+ } |
Tokens() << "call" << Space(); |
if (CallingConv != CallingConv::C) { |
Tokens() << PNaClABIProps::CallingConvName(CallingConv) << Space(); |
@@ -3234,9 +3287,12 @@ void NaClDisFunctionParser::ProcessRecord() { |
for (size_t i = ArgIndex; i < Values.size(); ++i, ++ParamIndex) { |
uint32_t ParamId = RelativeToAbsId(Values[i]); |
Type *ParamType = GetValueType(ParamId); |
- if (CheckArgRetTypes && !PNaClABITypeChecker::isValidParamType(ParamType)) |
+ if (CheckArgRetTypes && |
+ !IgnorePNaClABIChecks && |
+ !PNaClABITypeChecker::isValidParamType(ParamType)) { |
Errors() << "invalid type for parameter " << i << ": " |
<< *ParamType << "\n"; |
+ } |
if (FcnType) { |
if (ParamIndex < FcnType->getNumParams()) { |
Type *ExpectedType = FcnType->getParamType(ParamIndex); |
@@ -3316,6 +3372,7 @@ NaClDisModuleParser::~NaClDisModuleParser() { |
} |
if (FunctionType *FcnTy = dyn_cast<FunctionType>(GetFunctionValueType(i))) { |
if (!Context->IsFunctionIntrinsic(i) && |
+ !IgnorePNaClABIChecks && |
!PNaClABITypeChecker::isValidFunctionType(FcnTy)) { |
Context->SetRecordAddressToFunctionIdAddress(i); |
Errors() << "Invalid type signature for " |
@@ -3389,9 +3446,11 @@ void NaClDisModuleParser::ProcessRecord() { |
if (!naclbitc::DecodeLinkage(Values[3], Linkage)) { |
Errors() << "Unknown linkage value: " << Values[3] << "\n"; |
} else { |
- if (!PNaClABIProps::isValidGlobalLinkage(Linkage)) |
+ if (!IgnorePNaClABIChecks && |
+ !PNaClABIProps::isValidGlobalLinkage(Linkage)) { |
Errors() << "Disallowed linkage type: " |
<< PNaClABIProps::LinkageName(Linkage) << "\n"; |
+ } |
Tokens() << Space() << PNaClABIProps::LinkageName(Linkage); |
} |
CallingConv::ID CallingConv; |