xref: /aosp_15_r20/art/tools/veridex/flow_analysis.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker   * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor.h"
21*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors.h"
22*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_reference.h"
23*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
24*795d594fSAndroid Build Coastguard Worker #include "hidden_api.h"
25*795d594fSAndroid Build Coastguard Worker #include "resolver.h"
26*795d594fSAndroid Build Coastguard Worker #include "veridex.h"
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace art {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker /**
31*795d594fSAndroid Build Coastguard Worker  * The source where a dex register comes from.
32*795d594fSAndroid Build Coastguard Worker  */
33*795d594fSAndroid Build Coastguard Worker enum class RegisterSource {
34*795d594fSAndroid Build Coastguard Worker   kParameter,
35*795d594fSAndroid Build Coastguard Worker   kField,
36*795d594fSAndroid Build Coastguard Worker   kMethod,
37*795d594fSAndroid Build Coastguard Worker   kClass,
38*795d594fSAndroid Build Coastguard Worker   kString,
39*795d594fSAndroid Build Coastguard Worker   kConstant,
40*795d594fSAndroid Build Coastguard Worker   kNone
41*795d594fSAndroid Build Coastguard Worker };
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker /**
44*795d594fSAndroid Build Coastguard Worker  * Abstract representation of a dex register value.
45*795d594fSAndroid Build Coastguard Worker  */
46*795d594fSAndroid Build Coastguard Worker class RegisterValue {
47*795d594fSAndroid Build Coastguard Worker  public:
RegisterValue()48*795d594fSAndroid Build Coastguard Worker   RegisterValue() : source_(RegisterSource::kNone),
49*795d594fSAndroid Build Coastguard Worker                     value_(0),
50*795d594fSAndroid Build Coastguard Worker                     reference_(nullptr, 0),
51*795d594fSAndroid Build Coastguard Worker                     type_(nullptr) {}
RegisterValue(RegisterSource source,DexFileReference reference,const VeriClass * type)52*795d594fSAndroid Build Coastguard Worker   RegisterValue(RegisterSource source, DexFileReference reference, const VeriClass* type)
53*795d594fSAndroid Build Coastguard Worker       : source_(source), value_(0), reference_(reference), type_(type) {}
54*795d594fSAndroid Build Coastguard Worker 
RegisterValue(RegisterSource source,uint32_t value,DexFileReference reference,const VeriClass * type)55*795d594fSAndroid Build Coastguard Worker   RegisterValue(RegisterSource source,
56*795d594fSAndroid Build Coastguard Worker                 uint32_t value,
57*795d594fSAndroid Build Coastguard Worker                 DexFileReference reference,
58*795d594fSAndroid Build Coastguard Worker                 const VeriClass* type)
59*795d594fSAndroid Build Coastguard Worker       : source_(source), value_(value), reference_(reference), type_(type) {}
60*795d594fSAndroid Build Coastguard Worker 
GetSource()61*795d594fSAndroid Build Coastguard Worker   RegisterSource GetSource() const { return source_; }
GetDexFileReference()62*795d594fSAndroid Build Coastguard Worker   DexFileReference GetDexFileReference() const { return reference_; }
GetType()63*795d594fSAndroid Build Coastguard Worker   const VeriClass* GetType() const { return type_; }
GetParameterIndex()64*795d594fSAndroid Build Coastguard Worker   uint32_t GetParameterIndex() const {
65*795d594fSAndroid Build Coastguard Worker     CHECK(IsParameter());
66*795d594fSAndroid Build Coastguard Worker     return value_;
67*795d594fSAndroid Build Coastguard Worker   }
GetConstant()68*795d594fSAndroid Build Coastguard Worker   uint32_t GetConstant() const {
69*795d594fSAndroid Build Coastguard Worker     CHECK(IsConstant());
70*795d594fSAndroid Build Coastguard Worker     return value_;
71*795d594fSAndroid Build Coastguard Worker   }
IsParameter()72*795d594fSAndroid Build Coastguard Worker   bool IsParameter() const { return source_ == RegisterSource::kParameter; }
IsClass()73*795d594fSAndroid Build Coastguard Worker   bool IsClass() const { return source_ == RegisterSource::kClass; }
IsString()74*795d594fSAndroid Build Coastguard Worker   bool IsString() const { return source_ == RegisterSource::kString; }
IsConstant()75*795d594fSAndroid Build Coastguard Worker   bool IsConstant() const { return source_ == RegisterSource::kConstant; }
76*795d594fSAndroid Build Coastguard Worker 
ToString()77*795d594fSAndroid Build Coastguard Worker   std::string ToString() const {
78*795d594fSAndroid Build Coastguard Worker     switch (source_) {
79*795d594fSAndroid Build Coastguard Worker       case RegisterSource::kString: {
80*795d594fSAndroid Build Coastguard Worker         const char* str = reference_.dex_file->GetStringData(dex::StringIndex(reference_.index));
81*795d594fSAndroid Build Coastguard Worker         if (type_ == VeriClass::class_) {
82*795d594fSAndroid Build Coastguard Worker           // Class names at the Java level are of the form x.y.z, but the list encodes
83*795d594fSAndroid Build Coastguard Worker           // them of the form Lx/y/z;. Inner classes have '$' for both Java level class
84*795d594fSAndroid Build Coastguard Worker           // names in strings, and hidden API lists.
85*795d594fSAndroid Build Coastguard Worker           return HiddenApi::ToInternalName(str);
86*795d594fSAndroid Build Coastguard Worker         } else {
87*795d594fSAndroid Build Coastguard Worker           return str;
88*795d594fSAndroid Build Coastguard Worker         }
89*795d594fSAndroid Build Coastguard Worker       }
90*795d594fSAndroid Build Coastguard Worker       case RegisterSource::kClass:
91*795d594fSAndroid Build Coastguard Worker         return reference_.dex_file->GetTypeDescriptor(dex::TypeIndex(reference_.index));
92*795d594fSAndroid Build Coastguard Worker       case RegisterSource::kParameter:
93*795d594fSAndroid Build Coastguard Worker         return std::string("Parameter of ") + reference_.dex_file->PrettyMethod(reference_.index);
94*795d594fSAndroid Build Coastguard Worker       default:
95*795d594fSAndroid Build Coastguard Worker         return "<unknown>";
96*795d594fSAndroid Build Coastguard Worker     }
97*795d594fSAndroid Build Coastguard Worker   }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker  private:
100*795d594fSAndroid Build Coastguard Worker   RegisterSource source_;
101*795d594fSAndroid Build Coastguard Worker   uint32_t value_;
102*795d594fSAndroid Build Coastguard Worker   DexFileReference reference_;
103*795d594fSAndroid Build Coastguard Worker   const VeriClass* type_;
104*795d594fSAndroid Build Coastguard Worker };
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker struct InstructionInfo {
107*795d594fSAndroid Build Coastguard Worker   bool has_been_visited;
108*795d594fSAndroid Build Coastguard Worker };
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker class VeriFlowAnalysis {
111*795d594fSAndroid Build Coastguard Worker  public:
112*795d594fSAndroid Build Coastguard Worker   VeriFlowAnalysis(VeridexResolver* resolver, const ClassAccessor::Method& method);
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker   void Run();
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker   virtual RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) = 0;
117*795d594fSAndroid Build Coastguard Worker   virtual void AnalyzeFieldSet(const Instruction& instruction) = 0;
~VeriFlowAnalysis()118*795d594fSAndroid Build Coastguard Worker   virtual ~VeriFlowAnalysis() {}
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker  private:
121*795d594fSAndroid Build Coastguard Worker   // Find all branches in the code.
122*795d594fSAndroid Build Coastguard Worker   void FindBranches();
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker   // Analyze all non-deead instructions in the code.
125*795d594fSAndroid Build Coastguard Worker   void AnalyzeCode();
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   // Set the instruction at the given pc as a branch target.
128*795d594fSAndroid Build Coastguard Worker   void SetAsBranchTarget(uint32_t dex_pc);
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   // Whether the instruction at the given pc is a branch target.
131*795d594fSAndroid Build Coastguard Worker   bool IsBranchTarget(uint32_t dex_pc);
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker   // Merge the register values at the given pc with `current_registers`.
134*795d594fSAndroid Build Coastguard Worker   // Return whether the register values have changed, and the instruction needs
135*795d594fSAndroid Build Coastguard Worker   // to be visited again.
136*795d594fSAndroid Build Coastguard Worker   bool MergeRegisterValues(uint32_t dex_pc);
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   void UpdateRegister(
139*795d594fSAndroid Build Coastguard Worker       uint32_t dex_register, RegisterSource kind, VeriClass* cls, uint32_t source_id);
140*795d594fSAndroid Build Coastguard Worker   void UpdateRegister(uint32_t dex_register, const RegisterValue& value);
141*795d594fSAndroid Build Coastguard Worker   void UpdateRegister(uint32_t dex_register, const VeriClass* cls);
142*795d594fSAndroid Build Coastguard Worker   void UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls);
143*795d594fSAndroid Build Coastguard Worker   void ProcessDexInstruction(const Instruction& inst);
144*795d594fSAndroid Build Coastguard Worker   void SetVisited(uint32_t dex_pc);
145*795d594fSAndroid Build Coastguard Worker   RegisterValue GetFieldType(uint32_t field_index);
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker   int GetBranchFlags(const Instruction& instruction) const;
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker  protected:
150*795d594fSAndroid Build Coastguard Worker   const RegisterValue& GetRegister(uint32_t dex_register) const;
151*795d594fSAndroid Build Coastguard Worker   RegisterValue GetReturnType(uint32_t method_index);
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker   VeridexResolver* resolver_;
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker  private:
156*795d594fSAndroid Build Coastguard Worker   const uint32_t method_id_;
157*795d594fSAndroid Build Coastguard Worker   CodeItemDataAccessor code_item_accessor_;
158*795d594fSAndroid Build Coastguard Worker 
159*795d594fSAndroid Build Coastguard Worker   // Vector of register values for all branch targets.
160*795d594fSAndroid Build Coastguard Worker   std::vector<std::unique_ptr<std::vector<RegisterValue>>> dex_registers_;
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   // The current values of dex registers.
163*795d594fSAndroid Build Coastguard Worker   std::vector<RegisterValue> current_registers_;
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   // Information on each instruction useful for the analysis.
166*795d594fSAndroid Build Coastguard Worker   std::vector<InstructionInfo> instruction_infos_;
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker   // The value of invoke instructions, to be fetched when visiting move-result.
169*795d594fSAndroid Build Coastguard Worker   RegisterValue last_result_;
170*795d594fSAndroid Build Coastguard Worker };
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker struct ReflectAccessInfo {
173*795d594fSAndroid Build Coastguard Worker   RegisterValue cls;
174*795d594fSAndroid Build Coastguard Worker   RegisterValue name;
175*795d594fSAndroid Build Coastguard Worker   bool is_method;
176*795d594fSAndroid Build Coastguard Worker 
ReflectAccessInfoReflectAccessInfo177*795d594fSAndroid Build Coastguard Worker   ReflectAccessInfo(RegisterValue c, RegisterValue n, bool is_method)
178*795d594fSAndroid Build Coastguard Worker       : cls(c), name(n), is_method(is_method) {}
179*795d594fSAndroid Build Coastguard Worker 
IsConcreteReflectAccessInfo180*795d594fSAndroid Build Coastguard Worker   bool IsConcrete() const {
181*795d594fSAndroid Build Coastguard Worker     // We capture RegisterSource::kString for the class, for example in Class.forName.
182*795d594fSAndroid Build Coastguard Worker     return (cls.IsClass() || cls.IsString()) && name.IsString();
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker };
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker // Collects all reflection uses.
187*795d594fSAndroid Build Coastguard Worker class FlowAnalysisCollector : public VeriFlowAnalysis {
188*795d594fSAndroid Build Coastguard Worker  public:
FlowAnalysisCollector(VeridexResolver * resolver,const ClassAccessor::Method & method)189*795d594fSAndroid Build Coastguard Worker   FlowAnalysisCollector(VeridexResolver* resolver, const ClassAccessor::Method& method)
190*795d594fSAndroid Build Coastguard Worker       : VeriFlowAnalysis(resolver, method) {}
191*795d594fSAndroid Build Coastguard Worker 
GetUses()192*795d594fSAndroid Build Coastguard Worker   const std::vector<ReflectAccessInfo>& GetUses() const {
193*795d594fSAndroid Build Coastguard Worker     return uses_;
194*795d594fSAndroid Build Coastguard Worker   }
195*795d594fSAndroid Build Coastguard Worker 
196*795d594fSAndroid Build Coastguard Worker   RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) override;
197*795d594fSAndroid Build Coastguard Worker   void AnalyzeFieldSet(const Instruction& instruction) override;
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker  private:
200*795d594fSAndroid Build Coastguard Worker   // List of reflection uses found, concrete and abstract.
201*795d594fSAndroid Build Coastguard Worker   std::vector<ReflectAccessInfo> uses_;
202*795d594fSAndroid Build Coastguard Worker };
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker // Substitutes reflection uses by new ones.
205*795d594fSAndroid Build Coastguard Worker class FlowAnalysisSubstitutor : public VeriFlowAnalysis {
206*795d594fSAndroid Build Coastguard Worker  public:
FlowAnalysisSubstitutor(VeridexResolver * resolver,const ClassAccessor::Method & method,const std::map<MethodReference,std::vector<ReflectAccessInfo>> & accesses)207*795d594fSAndroid Build Coastguard Worker   FlowAnalysisSubstitutor(VeridexResolver* resolver,
208*795d594fSAndroid Build Coastguard Worker                           const ClassAccessor::Method& method,
209*795d594fSAndroid Build Coastguard Worker                           const std::map<MethodReference, std::vector<ReflectAccessInfo>>& accesses)
210*795d594fSAndroid Build Coastguard Worker       : VeriFlowAnalysis(resolver, method), accesses_(accesses) {}
211*795d594fSAndroid Build Coastguard Worker 
GetUses()212*795d594fSAndroid Build Coastguard Worker   const std::vector<ReflectAccessInfo>& GetUses() const {
213*795d594fSAndroid Build Coastguard Worker     return uses_;
214*795d594fSAndroid Build Coastguard Worker   }
215*795d594fSAndroid Build Coastguard Worker 
216*795d594fSAndroid Build Coastguard Worker   RegisterValue AnalyzeInvoke(const Instruction& instruction, bool is_range) override;
217*795d594fSAndroid Build Coastguard Worker   void AnalyzeFieldSet(const Instruction& instruction) override;
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker  private:
220*795d594fSAndroid Build Coastguard Worker   // List of reflection uses found, concrete and abstract.
221*795d594fSAndroid Build Coastguard Worker   std::vector<ReflectAccessInfo> uses_;
222*795d594fSAndroid Build Coastguard Worker   // The abstract uses we are trying to subsititute.
223*795d594fSAndroid Build Coastguard Worker   const std::map<MethodReference, std::vector<ReflectAccessInfo>>& accesses_;
224*795d594fSAndroid Build Coastguard Worker };
225*795d594fSAndroid Build Coastguard Worker 
226*795d594fSAndroid Build Coastguard Worker }  // namespace art
227*795d594fSAndroid Build Coastguard Worker 
228*795d594fSAndroid Build Coastguard Worker #endif  // ART_TOOLS_VERIDEX_FLOW_ANALYSIS_H_
229