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