1 /* 2 * Copyright (C) 2012 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_H_ 18 #define ART_RUNTIME_VERIFIER_REGISTER_LINE_H_ 19 20 #include <limits> 21 #include <memory> 22 #include <vector> 23 24 #include <android-base/logging.h> 25 26 #include "base/locks.h" 27 #include "base/macros.h" 28 #include "base/safe_map.h" 29 #include "base/scoped_arena_containers.h" 30 31 namespace art HIDDEN { 32 33 class Instruction; 34 35 namespace verifier { 36 37 class MethodVerifier; 38 class RegType; 39 class RegTypeCache; 40 41 /* 42 * Register type categories, for type checking. 43 * 44 * The spec says category 1 includes boolean, byte, char, short, int, float, reference, and 45 * returnAddress. Category 2 includes long and double. 46 * 47 * We treat object references separately, so we have "category1nr". We don't support jsr/ret, so 48 * there is no "returnAddress" type. 49 */ 50 enum TypeCategory { 51 kTypeCategoryUnknown = 0, 52 kTypeCategory1nr = 1, // boolean, byte, char, short, int, float 53 kTypeCategory2 = 2, // long, double 54 kTypeCategoryRef = 3, // object reference 55 }; 56 57 // What to do with the lock levels when setting the register type. 58 enum class LockOp { 59 kClear, // Clear the lock levels recorded. 60 kKeep // Leave the lock levels alone. 61 }; 62 63 // During verification, we associate one of these with every "interesting" instruction. We track 64 // the status of all registers, and (if the method has any monitor-enter instructions) maintain a 65 // stack of entered monitors (identified by code unit offset). 66 class RegisterLine { 67 public: 68 using RegisterStackMask = uint32_t; 69 // A map from register to a bit vector of indices into the monitors_ stack. 70 using RegToLockDepthsMap = ScopedArenaSafeMap<uint32_t, RegisterStackMask>; 71 72 // Maximum number of nested monitors to track before giving up and 73 // taking the slow path. 74 static constexpr size_t kMaxMonitorStackDepth = 75 std::numeric_limits<RegisterStackMask>::digits; 76 77 // Create a register line of num_regs registers. 78 static RegisterLine* Create(size_t num_regs, 79 ScopedArenaAllocator& allocator, 80 RegTypeCache* reg_types); 81 82 // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst". 83 void CopyRegister1(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc, TypeCategory cat) 84 REQUIRES_SHARED(Locks::mutator_lock_); 85 86 // Implement category-2 "move" instructions. Copy a 64-bit value from "vsrc" to "vdst". This 87 // copies both halves of the register. 88 void CopyRegister2(MethodVerifier* verifier, uint32_t vdst, uint32_t vsrc) 89 REQUIRES_SHARED(Locks::mutator_lock_); 90 91 // Implement "move-result". Copy the category-1 value from the result register to another 92 // register, and reset the result register. 93 void CopyResultRegister1(MethodVerifier* verifier, uint32_t vdst, bool is_reference) 94 REQUIRES_SHARED(Locks::mutator_lock_); 95 96 // Implement "move-result-wide". Copy the category-2 value from the result register to another 97 // register, and reset the result register. 98 void CopyResultRegister2(MethodVerifier* verifier, uint32_t vdst) 99 REQUIRES_SHARED(Locks::mutator_lock_); 100 101 // Set the invisible result register to unknown 102 void SetResultTypeToUnknown(RegTypeCache* reg_types) REQUIRES_SHARED(Locks::mutator_lock_); 103 104 // Set the type of register N, verifying that the register is valid. If "newType" is the "Lo" 105 // part of a 64-bit value, register N+1 will be set to "newType+1". 106 // The register index was validated during the static pass, so we don't need to check it here. 107 // 108 // LockOp::kClear should be used by default; it will clear the lock levels associated with the 109 // register. An example is setting the register type because an instruction writes to the 110 // register. 111 // LockOp::kKeep keeps the lock levels of the register and only changes the register type. This 112 // is typical when the underlying value did not change, but we have "different" type information 113 // available now. An example is sharpening types after a check-cast. Note that when given kKeep, 114 // the new_type is dchecked to be a reference type. 115 template <LockOp kLockOp> 116 ALWAYS_INLINE void SetRegisterType(uint32_t vdst, const RegType& new_type) 117 REQUIRES_SHARED(Locks::mutator_lock_); 118 119 void SetRegisterTypeWide(uint32_t vdst, 120 const RegType& new_type1, 121 const RegType& new_type2) 122 REQUIRES_SHARED(Locks::mutator_lock_); 123 124 /* Set the type of the "result" register. */ 125 void SetResultRegisterType(MethodVerifier* verifier, const RegType& new_type) 126 REQUIRES_SHARED(Locks::mutator_lock_); 127 128 void SetResultRegisterTypeWide(const RegType& new_type1, const RegType& new_type2) 129 REQUIRES_SHARED(Locks::mutator_lock_); 130 131 // Get the type of register vsrc. 132 const RegType& GetRegisterType(MethodVerifier* verifier, uint32_t vsrc) const; 133 134 ALWAYS_INLINE bool VerifyRegisterType(MethodVerifier* verifier, 135 uint32_t vsrc, 136 const RegType& check_type) 137 REQUIRES_SHARED(Locks::mutator_lock_); 138 139 bool VerifyRegisterTypeWide(MethodVerifier* verifier, 140 uint32_t vsrc, 141 const RegType& check_type1, 142 const RegType& check_type2) 143 REQUIRES_SHARED(Locks::mutator_lock_); 144 CopyFromLine(const RegisterLine * src)145 void CopyFromLine(const RegisterLine* src) { 146 DCHECK_EQ(num_regs_, src->num_regs_); 147 memcpy(&line_, &src->line_, num_regs_ * sizeof(uint16_t)); 148 monitors_ = src->monitors_; 149 reg_to_lock_depths_ = src->reg_to_lock_depths_; 150 this_initialized_ = src->this_initialized_; 151 } 152 153 std::string Dump(MethodVerifier* verifier) const REQUIRES_SHARED(Locks::mutator_lock_); 154 FillWithGarbage()155 void FillWithGarbage() { 156 memset(&line_, 0xf1, num_regs_ * sizeof(uint16_t)); 157 monitors_.clear(); 158 reg_to_lock_depths_.clear(); 159 } 160 161 /* 162 * We're creating a new instance of class C at address A. Any registers holding instances 163 * previously created at address A must be initialized by now. If not, we mark them as "conflict" 164 * to prevent them from being used (otherwise, MarkRefsAsInitialized would mark the old ones and 165 * the new ones at the same time). 166 */ 167 void MarkUninitRefsAsInvalid(MethodVerifier* verifier, const RegType& uninit_type) 168 REQUIRES_SHARED(Locks::mutator_lock_); 169 170 /* 171 * Update all registers holding "uninit_type" to instead hold the corresponding initialized 172 * reference type. This is called when an appropriate constructor is invoked -- all copies of 173 * the reference must be marked as initialized. 174 */ 175 void MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type) 176 REQUIRES_SHARED(Locks::mutator_lock_); 177 178 /* 179 * Update all registers to be Conflict except vsrc. 180 */ 181 void MarkAllRegistersAsConflicts(MethodVerifier* verifier); 182 void MarkAllRegistersAsConflictsExcept(MethodVerifier* verifier, uint32_t vsrc); 183 void MarkAllRegistersAsConflictsExceptWide(MethodVerifier* verifier, uint32_t vsrc); 184 SetThisInitialized()185 void SetThisInitialized() { 186 this_initialized_ = true; 187 } 188 CopyThisInitialized(const RegisterLine & src)189 void CopyThisInitialized(const RegisterLine& src) { 190 this_initialized_ = src.this_initialized_; 191 } 192 193 /* 194 * Check constraints on constructor return. Specifically, make sure that the "this" argument got 195 * initialized. 196 * The "this" argument to <init> uses code offset kUninitThisArgAddr, which puts it at the start 197 * of the list in slot 0. If we see a register with an uninitialized slot 0 reference, we know it 198 * somehow didn't get initialized. 199 */ 200 bool CheckConstructorReturn(MethodVerifier* verifier) const; 201 202 // Compare two register lines. Returns 0 if they match. 203 // Using this for a sort is unwise, since the value can change based on machine endianness. CompareLine(const RegisterLine * line2)204 int CompareLine(const RegisterLine* line2) const { 205 if (monitors_ != line2->monitors_) { 206 return 1; 207 } 208 // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_); 209 return memcmp(&line_, &line2->line_, num_regs_ * sizeof(uint16_t)); 210 } 211 NumRegs()212 size_t NumRegs() const { 213 return num_regs_; 214 } 215 216 // Return how many bytes of memory a register line uses. 217 ALWAYS_INLINE static size_t ComputeSize(size_t num_regs); 218 219 /* 220 * Get the "this" pointer from a non-static method invocation. This returns the RegType so the 221 * caller can decide whether it needs the reference to be initialized or not. (Can also return 222 * kRegTypeZero if the reference can only be zero at this point.) 223 * 224 * The argument count is in vA, and the first argument is in vC, for both "simple" and "range" 225 * versions. We just need to make sure vA is >= 1 and then return vC. 226 * allow_failure will return Conflict() instead of causing a verification failure if there is an 227 * error. 228 */ 229 const RegType& GetInvocationThis(MethodVerifier* verifier, 230 const Instruction* inst, 231 bool allow_failure = false) 232 REQUIRES_SHARED(Locks::mutator_lock_); 233 234 /* 235 * Verify types for a simple two-register instruction (e.g. "neg-int"). 236 * "dst_type" is stored into vA, and "src_type" is verified against vB. 237 */ 238 void CheckUnaryOp(MethodVerifier* verifier, 239 const Instruction* inst, 240 const RegType& dst_type, 241 const RegType& src_type) 242 REQUIRES_SHARED(Locks::mutator_lock_); 243 244 void CheckUnaryOpWide(MethodVerifier* verifier, 245 const Instruction* inst, 246 const RegType& dst_type1, 247 const RegType& dst_type2, 248 const RegType& src_type1, 249 const RegType& src_type2) 250 REQUIRES_SHARED(Locks::mutator_lock_); 251 252 void CheckUnaryOpToWide(MethodVerifier* verifier, 253 const Instruction* inst, 254 const RegType& dst_type1, 255 const RegType& dst_type2, 256 const RegType& src_type) 257 REQUIRES_SHARED(Locks::mutator_lock_); 258 259 void CheckUnaryOpFromWide(MethodVerifier* verifier, 260 const Instruction* inst, 261 const RegType& dst_type, 262 const RegType& src_type1, 263 const RegType& src_type2) 264 REQUIRES_SHARED(Locks::mutator_lock_); 265 266 /* 267 * Verify types for a simple three-register instruction (e.g. "add-int"). 268 * "dst_type" is stored into vA, and "src_type1"/"src_type2" are verified 269 * against vB/vC. 270 */ 271 void CheckBinaryOp(MethodVerifier* verifier, 272 const Instruction* inst, 273 const RegType& dst_type, 274 const RegType& src_type1, 275 const RegType& src_type2, 276 bool check_boolean_op) 277 REQUIRES_SHARED(Locks::mutator_lock_); 278 279 void CheckBinaryOpWide(MethodVerifier* verifier, 280 const Instruction* inst, 281 const RegType& dst_type1, 282 const RegType& dst_type2, 283 const RegType& src_type1_1, 284 const RegType& src_type1_2, 285 const RegType& src_type2_1, 286 const RegType& src_type2_2) 287 REQUIRES_SHARED(Locks::mutator_lock_); 288 289 void CheckBinaryOpWideShift(MethodVerifier* verifier, 290 const Instruction* inst, 291 const RegType& long_lo_type, 292 const RegType& long_hi_type, 293 const RegType& int_type) 294 REQUIRES_SHARED(Locks::mutator_lock_); 295 296 /* 297 * Verify types for a binary "2addr" operation. "src_type1"/"src_type2" 298 * are verified against vA/vB, then "dst_type" is stored into vA. 299 */ 300 void CheckBinaryOp2addr(MethodVerifier* verifier, 301 const Instruction* inst, 302 const RegType& dst_type, 303 const RegType& src_type1, 304 const RegType& src_type2, 305 bool check_boolean_op) 306 REQUIRES_SHARED(Locks::mutator_lock_); 307 308 void CheckBinaryOp2addrWide(MethodVerifier* verifier, 309 const Instruction* inst, 310 const RegType& dst_type1, 311 const RegType& dst_type2, 312 const RegType& src_type1_1, 313 const RegType& src_type1_2, 314 const RegType& src_type2_1, 315 const RegType& src_type2_2) 316 REQUIRES_SHARED(Locks::mutator_lock_); 317 318 void CheckBinaryOp2addrWideShift(MethodVerifier* verifier, 319 const Instruction* inst, 320 const RegType& long_lo_type, 321 const RegType& long_hi_type, 322 const RegType& int_type) 323 REQUIRES_SHARED(Locks::mutator_lock_); 324 325 /* 326 * Verify types for A two-register instruction with a literal constant (e.g. "add-int/lit8"). 327 * "dst_type" is stored into vA, and "src_type" is verified against vB. 328 * 329 * If "check_boolean_op" is set, we use the constant value in vC. 330 */ 331 void CheckLiteralOp(MethodVerifier* verifier, 332 const Instruction* inst, 333 const RegType& dst_type, 334 const RegType& src_type, 335 bool check_boolean_op, 336 bool is_lit16) 337 REQUIRES_SHARED(Locks::mutator_lock_); 338 339 // Verify/push monitor onto the monitor stack, locking the value in reg_idx at location insn_idx. 340 void PushMonitor(MethodVerifier* verifier, uint32_t reg_idx, int32_t insn_idx) 341 REQUIRES_SHARED(Locks::mutator_lock_); 342 343 // Verify/pop monitor from monitor stack ensuring that we believe the monitor is locked 344 void PopMonitor(MethodVerifier* verifier, uint32_t reg_idx) 345 REQUIRES_SHARED(Locks::mutator_lock_); 346 347 // Stack of currently held monitors and where they were locked MonitorStackDepth()348 size_t MonitorStackDepth() const { 349 return monitors_.size(); 350 } 351 352 // We expect no monitors to be held at certain points, such a method returns. Verify the stack 353 // is empty, queueing a LOCKING error else. 354 void VerifyMonitorStackEmpty(MethodVerifier* verifier) const; 355 356 bool MergeRegisters(MethodVerifier* verifier, const RegisterLine* incoming_line) 357 REQUIRES_SHARED(Locks::mutator_lock_); 358 GetMonitorEnterCount()359 size_t GetMonitorEnterCount() const { 360 return monitors_.size(); 361 } 362 GetMonitorEnterDexPc(size_t i)363 uint32_t GetMonitorEnterDexPc(size_t i) const { 364 return monitors_[i]; 365 } 366 367 // We give access to the lock depth map to avoid an expensive poll loop for FindLocksAtDexPC. 368 template <typename T> IterateRegToLockDepths(T fn)369 void IterateRegToLockDepths(T fn) const { 370 for (const auto& pair : reg_to_lock_depths_) { 371 const uint32_t reg = pair.first; 372 uint32_t depths = pair.second; 373 uint32_t depth = 0; 374 while (depths != 0) { 375 if ((depths & 1) != 0) { 376 fn(reg, depth); 377 } 378 depths >>= 1; 379 depth++; 380 } 381 } 382 } 383 384 private: CopyRegToLockDepth(size_t dst,size_t src)385 void CopyRegToLockDepth(size_t dst, size_t src) { 386 auto it = reg_to_lock_depths_.find(src); 387 if (it != reg_to_lock_depths_.end()) { 388 reg_to_lock_depths_.Put(dst, it->second); 389 } 390 } 391 IsSetLockDepth(size_t reg,size_t depth)392 bool IsSetLockDepth(size_t reg, size_t depth) { 393 auto it = reg_to_lock_depths_.find(reg); 394 if (it != reg_to_lock_depths_.end()) { 395 return (it->second & (1 << depth)) != 0; 396 } else { 397 return false; 398 } 399 } 400 SetRegToLockDepth(size_t reg,size_t depth)401 bool SetRegToLockDepth(size_t reg, size_t depth) { 402 CHECK_LT(depth, kMaxMonitorStackDepth); 403 if (IsSetLockDepth(reg, depth)) { 404 return false; // Register already holds lock so locking twice is erroneous. 405 } 406 auto it = reg_to_lock_depths_.find(reg); 407 if (it == reg_to_lock_depths_.end()) { 408 reg_to_lock_depths_.Put(reg, 1 << depth); 409 } else { 410 it->second |= (1 << depth); 411 } 412 return true; 413 } 414 415 void ClearRegToLockDepth(size_t reg, size_t depth); 416 ClearAllRegToLockDepths(size_t reg)417 void ClearAllRegToLockDepths(size_t reg) { 418 reg_to_lock_depths_.erase(reg); 419 } 420 421 RegisterLine(size_t num_regs, ScopedArenaAllocator& allocator, RegTypeCache* reg_types); 422 423 // Storage for the result register's type, valid after an invocation. 424 uint16_t result_[2]; 425 426 // Length of reg_types_ 427 const uint32_t num_regs_; 428 429 // A stack of monitor enter locations. 430 ScopedArenaVector<uint32_t> monitors_; 431 432 // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor 433 // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a 434 // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5. 435 RegToLockDepthsMap reg_to_lock_depths_; 436 437 // Whether "this" initialization (a constructor supercall) has happened. 438 bool this_initialized_; 439 440 // An array of RegType Ids associated with each dex register. 441 uint16_t line_[1]; 442 443 DISALLOW_COPY_AND_ASSIGN(RegisterLine); 444 }; 445 446 class RegisterLineArenaDelete : public ArenaDelete<RegisterLine> { 447 public: 448 void operator()(RegisterLine* ptr) const; 449 }; 450 451 } // namespace verifier 452 } // namespace art 453 454 #endif // ART_RUNTIME_VERIFIER_REGISTER_LINE_H_ 455