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