flow_analysis.h revision 242758af3cf6eae389f43d3804acaabaa4ba93da
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#ifndef ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
18#define ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
19
20#include "dex/code_item_accessors.h"
21#include "dex/dex_file_reference.h"
22#include "dex/method_reference.h"
23#include "veridex.h"
24
25namespace art {
26
27class VeridexClass;
28class VeridexResolver;
29
30/**
31 * The source where a dex register comes from.
32 */
33enum class RegisterSource {
34  kParameter,
35  kField,
36  kMethod,
37  kClass,
38  kString,
39  kNone
40};
41
42/**
43 * Abstract representation of a dex register value.
44 */
45class RegisterValue {
46 public:
47  RegisterValue() : source_(RegisterSource::kNone), reference_(nullptr, 0), type_(nullptr) {}
48  RegisterValue(RegisterSource source, DexFileReference reference, const VeriClass* type)
49      : source_(source), reference_(reference), type_(type) {}
50
51  RegisterSource GetSource() const { return source_; }
52  DexFileReference GetDexFileReference() const { return reference_; }
53  const VeriClass* GetType() const { return type_; }
54
55  const char* ToString() const {
56    switch (source_) {
57      case RegisterSource::kString:
58        return reference_.dex_file->StringDataByIdx(dex::StringIndex(reference_.index));
59      case RegisterSource::kClass:
60        return reference_.dex_file->StringByTypeIdx(dex::TypeIndex(reference_.index));
61      default:
62        return "<unknown>";
63    }
64  }
65
66 private:
67  RegisterSource source_;
68  DexFileReference reference_;
69  const VeriClass* type_;
70};
71
72struct InstructionInfo {
73  bool has_been_visited;
74};
75
76class VeriFlowAnalysis {
77 public:
78  VeriFlowAnalysis(VeridexResolver* resolver,
79                   const CodeItemDataAccessor& code_item_accessor)
80      : resolver_(resolver),
81        code_item_accessor_(code_item_accessor),
82        dex_registers_(code_item_accessor.InsnsSizeInCodeUnits()),
83        instruction_infos_(code_item_accessor.InsnsSizeInCodeUnits()) {}
84
85  void Run();
86
87  const std::vector<std::pair<RegisterValue, RegisterValue>>& GetFieldUses() const {
88    return field_uses_;
89  }
90
91  const std::vector<std::pair<RegisterValue, RegisterValue>>& GetMethodUses() const {
92    return method_uses_;
93  }
94
95 private:
96  // Find all branches in the code.
97  void FindBranches();
98
99  // Analyze all non-deead instructions in the code.
100  void AnalyzeCode();
101
102  // Set the instruction at the given pc as a branch target.
103  void SetAsBranchTarget(uint32_t dex_pc);
104
105  // Whether the instruction at the given pc is a branch target.
106  bool IsBranchTarget(uint32_t dex_pc);
107
108  // Merge the register values at the given pc with `current_registers`.
109  // Return whether the register values have changed, and the instruction needs
110  // to be visited again.
111  bool MergeRegisterValues(uint32_t dex_pc);
112
113  void UpdateRegister(
114      uint32_t dex_register, RegisterSource kind, VeriClass* cls, uint32_t source_id);
115  void UpdateRegister(uint32_t dex_register, const RegisterValue& value);
116  void UpdateRegister(uint32_t dex_register, const VeriClass* cls);
117  const RegisterValue& GetRegister(uint32_t dex_register);
118  void ProcessDexInstruction(const Instruction& inst);
119  void SetVisited(uint32_t dex_pc);
120  RegisterValue GetReturnType(uint32_t method_index);
121  RegisterValue GetFieldType(uint32_t field_index);
122
123  VeridexResolver* resolver_;
124  const CodeItemDataAccessor& code_item_accessor_;
125
126  // Vector of register values for all branch targets.
127  std::vector<std::unique_ptr<std::vector<RegisterValue>>> dex_registers_;
128
129  // The current values of dex registers.
130  std::vector<RegisterValue> current_registers_;
131
132  // Information on each instruction useful for the analysis.
133  std::vector<InstructionInfo> instruction_infos_;
134
135  // The value of invoke instructions, to be fetched when visiting move-result.
136  RegisterValue last_result_;
137
138  // List of reflection field uses found.
139  std::vector<std::pair<RegisterValue, RegisterValue>> field_uses_;
140
141  // List of reflection method uses found.
142  std::vector<std::pair<RegisterValue, RegisterValue>> method_uses_;
143};
144
145}  // namespace art
146
147#endif  // ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
148