xref: /aosp_15_r20/art/tools/art_verifier/art_verifier.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 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 #include <string>
18*795d594fSAndroid Build Coastguard Worker #include <vector>
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
24*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
26*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "interpreter/unstarted_runtime.h"
29*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
32*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "verifier/class_verifier.h"
34*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
37*795d594fSAndroid Build Coastguard Worker #include "cmdline.h"
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker namespace art {
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker namespace {
42*795d594fSAndroid Build Coastguard Worker 
LoadDexFile(const std::string & dex_filename,std::vector<std::unique_ptr<const DexFile>> * dex_files)43*795d594fSAndroid Build Coastguard Worker bool LoadDexFile(const std::string& dex_filename,
44*795d594fSAndroid Build Coastguard Worker                  std::vector<std::unique_ptr<const DexFile>>* dex_files) {
45*795d594fSAndroid Build Coastguard Worker   ArtDexFileLoader dex_file_loader(dex_filename);
46*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
47*795d594fSAndroid Build Coastguard Worker   if (!dex_file_loader.Open(/* verify= */ true,
48*795d594fSAndroid Build Coastguard Worker                             /* verify_checksum= */ true,
49*795d594fSAndroid Build Coastguard Worker                             &error_msg,
50*795d594fSAndroid Build Coastguard Worker                             dex_files)) {
51*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << error_msg;
52*795d594fSAndroid Build Coastguard Worker     return false;
53*795d594fSAndroid Build Coastguard Worker   }
54*795d594fSAndroid Build Coastguard Worker   return true;
55*795d594fSAndroid Build Coastguard Worker }
56*795d594fSAndroid Build Coastguard Worker 
Install(Runtime * runtime,std::vector<std::unique_ptr<const DexFile>> & in,std::vector<const DexFile * > * out)57*795d594fSAndroid Build Coastguard Worker jobject Install(Runtime* runtime,
58*795d594fSAndroid Build Coastguard Worker                 std::vector<std::unique_ptr<const DexFile>>& in,
59*795d594fSAndroid Build Coastguard Worker                 std::vector<const DexFile*>* out)
60*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
61*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
62*795d594fSAndroid Build Coastguard Worker   CHECK(self != nullptr);
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker   // Need well-known-classes.
65*795d594fSAndroid Build Coastguard Worker   WellKnownClasses::Init(self->GetJniEnv());
66*795d594fSAndroid Build Coastguard Worker   // Need a class loader. Fake that we're a compiler.
67*795d594fSAndroid Build Coastguard Worker   // Note: this will run initializers through the unstarted runtime, so make sure it's
68*795d594fSAndroid Build Coastguard Worker   //       initialized.
69*795d594fSAndroid Build Coastguard Worker   interpreter::UnstartedRuntime::Initialize();
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker   for (std::unique_ptr<const DexFile>& dex_file : in) {
72*795d594fSAndroid Build Coastguard Worker     out->push_back(dex_file.release());
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = runtime->GetClassLinker();
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker   jobject class_loader = class_linker->CreatePathClassLoader(self, *out);
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker   // Need to register dex files to get a working dex cache.
80*795d594fSAndroid Build Coastguard Worker   for (const DexFile* dex_file : *out) {
81*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::DexCache> dex_cache = class_linker->RegisterDexFile(
82*795d594fSAndroid Build Coastguard Worker         *dex_file, self->DecodeJObject(class_loader)->AsClassLoader());
83*795d594fSAndroid Build Coastguard Worker     CHECK(dex_cache != nullptr);
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker   return class_loader;
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker struct MethodVerifierArgs : public CmdlineArgs {
90*795d594fSAndroid Build Coastguard Worker  protected:
91*795d594fSAndroid Build Coastguard Worker   using Base = CmdlineArgs;
92*795d594fSAndroid Build Coastguard Worker 
ParseCustomart::__anon8f120b520111::MethodVerifierArgs93*795d594fSAndroid Build Coastguard Worker   ParseStatus ParseCustom(const char* raw_option,
94*795d594fSAndroid Build Coastguard Worker                           size_t raw_option_length,
95*795d594fSAndroid Build Coastguard Worker                           std::string* error_msg) override {
96*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(strlen(raw_option), raw_option_length);
97*795d594fSAndroid Build Coastguard Worker     {
98*795d594fSAndroid Build Coastguard Worker       ParseStatus base_parse = Base::ParseCustom(raw_option, raw_option_length, error_msg);
99*795d594fSAndroid Build Coastguard Worker       if (base_parse != kParseUnknownArgument) {
100*795d594fSAndroid Build Coastguard Worker         return base_parse;
101*795d594fSAndroid Build Coastguard Worker       }
102*795d594fSAndroid Build Coastguard Worker     }
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker     std::string_view option(raw_option, raw_option_length);
105*795d594fSAndroid Build Coastguard Worker     if (option.starts_with("--dex-file=")) {
106*795d594fSAndroid Build Coastguard Worker       dex_filename_ = raw_option + strlen("--dex-file=");
107*795d594fSAndroid Build Coastguard Worker     } else if (option == "--dex-file-verifier") {
108*795d594fSAndroid Build Coastguard Worker       dex_file_verifier_ = true;
109*795d594fSAndroid Build Coastguard Worker     } else if (option == "--verbose") {
110*795d594fSAndroid Build Coastguard Worker       method_verifier_verbose_ = true;
111*795d594fSAndroid Build Coastguard Worker     } else if (option == "--verbose-debug") {
112*795d594fSAndroid Build Coastguard Worker       method_verifier_verbose_debug_ = true;
113*795d594fSAndroid Build Coastguard Worker     } else if (option.starts_with("--repetitions=")) {
114*795d594fSAndroid Build Coastguard Worker       char* end;
115*795d594fSAndroid Build Coastguard Worker       repetitions_ = strtoul(raw_option + strlen("--repetitions="), &end, 10);
116*795d594fSAndroid Build Coastguard Worker     } else if (option.starts_with("--api-level=")) {
117*795d594fSAndroid Build Coastguard Worker       char* end;
118*795d594fSAndroid Build Coastguard Worker       api_level_ = strtoul(raw_option + strlen("--api-level="), &end, 10);
119*795d594fSAndroid Build Coastguard Worker     } else {
120*795d594fSAndroid Build Coastguard Worker       return kParseUnknownArgument;
121*795d594fSAndroid Build Coastguard Worker     }
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker     return kParseOk;
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker 
ParseChecksart::__anon8f120b520111::MethodVerifierArgs126*795d594fSAndroid Build Coastguard Worker   ParseStatus ParseChecks(std::string* error_msg) override {
127*795d594fSAndroid Build Coastguard Worker     // Perform the parent checks.
128*795d594fSAndroid Build Coastguard Worker     ParseStatus parent_checks = Base::ParseChecks(error_msg);
129*795d594fSAndroid Build Coastguard Worker     if (parent_checks != kParseOk) {
130*795d594fSAndroid Build Coastguard Worker       return parent_checks;
131*795d594fSAndroid Build Coastguard Worker     }
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker     // Perform our own checks.
134*795d594fSAndroid Build Coastguard Worker     if (dex_filename_ == nullptr) {
135*795d594fSAndroid Build Coastguard Worker       *error_msg = "--dex-filename not set";
136*795d594fSAndroid Build Coastguard Worker       return kParseError;
137*795d594fSAndroid Build Coastguard Worker     }
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker     return kParseOk;
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
GetUsageart::__anon8f120b520111::MethodVerifierArgs142*795d594fSAndroid Build Coastguard Worker   std::string GetUsage() const override {
143*795d594fSAndroid Build Coastguard Worker     std::string usage;
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker     usage +=
146*795d594fSAndroid Build Coastguard Worker         "Usage: method_verifier_cmd [options] ...\n"
147*795d594fSAndroid Build Coastguard Worker         // Dex file is required.
148*795d594fSAndroid Build Coastguard Worker         "  --dex-file=<file.dex>: specifies an input dex file.\n"
149*795d594fSAndroid Build Coastguard Worker         "      Example: --dex-file=app.apk\n"
150*795d594fSAndroid Build Coastguard Worker         "  --dex-file-verifier: only run dex file verifier.\n"
151*795d594fSAndroid Build Coastguard Worker         "  --verbose: use verbose verifier mode.\n"
152*795d594fSAndroid Build Coastguard Worker         "  --verbose-debug: use verbose verifier debug mode.\n"
153*795d594fSAndroid Build Coastguard Worker         "  --repetitions=<count>: repeat the verification count times.\n"
154*795d594fSAndroid Build Coastguard Worker         "  --api-level=<level>: use API level for verification.\n"
155*795d594fSAndroid Build Coastguard Worker         "\n";
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker     usage += Base::GetUsage();
158*795d594fSAndroid Build Coastguard Worker 
159*795d594fSAndroid Build Coastguard Worker     return usage;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker  public:
163*795d594fSAndroid Build Coastguard Worker   const char* dex_filename_ = nullptr;
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   bool dex_file_verifier_ = false;
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   bool method_verifier_verbose_ = false;
168*795d594fSAndroid Build Coastguard Worker   bool method_verifier_verbose_debug_ = false;
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   size_t repetitions_ = 0u;
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker   uint32_t api_level_ = 0u;
173*795d594fSAndroid Build Coastguard Worker };
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> {
NeedsRuntimeart::__anon8f120b520111::MethodVerifierMain176*795d594fSAndroid Build Coastguard Worker   bool NeedsRuntime() override {
177*795d594fSAndroid Build Coastguard Worker     return true;
178*795d594fSAndroid Build Coastguard Worker   }
179*795d594fSAndroid Build Coastguard Worker 
ExecuteWithoutRuntimeart::__anon8f120b520111::MethodVerifierMain180*795d594fSAndroid Build Coastguard Worker   bool ExecuteWithoutRuntime() override {
181*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unreachable";
182*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
ExecuteWithRuntimeart::__anon8f120b520111::MethodVerifierMain185*795d594fSAndroid Build Coastguard Worker   bool ExecuteWithRuntime(Runtime* runtime) override {
186*795d594fSAndroid Build Coastguard Worker     CHECK(args_ != nullptr);
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker     const size_t dex_reps = args_->dex_file_verifier_
189*795d594fSAndroid Build Coastguard Worker                                 // If we're focused on the dex file verifier, use the
190*795d594fSAndroid Build Coastguard Worker                                 // repetitions parameter.
191*795d594fSAndroid Build Coastguard Worker                                 ? std::max(static_cast<size_t>(1u), args_->repetitions_)
192*795d594fSAndroid Build Coastguard Worker                                 // Otherwise just load the dex files once.
193*795d594fSAndroid Build Coastguard Worker                                 : 1;
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> unique_dex_files;
196*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i != dex_reps; ++i) {
197*795d594fSAndroid Build Coastguard Worker       if (args_->dex_file_verifier_ && args_->repetitions_ != 0) {
198*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << "Repetition " << (i + 1);
199*795d594fSAndroid Build Coastguard Worker       }
200*795d594fSAndroid Build Coastguard Worker       unique_dex_files.clear();
201*795d594fSAndroid Build Coastguard Worker       if (!LoadDexFile(args_->dex_filename_, &unique_dex_files)) {
202*795d594fSAndroid Build Coastguard Worker         return false;
203*795d594fSAndroid Build Coastguard Worker       }
204*795d594fSAndroid Build Coastguard Worker     }
205*795d594fSAndroid Build Coastguard Worker     if (args_->dex_file_verifier_) {
206*795d594fSAndroid Build Coastguard Worker       // We're done here.
207*795d594fSAndroid Build Coastguard Worker       return true;
208*795d594fSAndroid Build Coastguard Worker     }
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
211*795d594fSAndroid Build Coastguard Worker     std::vector<const DexFile*> dex_files;
212*795d594fSAndroid Build Coastguard Worker     jobject class_loader = Install(runtime, unique_dex_files, &dex_files);
213*795d594fSAndroid Build Coastguard Worker     CHECK(class_loader != nullptr);
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker     StackHandleScope<3> scope(soa.Self());
216*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ClassLoader> h_loader = scope.NewHandle(
217*795d594fSAndroid Build Coastguard Worker         soa.Decode<mirror::ClassLoader>(class_loader));
218*795d594fSAndroid Build Coastguard Worker     MutableHandle<mirror::Class> h_klass(scope.NewHandle<mirror::Class>(nullptr));
219*795d594fSAndroid Build Coastguard Worker     MutableHandle<mirror::DexCache> h_dex_cache(scope.NewHandle<mirror::DexCache>(nullptr));
220*795d594fSAndroid Build Coastguard Worker 
221*795d594fSAndroid Build Coastguard Worker     if (args_->method_verifier_verbose_) {
222*795d594fSAndroid Build Coastguard Worker       gLogVerbosity.verifier = true;
223*795d594fSAndroid Build Coastguard Worker     }
224*795d594fSAndroid Build Coastguard Worker     if (args_->method_verifier_verbose_debug_) {
225*795d594fSAndroid Build Coastguard Worker       gLogVerbosity.verifier_debug = true;
226*795d594fSAndroid Build Coastguard Worker     }
227*795d594fSAndroid Build Coastguard Worker 
228*795d594fSAndroid Build Coastguard Worker     const size_t verifier_reps = std::max(static_cast<size_t>(1u), args_->repetitions_);
229*795d594fSAndroid Build Coastguard Worker 
230*795d594fSAndroid Build Coastguard Worker     ClassLinker* class_linker = runtime->GetClassLinker();
231*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i != verifier_reps; ++i) {
232*795d594fSAndroid Build Coastguard Worker       if (args_->repetitions_ != 0) {
233*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << "Repetition " << (i + 1);
234*795d594fSAndroid Build Coastguard Worker       }
235*795d594fSAndroid Build Coastguard Worker       for (const DexFile* dex_file : dex_files) {
236*795d594fSAndroid Build Coastguard Worker         for (ClassAccessor accessor : dex_file->GetClasses()) {
237*795d594fSAndroid Build Coastguard Worker           h_klass.Assign(
238*795d594fSAndroid Build Coastguard Worker               class_linker->FindClass(soa.Self(), *dex_file, accessor.GetClassIdx(), h_loader));
239*795d594fSAndroid Build Coastguard Worker           if (h_klass == nullptr || h_klass->IsErroneous()) {
240*795d594fSAndroid Build Coastguard Worker             if (args_->repetitions_ == 0) {
241*795d594fSAndroid Build Coastguard Worker               LOG(ERROR) << "Warning: could not load " << accessor.GetDescriptor();
242*795d594fSAndroid Build Coastguard Worker             }
243*795d594fSAndroid Build Coastguard Worker             soa.Self()->ClearException();
244*795d594fSAndroid Build Coastguard Worker             continue;
245*795d594fSAndroid Build Coastguard Worker           }
246*795d594fSAndroid Build Coastguard Worker           h_dex_cache.Assign(h_klass->GetDexCache());
247*795d594fSAndroid Build Coastguard Worker           std::string error_msg;
248*795d594fSAndroid Build Coastguard Worker           verifier::FailureKind res =
249*795d594fSAndroid Build Coastguard Worker             verifier::ClassVerifier::VerifyClass(soa.Self(),
250*795d594fSAndroid Build Coastguard Worker                                                  /* verifier_deps= */ nullptr,
251*795d594fSAndroid Build Coastguard Worker                                                  h_dex_cache->GetDexFile(),
252*795d594fSAndroid Build Coastguard Worker                                                  h_klass,
253*795d594fSAndroid Build Coastguard Worker                                                  h_dex_cache,
254*795d594fSAndroid Build Coastguard Worker                                                  h_loader,
255*795d594fSAndroid Build Coastguard Worker                                                  *h_klass->GetClassDef(),
256*795d594fSAndroid Build Coastguard Worker                                                  runtime->GetCompilerCallbacks(),
257*795d594fSAndroid Build Coastguard Worker                                                  verifier::HardFailLogMode::kLogWarning,
258*795d594fSAndroid Build Coastguard Worker                                                  args_->api_level_,
259*795d594fSAndroid Build Coastguard Worker                                                  &error_msg);
260*795d594fSAndroid Build Coastguard Worker           if (args_->repetitions_ == 0) {
261*795d594fSAndroid Build Coastguard Worker             LOG(INFO) << accessor.GetDescriptor() << ": " << res << " " << error_msg;
262*795d594fSAndroid Build Coastguard Worker           }
263*795d594fSAndroid Build Coastguard Worker         }
264*795d594fSAndroid Build Coastguard Worker       }
265*795d594fSAndroid Build Coastguard Worker     }
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker     return true;
268*795d594fSAndroid Build Coastguard Worker   }
269*795d594fSAndroid Build Coastguard Worker };
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker }  // namespace
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker }  // namespace art
274*795d594fSAndroid Build Coastguard Worker 
main(int argc,char ** argv)275*795d594fSAndroid Build Coastguard Worker int main(int argc, char** argv) {
276*795d594fSAndroid Build Coastguard Worker   // Output all logging to stderr.
277*795d594fSAndroid Build Coastguard Worker   android::base::SetLogger(android::base::StderrLogger);
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   art::MethodVerifierMain main;
280*795d594fSAndroid Build Coastguard Worker   return main.Main(argc, argv);
281*795d594fSAndroid Build Coastguard Worker }
282