Home | History | Annotate | Download | only in veridex
      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