blob: d88421e4891e6c4a1e072825e0414117e89c95e5 [file] [log] [blame]
Andreas Gampea43ba3d2019-03-13 15:49:20 -07001/*
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"
Alex Lightb1eebde2019-10-22 16:30:47 +000023#include "base/enums.h"
Alex Lightc2d0c962019-10-23 14:14:25 -070024#include "base/locks.h"
25#include "base/logging.h"
Andreas Gampea43ba3d2019-03-13 15:49:20 -070026#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"
Alex Lightb1eebde2019-10-22 16:30:47 +000034#include "handle.h"
Andreas Gampea43ba3d2019-03-13 15:49:20 -070035#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"
Alex Lightb1eebde2019-10-22 16:30:47 +000040#include "thread.h"
Nicolas Geoffray2ec38232021-07-02 16:36:29 +010041#include "verifier_compiler_binding.h"
Alex Lightc2d0c962019-10-23 14:14:25 -070042#include "verifier/method_verifier.h"
43#include "verifier/reg_type_cache.h"
Andreas Gampea43ba3d2019-03-13 15:49:20 -070044
45namespace art {
46namespace verifier {
47
48using 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.
52static bool gPrintedDxMonitorText = false;
53
Nicolas Geoffray7744b692021-07-06 16:19:32 +010054static void UpdateMethodFlags(uint32_t method_index,
55 Handle<mirror::Class> klass,
56 Handle<mirror::DexCache> dex_cache,
Nicolas Geoffray9e050ab2021-07-14 14:59:25 +010057 CompilerCallbacks* callbacks,
Nicolas Geoffray7744b692021-07-06 16:19:32 +010058 int error_types)
59 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray9e050ab2021-07-14 14:59:25 +010060 if (callbacks != nullptr && !CanCompilerHandleVerificationFailure(error_types)) {
61 MethodReference ref(dex_cache->GetDexFile(), method_index);
62 callbacks->AddUncompilableMethod(ref);
63 }
Nicolas Geoffray7744b692021-07-06 16:19:32 +010064 if (klass == nullptr) {
65 DCHECK(Runtime::Current()->IsAotCompiler());
66 // Flags will be set at runtime.
67 return;
Alex Lightc2d0c962019-10-23 14:14:25 -070068 }
Nicolas Geoffray7744b692021-07-06 16:19:32 +010069
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();
Alex Lightc2d0c962019-10-23 14:14:25 -070078 }
Nicolas Geoffray7744b692021-07-06 16:19:32 +010079 if ((error_types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
80 method->SetMustCountLocks();
Andreas Gampea43ba3d2019-03-13 15:49:20 -070081 }
Alex Lightb1eebde2019-10-22 16:30:47 +000082}
83
84FailureKind ClassVerifier::VerifyClass(Thread* self,
Nicolas Geoffray5b0b2e12021-03-19 14:48:40 +000085 VerifierDeps* verifier_deps,
Alex Lightb1eebde2019-10-22 16:30:47 +000086 const DexFile* dex_file,
Nicolas Geoffray7744b692021-07-06 16:19:32 +010087 Handle<mirror::Class> klass,
Alex Lightb1eebde2019-10-22 16:30:47 +000088 Handle<mirror::DexCache> dex_cache,
89 Handle<mirror::ClassLoader> class_loader,
90 const dex::ClassDef& class_def,
91 CompilerCallbacks* callbacks,
92 bool allow_soft_failures,
93 HardFailLogMode log_level,
94 uint32_t api_level,
Alex Lightb1eebde2019-10-22 16:30:47 +000095 std::string* error) {
Andreas Gampea43ba3d2019-03-13 15:49:20 -070096 // A class must not be abstract and final.
97 if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
98 *error = "Verifier rejected class ";
99 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
100 *error += ": class is abstract and final.";
101 return FailureKind::kHardFailure;
102 }
103
Nicolas Geoffray7744b692021-07-06 16:19:32 +0100104 // Note that `klass` can be a redefined class, not in the loader's table yet.
105 // Therefore, we do not use it for class resolution, but only when needing to
106 // update its methods' flags.
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700107 ClassAccessor accessor(*dex_file, class_def);
108 SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
Eric Holka79872b2020-10-01 13:09:53 -0700109 metrics::AutoTimer timer{GetMetrics()->ClassVerificationTotalTime()};
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700110
111 int64_t previous_method_idx[2] = { -1, -1 };
112 MethodVerifier::FailureData failure_data;
113 ClassLinker* const linker = Runtime::Current()->GetClassLinker();
114
115 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
116 int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
117 self->AllowThreadSuspension();
118 const uint32_t method_idx = method.GetIndex();
119 if (method_idx == *previous_idx) {
120 // smali can create dex files with two encoded_methods sharing the same method_idx
121 // http://code.google.com/p/smali/issues/detail?id=119
122 continue;
123 }
124 *previous_idx = method_idx;
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700125 std::string hard_failure_msg;
126 MethodVerifier::FailureData result =
127 MethodVerifier::VerifyMethod(self,
Andreas Gampee0bbab92019-07-25 12:28:22 -0700128 linker,
Andreas Gampef1468b52019-07-26 09:22:39 -0700129 Runtime::Current()->GetArenaPool(),
Nicolas Geoffray5b0b2e12021-03-19 14:48:40 +0000130 verifier_deps,
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700131 method_idx,
132 dex_file,
133 dex_cache,
134 class_loader,
135 class_def,
136 method.GetCodeItem(),
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700137 method.GetAccessFlags(),
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700138 allow_soft_failures,
139 log_level,
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700140 api_level,
Andreas Gampefef91cc2019-07-25 14:13:23 -0700141 Runtime::Current()->IsAotCompiler(),
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700142 &hard_failure_msg);
143 if (result.kind == FailureKind::kHardFailure) {
144 if (failure_data.kind == FailureKind::kHardFailure) {
145 // If we logged an error before, we need a newline.
146 *error += "\n";
147 } else {
148 // If we didn't log a hard failure before, print the header of the message.
149 *error += "Verifier rejected class ";
150 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
151 *error += ":";
152 }
153 *error += " ";
154 *error += hard_failure_msg;
Nicolas Geoffray2ec38232021-07-02 16:36:29 +0100155 } else if (result.kind != FailureKind::kNoFailure) {
Nicolas Geoffray9e050ab2021-07-14 14:59:25 +0100156 UpdateMethodFlags(method.GetIndex(), klass, dex_cache, callbacks, result.types);
Nicolas Geoffray7744b692021-07-06 16:19:32 +0100157 if ((result.types & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
158 // Print a warning about expected slow-down.
159 // Use a string temporary to print one contiguous warning.
160 std::string tmp =
161 StringPrintf("Method %s failed lock verification and will run slower.",
162 dex_file->PrettyMethod(method.GetIndex()).c_str());
163 if (!gPrintedDxMonitorText) {
164 tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
165 "and incorrect proguard optimizations.";
166 gPrintedDxMonitorText = true;
Nicolas Geoffray2ec38232021-07-02 16:36:29 +0100167 }
Nicolas Geoffray7744b692021-07-06 16:19:32 +0100168 LOG(WARNING) << tmp;
Nicolas Geoffray2ec38232021-07-02 16:36:29 +0100169 }
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700170 }
Nicolas Geoffray2ec38232021-07-02 16:36:29 +0100171
172 // Merge the result for the method into the global state for the class.
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700173 failure_data.Merge(result);
174 }
Eric Holka79872b2020-10-01 13:09:53 -0700175 uint64_t elapsed_time_microseconds = timer.Stop();
Eric Holk4bb09002020-09-30 11:42:34 -0700176 VLOG(verifier) << "VerifyClass took " << PrettyDuration(UsToNs(elapsed_time_microseconds))
Rock.Yehfa88d522020-06-23 21:29:19 +0800177 << ", class: " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700178
Eric Holke7ff7ef2021-03-17 16:42:24 -0700179 GetMetrics()->ClassVerificationCount()->AddOne();
Nicolas Geoffray9e050ab2021-07-14 14:59:25 +0100180
181 if (failure_data.kind == verifier::FailureKind::kHardFailure && callbacks != nullptr) {
182 ClassReference ref(dex_file, dex_file->GetIndexForClassDef(class_def));
183 callbacks->ClassRejected(ref);
184 }
185
Nicolas Geoffray2ec38232021-07-02 16:36:29 +0100186 return failure_data.kind;
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700187}
188
Andreas Gampee0bbab92019-07-25 12:28:22 -0700189void ClassVerifier::Init(ClassLinker* class_linker) {
190 MethodVerifier::Init(class_linker);
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700191}
192
193void ClassVerifier::Shutdown() {
194 MethodVerifier::Shutdown();
195}
196
197void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
198 MethodVerifier::VisitStaticRoots(visitor);
199}
200
201} // namespace verifier
202} // namespace art