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