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