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