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 if (accessor.NumMethods() != 0u) {
115 ArenaPool* arena_pool = Runtime::Current()->GetArenaPool();
116 RegTypeCache reg_types(self, linker, arena_pool, class_loader, dex_file);
117 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
118 int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
119 self->AllowThreadSuspension();
120 const uint32_t method_idx = method.GetIndex();
121 if (method_idx == *previous_idx) {
122 // smali can create dex files with two encoded_methods sharing the same method_idx
123 // http://code.google.com/p/smali/issues/detail?id=119
124 continue;
125 }
126 *previous_idx = method_idx;
127 std::string hard_failure_msg;
128 MethodVerifier::FailureData result =
129 MethodVerifier::VerifyMethod(self,
130 arena_pool,
131 ®_types,
132 verifier_deps,
133 method_idx,
134 dex_cache,
135 class_def,
136 method.GetCodeItem(),
137 method.GetAccessFlags(),
138 log_level,
139 api_level,
140 Runtime::Current()->IsAotCompiler(),
141 &hard_failure_msg);
142 if (result.kind == FailureKind::kHardFailure) {
143 if (failure_data.kind == FailureKind::kHardFailure) {
144 // If we logged an error before, we need a newline.
145 *error += "\n";
146 } else {
147 // If we didn't log a hard failure before, print the header of the message.
148 *error += "Verifier rejected class ";
149 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
150 *error += ":";
151 }
152 *error += " ";
153 *error += hard_failure_msg;
154 } else if (result.kind != FailureKind::kNoFailure) {
155 UpdateMethodFlags(method.GetIndex(), klass, dex_cache, callbacks, result.types);
156 if ((result.types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
157 // Print a warning about expected slow-down.
158 // Use a string temporary to print one contiguous warning.
159 std::string tmp =
160 StringPrintf("Method %s failed lock verification and will run slower.",
161 dex_file->PrettyMethod(method.GetIndex()).c_str());
162 if (!gPrintedDxMonitorText) {
163 tmp +=
164 "\nCommon causes for lock verification issues are non-optimized dex code\n"
165 "and incorrect proguard optimizations.";
166 gPrintedDxMonitorText = true;
167 }
168 LOG(WARNING) << tmp;
169 }
170 }
171
172 // Merge the result for the method into the global state for the class.
173 failure_data.Merge(result);
174 }
175 }
176 uint64_t elapsed_time_microseconds = timer.Stop();
177 VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
178 << ", class: " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
179
180 GetMetrics()->ClassVerificationCount()->AddOne();
181
182 GetMetrics()->ClassVerificationTotalTimeDelta()->Add(elapsed_time_microseconds);
183 GetMetrics()->ClassVerificationCountDelta()->AddOne();
184
185 if (failure_data.kind == verifier::FailureKind::kHardFailure && callbacks != nullptr) {
186 ClassReference ref(dex_file, dex_file->GetIndexForClassDef(class_def));
187 callbacks->ClassRejected(ref);
188 }
189
190 return failure_data.kind;
191 }
192
193 } // namespace verifier
194 } // namespace art
195