1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_VERIFIER_REGISTER_LINE_INL_H_ 18 #define ART_RUNTIME_VERIFIER_REGISTER_LINE_INL_H_ 19 20 #include "register_line.h" 21 22 #include "method_verifier.h" 23 #include "reg_type_cache-inl.h" 24 25 namespace art { 26 namespace verifier { 27 28 // Should we dump a warning on failures to verify balanced locking? That would be an indication to 29 // developers that their code will be slow. 30 static constexpr bool kDumpLockFailures = true; 31 32 inline const RegType& RegisterLine::GetRegisterType(MethodVerifier* verifier, uint32_t vsrc) const { 33 // The register index was validated during the static pass, so we don't need to check it here. 34 DCHECK_LT(vsrc, num_regs_); 35 return verifier->GetRegTypeCache()->GetFromId(line_[vsrc]); 36 } 37 38 template <LockOp kLockOp> 39 inline bool RegisterLine::SetRegisterType(MethodVerifier* verifier, uint32_t vdst, 40 const RegType& new_type) { 41 DCHECK_LT(vdst, num_regs_); 42 if (new_type.IsLowHalf() || new_type.IsHighHalf()) { 43 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected category1 register type not '" 44 << new_type << "'"; 45 return false; 46 } else { 47 // Note: previously we failed when asked to set a conflict. However, conflicts are OK as long 48 // as they are not accessed, and our backends can handle this nowadays. 49 line_[vdst] = new_type.GetId(); 50 } 51 switch (kLockOp) { 52 case LockOp::kClear: 53 // Clear the monitor entry bits for this register. 54 ClearAllRegToLockDepths(vdst); 55 break; 56 case LockOp::kKeep: 57 // Should only be doing this with reference types. 58 DCHECK(new_type.IsReferenceTypes()); 59 break; 60 } 61 return true; 62 } 63 64 inline bool RegisterLine::SetRegisterTypeWide(MethodVerifier* verifier, uint32_t vdst, 65 const RegType& new_type1, 66 const RegType& new_type2) { 67 DCHECK_LT(vdst + 1, num_regs_); 68 if (!new_type1.CheckWidePair(new_type2)) { 69 verifier->Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "Invalid wide pair '" 70 << new_type1 << "' '" << new_type2 << "'"; 71 return false; 72 } else { 73 line_[vdst] = new_type1.GetId(); 74 line_[vdst + 1] = new_type2.GetId(); 75 } 76 // Clear the monitor entry bits for this register. 77 ClearAllRegToLockDepths(vdst); 78 ClearAllRegToLockDepths(vdst + 1); 79 return true; 80 } 81 82 inline void RegisterLine::SetResultTypeToUnknown(MethodVerifier* verifier) { 83 result_[0] = verifier->GetRegTypeCache()->Undefined().GetId(); 84 result_[1] = result_[0]; 85 } 86 87 inline void RegisterLine::SetResultRegisterType(MethodVerifier* verifier, const RegType& new_type) { 88 DCHECK(!new_type.IsLowHalf()); 89 DCHECK(!new_type.IsHighHalf()); 90 result_[0] = new_type.GetId(); 91 result_[1] = verifier->GetRegTypeCache()->Undefined().GetId(); 92 } 93 94 inline void RegisterLine::SetResultRegisterTypeWide(const RegType& new_type1, 95 const RegType& new_type2) { 96 DCHECK(new_type1.CheckWidePair(new_type2)); 97 result_[0] = new_type1.GetId(); 98 result_[1] = new_type2.GetId(); 99 } 100 101 inline void RegisterLine::CopyRegister1(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc, 102 TypeCategory cat) { 103 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef); 104 const RegType& type = GetRegisterType(verifier, vsrc); 105 if (!SetRegisterType<LockOp::kClear>(verifier, vdst, type)) { 106 return; 107 } 108 if (!type.IsConflict() && // Allow conflicts to be copied around. 109 ((cat == kTypeCategory1nr && !type.IsCategory1Types()) || 110 (cat == kTypeCategoryRef && !type.IsReferenceTypes()))) { 111 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy1 v" << vdst << "<-v" << vsrc << " type=" << type 112 << " cat=" << static_cast<int>(cat); 113 } else if (cat == kTypeCategoryRef) { 114 CopyRegToLockDepth(vdst, vsrc); 115 } 116 } 117 118 inline void RegisterLine::CopyRegister2(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc) { 119 const RegType& type_l = GetRegisterType(verifier, vsrc); 120 const RegType& type_h = GetRegisterType(verifier, vsrc + 1); 121 122 if (!type_l.CheckWidePair(type_h)) { 123 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "copy2 v" << vdst << "<-v" << vsrc 124 << " type=" << type_l << "/" << type_h; 125 } else { 126 SetRegisterTypeWide(verifier, vdst, type_l, type_h); 127 } 128 } 129 130 inline bool RegisterLine::VerifyRegisterType(MethodVerifier* verifier, uint32_t vsrc, 131 const RegType& check_type) { 132 // Verify the src register type against the check type refining the type of the register 133 const RegType& src_type = GetRegisterType(verifier, vsrc); 134 if (UNLIKELY(!check_type.IsAssignableFrom(src_type))) { 135 enum VerifyError fail_type; 136 if (!check_type.IsNonZeroReferenceTypes() || !src_type.IsNonZeroReferenceTypes()) { 137 // Hard fail if one of the types is primitive, since they are concretely known. 138 fail_type = VERIFY_ERROR_BAD_CLASS_HARD; 139 } else if (check_type.IsUninitializedTypes() || src_type.IsUninitializedTypes()) { 140 // Hard fail for uninitialized types, which don't match anything but themselves. 141 fail_type = VERIFY_ERROR_BAD_CLASS_HARD; 142 } else if (check_type.IsUnresolvedTypes() || src_type.IsUnresolvedTypes()) { 143 fail_type = VERIFY_ERROR_NO_CLASS; 144 } else { 145 fail_type = VERIFY_ERROR_BAD_CLASS_SOFT; 146 } 147 verifier->Fail(fail_type) << "register v" << vsrc << " has type " 148 << src_type << " but expected " << check_type; 149 return false; 150 } 151 if (check_type.IsLowHalf()) { 152 const RegType& src_type_h = GetRegisterType(verifier, vsrc + 1); 153 if (UNLIKELY(!src_type.CheckWidePair(src_type_h))) { 154 verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register v" << vsrc << " has type " 155 << src_type << "/" << src_type_h; 156 return false; 157 } 158 } 159 // The register at vsrc has a defined type, we know the lower-upper-bound, but this is less 160 // precise than the subtype in vsrc so leave it for reference types. For primitive types 161 // if they are a defined type then they are as precise as we can get, however, for constant 162 // types we may wish to refine them. Unfortunately constant propagation has rendered this useless. 163 return true; 164 } 165 166 inline void RegisterLine::VerifyMonitorStackEmpty(MethodVerifier* verifier) const { 167 if (MonitorStackDepth() != 0) { 168 verifier->Fail(VERIFY_ERROR_LOCKING); 169 if (kDumpLockFailures) { 170 VLOG(verifier) << "expected empty monitor stack in " 171 << PrettyMethod(verifier->GetMethodReference().dex_method_index, 172 *verifier->GetMethodReference().dex_file); 173 } 174 } 175 } 176 177 inline size_t RegisterLine::ComputeSize(size_t num_regs) { 178 return OFFSETOF_MEMBER(RegisterLine, line_) + num_regs * sizeof(uint16_t); 179 } 180 181 inline RegisterLine* RegisterLine::Create(size_t num_regs, MethodVerifier* verifier) { 182 void* memory = verifier->GetArena().Alloc(ComputeSize(num_regs)); 183 return new (memory) RegisterLine(num_regs, verifier); 184 } 185 186 inline RegisterLine::RegisterLine(size_t num_regs, MethodVerifier* verifier) 187 : num_regs_(num_regs), 188 monitors_(verifier->GetArena().Adapter(kArenaAllocVerifier)), 189 reg_to_lock_depths_(std::less<uint32_t>(), verifier->GetArena().Adapter(kArenaAllocVerifier)), 190 this_initialized_(false) { 191 std::uninitialized_fill_n(line_, num_regs_, 0u); 192 SetResultTypeToUnknown(verifier); 193 } 194 195 inline void RegisterLineArenaDelete::operator()(RegisterLine* ptr) const { 196 if (ptr != nullptr) { 197 ptr->~RegisterLine(); 198 ProtectMemory(ptr, RegisterLine::ComputeSize(ptr->NumRegs())); 199 } 200 } 201 202 } // namespace verifier 203 } // namespace art 204 205 #endif // ART_RUNTIME_VERIFIER_REGISTER_LINE_INL_H_ 206