1 /* 2 * Copyright (C) 2018 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 #include "flow_analysis.h" 18 19 #include "dex/bytecode_utils.h" 20 #include "dex/code_item_accessors-inl.h" 21 #include "dex/dex_instruction-inl.h" 22 #include "dex/dex_file-inl.h" 23 #include "dex/dex_file_exception_helpers.h" 24 #include "resolver.h" 25 #include "veridex.h" 26 27 namespace art { 28 29 30 void VeriFlowAnalysis::SetAsBranchTarget(uint32_t dex_pc) { 31 if (dex_registers_[dex_pc] == nullptr) { 32 dex_registers_[dex_pc].reset( 33 new std::vector<RegisterValue>(code_item_accessor_.RegistersSize())); 34 } 35 } 36 37 bool VeriFlowAnalysis::IsBranchTarget(uint32_t dex_pc) { 38 return dex_registers_[dex_pc] != nullptr; 39 } 40 41 bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) { 42 // TODO: Do the merging. Right now, just return that we should continue 43 // the iteration if the instruction has not been visited. 44 if (!instruction_infos_[dex_pc].has_been_visited) { 45 dex_registers_[dex_pc]->assign(current_registers_.begin(), current_registers_.end()); 46 return true; 47 } 48 return false; 49 } 50 51 void VeriFlowAnalysis::SetVisited(uint32_t dex_pc) { 52 instruction_infos_[dex_pc].has_been_visited = true; 53 } 54 55 void VeriFlowAnalysis::FindBranches() { 56 SetAsBranchTarget(0); 57 58 if (code_item_accessor_.TriesSize() != 0) { 59 // TODO: We need to mark the range of dex pcs as flowing in the handlers. 60 /* 61 for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) { 62 uint32_t dex_pc_start = try_item.start_addr_; 63 uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_; 64 } 65 */ 66 67 // Create branch targets for exception handlers. 68 const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData(); 69 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr); 70 for (uint32_t idx = 0; idx < handlers_size; ++idx) { 71 CatchHandlerIterator iterator(handlers_ptr); 72 for (; iterator.HasNext(); iterator.Next()) { 73 SetAsBranchTarget(iterator.GetHandlerAddress()); 74 } 75 handlers_ptr = iterator.EndDataPointer(); 76 } 77 } 78 79 // Iterate over all instructions and find branching instructions. 80 for (const DexInstructionPcPair& pair : code_item_accessor_) { 81 const uint32_t dex_pc = pair.DexPc(); 82 const Instruction& instruction = pair.Inst(); 83 84 if (instruction.IsBranch()) { 85 SetAsBranchTarget(dex_pc + instruction.GetTargetOffset()); 86 } else if (instruction.IsSwitch()) { 87 DexSwitchTable table(instruction, dex_pc); 88 for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) { 89 SetAsBranchTarget(dex_pc + s_it.CurrentTargetOffset()); 90 if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) { 91 SetAsBranchTarget(s_it.GetDexPcForCurrentIndex()); 92 } 93 } 94 } 95 } 96 } 97 98 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, 99 RegisterSource kind, 100 VeriClass* cls, 101 uint32_t source_id) { 102 current_registers_[dex_register] = RegisterValue( 103 kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls); 104 } 105 106 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) { 107 current_registers_[dex_register] = value; 108 } 109 110 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) { 111 current_registers_[dex_register] = 112 RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls); 113 } 114 115 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls) { 116 current_registers_[dex_register] = 117 RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls); 118 } 119 120 const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) const { 121 return current_registers_[dex_register]; 122 } 123 124 RegisterValue VeriFlowAnalysis::GetReturnType(uint32_t method_index) { 125 const DexFile& dex_file = resolver_->GetDexFile(); 126 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_index); 127 const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id); 128 VeriClass* cls = resolver_->GetVeriClass(proto_id.return_type_idx_); 129 return RegisterValue(RegisterSource::kMethod, DexFileReference(&dex_file, method_index), cls); 130 } 131 132 RegisterValue VeriFlowAnalysis::GetFieldType(uint32_t field_index) { 133 const DexFile& dex_file = resolver_->GetDexFile(); 134 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index); 135 VeriClass* cls = resolver_->GetVeriClass(field_id.type_idx_); 136 return RegisterValue(RegisterSource::kField, DexFileReference(&dex_file, field_index), cls); 137 } 138 139 int VeriFlowAnalysis::GetBranchFlags(const Instruction& instruction) const { 140 switch (instruction.Opcode()) { 141 #define IF_XX(cond, op) \ 142 case Instruction::IF_##cond: { \ 143 RegisterValue lhs = GetRegister(instruction.VRegA()); \ 144 RegisterValue rhs = GetRegister(instruction.VRegB()); \ 145 if (lhs.IsConstant() && rhs.IsConstant()) { \ 146 if (lhs.GetConstant() op rhs.GetConstant()) { \ 147 return Instruction::kBranch; \ 148 } else { \ 149 return Instruction::kContinue; \ 150 } \ 151 } \ 152 break; \ 153 } \ 154 case Instruction::IF_##cond##Z: { \ 155 RegisterValue val = GetRegister(instruction.VRegA()); \ 156 if (val.IsConstant()) { \ 157 if (val.GetConstant() op 0) { \ 158 return Instruction::kBranch; \ 159 } else { \ 160 return Instruction::kContinue; \ 161 } \ 162 } \ 163 break; \ 164 } 165 166 IF_XX(EQ, ==); 167 IF_XX(NE, !=); 168 IF_XX(LT, <); 169 IF_XX(LE, <=); 170 IF_XX(GT, >); 171 IF_XX(GE, >=); 172 173 #undef IF_XX 174 175 default: 176 break; 177 } 178 179 return Instruction::FlagsOf(instruction.Opcode()); 180 } 181 182 void VeriFlowAnalysis::AnalyzeCode() { 183 std::vector<uint32_t> work_list; 184 work_list.push_back(0); 185 // Iterate over the code. 186 // When visiting unconditional branches (goto), move to that instruction. 187 // When visiting conditional branches, move to one destination, and put the other 188 // in the worklist. 189 while (!work_list.empty()) { 190 uint32_t dex_pc = work_list.back(); 191 work_list.pop_back(); 192 CHECK(IsBranchTarget(dex_pc)); 193 current_registers_ = *dex_registers_[dex_pc].get(); 194 while (true) { 195 const uint16_t* insns = code_item_accessor_.Insns() + dex_pc; 196 const Instruction& inst = *Instruction::At(insns); 197 ProcessDexInstruction(inst); 198 SetVisited(dex_pc); 199 200 int branch_flags = GetBranchFlags(inst); 201 202 if ((branch_flags & Instruction::kContinue) != 0) { 203 if ((branch_flags & Instruction::kBranch) != 0) { 204 uint32_t branch_dex_pc = dex_pc + inst.GetTargetOffset(); 205 if (MergeRegisterValues(branch_dex_pc)) { 206 work_list.push_back(branch_dex_pc); 207 } 208 } 209 dex_pc += inst.SizeInCodeUnits(); 210 } else if ((branch_flags & Instruction::kBranch) != 0) { 211 dex_pc += inst.GetTargetOffset(); 212 DCHECK(IsBranchTarget(dex_pc)); 213 } else { 214 break; 215 } 216 217 if (IsBranchTarget(dex_pc)) { 218 if (MergeRegisterValues(dex_pc)) { 219 current_registers_ = *dex_registers_[dex_pc].get(); 220 } else { 221 break; 222 } 223 } 224 } 225 } 226 } 227 228 void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) { 229 switch (instruction.Opcode()) { 230 case Instruction::CONST_4: { 231 int32_t register_index = instruction.VRegA(); 232 int32_t value = instruction.VRegB_11n(); 233 UpdateRegister(register_index, value, VeriClass::integer_); 234 break; 235 } 236 case Instruction::CONST_16: { 237 int32_t register_index = instruction.VRegA(); 238 int32_t value = instruction.VRegB_21s(); 239 UpdateRegister(register_index, value, VeriClass::integer_); 240 break; 241 } 242 243 case Instruction::CONST: { 244 int32_t register_index = instruction.VRegA(); 245 int32_t value = instruction.VRegB_31i(); 246 UpdateRegister(register_index, value, VeriClass::integer_); 247 break; 248 } 249 250 case Instruction::CONST_HIGH16: { 251 int32_t register_index = instruction.VRegA(); 252 int32_t value = instruction.VRegB_21h(); 253 UpdateRegister(register_index, value, VeriClass::integer_); 254 break; 255 } 256 257 case Instruction::CONST_WIDE_16: 258 case Instruction::CONST_WIDE_32: 259 case Instruction::CONST_WIDE: 260 case Instruction::CONST_WIDE_HIGH16: { 261 int32_t register_index = instruction.VRegA(); 262 UpdateRegister(register_index, VeriClass::long_); 263 break; 264 } 265 266 case Instruction::MOVE: 267 case Instruction::MOVE_FROM16: 268 case Instruction::MOVE_16: { 269 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB())); 270 break; 271 } 272 273 case Instruction::MOVE_WIDE: 274 case Instruction::MOVE_WIDE_FROM16: 275 case Instruction::MOVE_WIDE_16: { 276 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB())); 277 break; 278 } 279 280 case Instruction::MOVE_OBJECT: 281 case Instruction::MOVE_OBJECT_16: 282 case Instruction::MOVE_OBJECT_FROM16: { 283 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB())); 284 break; 285 } 286 case Instruction::CONST_CLASS: { 287 UpdateRegister(instruction.VRegA_21c(), 288 RegisterSource::kClass, 289 VeriClass::class_, 290 instruction.VRegB_21c()); 291 break; 292 } 293 case Instruction::CONST_STRING: { 294 UpdateRegister(instruction.VRegA_21c(), 295 RegisterSource::kString, 296 VeriClass::string_, 297 instruction.VRegB_21c()); 298 break; 299 } 300 301 case Instruction::CONST_STRING_JUMBO: { 302 UpdateRegister(instruction.VRegA_31c(), 303 RegisterSource::kString, 304 VeriClass::string_, 305 instruction.VRegB_31c()); 306 break; 307 } 308 case Instruction::INVOKE_DIRECT: 309 case Instruction::INVOKE_INTERFACE: 310 case Instruction::INVOKE_STATIC: 311 case Instruction::INVOKE_SUPER: 312 case Instruction::INVOKE_VIRTUAL: { 313 last_result_ = AnalyzeInvoke(instruction, /* is_range */ false); 314 break; 315 } 316 317 case Instruction::INVOKE_DIRECT_RANGE: 318 case Instruction::INVOKE_INTERFACE_RANGE: 319 case Instruction::INVOKE_STATIC_RANGE: 320 case Instruction::INVOKE_SUPER_RANGE: 321 case Instruction::INVOKE_VIRTUAL_RANGE: { 322 last_result_ = AnalyzeInvoke(instruction, /* is_range */ true); 323 break; 324 } 325 326 case Instruction::MOVE_RESULT: 327 case Instruction::MOVE_RESULT_WIDE: 328 case Instruction::MOVE_RESULT_OBJECT: { 329 UpdateRegister(instruction.VRegA(), last_result_); 330 break; 331 } 332 case Instruction::RETURN_VOID: 333 case Instruction::RETURN_OBJECT: 334 case Instruction::RETURN_WIDE: 335 case Instruction::RETURN: { 336 break; 337 } 338 339 // If operations will be handled when looking at the control flow. 340 #define IF_XX(cond) \ 341 case Instruction::IF_##cond: break; \ 342 case Instruction::IF_##cond##Z: break 343 344 IF_XX(EQ); 345 IF_XX(NE); 346 IF_XX(LT); 347 IF_XX(LE); 348 IF_XX(GT); 349 IF_XX(GE); 350 351 #undef IF_XX 352 353 case Instruction::GOTO: 354 case Instruction::GOTO_16: 355 case Instruction::GOTO_32: { 356 break; 357 } 358 case Instruction::INVOKE_POLYMORPHIC: { 359 // TODO 360 break; 361 } 362 363 case Instruction::INVOKE_POLYMORPHIC_RANGE: { 364 // TODO 365 break; 366 } 367 368 case Instruction::NEG_INT: 369 case Instruction::NEG_LONG: 370 case Instruction::NEG_FLOAT: 371 case Instruction::NEG_DOUBLE: 372 case Instruction::NOT_INT: 373 case Instruction::NOT_LONG: { 374 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 375 break; 376 } 377 378 case Instruction::INT_TO_LONG: 379 case Instruction::INT_TO_FLOAT: 380 case Instruction::INT_TO_DOUBLE: 381 case Instruction::LONG_TO_INT: 382 case Instruction::LONG_TO_FLOAT: 383 case Instruction::LONG_TO_DOUBLE: 384 case Instruction::FLOAT_TO_INT: 385 case Instruction::FLOAT_TO_LONG: 386 case Instruction::FLOAT_TO_DOUBLE: 387 case Instruction::DOUBLE_TO_INT: 388 case Instruction::DOUBLE_TO_LONG: 389 case Instruction::DOUBLE_TO_FLOAT: 390 case Instruction::INT_TO_BYTE: 391 case Instruction::INT_TO_SHORT: 392 case Instruction::INT_TO_CHAR: { 393 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 394 break; 395 } 396 397 case Instruction::ADD_INT: 398 case Instruction::ADD_LONG: 399 case Instruction::ADD_DOUBLE: 400 case Instruction::ADD_FLOAT: 401 case Instruction::SUB_INT: 402 case Instruction::SUB_LONG: 403 case Instruction::SUB_FLOAT: 404 case Instruction::SUB_DOUBLE: 405 case Instruction::MUL_INT: 406 case Instruction::MUL_LONG: 407 case Instruction::MUL_FLOAT: 408 case Instruction::MUL_DOUBLE: 409 case Instruction::DIV_INT: 410 case Instruction::DIV_LONG: 411 case Instruction::DIV_FLOAT: 412 case Instruction::DIV_DOUBLE: 413 case Instruction::REM_INT: 414 case Instruction::REM_LONG: 415 case Instruction::REM_FLOAT: 416 case Instruction::REM_DOUBLE: 417 case Instruction::AND_INT: 418 case Instruction::AND_LONG: 419 case Instruction::SHL_INT: 420 case Instruction::SHL_LONG: 421 case Instruction::SHR_INT: 422 case Instruction::SHR_LONG: 423 case Instruction::USHR_INT: 424 case Instruction::USHR_LONG: 425 case Instruction::OR_INT: 426 case Instruction::OR_LONG: 427 case Instruction::XOR_INT: 428 case Instruction::XOR_LONG: { 429 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 430 break; 431 } 432 433 case Instruction::ADD_INT_2ADDR: 434 case Instruction::ADD_LONG_2ADDR: 435 case Instruction::ADD_DOUBLE_2ADDR: 436 case Instruction::ADD_FLOAT_2ADDR: 437 case Instruction::SUB_INT_2ADDR: 438 case Instruction::SUB_LONG_2ADDR: 439 case Instruction::SUB_FLOAT_2ADDR: 440 case Instruction::SUB_DOUBLE_2ADDR: 441 case Instruction::MUL_INT_2ADDR: 442 case Instruction::MUL_LONG_2ADDR: 443 case Instruction::MUL_FLOAT_2ADDR: 444 case Instruction::MUL_DOUBLE_2ADDR: 445 case Instruction::DIV_INT_2ADDR: 446 case Instruction::DIV_LONG_2ADDR: 447 case Instruction::REM_INT_2ADDR: 448 case Instruction::REM_LONG_2ADDR: 449 case Instruction::REM_FLOAT_2ADDR: 450 case Instruction::REM_DOUBLE_2ADDR: 451 case Instruction::SHL_INT_2ADDR: 452 case Instruction::SHL_LONG_2ADDR: 453 case Instruction::SHR_INT_2ADDR: 454 case Instruction::SHR_LONG_2ADDR: 455 case Instruction::USHR_INT_2ADDR: 456 case Instruction::USHR_LONG_2ADDR: 457 case Instruction::DIV_FLOAT_2ADDR: 458 case Instruction::DIV_DOUBLE_2ADDR: 459 case Instruction::AND_INT_2ADDR: 460 case Instruction::AND_LONG_2ADDR: 461 case Instruction::OR_INT_2ADDR: 462 case Instruction::OR_LONG_2ADDR: 463 case Instruction::XOR_INT_2ADDR: 464 case Instruction::XOR_LONG_2ADDR: { 465 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 466 break; 467 } 468 469 case Instruction::ADD_INT_LIT16: 470 case Instruction::AND_INT_LIT16: 471 case Instruction::OR_INT_LIT16: 472 case Instruction::XOR_INT_LIT16: 473 case Instruction::RSUB_INT: 474 case Instruction::MUL_INT_LIT16: 475 case Instruction::DIV_INT_LIT16: 476 case Instruction::REM_INT_LIT16: { 477 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 478 break; 479 } 480 481 case Instruction::ADD_INT_LIT8: 482 case Instruction::AND_INT_LIT8: 483 case Instruction::OR_INT_LIT8: 484 case Instruction::XOR_INT_LIT8: 485 case Instruction::RSUB_INT_LIT8: 486 case Instruction::MUL_INT_LIT8: 487 case Instruction::DIV_INT_LIT8: 488 case Instruction::REM_INT_LIT8: 489 case Instruction::SHL_INT_LIT8: 490 case Instruction::SHR_INT_LIT8: { 491 case Instruction::USHR_INT_LIT8: { 492 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 493 break; 494 } 495 496 case Instruction::NEW_INSTANCE: { 497 VeriClass* cls = resolver_->GetVeriClass(dex::TypeIndex(instruction.VRegB_21c())); 498 UpdateRegister(instruction.VRegA(), cls); 499 break; 500 } 501 502 case Instruction::NEW_ARRAY: { 503 dex::TypeIndex type_index(instruction.VRegC_22c()); 504 VeriClass* cls = resolver_->GetVeriClass(type_index); 505 UpdateRegister(instruction.VRegA_22c(), cls); 506 break; 507 } 508 509 case Instruction::FILLED_NEW_ARRAY: { 510 dex::TypeIndex type_index(instruction.VRegB_35c()); 511 VeriClass* cls = resolver_->GetVeriClass(type_index); 512 UpdateRegister(instruction.VRegA_22c(), cls); 513 break; 514 } 515 516 case Instruction::FILLED_NEW_ARRAY_RANGE: { 517 dex::TypeIndex type_index(instruction.VRegB_3rc()); 518 uint32_t register_index = instruction.VRegC_3rc(); 519 VeriClass* cls = resolver_->GetVeriClass(type_index); 520 UpdateRegister(register_index, cls); 521 break; 522 } 523 524 case Instruction::FILL_ARRAY_DATA: { 525 break; 526 } 527 528 case Instruction::CMP_LONG: 529 case Instruction::CMPG_FLOAT: 530 case Instruction::CMPG_DOUBLE: 531 case Instruction::CMPL_FLOAT: 532 case Instruction::CMPL_DOUBLE: 533 UpdateRegister(instruction.VRegA(), VeriClass::integer_); 534 break; 535 } 536 537 case Instruction::NOP: 538 break; 539 540 case Instruction::IGET: 541 case Instruction::IGET_WIDE: 542 case Instruction::IGET_OBJECT: 543 case Instruction::IGET_BOOLEAN: 544 case Instruction::IGET_BYTE: 545 case Instruction::IGET_CHAR: 546 case Instruction::IGET_SHORT: { 547 UpdateRegister(instruction.VRegA_22c(), GetFieldType(instruction.VRegC_22c())); 548 break; 549 } 550 551 case Instruction::IPUT: 552 case Instruction::IPUT_WIDE: 553 case Instruction::IPUT_OBJECT: 554 case Instruction::IPUT_BOOLEAN: 555 case Instruction::IPUT_BYTE: 556 case Instruction::IPUT_CHAR: 557 case Instruction::IPUT_SHORT: { 558 AnalyzeFieldSet(instruction); 559 break; 560 } 561 562 case Instruction::SGET: 563 case Instruction::SGET_WIDE: 564 case Instruction::SGET_OBJECT: 565 case Instruction::SGET_BOOLEAN: 566 case Instruction::SGET_BYTE: 567 case Instruction::SGET_CHAR: 568 case Instruction::SGET_SHORT: { 569 uint32_t dest_reg = instruction.VRegA_21c(); 570 uint16_t field_index = instruction.VRegB_21c(); 571 if (VeriClass::sdkInt_ != nullptr && resolver_->GetField(field_index) == VeriClass::sdkInt_) { 572 UpdateRegister(dest_reg, gTargetSdkVersion, VeriClass::integer_); 573 } else { 574 UpdateRegister(dest_reg, GetFieldType(instruction.VRegC_22c())); 575 } 576 break; 577 } 578 579 case Instruction::SPUT: 580 case Instruction::SPUT_WIDE: 581 case Instruction::SPUT_OBJECT: 582 case Instruction::SPUT_BOOLEAN: 583 case Instruction::SPUT_BYTE: 584 case Instruction::SPUT_CHAR: 585 case Instruction::SPUT_SHORT: { 586 AnalyzeFieldSet(instruction); 587 break; 588 } 589 590 #define ARRAY_XX(kind, anticipated_type) \ 591 case Instruction::AGET##kind: { \ 592 UpdateRegister(instruction.VRegA_23x(), anticipated_type); \ 593 break; \ 594 } \ 595 case Instruction::APUT##kind: { \ 596 break; \ 597 } 598 599 ARRAY_XX(, VeriClass::integer_); 600 ARRAY_XX(_WIDE, VeriClass::long_); 601 ARRAY_XX(_BOOLEAN, VeriClass::boolean_); 602 ARRAY_XX(_BYTE, VeriClass::byte_); 603 ARRAY_XX(_CHAR, VeriClass::char_); 604 ARRAY_XX(_SHORT, VeriClass::short_); 605 606 case Instruction::AGET_OBJECT: { 607 // TODO: take the component type. 608 UpdateRegister(instruction.VRegA_23x(), VeriClass::object_); 609 break; 610 } 611 612 case Instruction::APUT_OBJECT: { 613 break; 614 } 615 616 case Instruction::ARRAY_LENGTH: { 617 UpdateRegister(instruction.VRegA_12x(), VeriClass::integer_); 618 break; 619 } 620 621 case Instruction::MOVE_EXCEPTION: { 622 UpdateRegister(instruction.VRegA_11x(), VeriClass::throwable_); 623 break; 624 } 625 626 case Instruction::THROW: { 627 break; 628 } 629 630 case Instruction::INSTANCE_OF: { 631 uint8_t destination = instruction.VRegA_22c(); 632 UpdateRegister(destination, VeriClass::boolean_); 633 break; 634 } 635 636 case Instruction::CHECK_CAST: { 637 uint8_t reference = instruction.VRegA_21c(); 638 dex::TypeIndex type_index(instruction.VRegB_21c()); 639 UpdateRegister(reference, resolver_->GetVeriClass(type_index)); 640 break; 641 } 642 643 case Instruction::MONITOR_ENTER: 644 case Instruction::MONITOR_EXIT: { 645 break; 646 } 647 648 case Instruction::SPARSE_SWITCH: 649 case Instruction::PACKED_SWITCH: 650 break; 651 652 default: 653 break; 654 } 655 } 656 657 void VeriFlowAnalysis::Run() { 658 FindBranches(); 659 uint32_t number_of_registers = code_item_accessor_.RegistersSize(); 660 uint32_t number_of_parameters = code_item_accessor_.InsSize(); 661 std::vector<RegisterValue>& initial_values = *dex_registers_[0].get(); 662 for (uint32_t i = 0; i < number_of_parameters; ++i) { 663 initial_values[number_of_registers - number_of_parameters + i] = RegisterValue( 664 RegisterSource::kParameter, 665 i, 666 DexFileReference(&resolver_->GetDexFile(), method_id_), 667 nullptr); 668 } 669 AnalyzeCode(); 670 } 671 672 static uint32_t GetParameterAt(const Instruction& instruction, 673 bool is_range, 674 uint32_t* args, 675 uint32_t index) { 676 return is_range ? instruction.VRegC() + index : args[index]; 677 } 678 679 RegisterValue FlowAnalysisCollector::AnalyzeInvoke(const Instruction& instruction, bool is_range) { 680 uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c(); 681 VeriMethod method = resolver_->GetMethod(id); 682 uint32_t args[5]; 683 if (!is_range) { 684 instruction.GetVarArgs(args); 685 } 686 687 if (method == VeriClass::forName_) { 688 // Class.forName. Fetch the first parameter. 689 RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 0)); 690 return RegisterValue( 691 value.GetSource(), value.GetDexFileReference(), VeriClass::class_); 692 } else if (IsGetField(method)) { 693 // Class.getField or Class.getDeclaredField. Fetch the first parameter for the class, and the 694 // second parameter for the field name. 695 RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0)); 696 RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1)); 697 uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ false)); 698 return GetReturnType(id); 699 } else if (IsGetMethod(method)) { 700 // Class.getMethod or Class.getDeclaredMethod. Fetch the first parameter for the class, and the 701 // second parameter for the field name. 702 RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0)); 703 RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1)); 704 uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ true)); 705 return GetReturnType(id); 706 } else if (method == VeriClass::getClass_) { 707 // Get the type of the first parameter. 708 RegisterValue obj = GetRegister(GetParameterAt(instruction, is_range, args, 0)); 709 const VeriClass* cls = obj.GetType(); 710 if (cls != nullptr && cls->GetClassDef() != nullptr) { 711 const DexFile::ClassDef* def = cls->GetClassDef(); 712 return RegisterValue( 713 RegisterSource::kClass, 714 DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_), 715 VeriClass::class_); 716 } else { 717 return RegisterValue( 718 obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_); 719 } 720 } else if (method == VeriClass::loadClass_) { 721 // ClassLoader.loadClass. Fetch the first parameter. 722 RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 1)); 723 return RegisterValue( 724 value.GetSource(), value.GetDexFileReference(), VeriClass::class_); 725 } else { 726 // Return a RegisterValue referencing the method whose type is the return type 727 // of the method. 728 return GetReturnType(id); 729 } 730 } 731 732 void FlowAnalysisCollector::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) { 733 // There are no fields that escape reflection uses. 734 } 735 736 RegisterValue FlowAnalysisSubstitutor::AnalyzeInvoke(const Instruction& instruction, 737 bool is_range) { 738 uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c(); 739 MethodReference method(&resolver_->GetDexFile(), id); 740 // TODO: doesn't work for multidex 741 // TODO: doesn't work for overriding (but maybe should be done at a higher level); 742 if (accesses_.find(method) == accesses_.end()) { 743 return GetReturnType(id); 744 } 745 uint32_t args[5]; 746 if (!is_range) { 747 instruction.GetVarArgs(args); 748 } 749 for (const ReflectAccessInfo& info : accesses_.at(method)) { 750 if (info.cls.IsParameter() || info.name.IsParameter()) { 751 RegisterValue cls = info.cls.IsParameter() 752 ? GetRegister(GetParameterAt(instruction, is_range, args, info.cls.GetParameterIndex())) 753 : info.cls; 754 RegisterValue name = info.name.IsParameter() 755 ? GetRegister(GetParameterAt(instruction, is_range, args, info.name.GetParameterIndex())) 756 : info.name; 757 uses_.push_back(ReflectAccessInfo(cls, name, info.is_method)); 758 } 759 } 760 return GetReturnType(id); 761 } 762 763 void FlowAnalysisSubstitutor::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) { 764 // TODO: analyze field sets. 765 } 766 767 } // namespace art 768