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