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