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