blob: 1df11ada502db1d563fa273c18069e1f93df695a [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"
23#include "base/systrace.h"
24#include "base/utils.h"
25#include "class_linker.h"
26#include "compiler_callbacks.h"
27#include "dex/class_accessor-inl.h"
28#include "dex/class_reference.h"
29#include "dex/descriptors_names.h"
30#include "dex/dex_file-inl.h"
31#include "handle_scope-inl.h"
32#include "method_verifier-inl.h"
33#include "mirror/class-inl.h"
34#include "mirror/dex_cache.h"
35#include "runtime.h"
36
37namespace art {
38namespace verifier {
39
40using android::base::StringPrintf;
41
42// We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
43// sure we only print this once.
44static bool gPrintedDxMonitorText = false;
45
46FailureKind ClassVerifier::VerifyClass(Thread* self,
47 ObjPtr<mirror::Class> klass,
48 CompilerCallbacks* callbacks,
49 bool allow_soft_failures,
50 HardFailLogMode log_level,
51 uint32_t api_level,
52 std::string* error) {
53 if (klass->IsVerified()) {
54 return FailureKind::kNoFailure;
55 }
56 bool early_failure = false;
57 std::string failure_message;
58 const DexFile& dex_file = klass->GetDexFile();
59 const dex::ClassDef* class_def = klass->GetClassDef();
60 ObjPtr<mirror::Class> super = klass->GetSuperClass();
61 std::string temp;
62 if (super == nullptr && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
63 early_failure = true;
64 failure_message = " that has no super class";
65 } else if (super != nullptr && super->IsFinal()) {
66 early_failure = true;
67 failure_message = " that attempts to sub-class final class " + super->PrettyDescriptor();
68 } else if (class_def == nullptr) {
69 early_failure = true;
70 failure_message = " that isn't present in dex file " + dex_file.GetLocation();
71 }
72 if (early_failure) {
73 *error = "Verifier rejected class " + klass->PrettyDescriptor() + failure_message;
74 if (callbacks != nullptr) {
75 ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
76 callbacks->ClassRejected(ref);
77 }
78 return FailureKind::kHardFailure;
79 }
80 StackHandleScope<2> hs(self);
81 Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
82 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
83 return VerifyClass(self,
84 &dex_file,
85 dex_cache,
86 class_loader,
87 *class_def,
88 callbacks,
89 allow_soft_failures,
90 log_level,
91 api_level,
92 error);
93}
94
95FailureKind ClassVerifier::VerifyClass(Thread* self,
96 const DexFile* dex_file,
97 Handle<mirror::DexCache> dex_cache,
98 Handle<mirror::ClassLoader> class_loader,
99 const dex::ClassDef& class_def,
100 CompilerCallbacks* callbacks,
101 bool allow_soft_failures,
102 HardFailLogMode log_level,
103 uint32_t api_level,
104 std::string* error) {
105 // A class must not be abstract and final.
106 if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
107 *error = "Verifier rejected class ";
108 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
109 *error += ": class is abstract and final.";
110 return FailureKind::kHardFailure;
111 }
112
113 ClassAccessor accessor(*dex_file, class_def);
114 SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
115
116 int64_t previous_method_idx[2] = { -1, -1 };
117 MethodVerifier::FailureData failure_data;
118 ClassLinker* const linker = Runtime::Current()->GetClassLinker();
119
120 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
121 int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
122 self->AllowThreadSuspension();
123 const uint32_t method_idx = method.GetIndex();
124 if (method_idx == *previous_idx) {
125 // smali can create dex files with two encoded_methods sharing the same method_idx
126 // http://code.google.com/p/smali/issues/detail?id=119
127 continue;
128 }
129 *previous_idx = method_idx;
130 const InvokeType type = method.GetInvokeType(class_def.access_flags_);
131 ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
132 method_idx, dex_cache, class_loader, /* referrer= */ nullptr, type);
133 if (resolved_method == nullptr) {
134 DCHECK(self->IsExceptionPending());
135 // We couldn't resolve the method, but continue regardless.
136 self->ClearException();
137 } else {
138 DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
139 }
140 std::string hard_failure_msg;
141 MethodVerifier::FailureData result =
142 MethodVerifier::VerifyMethod(self,
Andreas Gampee0bbab92019-07-25 12:28:22 -0700143 linker,
Andreas Gampef1468b52019-07-26 09:22:39 -0700144 Runtime::Current()->GetArenaPool(),
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700145 method_idx,
146 dex_file,
147 dex_cache,
148 class_loader,
149 class_def,
150 method.GetCodeItem(),
151 resolved_method,
152 method.GetAccessFlags(),
153 callbacks,
154 allow_soft_failures,
155 log_level,
156 /*need_precise_constants=*/ false,
157 api_level,
Andreas Gampefef91cc2019-07-25 14:13:23 -0700158 Runtime::Current()->IsAotCompiler(),
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700159 &hard_failure_msg);
160 if (result.kind == FailureKind::kHardFailure) {
161 if (failure_data.kind == FailureKind::kHardFailure) {
162 // If we logged an error before, we need a newline.
163 *error += "\n";
164 } else {
165 // If we didn't log a hard failure before, print the header of the message.
166 *error += "Verifier rejected class ";
167 *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
168 *error += ":";
169 }
170 *error += " ";
171 *error += hard_failure_msg;
172 }
173 failure_data.Merge(result);
174 }
175
176 if (failure_data.kind == FailureKind::kNoFailure) {
177 return FailureKind::kNoFailure;
178 } else {
179 if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
180 // Print a warning about expected slow-down. Use a string temporary to print one contiguous
181 // warning.
182 std::string tmp =
183 StringPrintf("Class %s failed lock verification and will run slower.",
184 PrettyDescriptor(accessor.GetDescriptor()).c_str());
185 if (!gPrintedDxMonitorText) {
186 tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
187 "and incorrect proguard optimizations.";
188 gPrintedDxMonitorText = true;
189 }
190 LOG(WARNING) << tmp;
191 }
192 return failure_data.kind;
193 }
194}
195
Andreas Gampee0bbab92019-07-25 12:28:22 -0700196void ClassVerifier::Init(ClassLinker* class_linker) {
197 MethodVerifier::Init(class_linker);
Andreas Gampea43ba3d2019-03-13 15:49:20 -0700198}
199
200void ClassVerifier::Shutdown() {
201 MethodVerifier::Shutdown();
202}
203
204void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
205 MethodVerifier::VisitStaticRoots(visitor);
206}
207
208} // namespace verifier
209} // namespace art