xref: /aosp_15_r20/art/runtime/verifier/method_verifier.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 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_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <memory>
21*795d594fSAndroid Build Coastguard Worker #include <sstream>
22*795d594fSAndroid Build Coastguard Worker #include <vector>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
32*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
33*795d594fSAndroid Build Coastguard Worker #include "handle.h"
34*795d594fSAndroid Build Coastguard Worker #include "instruction_flags.h"
35*795d594fSAndroid Build Coastguard Worker #include "register_line.h"
36*795d594fSAndroid Build Coastguard Worker #include "verifier_enums.h"
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker class ClassLinker;
41*795d594fSAndroid Build Coastguard Worker class DexFile;
42*795d594fSAndroid Build Coastguard Worker class Instruction;
43*795d594fSAndroid Build Coastguard Worker struct ReferenceMap2Visitor;
44*795d594fSAndroid Build Coastguard Worker class Thread;
45*795d594fSAndroid Build Coastguard Worker class VariableIndentationOutputStream;
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker namespace dex {
48*795d594fSAndroid Build Coastguard Worker struct ClassDef;
49*795d594fSAndroid Build Coastguard Worker struct CodeItem;
50*795d594fSAndroid Build Coastguard Worker }  // namespace dex
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker namespace mirror {
53*795d594fSAndroid Build Coastguard Worker class ClassLoader;
54*795d594fSAndroid Build Coastguard Worker class DexCache;
55*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker namespace verifier {
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker class MethodVerifier;
60*795d594fSAndroid Build Coastguard Worker class RegType;
61*795d594fSAndroid Build Coastguard Worker class RegTypeCache;
62*795d594fSAndroid Build Coastguard Worker struct ScopedNewLine;
63*795d594fSAndroid Build Coastguard Worker class VerifierDeps;
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker // A mapping from a dex pc to the register line statuses as they are immediately prior to the
66*795d594fSAndroid Build Coastguard Worker // execution of that instruction.
67*795d594fSAndroid Build Coastguard Worker class PcToRegisterLineTable {
68*795d594fSAndroid Build Coastguard Worker  public:
69*795d594fSAndroid Build Coastguard Worker   explicit PcToRegisterLineTable(ArenaAllocator& allocator);
70*795d594fSAndroid Build Coastguard Worker   ~PcToRegisterLineTable();
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker   // Initialize the RegisterTable. Every instruction address can have a different set of information
73*795d594fSAndroid Build Coastguard Worker   // about what's in which register, but for verification purposes we only need to store it at
74*795d594fSAndroid Build Coastguard Worker   // branch target addresses (because we merge into that).
75*795d594fSAndroid Build Coastguard Worker   void Init(InstructionFlags* flags,
76*795d594fSAndroid Build Coastguard Worker             uint32_t insns_size,
77*795d594fSAndroid Build Coastguard Worker             uint16_t registers_size,
78*795d594fSAndroid Build Coastguard Worker             ArenaAllocator& allocator,
79*795d594fSAndroid Build Coastguard Worker             RegTypeCache* reg_types,
80*795d594fSAndroid Build Coastguard Worker             uint32_t interesting_dex_pc);
81*795d594fSAndroid Build Coastguard Worker 
IsInitialized()82*795d594fSAndroid Build Coastguard Worker   bool IsInitialized() const {
83*795d594fSAndroid Build Coastguard Worker     return !register_lines_.empty();
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
GetLine(size_t idx)86*795d594fSAndroid Build Coastguard Worker   RegisterLine* GetLine(size_t idx) const {
87*795d594fSAndroid Build Coastguard Worker     return register_lines_[idx].get();
88*795d594fSAndroid Build Coastguard Worker   }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker  private:
91*795d594fSAndroid Build Coastguard Worker   ArenaVector<RegisterLineArenaUniquePtr> register_lines_;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(PcToRegisterLineTable);
94*795d594fSAndroid Build Coastguard Worker };
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker // The verifier
97*795d594fSAndroid Build Coastguard Worker class MethodVerifier {
98*795d594fSAndroid Build Coastguard Worker  public:
99*795d594fSAndroid Build Coastguard Worker   EXPORT static void VerifyMethodAndDump(Thread* self,
100*795d594fSAndroid Build Coastguard Worker                                          VariableIndentationOutputStream* vios,
101*795d594fSAndroid Build Coastguard Worker                                          uint32_t method_idx,
102*795d594fSAndroid Build Coastguard Worker                                          const DexFile* dex_file,
103*795d594fSAndroid Build Coastguard Worker                                          Handle<mirror::DexCache> dex_cache,
104*795d594fSAndroid Build Coastguard Worker                                          Handle<mirror::ClassLoader> class_loader,
105*795d594fSAndroid Build Coastguard Worker                                          const dex::ClassDef& class_def,
106*795d594fSAndroid Build Coastguard Worker                                          const dex::CodeItem* code_item,
107*795d594fSAndroid Build Coastguard Worker                                          uint32_t method_access_flags,
108*795d594fSAndroid Build Coastguard Worker                                          uint32_t api_level)
109*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker   // Calculates the type information at the given `dex_pc`.
112*795d594fSAndroid Build Coastguard Worker   // No classes will be loaded.
113*795d594fSAndroid Build Coastguard Worker   EXPORT static MethodVerifier* CalculateVerificationInfo(Thread* self,
114*795d594fSAndroid Build Coastguard Worker                                                           RegTypeCache* reg_types,
115*795d594fSAndroid Build Coastguard Worker                                                           ArtMethod* method,
116*795d594fSAndroid Build Coastguard Worker                                                           Handle<mirror::DexCache> dex_cache,
117*795d594fSAndroid Build Coastguard Worker                                                           uint32_t dex_pc)
118*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
119*795d594fSAndroid Build Coastguard Worker 
GetDexFile()120*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const {
121*795d594fSAndroid Build Coastguard Worker     DCHECK(dex_file_ != nullptr);
122*795d594fSAndroid Build Coastguard Worker     return *dex_file_;
123*795d594fSAndroid Build Coastguard Worker   }
124*795d594fSAndroid Build Coastguard Worker 
GetClassDef()125*795d594fSAndroid Build Coastguard Worker   const dex::ClassDef& GetClassDef() const {
126*795d594fSAndroid Build Coastguard Worker     return class_def_;
127*795d594fSAndroid Build Coastguard Worker   }
128*795d594fSAndroid Build Coastguard Worker 
GetRegTypeCache()129*795d594fSAndroid Build Coastguard Worker   RegTypeCache* GetRegTypeCache() {
130*795d594fSAndroid Build Coastguard Worker     return &reg_types_;
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker   // Log a verification failure.
134*795d594fSAndroid Build Coastguard Worker   std::ostream& Fail(VerifyError error, bool pending_exc = true);
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker   // Log for verification information.
137*795d594fSAndroid Build Coastguard Worker   ScopedNewLine LogVerifyInfo();
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   // Information structure for a lock held at a certain point in time.
140*795d594fSAndroid Build Coastguard Worker   struct DexLockInfo {
141*795d594fSAndroid Build Coastguard Worker     // The registers aliasing the lock.
142*795d594fSAndroid Build Coastguard Worker     std::set<uint32_t> dex_registers;
143*795d594fSAndroid Build Coastguard Worker     // The dex PC of the monitor-enter instruction.
144*795d594fSAndroid Build Coastguard Worker     uint32_t dex_pc;
145*795d594fSAndroid Build Coastguard Worker 
DexLockInfoDexLockInfo146*795d594fSAndroid Build Coastguard Worker     explicit DexLockInfo(uint32_t dex_pc_in) {
147*795d594fSAndroid Build Coastguard Worker       dex_pc = dex_pc_in;
148*795d594fSAndroid Build Coastguard Worker     }
149*795d594fSAndroid Build Coastguard Worker   };
150*795d594fSAndroid Build Coastguard Worker   // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
151*795d594fSAndroid Build Coastguard Worker   // to the locks held at 'dex_pc' in method 'm'.
152*795d594fSAndroid Build Coastguard Worker   // Note: this is the only situation where the verifier will visit quickened instructions.
153*795d594fSAndroid Build Coastguard Worker   static void FindLocksAtDexPc(ArtMethod* m,
154*795d594fSAndroid Build Coastguard Worker                                uint32_t dex_pc,
155*795d594fSAndroid Build Coastguard Worker                                std::vector<DexLockInfo>* monitor_enter_dex_pcs,
156*795d594fSAndroid Build Coastguard Worker                                uint32_t api_level)
157*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
158*795d594fSAndroid Build Coastguard Worker 
159*795d594fSAndroid Build Coastguard Worker   virtual ~MethodVerifier();
160*795d594fSAndroid Build Coastguard Worker 
CodeItem()161*795d594fSAndroid Build Coastguard Worker   const CodeItemDataAccessor& CodeItem() const {
162*795d594fSAndroid Build Coastguard Worker     return code_item_accessor_;
163*795d594fSAndroid Build Coastguard Worker   }
164*795d594fSAndroid Build Coastguard Worker   RegisterLine* GetRegLine(uint32_t dex_pc);
165*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE const InstructionFlags& GetInstructionFlags(size_t index) const;
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   MethodReference GetMethodReference() const;
168*795d594fSAndroid Build Coastguard Worker   bool HasFailures() const;
HasInstructionThatWillThrow()169*795d594fSAndroid Build Coastguard Worker   bool HasInstructionThatWillThrow() const {
170*795d594fSAndroid Build Coastguard Worker     return (encountered_failure_types_ & VERIFY_ERROR_RUNTIME_THROW) != 0;
171*795d594fSAndroid Build Coastguard Worker   }
172*795d594fSAndroid Build Coastguard Worker 
GetEncounteredFailureTypes()173*795d594fSAndroid Build Coastguard Worker   uint32_t GetEncounteredFailureTypes() const {
174*795d594fSAndroid Build Coastguard Worker     return encountered_failure_types_;
175*795d594fSAndroid Build Coastguard Worker   }
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker   ClassLinker* GetClassLinker() const;
178*795d594fSAndroid Build Coastguard Worker 
IsAotMode()179*795d594fSAndroid Build Coastguard Worker   bool IsAotMode() const {
180*795d594fSAndroid Build Coastguard Worker     return const_flags_.aot_mode_;
181*795d594fSAndroid Build Coastguard Worker   }
182*795d594fSAndroid Build Coastguard Worker 
CanLoadClasses()183*795d594fSAndroid Build Coastguard Worker   bool CanLoadClasses() const {
184*795d594fSAndroid Build Coastguard Worker     return const_flags_.can_load_classes_;
185*795d594fSAndroid Build Coastguard Worker   }
186*795d594fSAndroid Build Coastguard Worker 
GetVerifierDeps()187*795d594fSAndroid Build Coastguard Worker   VerifierDeps* GetVerifierDeps() const {
188*795d594fSAndroid Build Coastguard Worker     return verifier_deps_;
189*795d594fSAndroid Build Coastguard Worker   }
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker  protected:
192*795d594fSAndroid Build Coastguard Worker   MethodVerifier(Thread* self,
193*795d594fSAndroid Build Coastguard Worker                  ArenaPool* arena_pool,
194*795d594fSAndroid Build Coastguard Worker                  RegTypeCache* reg_types,
195*795d594fSAndroid Build Coastguard Worker                  VerifierDeps* verifier_deps,
196*795d594fSAndroid Build Coastguard Worker                  const dex::ClassDef& class_def,
197*795d594fSAndroid Build Coastguard Worker                  const dex::CodeItem* code_item,
198*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_method_idx,
199*795d594fSAndroid Build Coastguard Worker                  bool aot_mode)
200*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   // Verification result for method(s). Includes a (maximum) failure kind, and (the union of)
203*795d594fSAndroid Build Coastguard Worker   // all failure types.
204*795d594fSAndroid Build Coastguard Worker   struct FailureData : ValueObject {
205*795d594fSAndroid Build Coastguard Worker     FailureKind kind = FailureKind::kNoFailure;
206*795d594fSAndroid Build Coastguard Worker     uint32_t types = 0U;
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker     // Merge src into this. Uses the most severe failure kind, and the union of types.
209*795d594fSAndroid Build Coastguard Worker     void Merge(const FailureData& src);
210*795d594fSAndroid Build Coastguard Worker   };
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker   /*
213*795d594fSAndroid Build Coastguard Worker    * Perform verification on a single method.
214*795d594fSAndroid Build Coastguard Worker    *
215*795d594fSAndroid Build Coastguard Worker    * We do this in three passes:
216*795d594fSAndroid Build Coastguard Worker    *  (1) Walk through all code units, determining instruction locations,
217*795d594fSAndroid Build Coastguard Worker    *      widths, and other characteristics.
218*795d594fSAndroid Build Coastguard Worker    *  (2) Walk through all code units, performing static checks on
219*795d594fSAndroid Build Coastguard Worker    *      operands.
220*795d594fSAndroid Build Coastguard Worker    *  (3) Iterate through the method, checking type safety and looking
221*795d594fSAndroid Build Coastguard Worker    *      for code flow problems.
222*795d594fSAndroid Build Coastguard Worker    */
223*795d594fSAndroid Build Coastguard Worker   static FailureData VerifyMethod(Thread* self,
224*795d594fSAndroid Build Coastguard Worker                                   ArenaPool* arena_pool,
225*795d594fSAndroid Build Coastguard Worker                                   RegTypeCache* reg_types,
226*795d594fSAndroid Build Coastguard Worker                                   VerifierDeps* verifier_deps,
227*795d594fSAndroid Build Coastguard Worker                                   uint32_t method_idx,
228*795d594fSAndroid Build Coastguard Worker                                   Handle<mirror::DexCache> dex_cache,
229*795d594fSAndroid Build Coastguard Worker                                   const dex::ClassDef& class_def_idx,
230*795d594fSAndroid Build Coastguard Worker                                   const dex::CodeItem* code_item,
231*795d594fSAndroid Build Coastguard Worker                                   uint32_t method_access_flags,
232*795d594fSAndroid Build Coastguard Worker                                   HardFailLogMode log_level,
233*795d594fSAndroid Build Coastguard Worker                                   uint32_t api_level,
234*795d594fSAndroid Build Coastguard Worker                                   bool aot_mode,
235*795d594fSAndroid Build Coastguard Worker                                   std::string* hard_failure_msg)
236*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
237*795d594fSAndroid Build Coastguard Worker 
238*795d594fSAndroid Build Coastguard Worker   template <bool kVerifierDebug>
239*795d594fSAndroid Build Coastguard Worker   static FailureData VerifyMethod(Thread* self,
240*795d594fSAndroid Build Coastguard Worker                                   ArenaPool* arena_pool,
241*795d594fSAndroid Build Coastguard Worker                                   RegTypeCache* reg_types,
242*795d594fSAndroid Build Coastguard Worker                                   VerifierDeps* verifier_deps,
243*795d594fSAndroid Build Coastguard Worker                                   uint32_t method_idx,
244*795d594fSAndroid Build Coastguard Worker                                   Handle<mirror::DexCache> dex_cache,
245*795d594fSAndroid Build Coastguard Worker                                   const dex::ClassDef& class_def_idx,
246*795d594fSAndroid Build Coastguard Worker                                   const dex::CodeItem* code_item,
247*795d594fSAndroid Build Coastguard Worker                                   uint32_t method_access_flags,
248*795d594fSAndroid Build Coastguard Worker                                   HardFailLogMode log_level,
249*795d594fSAndroid Build Coastguard Worker                                   uint32_t api_level,
250*795d594fSAndroid Build Coastguard Worker                                   bool aot_mode,
251*795d594fSAndroid Build Coastguard Worker                                   std::string* hard_failure_msg)
252*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
253*795d594fSAndroid Build Coastguard Worker 
254*795d594fSAndroid Build Coastguard Worker   /*
255*795d594fSAndroid Build Coastguard Worker    * Get the "this" pointer from a non-static method invocation. This returns the RegType so the
256*795d594fSAndroid Build Coastguard Worker    * caller can decide whether it needs the reference to be initialized or not.
257*795d594fSAndroid Build Coastguard Worker    *
258*795d594fSAndroid Build Coastguard Worker    * The argument count is in vA, and the first argument is in vC, for both "simple" and "range"
259*795d594fSAndroid Build Coastguard Worker    * versions. We just need to make sure vA is >= 1 and then return vC.
260*795d594fSAndroid Build Coastguard Worker    */
261*795d594fSAndroid Build Coastguard Worker   const RegType& GetInvocationThis(const Instruction* inst)
262*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
263*795d594fSAndroid Build Coastguard Worker 
264*795d594fSAndroid Build Coastguard Worker   // Can a variable with type `lhs` be assigned a value with type `rhs`?
265*795d594fSAndroid Build Coastguard Worker   // Note: Object and interface types may always be assigned to one another, see
266*795d594fSAndroid Build Coastguard Worker   // comment on `ClassJoin()`.
267*795d594fSAndroid Build Coastguard Worker   bool IsAssignableFrom(const RegType& lhs, const RegType& rhs) const
268*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   // Can a variable with type `lhs` be assigned a value with type `rhs`?
271*795d594fSAndroid Build Coastguard Worker   // Variant of IsAssignableFrom that doesn't allow assignment to an interface from an Object.
272*795d594fSAndroid Build Coastguard Worker   bool IsStrictlyAssignableFrom(const RegType& lhs, const RegType& rhs) const
273*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   // Implementation helper for `IsAssignableFrom()` and `IsStrictlyAssignableFrom()`.
276*795d594fSAndroid Build Coastguard Worker   bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict) const
277*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   // For VerifierDepsTest. TODO: Refactor.
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker   // Run verification on the method. Returns true if verification completes and false if the input
282*795d594fSAndroid Build Coastguard Worker   // has an irrecoverable corruption.
283*795d594fSAndroid Build Coastguard Worker   virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
284*795d594fSAndroid Build Coastguard Worker   static MethodVerifier* CreateVerifier(Thread* self,
285*795d594fSAndroid Build Coastguard Worker                                         RegTypeCache* reg_types,
286*795d594fSAndroid Build Coastguard Worker                                         VerifierDeps* verifier_deps,
287*795d594fSAndroid Build Coastguard Worker                                         Handle<mirror::DexCache> dex_cache,
288*795d594fSAndroid Build Coastguard Worker                                         const dex::ClassDef& class_def,
289*795d594fSAndroid Build Coastguard Worker                                         const dex::CodeItem* code_item,
290*795d594fSAndroid Build Coastguard Worker                                         uint32_t method_idx,
291*795d594fSAndroid Build Coastguard Worker                                         uint32_t access_flags,
292*795d594fSAndroid Build Coastguard Worker                                         bool verify_to_dump,
293*795d594fSAndroid Build Coastguard Worker                                         uint32_t api_level)
294*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   virtual bool PotentiallyMarkRuntimeThrow() = 0;
297*795d594fSAndroid Build Coastguard Worker 
InfoMessages()298*795d594fSAndroid Build Coastguard Worker   std::ostringstream& InfoMessages() {
299*795d594fSAndroid Build Coastguard Worker     if (!info_messages_.has_value()) {
300*795d594fSAndroid Build Coastguard Worker       info_messages_.emplace();
301*795d594fSAndroid Build Coastguard Worker     }
302*795d594fSAndroid Build Coastguard Worker     return info_messages_.value();
303*795d594fSAndroid Build Coastguard Worker   }
304*795d594fSAndroid Build Coastguard Worker 
305*795d594fSAndroid Build Coastguard Worker   // The thread we're verifying on.
306*795d594fSAndroid Build Coastguard Worker   Thread* const self_;
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker   // Arena allocator.
309*795d594fSAndroid Build Coastguard Worker   ArenaAllocator allocator_;
310*795d594fSAndroid Build Coastguard Worker 
311*795d594fSAndroid Build Coastguard Worker   RegTypeCache& reg_types_;  // TODO: Change to a pointer in a separate CL.
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker   PcToRegisterLineTable reg_table_;
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker   // Storage for the register status we're currently working on.
316*795d594fSAndroid Build Coastguard Worker   RegisterLineArenaUniquePtr work_line_;
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker   // The address of the instruction we're currently working on, note that this is in 2 byte
319*795d594fSAndroid Build Coastguard Worker   // quantities
320*795d594fSAndroid Build Coastguard Worker   uint32_t work_insn_idx_;
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker   // Storage for the register status we're saving for later.
323*795d594fSAndroid Build Coastguard Worker   RegisterLineArenaUniquePtr saved_line_;
324*795d594fSAndroid Build Coastguard Worker 
325*795d594fSAndroid Build Coastguard Worker   const uint32_t dex_method_idx_;   // The method we're working on.
326*795d594fSAndroid Build Coastguard Worker   const DexFile* const dex_file_;   // The dex file containing the method.
327*795d594fSAndroid Build Coastguard Worker   const dex::ClassDef& class_def_;  // The class being verified.
328*795d594fSAndroid Build Coastguard Worker   const CodeItemDataAccessor code_item_accessor_;
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker   // Instruction widths and flags, one entry per code unit.
331*795d594fSAndroid Build Coastguard Worker   // Owned, but not unique_ptr since insn_flags_ are allocated in arenas.
332*795d594fSAndroid Build Coastguard Worker   ArenaUniquePtr<InstructionFlags[]> insn_flags_;
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker   // The types of any error that occurs.
335*795d594fSAndroid Build Coastguard Worker   std::vector<VerifyError> failures_;
336*795d594fSAndroid Build Coastguard Worker   // Error messages associated with failures.
337*795d594fSAndroid Build Coastguard Worker   std::vector<std::ostringstream*> failure_messages_;
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   struct {
340*795d594fSAndroid Build Coastguard Worker     // Is there a pending hard failure?
341*795d594fSAndroid Build Coastguard Worker     bool have_pending_hard_failure_ : 1;
342*795d594fSAndroid Build Coastguard Worker 
343*795d594fSAndroid Build Coastguard Worker     // Is there a pending runtime throw failure? A runtime throw failure is when an instruction
344*795d594fSAndroid Build Coastguard Worker     // would fail at runtime throwing an exception. Such an instruction causes the following code
345*795d594fSAndroid Build Coastguard Worker     // to be unreachable. This is set by Fail and used to ensure we don't process unreachable
346*795d594fSAndroid Build Coastguard Worker     // instructions that would hard fail the verification.
347*795d594fSAndroid Build Coastguard Worker     // Note: this flag is reset after processing each instruction.
348*795d594fSAndroid Build Coastguard Worker     bool have_pending_runtime_throw_failure_ : 1;
349*795d594fSAndroid Build Coastguard Worker   } flags_;
350*795d594fSAndroid Build Coastguard Worker 
351*795d594fSAndroid Build Coastguard Worker   struct {
352*795d594fSAndroid Build Coastguard Worker     // Verify in AoT mode?
353*795d594fSAndroid Build Coastguard Worker     bool aot_mode_ : 1;
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker     // Whether the `MethodVerifer` can load classes.
356*795d594fSAndroid Build Coastguard Worker     bool can_load_classes_ : 1;
357*795d594fSAndroid Build Coastguard Worker   } const const_flags_;
358*795d594fSAndroid Build Coastguard Worker 
359*795d594fSAndroid Build Coastguard Worker   // Bitset of the encountered failure types. Bits are according to the values in VerifyError.
360*795d594fSAndroid Build Coastguard Worker   uint32_t encountered_failure_types_;
361*795d594fSAndroid Build Coastguard Worker 
362*795d594fSAndroid Build Coastguard Worker   // Info message log use primarily for verifier diagnostics.
363*795d594fSAndroid Build Coastguard Worker   std::optional<std::ostringstream> info_messages_;
364*795d594fSAndroid Build Coastguard Worker 
365*795d594fSAndroid Build Coastguard Worker   // The verifier deps object we are going to report type assigability
366*795d594fSAndroid Build Coastguard Worker   // constraints to. Can be null for runtime verification.
367*795d594fSAndroid Build Coastguard Worker   VerifierDeps* verifier_deps_;
368*795d594fSAndroid Build Coastguard Worker 
369*795d594fSAndroid Build Coastguard Worker   // Link, for the method verifier root linked list.
370*795d594fSAndroid Build Coastguard Worker   MethodVerifier* link_;
371*795d594fSAndroid Build Coastguard Worker 
372*795d594fSAndroid Build Coastguard Worker   friend class art::Thread;
373*795d594fSAndroid Build Coastguard Worker   friend class ClassVerifier;
374*795d594fSAndroid Build Coastguard Worker   friend class RegisterLineTest;
375*795d594fSAndroid Build Coastguard Worker   friend class VerifierDepsTest;
376*795d594fSAndroid Build Coastguard Worker 
377*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
378*795d594fSAndroid Build Coastguard Worker };
379*795d594fSAndroid Build Coastguard Worker 
380*795d594fSAndroid Build Coastguard Worker }  // namespace verifier
381*795d594fSAndroid Build Coastguard Worker }  // namespace art
382*795d594fSAndroid Build Coastguard Worker 
383*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
384