• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 "class_verifier.h"
18 
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 
22 #include "art_method-inl.h"
23 #include "base/locks.h"
24 #include "base/logging.h"
25 #include "base/pointer_size.h"
26 #include "base/systrace.h"
27 #include "base/utils.h"
28 #include "class_linker.h"
29 #include "compiler_callbacks.h"
30 #include "dex/class_accessor-inl.h"
31 #include "dex/class_reference.h"
32 #include "dex/descriptors_names.h"
33 #include "dex/dex_file-inl.h"
34 #include "handle.h"
35 #include "handle_scope-inl.h"
36 #include "method_verifier-inl.h"
37 #include "mirror/class-inl.h"
38 #include "mirror/dex_cache.h"
39 #include "runtime.h"
40 #include "thread.h"
41 #include "verifier_compiler_binding.h"
42 #include "verifier/method_verifier.h"
43 #include "verifier/reg_type_cache.h"
44 
45 namespace art HIDDEN {
46 namespace verifier {
47 
48 using android::base::StringPrintf;
49 
50 // We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
51 // sure we only print this once.
52 static bool gPrintedDxMonitorText = false;
53 
UpdateMethodFlags(uint32_t method_index,Handle<mirror::Class> klass,Handle<mirror::DexCache> dex_cache,CompilerCallbacks * callbacks,int error_types)54 static void UpdateMethodFlags(uint32_t method_index,
55                               Handle<mirror::Class> klass,
56                               Handle<mirror::DexCache> dex_cache,
57                               CompilerCallbacks* callbacks,
58                               int error_types)
59     REQUIRES_SHARED(Locks::mutator_lock_) {
60   if (callbacks != nullptr && !CanCompilerHandleVerificationFailure(error_types)) {
61     MethodReference ref(dex_cache->GetDexFile(), method_index);
62     callbacks->AddUncompilableMethod(ref);
63   }
64   if (klass == nullptr) {
65     DCHECK(Runtime::Current()->IsAotCompiler());
66     // Flags will be set at runtime.
67     return;
68   }
69 
70   // Mark methods with DontCompile/MustCountLocks flags.
71   ClassLinker* const linker = Runtime::Current()->GetClassLinker();
72   ArtMethod* method =
73       klass->FindClassMethod(dex_cache.Get(), method_index, linker->GetImagePointerSize());
74   DCHECK(method != nullptr);
75   DCHECK(method->GetDeclaringClass() == klass.Get());
76   if (!CanCompilerHandleVerificationFailure(error_types)) {
77     method->SetDontCompile();
78   }
79   if ((error_types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
80     method->SetMustCountLocks();
81   }
82 }
83 
VerifyClass(Thread * self,VerifierDeps * verifier_deps,const DexFile * dex_file,Handle<mirror::Class> klass,Handle<mirror::DexCache> dex_cache,Handle<mirror::ClassLoader> class_loader,const dex::ClassDef & class_def,CompilerCallbacks * callbacks,HardFailLogMode log_level,uint32_t api_level,std::string * error)84 FailureKind ClassVerifier::VerifyClass(Thread* self,
85                                        VerifierDeps* verifier_deps,
86                                        const DexFile* dex_file,
87                                        Handle<mirror::Class> klass,
88                                        Handle<mirror::DexCache> dex_cache,
89                                        Handle<mirror::ClassLoader> class_loader,
90                                        const dex::ClassDef& class_def,
91                                        CompilerCallbacks* callbacks,
92                                        HardFailLogMode log_level,
93                                        uint32_t api_level,
94                                        std::string* error) {
95   // A class must not be abstract and final.
96   if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
97     *error = "Verifier rejected class ";
98     *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
99     *error += ": class is abstract and final.";
100     return FailureKind::kHardFailure;
101   }
102 
103   // Note that `klass` can be a redefined class, not in the loader's table yet.
104   // Therefore, we do not use it for class resolution, but only when needing to
105   // update its methods' flags.
106   ClassAccessor accessor(*dex_file, class_def);
107   SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
108   metrics::AutoTimer timer{GetMetrics()->ClassVerificationTotalTime()};
109 
110   int64_t previous_method_idx[2] = { -1, -1 };
111   MethodVerifier::FailureData failure_data;
112   ClassLinker* const linker = Runtime::Current()->GetClassLinker();
113 
114   for (const ClassAccessor::Method& method : accessor.GetMethods()) {
115     int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
116     self->AllowThreadSuspension();
117     const uint32_t method_idx = method.GetIndex();
118     if (method_idx == *previous_idx) {
119       // smali can create dex files with two encoded_methods sharing the same method_idx
120       // http://code.google.com/p/smali/issues/detail?id=119
121       continue;
122     }
123     *previous_idx = method_idx;
124     std::string hard_failure_msg;
125     MethodVerifier::FailureData result =
126         MethodVerifier::VerifyMethod(self,
127                                      linker,
128                                      Runtime::Current()->GetArenaPool(),
129                                      verifier_deps,
130                                      method_idx,
131                                      dex_file,
132                                      dex_cache,
133                                      class_loader,
134                                      class_def,
135                                      method.GetCodeItem(),
136                                      method.GetAccessFlags(),
137                                      log_level,
138                                      api_level,
139                                      Runtime::Current()->IsAotCompiler(),
140                                      &hard_failure_msg);
141     if (result.kind == FailureKind::kHardFailure) {
142       if (failure_data.kind == FailureKind::kHardFailure) {
143         // If we logged an error before, we need a newline.
144         *error += "\n";
145       } else {
146         // If we didn't log a hard failure before, print the header of the message.
147         *error += "Verifier rejected class ";
148         *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
149         *error += ":";
150       }
151       *error += " ";
152       *error += hard_failure_msg;
153     } else if (result.kind != FailureKind::kNoFailure) {
154       UpdateMethodFlags(method.GetIndex(), klass, dex_cache, callbacks, result.types);
155       if ((result.types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
156         // Print a warning about expected slow-down.
157         // Use a string temporary to print one contiguous warning.
158         std::string tmp =
159             StringPrintf("Method %s failed lock verification and will run slower.",
160                          dex_file->PrettyMethod(method.GetIndex()).c_str());
161         if (!gPrintedDxMonitorText) {
162           tmp +=
163               "\nCommon causes for lock verification issues are non-optimized dex code\n"
164               "and incorrect proguard optimizations.";
165           gPrintedDxMonitorText = true;
166         }
167         LOG(WARNING) << tmp;
168       }
169     }
170 
171     // Merge the result for the method into the global state for the class.
172     failure_data.Merge(result);
173   }
174   uint64_t elapsed_time_microseconds = timer.Stop();
175   VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
176                  << ", class: " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
177 
178   GetMetrics()->ClassVerificationCount()->AddOne();
179 
180   GetMetrics()->ClassVerificationTotalTimeDelta()->Add(elapsed_time_microseconds);
181   GetMetrics()->ClassVerificationCountDelta()->AddOne();
182 
183   if (failure_data.kind == verifier::FailureKind::kHardFailure && callbacks != nullptr) {
184     ClassReference ref(dex_file, dex_file->GetIndexForClassDef(class_def));
185     callbacks->ClassRejected(ref);
186   }
187 
188   return failure_data.kind;
189 }
190 
191 }  // namespace verifier
192 }  // namespace art
193