blob: e2833bf01d718fd822bddc5764af8cf13ae667cf [file] [log] [blame]
Nicolas Geoffray242758a2018-04-04 22:32:03 +01001/*
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
27namespace art {
28
29
30void 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
37bool VeriFlowAnalysis::IsBranchTarget(uint32_t dex_pc) {
38 return dex_registers_[dex_pc] != nullptr;
39}
40
41bool 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.
Nicolas Geoffray295cba02018-04-18 12:54:04 +010044 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;
Nicolas Geoffray242758a2018-04-04 22:32:03 +010049}
50
51void VeriFlowAnalysis::SetVisited(uint32_t dex_pc) {
52 instruction_infos_[dex_pc].has_been_visited = true;
53}
54
55void 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
98void 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
106void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) {
107 current_registers_[dex_register] = value;
108}
109
110void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) {
111 current_registers_[dex_register] =
112 RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
113}
114
115const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) {
116 return current_registers_[dex_register];
117}
118
119RegisterValue VeriFlowAnalysis::GetReturnType(uint32_t method_index) {
120 const DexFile& dex_file = resolver_->GetDexFile();
121 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_index);
122 const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
123 VeriClass* cls = resolver_->GetVeriClass(proto_id.return_type_idx_);
124 return RegisterValue(RegisterSource::kMethod, DexFileReference(&dex_file, method_index), cls);
125}
126
127RegisterValue VeriFlowAnalysis::GetFieldType(uint32_t field_index) {
128 const DexFile& dex_file = resolver_->GetDexFile();
129 const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
130 VeriClass* cls = resolver_->GetVeriClass(field_id.type_idx_);
131 return RegisterValue(RegisterSource::kField, DexFileReference(&dex_file, field_index), cls);
132}
133
134void VeriFlowAnalysis::AnalyzeCode() {
135 std::vector<uint32_t> work_list;
136 work_list.push_back(0);
137 // Iterate over the code.
138 // When visiting unconditional branches (goto), move to that instruction.
139 // When visiting conditional branches, move to one destination, and put the other
140 // in the worklist.
141 while (!work_list.empty()) {
142 uint32_t dex_pc = work_list.back();
143 work_list.pop_back();
144 CHECK(IsBranchTarget(dex_pc));
145 current_registers_ = *dex_registers_[dex_pc].get();
146 while (true) {
147 const uint16_t* insns = code_item_accessor_.Insns() + dex_pc;
148 const Instruction& inst = *Instruction::At(insns);
149 ProcessDexInstruction(inst);
150 SetVisited(dex_pc);
151
152 int opcode_flags = Instruction::FlagsOf(inst.Opcode());
153 if ((opcode_flags & Instruction::kContinue) != 0) {
154 if ((opcode_flags & Instruction::kBranch) != 0) {
155 uint32_t branch_dex_pc = dex_pc + inst.GetTargetOffset();
156 if (MergeRegisterValues(branch_dex_pc)) {
157 work_list.push_back(branch_dex_pc);
158 }
159 }
160 dex_pc += inst.SizeInCodeUnits();
161 } else if ((opcode_flags & Instruction::kBranch) != 0) {
162 dex_pc += inst.GetTargetOffset();
163 DCHECK(IsBranchTarget(dex_pc));
164 } else {
165 break;
166 }
167
168 if (IsBranchTarget(dex_pc)) {
169 if (MergeRegisterValues(dex_pc)) {
170 current_registers_ = *dex_registers_[dex_pc].get();
171 } else {
172 break;
173 }
174 }
175 }
176 }
177}
178
179void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) {
180 switch (instruction.Opcode()) {
181 case Instruction::CONST_4:
182 case Instruction::CONST_16:
183 case Instruction::CONST:
184 case Instruction::CONST_HIGH16: {
185 int32_t register_index = instruction.VRegA();
186 UpdateRegister(register_index, VeriClass::integer_);
187 break;
188 }
189
190 case Instruction::CONST_WIDE_16:
191 case Instruction::CONST_WIDE_32:
192 case Instruction::CONST_WIDE:
193 case Instruction::CONST_WIDE_HIGH16: {
194 int32_t register_index = instruction.VRegA();
195 UpdateRegister(register_index, VeriClass::long_);
196 break;
197 }
198
199 case Instruction::MOVE:
200 case Instruction::MOVE_FROM16:
201 case Instruction::MOVE_16: {
202 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
203 break;
204 }
205
206 case Instruction::MOVE_WIDE:
207 case Instruction::MOVE_WIDE_FROM16:
208 case Instruction::MOVE_WIDE_16: {
209 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
210 break;
211 }
212
213 case Instruction::MOVE_OBJECT:
214 case Instruction::MOVE_OBJECT_16:
215 case Instruction::MOVE_OBJECT_FROM16: {
216 UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
217 break;
218 }
219 case Instruction::CONST_CLASS: {
220 UpdateRegister(instruction.VRegA_21c(),
221 RegisterSource::kClass,
222 VeriClass::class_,
223 instruction.VRegB_21c());
224 break;
225 }
226 case Instruction::CONST_STRING: {
227 UpdateRegister(instruction.VRegA_21c(),
228 RegisterSource::kString,
229 VeriClass::string_,
230 instruction.VRegB_21c());
231 break;
232 }
233
234 case Instruction::CONST_STRING_JUMBO: {
235 UpdateRegister(instruction.VRegA_31c(),
236 RegisterSource::kString,
237 VeriClass::string_,
238 instruction.VRegB_31c());
239 break;
240 }
241 case Instruction::INVOKE_DIRECT:
242 case Instruction::INVOKE_INTERFACE:
243 case Instruction::INVOKE_STATIC:
244 case Instruction::INVOKE_SUPER:
245 case Instruction::INVOKE_VIRTUAL: {
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100246 last_result_ = AnalyzeInvoke(instruction, /* is_range */ false);
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100247 break;
248 }
249
250 case Instruction::INVOKE_DIRECT_RANGE:
251 case Instruction::INVOKE_INTERFACE_RANGE:
252 case Instruction::INVOKE_STATIC_RANGE:
253 case Instruction::INVOKE_SUPER_RANGE:
254 case Instruction::INVOKE_VIRTUAL_RANGE: {
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100255 last_result_ = AnalyzeInvoke(instruction, /* is_range */ true);
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100256 break;
257 }
258
259 case Instruction::MOVE_RESULT:
260 case Instruction::MOVE_RESULT_WIDE:
261 case Instruction::MOVE_RESULT_OBJECT: {
262 UpdateRegister(instruction.VRegA(), last_result_);
263 break;
264 }
265 case Instruction::RETURN_VOID:
266 case Instruction::RETURN_OBJECT:
267 case Instruction::RETURN_WIDE:
268 case Instruction::RETURN: {
269 break;
270 }
271 #define IF_XX(cond) \
272 case Instruction::IF_##cond: break; \
273 case Instruction::IF_##cond##Z: break
274
275 IF_XX(EQ);
276 IF_XX(NE);
277 IF_XX(LT);
278 IF_XX(LE);
279 IF_XX(GT);
280 IF_XX(GE);
281
282 case Instruction::GOTO:
283 case Instruction::GOTO_16:
284 case Instruction::GOTO_32: {
285 break;
286 }
287 case Instruction::INVOKE_POLYMORPHIC: {
288 // TODO
289 break;
290 }
291
292 case Instruction::INVOKE_POLYMORPHIC_RANGE: {
293 // TODO
294 break;
295 }
296
297 case Instruction::NEG_INT:
298 case Instruction::NEG_LONG:
299 case Instruction::NEG_FLOAT:
300 case Instruction::NEG_DOUBLE:
301 case Instruction::NOT_INT:
302 case Instruction::NOT_LONG: {
303 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
304 break;
305 }
306
307 case Instruction::INT_TO_LONG:
308 case Instruction::INT_TO_FLOAT:
309 case Instruction::INT_TO_DOUBLE:
310 case Instruction::LONG_TO_INT:
311 case Instruction::LONG_TO_FLOAT:
312 case Instruction::LONG_TO_DOUBLE:
313 case Instruction::FLOAT_TO_INT:
314 case Instruction::FLOAT_TO_LONG:
315 case Instruction::FLOAT_TO_DOUBLE:
316 case Instruction::DOUBLE_TO_INT:
317 case Instruction::DOUBLE_TO_LONG:
318 case Instruction::DOUBLE_TO_FLOAT:
319 case Instruction::INT_TO_BYTE:
320 case Instruction::INT_TO_SHORT:
321 case Instruction::INT_TO_CHAR: {
322 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
323 break;
324 }
325
326 case Instruction::ADD_INT:
327 case Instruction::ADD_LONG:
328 case Instruction::ADD_DOUBLE:
329 case Instruction::ADD_FLOAT:
330 case Instruction::SUB_INT:
331 case Instruction::SUB_LONG:
332 case Instruction::SUB_FLOAT:
333 case Instruction::SUB_DOUBLE:
334 case Instruction::MUL_INT:
335 case Instruction::MUL_LONG:
336 case Instruction::MUL_FLOAT:
337 case Instruction::MUL_DOUBLE:
338 case Instruction::DIV_INT:
339 case Instruction::DIV_LONG:
340 case Instruction::DIV_FLOAT:
341 case Instruction::DIV_DOUBLE:
342 case Instruction::REM_INT:
343 case Instruction::REM_LONG:
344 case Instruction::REM_FLOAT:
345 case Instruction::REM_DOUBLE:
346 case Instruction::AND_INT:
347 case Instruction::AND_LONG:
348 case Instruction::SHL_INT:
349 case Instruction::SHL_LONG:
350 case Instruction::SHR_INT:
351 case Instruction::SHR_LONG:
352 case Instruction::USHR_INT:
353 case Instruction::USHR_LONG:
354 case Instruction::OR_INT:
355 case Instruction::OR_LONG:
356 case Instruction::XOR_INT:
357 case Instruction::XOR_LONG: {
358 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
359 break;
360 }
361
362 case Instruction::ADD_INT_2ADDR:
363 case Instruction::ADD_LONG_2ADDR:
364 case Instruction::ADD_DOUBLE_2ADDR:
365 case Instruction::ADD_FLOAT_2ADDR:
366 case Instruction::SUB_INT_2ADDR:
367 case Instruction::SUB_LONG_2ADDR:
368 case Instruction::SUB_FLOAT_2ADDR:
369 case Instruction::SUB_DOUBLE_2ADDR:
370 case Instruction::MUL_INT_2ADDR:
371 case Instruction::MUL_LONG_2ADDR:
372 case Instruction::MUL_FLOAT_2ADDR:
373 case Instruction::MUL_DOUBLE_2ADDR:
374 case Instruction::DIV_INT_2ADDR:
375 case Instruction::DIV_LONG_2ADDR:
376 case Instruction::REM_INT_2ADDR:
377 case Instruction::REM_LONG_2ADDR:
378 case Instruction::REM_FLOAT_2ADDR:
379 case Instruction::REM_DOUBLE_2ADDR:
380 case Instruction::SHL_INT_2ADDR:
381 case Instruction::SHL_LONG_2ADDR:
382 case Instruction::SHR_INT_2ADDR:
383 case Instruction::SHR_LONG_2ADDR:
384 case Instruction::USHR_INT_2ADDR:
385 case Instruction::USHR_LONG_2ADDR:
386 case Instruction::DIV_FLOAT_2ADDR:
387 case Instruction::DIV_DOUBLE_2ADDR:
388 case Instruction::AND_INT_2ADDR:
389 case Instruction::AND_LONG_2ADDR:
390 case Instruction::OR_INT_2ADDR:
391 case Instruction::OR_LONG_2ADDR:
392 case Instruction::XOR_INT_2ADDR:
393 case Instruction::XOR_LONG_2ADDR: {
394 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
395 break;
396 }
397
398 case Instruction::ADD_INT_LIT16:
399 case Instruction::AND_INT_LIT16:
400 case Instruction::OR_INT_LIT16:
401 case Instruction::XOR_INT_LIT16:
402 case Instruction::RSUB_INT:
403 case Instruction::MUL_INT_LIT16:
404 case Instruction::DIV_INT_LIT16:
405 case Instruction::REM_INT_LIT16: {
406 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
407 break;
408 }
409
410 case Instruction::ADD_INT_LIT8:
411 case Instruction::AND_INT_LIT8:
412 case Instruction::OR_INT_LIT8:
413 case Instruction::XOR_INT_LIT8:
414 case Instruction::RSUB_INT_LIT8:
415 case Instruction::MUL_INT_LIT8:
416 case Instruction::DIV_INT_LIT8:
417 case Instruction::REM_INT_LIT8:
418 case Instruction::SHL_INT_LIT8:
419 case Instruction::SHR_INT_LIT8: {
420 case Instruction::USHR_INT_LIT8: {
421 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
422 break;
423 }
424
425 case Instruction::NEW_INSTANCE: {
426 VeriClass* cls = resolver_->GetVeriClass(dex::TypeIndex(instruction.VRegB_21c()));
427 UpdateRegister(instruction.VRegA(), cls);
428 break;
429 }
430
431 case Instruction::NEW_ARRAY: {
432 dex::TypeIndex type_index(instruction.VRegC_22c());
433 VeriClass* cls = resolver_->GetVeriClass(type_index);
434 UpdateRegister(instruction.VRegA_22c(), cls);
435 break;
436 }
437
438 case Instruction::FILLED_NEW_ARRAY: {
439 dex::TypeIndex type_index(instruction.VRegB_35c());
440 VeriClass* cls = resolver_->GetVeriClass(type_index);
441 UpdateRegister(instruction.VRegA_22c(), cls);
442 break;
443 }
444
445 case Instruction::FILLED_NEW_ARRAY_RANGE: {
446 dex::TypeIndex type_index(instruction.VRegB_3rc());
447 uint32_t register_index = instruction.VRegC_3rc();
448 VeriClass* cls = resolver_->GetVeriClass(type_index);
449 UpdateRegister(register_index, cls);
450 break;
451 }
452
453 case Instruction::FILL_ARRAY_DATA: {
454 break;
455 }
456
457 case Instruction::CMP_LONG:
458 case Instruction::CMPG_FLOAT:
459 case Instruction::CMPG_DOUBLE:
460 case Instruction::CMPL_FLOAT:
461 case Instruction::CMPL_DOUBLE:
462 UpdateRegister(instruction.VRegA(), VeriClass::integer_);
463 break;
464 }
465
466 case Instruction::NOP:
467 break;
468
469 case Instruction::IGET:
470 case Instruction::IGET_WIDE:
471 case Instruction::IGET_OBJECT:
472 case Instruction::IGET_BOOLEAN:
473 case Instruction::IGET_BYTE:
474 case Instruction::IGET_CHAR:
475 case Instruction::IGET_SHORT: {
476 UpdateRegister(instruction.VRegA_22c(), GetFieldType(instruction.VRegC_22c()));
477 break;
478 }
479
480 case Instruction::IPUT:
481 case Instruction::IPUT_WIDE:
482 case Instruction::IPUT_OBJECT:
483 case Instruction::IPUT_BOOLEAN:
484 case Instruction::IPUT_BYTE:
485 case Instruction::IPUT_CHAR:
486 case Instruction::IPUT_SHORT: {
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100487 AnalyzeFieldSet(instruction);
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100488 break;
489 }
490
491 case Instruction::SGET:
492 case Instruction::SGET_WIDE:
493 case Instruction::SGET_OBJECT:
494 case Instruction::SGET_BOOLEAN:
495 case Instruction::SGET_BYTE:
496 case Instruction::SGET_CHAR:
497 case Instruction::SGET_SHORT: {
498 UpdateRegister(instruction.VRegA_22c(), GetFieldType(instruction.VRegC_22c()));
499 break;
500 }
501
502 case Instruction::SPUT:
503 case Instruction::SPUT_WIDE:
504 case Instruction::SPUT_OBJECT:
505 case Instruction::SPUT_BOOLEAN:
506 case Instruction::SPUT_BYTE:
507 case Instruction::SPUT_CHAR:
508 case Instruction::SPUT_SHORT: {
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100509 AnalyzeFieldSet(instruction);
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100510 break;
511 }
512
513#define ARRAY_XX(kind, anticipated_type) \
514 case Instruction::AGET##kind: { \
515 UpdateRegister(instruction.VRegA_23x(), anticipated_type); \
516 break; \
517 } \
518 case Instruction::APUT##kind: { \
519 break; \
520 }
521
522 ARRAY_XX(, VeriClass::integer_);
523 ARRAY_XX(_WIDE, VeriClass::long_);
524 ARRAY_XX(_BOOLEAN, VeriClass::boolean_);
525 ARRAY_XX(_BYTE, VeriClass::byte_);
526 ARRAY_XX(_CHAR, VeriClass::char_);
527 ARRAY_XX(_SHORT, VeriClass::short_);
528
529 case Instruction::AGET_OBJECT: {
530 // TODO: take the component type.
531 UpdateRegister(instruction.VRegA_23x(), VeriClass::object_);
532 break;
533 }
534
535 case Instruction::APUT_OBJECT: {
536 break;
537 }
538
539 case Instruction::ARRAY_LENGTH: {
540 UpdateRegister(instruction.VRegA_12x(), VeriClass::integer_);
541 break;
542 }
543
544 case Instruction::MOVE_EXCEPTION: {
545 UpdateRegister(instruction.VRegA_11x(), VeriClass::throwable_);
546 break;
547 }
548
549 case Instruction::THROW: {
550 break;
551 }
552
553 case Instruction::INSTANCE_OF: {
554 uint8_t destination = instruction.VRegA_22c();
555 UpdateRegister(destination, VeriClass::boolean_);
556 break;
557 }
558
559 case Instruction::CHECK_CAST: {
560 uint8_t reference = instruction.VRegA_21c();
561 dex::TypeIndex type_index(instruction.VRegB_21c());
562 UpdateRegister(reference, resolver_->GetVeriClass(type_index));
563 break;
564 }
565
566 case Instruction::MONITOR_ENTER:
567 case Instruction::MONITOR_EXIT: {
568 break;
569 }
570
571 case Instruction::SPARSE_SWITCH:
572 case Instruction::PACKED_SWITCH:
573 break;
574
575 default:
576 break;
577 }
578}
579
580void VeriFlowAnalysis::Run() {
581 FindBranches();
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100582 uint32_t number_of_registers = code_item_accessor_.RegistersSize();
583 uint32_t number_of_parameters = code_item_accessor_.InsSize();
584 std::vector<RegisterValue>& initial_values = *dex_registers_[0].get();
585 for (uint32_t i = 0; i < number_of_parameters; ++i) {
586 initial_values[number_of_registers - number_of_parameters + i] = RegisterValue(
587 RegisterSource::kParameter,
588 i,
589 DexFileReference(&resolver_->GetDexFile(), method_id_),
590 nullptr);
591 }
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100592 AnalyzeCode();
593}
594
Nicolas Geoffray5de2ff22018-04-25 09:09:28 +0100595static uint32_t GetParameterAt(const Instruction& instruction,
596 bool is_range,
597 uint32_t* args,
598 uint32_t index) {
599 return is_range ? instruction.VRegC() + index : args[index];
600}
601
602RegisterValue FlowAnalysisCollector::AnalyzeInvoke(const Instruction& instruction, bool is_range) {
603 uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
604 VeriMethod method = resolver_->GetMethod(id);
605 uint32_t args[5];
606 if (!is_range) {
607 instruction.GetVarArgs(args);
608 }
609
610 if (method == VeriClass::forName_) {
611 // Class.forName. Fetch the first parameter.
612 RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 0));
613 return RegisterValue(
614 value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
615 } else if (IsGetField(method)) {
616 // Class.getField or Class.getDeclaredField. Fetch the first parameter for the class, and the
617 // second parameter for the field name.
618 RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
619 RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
620 uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ false));
621 return GetReturnType(id);
622 } else if (IsGetMethod(method)) {
623 // Class.getMethod or Class.getDeclaredMethod. Fetch the first parameter for the class, and the
624 // second parameter for the field name.
625 RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
626 RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
627 uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ true));
628 return GetReturnType(id);
629 } else if (method == VeriClass::getClass_) {
630 // Get the type of the first parameter.
631 RegisterValue obj = GetRegister(GetParameterAt(instruction, is_range, args, 0));
632 const VeriClass* cls = obj.GetType();
633 if (cls != nullptr && cls->GetClassDef() != nullptr) {
634 const DexFile::ClassDef* def = cls->GetClassDef();
635 return RegisterValue(
636 RegisterSource::kClass,
637 DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_),
638 VeriClass::class_);
639 } else {
640 return RegisterValue(
641 obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
642 }
643 } else if (method == VeriClass::loadClass_) {
644 // ClassLoader.loadClass. Fetch the first parameter.
645 RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 1));
646 return RegisterValue(
647 value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
648 } else {
649 // Return a RegisterValue referencing the method whose type is the return type
650 // of the method.
651 return GetReturnType(id);
652 }
653}
654
655void FlowAnalysisCollector::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
656 // There are no fields that escape reflection uses.
657}
658
659RegisterValue FlowAnalysisSubstitutor::AnalyzeInvoke(const Instruction& instruction,
660 bool is_range) {
661 uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
662 MethodReference method(&resolver_->GetDexFile(), id);
663 // TODO: doesn't work for multidex
664 // TODO: doesn't work for overriding (but maybe should be done at a higher level);
665 if (accesses_.find(method) == accesses_.end()) {
666 return GetReturnType(id);
667 }
668 uint32_t args[5];
669 if (!is_range) {
670 instruction.GetVarArgs(args);
671 }
672 for (const ReflectAccessInfo& info : accesses_.at(method)) {
673 if (info.cls.IsParameter() || info.name.IsParameter()) {
674 RegisterValue cls = info.cls.IsParameter()
675 ? GetRegister(GetParameterAt(instruction, is_range, args, info.cls.GetParameterIndex()))
676 : info.cls;
677 RegisterValue name = info.name.IsParameter()
678 ? GetRegister(GetParameterAt(instruction, is_range, args, info.name.GetParameterIndex()))
679 : info.name;
680 uses_.push_back(ReflectAccessInfo(cls, name, info.is_method));
681 }
682 }
683 return GetReturnType(id);
684}
685
686void FlowAnalysisSubstitutor::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
687 // TODO: analyze field sets.
688}
689
Nicolas Geoffray242758a2018-04-04 22:32:03 +0100690} // namespace art