1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 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 "oat_file_manager.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <queue>
24*795d594fSAndroid Build Coastguard Worker #include <vector>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
27*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
28*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
29*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/bit_vector-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/logging.h" // For VLOG.
33*795d594fSAndroid Build Coastguard Worker #include "base/mutex-inl.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/sdk_version.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
36*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
37*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
38*795d594fSAndroid Build Coastguard Worker #include "class_loader_context.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
40*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
42*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_tracking_registrar.h"
43*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
44*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
45*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
47*795d594fSAndroid Build Coastguard Worker #include "jni/java_vm_ext.h"
48*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
49*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
50*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
51*795d594fSAndroid Build Coastguard Worker #include "oat_file.h"
52*795d594fSAndroid Build Coastguard Worker #include "oat_file_assistant.h"
53*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
54*795d594fSAndroid Build Coastguard Worker #include "runtime_image.h"
55*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
56*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
57*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
58*795d594fSAndroid Build Coastguard Worker #include "thread_pool.h"
59*795d594fSAndroid Build Coastguard Worker #include "vdex_file.h"
60*795d594fSAndroid Build Coastguard Worker #include "verifier/verifier_deps.h"
61*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
66*795d594fSAndroid Build Coastguard Worker
67*795d594fSAndroid Build Coastguard Worker // If true, we attempt to load the application image if it exists.
68*795d594fSAndroid Build Coastguard Worker static constexpr bool kEnableAppImage = true;
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker // If true, we attempt to load an app image generated by the runtime.
71*795d594fSAndroid Build Coastguard Worker static const bool kEnableRuntimeAppImage = true;
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker #if defined(__ANDROID__)
74*795d594fSAndroid Build Coastguard Worker static const char* kDisableAppImageKeyword = "_disable_art_image_";
75*795d594fSAndroid Build Coastguard Worker #endif
76*795d594fSAndroid Build Coastguard Worker
RegisterOatFile(std::unique_ptr<const OatFile> oat_file,bool in_memory)77*795d594fSAndroid Build Coastguard Worker const OatFile* OatFileManager::RegisterOatFile(std::unique_ptr<const OatFile> oat_file,
78*795d594fSAndroid Build Coastguard Worker bool in_memory) {
79*795d594fSAndroid Build Coastguard Worker // Use class_linker vlog to match the log for dex file registration.
80*795d594fSAndroid Build Coastguard Worker VLOG(class_linker) << "Registered oat file " << oat_file->GetLocation();
81*795d594fSAndroid Build Coastguard Worker PaletteNotifyOatFileLoaded(oat_file->GetLocation().c_str());
82*795d594fSAndroid Build Coastguard Worker
83*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
84*795d594fSAndroid Build Coastguard Worker CHECK(in_memory ||
85*795d594fSAndroid Build Coastguard Worker !only_use_system_oat_files_ ||
86*795d594fSAndroid Build Coastguard Worker LocationIsTrusted(oat_file->GetLocation(), !Runtime::Current()->DenyArtApexDataFiles()) ||
87*795d594fSAndroid Build Coastguard Worker !oat_file->IsExecutable())
88*795d594fSAndroid Build Coastguard Worker << "Registering a non /system oat file: " << oat_file->GetLocation() << " android-root="
89*795d594fSAndroid Build Coastguard Worker << GetAndroidRoot();
90*795d594fSAndroid Build Coastguard Worker DCHECK(oat_file != nullptr);
91*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
92*795d594fSAndroid Build Coastguard Worker CHECK(oat_files_.find(oat_file) == oat_files_.end());
93*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const OatFile>& existing : oat_files_) {
94*795d594fSAndroid Build Coastguard Worker CHECK_NE(oat_file.get(), existing.get()) << oat_file->GetLocation();
95*795d594fSAndroid Build Coastguard Worker // Check that we don't have an oat file with the same address. Copies of the same oat file
96*795d594fSAndroid Build Coastguard Worker // should be loaded at different addresses.
97*795d594fSAndroid Build Coastguard Worker CHECK_NE(oat_file->Begin(), existing->Begin()) << "Oat file already mapped at that location";
98*795d594fSAndroid Build Coastguard Worker }
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker const OatFile* ret = oat_file.get();
101*795d594fSAndroid Build Coastguard Worker oat_files_.insert(std::move(oat_file));
102*795d594fSAndroid Build Coastguard Worker return ret;
103*795d594fSAndroid Build Coastguard Worker }
104*795d594fSAndroid Build Coastguard Worker
UnRegisterAndDeleteOatFile(const OatFile * oat_file)105*795d594fSAndroid Build Coastguard Worker void OatFileManager::UnRegisterAndDeleteOatFile(const OatFile* oat_file) {
106*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
107*795d594fSAndroid Build Coastguard Worker DCHECK(oat_file != nullptr);
108*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const OatFile> compare(oat_file);
109*795d594fSAndroid Build Coastguard Worker auto it = oat_files_.find(compare);
110*795d594fSAndroid Build Coastguard Worker CHECK(it != oat_files_.end());
111*795d594fSAndroid Build Coastguard Worker oat_files_.erase(it);
112*795d594fSAndroid Build Coastguard Worker compare.release(); // NOLINT b/117926937
113*795d594fSAndroid Build Coastguard Worker }
114*795d594fSAndroid Build Coastguard Worker
FindOpenedOatFileFromDexLocation(const std::string & dex_base_location) const115*795d594fSAndroid Build Coastguard Worker const OatFile* OatFileManager::FindOpenedOatFileFromDexLocation(
116*795d594fSAndroid Build Coastguard Worker const std::string& dex_base_location) const {
117*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
118*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
119*795d594fSAndroid Build Coastguard Worker const std::vector<const OatDexFile*>& oat_dex_files = oat_file->GetOatDexFiles();
120*795d594fSAndroid Build Coastguard Worker for (const OatDexFile* oat_dex_file : oat_dex_files) {
121*795d594fSAndroid Build Coastguard Worker if (DexFileLoader::GetBaseLocation(oat_dex_file->GetDexFileLocation()) == dex_base_location) {
122*795d594fSAndroid Build Coastguard Worker return oat_file.get();
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker }
126*795d594fSAndroid Build Coastguard Worker return nullptr;
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker
FindOpenedOatFileFromOatLocation(const std::string & oat_location) const129*795d594fSAndroid Build Coastguard Worker const OatFile* OatFileManager::FindOpenedOatFileFromOatLocation(const std::string& oat_location)
130*795d594fSAndroid Build Coastguard Worker const {
131*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
132*795d594fSAndroid Build Coastguard Worker return FindOpenedOatFileFromOatLocationLocked(oat_location);
133*795d594fSAndroid Build Coastguard Worker }
134*795d594fSAndroid Build Coastguard Worker
FindOpenedOatFileFromOatLocationLocked(const std::string & oat_location) const135*795d594fSAndroid Build Coastguard Worker const OatFile* OatFileManager::FindOpenedOatFileFromOatLocationLocked(
136*795d594fSAndroid Build Coastguard Worker const std::string& oat_location) const {
137*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
138*795d594fSAndroid Build Coastguard Worker if (oat_file->GetLocation() == oat_location) {
139*795d594fSAndroid Build Coastguard Worker return oat_file.get();
140*795d594fSAndroid Build Coastguard Worker }
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker return nullptr;
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker
GetBootOatFiles() const145*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> OatFileManager::GetBootOatFiles() const {
146*795d594fSAndroid Build Coastguard Worker std::vector<gc::space::ImageSpace*> image_spaces =
147*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->GetBootImageSpaces();
148*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> oat_files;
149*795d594fSAndroid Build Coastguard Worker oat_files.reserve(image_spaces.size());
150*795d594fSAndroid Build Coastguard Worker for (gc::space::ImageSpace* image_space : image_spaces) {
151*795d594fSAndroid Build Coastguard Worker oat_files.push_back(image_space->GetOatFile());
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker return oat_files;
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker
OatFileManager()156*795d594fSAndroid Build Coastguard Worker OatFileManager::OatFileManager()
157*795d594fSAndroid Build Coastguard Worker : only_use_system_oat_files_(false) {}
158*795d594fSAndroid Build Coastguard Worker
~OatFileManager()159*795d594fSAndroid Build Coastguard Worker OatFileManager::~OatFileManager() {
160*795d594fSAndroid Build Coastguard Worker // Explicitly clear oat_files_ since the OatFile destructor calls back into OatFileManager for
161*795d594fSAndroid Build Coastguard Worker // UnRegisterOatFileLocation.
162*795d594fSAndroid Build Coastguard Worker oat_files_.clear();
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker
RegisterImageOatFiles(const std::vector<gc::space::ImageSpace * > & spaces)165*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> OatFileManager::RegisterImageOatFiles(
166*795d594fSAndroid Build Coastguard Worker const std::vector<gc::space::ImageSpace*>& spaces) {
167*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> oat_files;
168*795d594fSAndroid Build Coastguard Worker oat_files.reserve(spaces.size());
169*795d594fSAndroid Build Coastguard Worker for (gc::space::ImageSpace* space : spaces) {
170*795d594fSAndroid Build Coastguard Worker // The oat file was generated in memory if the image space has a profile.
171*795d594fSAndroid Build Coastguard Worker bool in_memory = !space->GetProfileFiles().empty();
172*795d594fSAndroid Build Coastguard Worker oat_files.push_back(RegisterOatFile(space->ReleaseOatFile(), in_memory));
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker return oat_files;
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker
ShouldLoadAppImage() const177*795d594fSAndroid Build Coastguard Worker bool OatFileManager::ShouldLoadAppImage() const {
178*795d594fSAndroid Build Coastguard Worker Runtime* const runtime = Runtime::Current();
179*795d594fSAndroid Build Coastguard Worker if (!kEnableAppImage || runtime->IsJavaDebuggableAtInit()) {
180*795d594fSAndroid Build Coastguard Worker return false;
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker
183*795d594fSAndroid Build Coastguard Worker #if defined(__ANDROID__)
184*795d594fSAndroid Build Coastguard Worker const char* process_name = getprogname();
185*795d594fSAndroid Build Coastguard Worker // Some processes would rather take the runtime impact in the interest of memory (b/292210260)
186*795d594fSAndroid Build Coastguard Worker if (process_name != nullptr && strstr(process_name, kDisableAppImageKeyword) != nullptr) {
187*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "Skipping app image load for " << process_name;
188*795d594fSAndroid Build Coastguard Worker return false;
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker #endif
191*795d594fSAndroid Build Coastguard Worker
192*795d594fSAndroid Build Coastguard Worker return true;
193*795d594fSAndroid Build Coastguard Worker }
194*795d594fSAndroid Build Coastguard Worker
OpenDexFilesFromOat(const char * dex_location,jobject class_loader,jobjectArray dex_elements,const OatFile ** out_oat_file,std::vector<std::string> * error_msgs)195*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
196*795d594fSAndroid Build Coastguard Worker const char* dex_location,
197*795d594fSAndroid Build Coastguard Worker jobject class_loader,
198*795d594fSAndroid Build Coastguard Worker jobjectArray dex_elements,
199*795d594fSAndroid Build Coastguard Worker const OatFile** out_oat_file,
200*795d594fSAndroid Build Coastguard Worker std::vector<std::string>* error_msgs) {
201*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(StringPrintf("%s(%s)", __FUNCTION__, dex_location));
202*795d594fSAndroid Build Coastguard Worker CHECK(dex_location != nullptr);
203*795d594fSAndroid Build Coastguard Worker CHECK(error_msgs != nullptr);
204*795d594fSAndroid Build Coastguard Worker
205*795d594fSAndroid Build Coastguard Worker // Verify we aren't holding the mutator lock, which could starve GC when
206*795d594fSAndroid Build Coastguard Worker // hitting the disk.
207*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
208*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertNotHeld(self);
209*795d594fSAndroid Build Coastguard Worker Runtime* const runtime = Runtime::Current();
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
212*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderContext> context(
213*795d594fSAndroid Build Coastguard Worker ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements));
214*795d594fSAndroid Build Coastguard Worker
215*795d594fSAndroid Build Coastguard Worker // If the class_loader is null there's not much we can do. This happens if a dex files is loaded
216*795d594fSAndroid Build Coastguard Worker // directly with DexFile APIs instead of using class loaders.
217*795d594fSAndroid Build Coastguard Worker if (class_loader == nullptr) {
218*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Opening an oat file without a class loader. "
219*795d594fSAndroid Build Coastguard Worker << "Are you using the deprecated DexFile APIs?";
220*795d594fSAndroid Build Coastguard Worker } else if (context != nullptr) {
221*795d594fSAndroid Build Coastguard Worker auto oat_file_assistant = std::make_unique<OatFileAssistant>(dex_location,
222*795d594fSAndroid Build Coastguard Worker kRuntimeQuickCodeISA,
223*795d594fSAndroid Build Coastguard Worker context.get(),
224*795d594fSAndroid Build Coastguard Worker runtime->GetOatFilesExecutable(),
225*795d594fSAndroid Build Coastguard Worker only_use_system_oat_files_);
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker // Get the current optimization status for trace debugging.
228*795d594fSAndroid Build Coastguard Worker // Implementation detail note: GetOptimizationStatus will select the same
229*795d594fSAndroid Build Coastguard Worker // oat file as GetBestOatFile used below, and in doing so it already pre-populates
230*795d594fSAndroid Build Coastguard Worker // some OatFileAssistant internal fields.
231*795d594fSAndroid Build Coastguard Worker std::string odex_location;
232*795d594fSAndroid Build Coastguard Worker std::string compilation_filter;
233*795d594fSAndroid Build Coastguard Worker std::string compilation_reason;
234*795d594fSAndroid Build Coastguard Worker std::string odex_status;
235*795d594fSAndroid Build Coastguard Worker OatFileAssistant::Location ignored_location;
236*795d594fSAndroid Build Coastguard Worker oat_file_assistant->GetOptimizationStatus(
237*795d594fSAndroid Build Coastguard Worker &odex_location, &compilation_filter, &compilation_reason, &odex_status, &ignored_location);
238*795d594fSAndroid Build Coastguard Worker
239*795d594fSAndroid Build Coastguard Worker ScopedTrace odex_loading(StringPrintf(
240*795d594fSAndroid Build Coastguard Worker "location=%s status=%s filter=%s reason=%s",
241*795d594fSAndroid Build Coastguard Worker odex_location.c_str(),
242*795d594fSAndroid Build Coastguard Worker odex_status.c_str(),
243*795d594fSAndroid Build Coastguard Worker compilation_filter.c_str(),
244*795d594fSAndroid Build Coastguard Worker compilation_reason.c_str()));
245*795d594fSAndroid Build Coastguard Worker
246*795d594fSAndroid Build Coastguard Worker const bool has_registered_app_info = Runtime::Current()->GetAppInfo()->HasRegisteredAppInfo();
247*795d594fSAndroid Build Coastguard Worker const AppInfo::CodeType code_type =
248*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetAppInfo()->GetRegisteredCodeType(dex_location);
249*795d594fSAndroid Build Coastguard Worker // We only want to madvise primary/split dex artifacts as a startup optimization. However,
250*795d594fSAndroid Build Coastguard Worker // as the code_type for those artifacts may not be set until the initial app info registration,
251*795d594fSAndroid Build Coastguard Worker // we conservatively madvise everything until the app info registration is complete.
252*795d594fSAndroid Build Coastguard Worker const bool should_madvise = !has_registered_app_info ||
253*795d594fSAndroid Build Coastguard Worker code_type == AppInfo::CodeType::kPrimaryApk ||
254*795d594fSAndroid Build Coastguard Worker code_type == AppInfo::CodeType::kSplitApk;
255*795d594fSAndroid Build Coastguard Worker
256*795d594fSAndroid Build Coastguard Worker // Proceed with oat file loading.
257*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const OatFile> oat_file(oat_file_assistant->GetBestOatFile().release());
258*795d594fSAndroid Build Coastguard Worker VLOG(oat) << "OatFileAssistant(" << dex_location << ").GetBestOatFile()="
259*795d594fSAndroid Build Coastguard Worker << (oat_file != nullptr ? oat_file->GetLocation() : "")
260*795d594fSAndroid Build Coastguard Worker << " (executable=" << (oat_file != nullptr ? oat_file->IsExecutable() : false) << ")";
261*795d594fSAndroid Build Coastguard Worker
262*795d594fSAndroid Build Coastguard Worker CHECK(oat_file == nullptr || odex_location == oat_file->GetLocation())
263*795d594fSAndroid Build Coastguard Worker << "OatFileAssistant non-determinism in choosing best oat files. "
264*795d594fSAndroid Build Coastguard Worker << "optimization-status-location=" << odex_location
265*795d594fSAndroid Build Coastguard Worker << " best_oat_file-location=" << oat_file->GetLocation();
266*795d594fSAndroid Build Coastguard Worker
267*795d594fSAndroid Build Coastguard Worker if (oat_file != nullptr) {
268*795d594fSAndroid Build Coastguard Worker bool compilation_enabled =
269*795d594fSAndroid Build Coastguard Worker CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter());
270*795d594fSAndroid Build Coastguard Worker // Load the dex files from the oat file.
271*795d594fSAndroid Build Coastguard Worker bool added_image_space = false;
272*795d594fSAndroid Build Coastguard Worker if (should_madvise) {
273*795d594fSAndroid Build Coastguard Worker VLOG(oat) << "Madvising oat file: " << oat_file->GetLocation();
274*795d594fSAndroid Build Coastguard Worker size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
275*795d594fSAndroid Build Coastguard Worker Runtime::MadviseFileForRange(madvise_size_limit,
276*795d594fSAndroid Build Coastguard Worker oat_file->Size(),
277*795d594fSAndroid Build Coastguard Worker oat_file->Begin(),
278*795d594fSAndroid Build Coastguard Worker oat_file->End(),
279*795d594fSAndroid Build Coastguard Worker oat_file->GetLocation());
280*795d594fSAndroid Build Coastguard Worker }
281*795d594fSAndroid Build Coastguard Worker
282*795d594fSAndroid Build Coastguard Worker ScopedTrace app_image_timing("AppImage:Loading");
283*795d594fSAndroid Build Coastguard Worker
284*795d594fSAndroid Build Coastguard Worker // We need to throw away the image space if we are debuggable but the oat-file source of the
285*795d594fSAndroid Build Coastguard Worker // image is not otherwise we might get classes with inlined methods or other such things.
286*795d594fSAndroid Build Coastguard Worker std::unique_ptr<gc::space::ImageSpace> image_space;
287*795d594fSAndroid Build Coastguard Worker if (ShouldLoadAppImage()) {
288*795d594fSAndroid Build Coastguard Worker if (oat_file->IsExecutable()) {
289*795d594fSAndroid Build Coastguard Worker // App images generated by the compiler can only be used if the oat file
290*795d594fSAndroid Build Coastguard Worker // is executable.
291*795d594fSAndroid Build Coastguard Worker image_space = oat_file_assistant->OpenImageSpace(oat_file.get());
292*795d594fSAndroid Build Coastguard Worker }
293*795d594fSAndroid Build Coastguard Worker // Load the runtime image. This logic must be aligned with the one that determines when to
294*795d594fSAndroid Build Coastguard Worker // keep runtime images in `ArtManagerLocal.cleanup` in
295*795d594fSAndroid Build Coastguard Worker // `art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java`.
296*795d594fSAndroid Build Coastguard Worker if (kEnableRuntimeAppImage && image_space == nullptr && !compilation_enabled) {
297*795d594fSAndroid Build Coastguard Worker std::string art_file = RuntimeImage::GetRuntimeImagePath(dex_location);
298*795d594fSAndroid Build Coastguard Worker std::string error_msg;
299*795d594fSAndroid Build Coastguard Worker image_space = gc::space::ImageSpace::CreateFromAppImage(
300*795d594fSAndroid Build Coastguard Worker art_file.c_str(), oat_file.get(), &error_msg);
301*795d594fSAndroid Build Coastguard Worker if (image_space == nullptr) {
302*795d594fSAndroid Build Coastguard Worker (OS::FileExists(art_file.c_str()) ? LOG_STREAM(INFO) : VLOG_STREAM(image))
303*795d594fSAndroid Build Coastguard Worker << "Could not load runtime generated app image: " << error_msg;
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker }
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker if (image_space != nullptr) {
308*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
309*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self);
310*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> h_loader(
311*795d594fSAndroid Build Coastguard Worker hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader)));
312*795d594fSAndroid Build Coastguard Worker // Can not load app image without class loader.
313*795d594fSAndroid Build Coastguard Worker if (h_loader != nullptr) {
314*795d594fSAndroid Build Coastguard Worker oat_file->SetAppImageBegin(image_space->Begin());
315*795d594fSAndroid Build Coastguard Worker std::string temp_error_msg;
316*795d594fSAndroid Build Coastguard Worker // Add image space has a race condition since other threads could be reading from the
317*795d594fSAndroid Build Coastguard Worker // spaces array.
318*795d594fSAndroid Build Coastguard Worker {
319*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
320*795d594fSAndroid Build Coastguard Worker gc::ScopedGCCriticalSection gcs(self,
321*795d594fSAndroid Build Coastguard Worker gc::kGcCauseAddRemoveAppImageSpace,
322*795d594fSAndroid Build Coastguard Worker gc::kCollectorTypeAddRemoveAppImageSpace);
323*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa("Add image space");
324*795d594fSAndroid Build Coastguard Worker runtime->GetHeap()->AddSpace(image_space.get());
325*795d594fSAndroid Build Coastguard Worker }
326*795d594fSAndroid Build Coastguard Worker {
327*795d594fSAndroid Build Coastguard Worker ScopedTrace image_space_timing("Adding image space");
328*795d594fSAndroid Build Coastguard Worker gc::space::ImageSpace* space_ptr = image_space.get();
329*795d594fSAndroid Build Coastguard Worker added_image_space = runtime->GetClassLinker()->AddImageSpaces(
330*795d594fSAndroid Build Coastguard Worker ArrayRef<gc::space::ImageSpace*>(&space_ptr, /*size=*/1),
331*795d594fSAndroid Build Coastguard Worker h_loader,
332*795d594fSAndroid Build Coastguard Worker context.get(),
333*795d594fSAndroid Build Coastguard Worker /*out*/ &dex_files,
334*795d594fSAndroid Build Coastguard Worker /*out*/ &temp_error_msg);
335*795d594fSAndroid Build Coastguard Worker }
336*795d594fSAndroid Build Coastguard Worker if (added_image_space) {
337*795d594fSAndroid Build Coastguard Worker // Successfully added image space to heap, release the map so that it does not get
338*795d594fSAndroid Build Coastguard Worker // freed.
339*795d594fSAndroid Build Coastguard Worker image_space.release(); // NOLINT b/117926937
340*795d594fSAndroid Build Coastguard Worker
341*795d594fSAndroid Build Coastguard Worker // Register for tracking.
342*795d594fSAndroid Build Coastguard Worker for (const auto& dex_file : dex_files) {
343*795d594fSAndroid Build Coastguard Worker dex::tracking::RegisterDexFile(dex_file.get());
344*795d594fSAndroid Build Coastguard Worker }
345*795d594fSAndroid Build Coastguard Worker } else {
346*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "Failed to add image file: " << temp_error_msg;
347*795d594fSAndroid Build Coastguard Worker oat_file->SetAppImageBegin(nullptr);
348*795d594fSAndroid Build Coastguard Worker dex_files.clear();
349*795d594fSAndroid Build Coastguard Worker {
350*795d594fSAndroid Build Coastguard Worker ScopedThreadSuspension sts(self, ThreadState::kSuspended);
351*795d594fSAndroid Build Coastguard Worker gc::ScopedGCCriticalSection gcs(self,
352*795d594fSAndroid Build Coastguard Worker gc::kGcCauseAddRemoveAppImageSpace,
353*795d594fSAndroid Build Coastguard Worker gc::kCollectorTypeAddRemoveAppImageSpace);
354*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa("Remove image space");
355*795d594fSAndroid Build Coastguard Worker runtime->GetHeap()->RemoveSpace(image_space.get());
356*795d594fSAndroid Build Coastguard Worker }
357*795d594fSAndroid Build Coastguard Worker // Non-fatal, don't update error_msg.
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker }
361*795d594fSAndroid Build Coastguard Worker if (!added_image_space) {
362*795d594fSAndroid Build Coastguard Worker DCHECK(dex_files.empty());
363*795d594fSAndroid Build Coastguard Worker
364*795d594fSAndroid Build Coastguard Worker if (oat_file->RequiresImage()) {
365*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Loading "
366*795d594fSAndroid Build Coastguard Worker << oat_file->GetLocation()
367*795d594fSAndroid Build Coastguard Worker << " non-executable as it requires an image which we failed to load";
368*795d594fSAndroid Build Coastguard Worker // file as non-executable.
369*795d594fSAndroid Build Coastguard Worker auto nonexecutable_oat_file_assistant =
370*795d594fSAndroid Build Coastguard Worker std::make_unique<OatFileAssistant>(dex_location,
371*795d594fSAndroid Build Coastguard Worker kRuntimeQuickCodeISA,
372*795d594fSAndroid Build Coastguard Worker context.get(),
373*795d594fSAndroid Build Coastguard Worker /*load_executable=*/false,
374*795d594fSAndroid Build Coastguard Worker only_use_system_oat_files_);
375*795d594fSAndroid Build Coastguard Worker oat_file.reset(nonexecutable_oat_file_assistant->GetBestOatFile().release());
376*795d594fSAndroid Build Coastguard Worker
377*795d594fSAndroid Build Coastguard Worker // The file could be deleted concurrently (for example background
378*795d594fSAndroid Build Coastguard Worker // dexopt, or secondary oat file being deleted by the app).
379*795d594fSAndroid Build Coastguard Worker if (oat_file == nullptr) {
380*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Failed to reload oat file non-executable " << dex_location;
381*795d594fSAndroid Build Coastguard Worker }
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker
384*795d594fSAndroid Build Coastguard Worker if (oat_file != nullptr) {
385*795d594fSAndroid Build Coastguard Worker dex_files = oat_file_assistant->LoadDexFiles(*oat_file.get(), dex_location);
386*795d594fSAndroid Build Coastguard Worker
387*795d594fSAndroid Build Coastguard Worker // Register for tracking.
388*795d594fSAndroid Build Coastguard Worker for (const auto& dex_file : dex_files) {
389*795d594fSAndroid Build Coastguard Worker dex::tracking::RegisterDexFile(dex_file.get());
390*795d594fSAndroid Build Coastguard Worker }
391*795d594fSAndroid Build Coastguard Worker }
392*795d594fSAndroid Build Coastguard Worker }
393*795d594fSAndroid Build Coastguard Worker if (dex_files.empty()) {
394*795d594fSAndroid Build Coastguard Worker ScopedTrace failed_to_open_dex_files("FailedToOpenDexFilesFromOat");
395*795d594fSAndroid Build Coastguard Worker error_msgs->push_back("Failed to open dex files from " + odex_location);
396*795d594fSAndroid Build Coastguard Worker } else if (should_madvise) {
397*795d594fSAndroid Build Coastguard Worker size_t madvise_size_limit = Runtime::Current()->GetMadviseWillNeedTotalDexSize();
398*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
399*795d594fSAndroid Build Coastguard Worker // Prefetch the dex file based on vdex size limit (name should
400*795d594fSAndroid Build Coastguard Worker // have been dex size limit).
401*795d594fSAndroid Build Coastguard Worker VLOG(oat) << "Madvising dex file: " << dex_file->GetLocation();
402*795d594fSAndroid Build Coastguard Worker Runtime::MadviseFileForRange(madvise_size_limit,
403*795d594fSAndroid Build Coastguard Worker dex_file->Size(),
404*795d594fSAndroid Build Coastguard Worker dex_file->Begin(),
405*795d594fSAndroid Build Coastguard Worker dex_file->Begin() + dex_file->Size(),
406*795d594fSAndroid Build Coastguard Worker dex_file->GetLocation());
407*795d594fSAndroid Build Coastguard Worker if (dex_file->Size() >= madvise_size_limit) {
408*795d594fSAndroid Build Coastguard Worker break;
409*795d594fSAndroid Build Coastguard Worker }
410*795d594fSAndroid Build Coastguard Worker madvise_size_limit -= dex_file->Size();
411*795d594fSAndroid Build Coastguard Worker }
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker
414*795d594fSAndroid Build Coastguard Worker if (oat_file != nullptr) {
415*795d594fSAndroid Build Coastguard Worker VLOG(class_linker) << "Registering " << oat_file->GetLocation();
416*795d594fSAndroid Build Coastguard Worker *out_oat_file = RegisterOatFile(std::move(oat_file));
417*795d594fSAndroid Build Coastguard Worker }
418*795d594fSAndroid Build Coastguard Worker } else {
419*795d594fSAndroid Build Coastguard Worker // oat_file == nullptr
420*795d594fSAndroid Build Coastguard Worker // Verify if any of the dex files being loaded is already in the class path.
421*795d594fSAndroid Build Coastguard Worker // If so, report an error with the current stack trace.
422*795d594fSAndroid Build Coastguard Worker // Most likely the developer didn't intend to do this because it will waste
423*795d594fSAndroid Build Coastguard Worker // performance and memory.
424*795d594fSAndroid Build Coastguard Worker if (oat_file_assistant->GetBestStatus() == OatFileAssistant::kOatContextOutOfDate) {
425*795d594fSAndroid Build Coastguard Worker std::set<const DexFile*> already_exists_in_classpath =
426*795d594fSAndroid Build Coastguard Worker context->CheckForDuplicateDexFiles(MakeNonOwningPointerVector(dex_files));
427*795d594fSAndroid Build Coastguard Worker if (!already_exists_in_classpath.empty()) {
428*795d594fSAndroid Build Coastguard Worker ScopedTrace duplicate_dex_files("DuplicateDexFilesInContext");
429*795d594fSAndroid Build Coastguard Worker auto duplicate_it = already_exists_in_classpath.begin();
430*795d594fSAndroid Build Coastguard Worker std::string duplicates = (*duplicate_it)->GetLocation();
431*795d594fSAndroid Build Coastguard Worker for (duplicate_it++ ; duplicate_it != already_exists_in_classpath.end(); duplicate_it++) {
432*795d594fSAndroid Build Coastguard Worker duplicates += "," + (*duplicate_it)->GetLocation();
433*795d594fSAndroid Build Coastguard Worker }
434*795d594fSAndroid Build Coastguard Worker
435*795d594fSAndroid Build Coastguard Worker std::ostringstream out;
436*795d594fSAndroid Build Coastguard Worker out << "Trying to load dex files which is already loaded in the same ClassLoader "
437*795d594fSAndroid Build Coastguard Worker << "hierarchy.\n"
438*795d594fSAndroid Build Coastguard Worker << "This is a strong indication of bad ClassLoader construct which leads to poor "
439*795d594fSAndroid Build Coastguard Worker << "performance and wastes memory.\n"
440*795d594fSAndroid Build Coastguard Worker << "The list of duplicate dex files is: " << duplicates << "\n"
441*795d594fSAndroid Build Coastguard Worker << "The current class loader context is: "
442*795d594fSAndroid Build Coastguard Worker << context->EncodeContextForOatFile("") << "\n"
443*795d594fSAndroid Build Coastguard Worker << "Java stack trace:\n";
444*795d594fSAndroid Build Coastguard Worker
445*795d594fSAndroid Build Coastguard Worker {
446*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
447*795d594fSAndroid Build Coastguard Worker self->DumpJavaStack(out);
448*795d594fSAndroid Build Coastguard Worker }
449*795d594fSAndroid Build Coastguard Worker
450*795d594fSAndroid Build Coastguard Worker // We log this as an ERROR to stress the fact that this is most likely unintended.
451*795d594fSAndroid Build Coastguard Worker // Note that ART cannot do anything about it. It is up to the app to fix their logic.
452*795d594fSAndroid Build Coastguard Worker // Here we are trying to give a heads up on why the app might have performance issues.
453*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << out.str();
454*795d594fSAndroid Build Coastguard Worker }
455*795d594fSAndroid Build Coastguard Worker }
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker
458*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetAppInfo()->RegisterOdexStatus(
459*795d594fSAndroid Build Coastguard Worker dex_location,
460*795d594fSAndroid Build Coastguard Worker compilation_filter,
461*795d594fSAndroid Build Coastguard Worker compilation_reason,
462*795d594fSAndroid Build Coastguard Worker odex_status);
463*795d594fSAndroid Build Coastguard Worker }
464*795d594fSAndroid Build Coastguard Worker
465*795d594fSAndroid Build Coastguard Worker // If we arrive here with an empty dex files list, it means we fail to load
466*795d594fSAndroid Build Coastguard Worker // it/them through an .oat file.
467*795d594fSAndroid Build Coastguard Worker if (dex_files.empty()) {
468*795d594fSAndroid Build Coastguard Worker std::string error_msg;
469*795d594fSAndroid Build Coastguard Worker static constexpr bool kVerifyChecksum = true;
470*795d594fSAndroid Build Coastguard Worker ArtDexFileLoader dex_file_loader(dex_location);
471*795d594fSAndroid Build Coastguard Worker if (!dex_file_loader.Open(Runtime::Current()->IsVerificationEnabled(),
472*795d594fSAndroid Build Coastguard Worker kVerifyChecksum,
473*795d594fSAndroid Build Coastguard Worker /*out*/ &error_msg,
474*795d594fSAndroid Build Coastguard Worker &dex_files)) {
475*795d594fSAndroid Build Coastguard Worker ScopedTrace fail_to_open_dex_from_apk("FailedToOpenDexFilesFromApk");
476*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << error_msg;
477*795d594fSAndroid Build Coastguard Worker error_msgs->push_back("Failed to open dex files from " + std::string(dex_location)
478*795d594fSAndroid Build Coastguard Worker + " because: " + error_msg);
479*795d594fSAndroid Build Coastguard Worker }
480*795d594fSAndroid Build Coastguard Worker }
481*795d594fSAndroid Build Coastguard Worker
482*795d594fSAndroid Build Coastguard Worker if (Runtime::Current()->GetJit() != nullptr) {
483*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJit()->RegisterDexFiles(dex_files, class_loader);
484*795d594fSAndroid Build Coastguard Worker }
485*795d594fSAndroid Build Coastguard Worker
486*795d594fSAndroid Build Coastguard Worker // Now that we loaded the dex/odex files, notify the runtime.
487*795d594fSAndroid Build Coastguard Worker // Note that we do this everytime we load dex files.
488*795d594fSAndroid Build Coastguard Worker Runtime::Current()->NotifyDexFileLoaded();
489*795d594fSAndroid Build Coastguard Worker
490*795d594fSAndroid Build Coastguard Worker return dex_files;
491*795d594fSAndroid Build Coastguard Worker }
492*795d594fSAndroid Build Coastguard Worker
GetDexFileHeaders(const std::vector<MemMap> & maps)493*795d594fSAndroid Build Coastguard Worker static std::vector<const DexFile::Header*> GetDexFileHeaders(const std::vector<MemMap>& maps) {
494*795d594fSAndroid Build Coastguard Worker std::vector<const DexFile::Header*> headers;
495*795d594fSAndroid Build Coastguard Worker headers.reserve(maps.size());
496*795d594fSAndroid Build Coastguard Worker for (const MemMap& map : maps) {
497*795d594fSAndroid Build Coastguard Worker DCHECK(map.IsValid());
498*795d594fSAndroid Build Coastguard Worker headers.push_back(reinterpret_cast<const DexFile::Header*>(map.Begin()));
499*795d594fSAndroid Build Coastguard Worker }
500*795d594fSAndroid Build Coastguard Worker return headers;
501*795d594fSAndroid Build Coastguard Worker }
502*795d594fSAndroid Build Coastguard Worker
OpenDexFilesFromOat(std::vector<MemMap> && dex_mem_maps,jobject class_loader,jobjectArray dex_elements,const OatFile ** out_oat_file,std::vector<std::string> * error_msgs)503*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat(
504*795d594fSAndroid Build Coastguard Worker std::vector<MemMap>&& dex_mem_maps,
505*795d594fSAndroid Build Coastguard Worker jobject class_loader,
506*795d594fSAndroid Build Coastguard Worker jobjectArray dex_elements,
507*795d594fSAndroid Build Coastguard Worker const OatFile** out_oat_file,
508*795d594fSAndroid Build Coastguard Worker std::vector<std::string>* error_msgs) {
509*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files = OpenDexFilesFromOat_Impl(
510*795d594fSAndroid Build Coastguard Worker std::move(dex_mem_maps),
511*795d594fSAndroid Build Coastguard Worker class_loader,
512*795d594fSAndroid Build Coastguard Worker dex_elements,
513*795d594fSAndroid Build Coastguard Worker out_oat_file,
514*795d594fSAndroid Build Coastguard Worker error_msgs);
515*795d594fSAndroid Build Coastguard Worker
516*795d594fSAndroid Build Coastguard Worker if (error_msgs->empty()) {
517*795d594fSAndroid Build Coastguard Worker // Remove write permission from DexFile pages. We do this at the end because
518*795d594fSAndroid Build Coastguard Worker // OatFile assigns OatDexFile pointer in the DexFile objects.
519*795d594fSAndroid Build Coastguard Worker for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
520*795d594fSAndroid Build Coastguard Worker if (!dex_file->DisableWrite()) {
521*795d594fSAndroid Build Coastguard Worker error_msgs->push_back("Failed to make dex file " + dex_file->GetLocation() + " read-only");
522*795d594fSAndroid Build Coastguard Worker }
523*795d594fSAndroid Build Coastguard Worker }
524*795d594fSAndroid Build Coastguard Worker }
525*795d594fSAndroid Build Coastguard Worker
526*795d594fSAndroid Build Coastguard Worker if (!error_msgs->empty()) {
527*795d594fSAndroid Build Coastguard Worker return std::vector<std::unique_ptr<const DexFile>>();
528*795d594fSAndroid Build Coastguard Worker }
529*795d594fSAndroid Build Coastguard Worker
530*795d594fSAndroid Build Coastguard Worker return dex_files;
531*795d594fSAndroid Build Coastguard Worker }
532*795d594fSAndroid Build Coastguard Worker
OpenDexFilesFromOat_Impl(std::vector<MemMap> && dex_mem_maps,jobject class_loader,jobjectArray dex_elements,const OatFile ** out_oat_file,std::vector<std::string> * error_msgs)533*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat_Impl(
534*795d594fSAndroid Build Coastguard Worker std::vector<MemMap>&& dex_mem_maps,
535*795d594fSAndroid Build Coastguard Worker jobject class_loader,
536*795d594fSAndroid Build Coastguard Worker jobjectArray dex_elements,
537*795d594fSAndroid Build Coastguard Worker const OatFile** out_oat_file,
538*795d594fSAndroid Build Coastguard Worker std::vector<std::string>* error_msgs) {
539*795d594fSAndroid Build Coastguard Worker ScopedTrace trace(__FUNCTION__);
540*795d594fSAndroid Build Coastguard Worker std::string error_msg;
541*795d594fSAndroid Build Coastguard Worker DCHECK(error_msgs != nullptr);
542*795d594fSAndroid Build Coastguard Worker
543*795d594fSAndroid Build Coastguard Worker // Extract dex file headers from `dex_mem_maps`.
544*795d594fSAndroid Build Coastguard Worker const std::vector<const DexFile::Header*> dex_headers = GetDexFileHeaders(dex_mem_maps);
545*795d594fSAndroid Build Coastguard Worker
546*795d594fSAndroid Build Coastguard Worker // Determine dex/vdex locations and the combined location checksum.
547*795d594fSAndroid Build Coastguard Worker std::string dex_location;
548*795d594fSAndroid Build Coastguard Worker std::string vdex_path;
549*795d594fSAndroid Build Coastguard Worker bool has_vdex = OatFileAssistant::AnonymousDexVdexLocation(dex_headers,
550*795d594fSAndroid Build Coastguard Worker kRuntimeQuickCodeISA,
551*795d594fSAndroid Build Coastguard Worker &dex_location,
552*795d594fSAndroid Build Coastguard Worker &vdex_path);
553*795d594fSAndroid Build Coastguard Worker
554*795d594fSAndroid Build Coastguard Worker // Attempt to open an existing vdex and check dex file checksums match.
555*795d594fSAndroid Build Coastguard Worker std::unique_ptr<VdexFile> vdex_file = nullptr;
556*795d594fSAndroid Build Coastguard Worker if (has_vdex && OS::FileExists(vdex_path.c_str())) {
557*795d594fSAndroid Build Coastguard Worker vdex_file = VdexFile::Open(vdex_path,
558*795d594fSAndroid Build Coastguard Worker /* writable= */ false,
559*795d594fSAndroid Build Coastguard Worker /* low_4gb= */ false,
560*795d594fSAndroid Build Coastguard Worker &error_msg);
561*795d594fSAndroid Build Coastguard Worker if (vdex_file == nullptr) {
562*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Failed to open vdex " << vdex_path << ": " << error_msg;
563*795d594fSAndroid Build Coastguard Worker } else if (!vdex_file->MatchesDexFileChecksums(dex_headers)) {
564*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Failed to open vdex " << vdex_path << ": dex file checksum mismatch";
565*795d594fSAndroid Build Coastguard Worker vdex_file.reset(nullptr);
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker }
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker // Load dex files. Skip structural dex file verification if vdex was found
570*795d594fSAndroid Build Coastguard Worker // and dex checksums matched.
571*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
572*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < dex_mem_maps.size(); ++i) {
573*795d594fSAndroid Build Coastguard Worker static constexpr bool kVerifyChecksum = true;
574*795d594fSAndroid Build Coastguard Worker ArtDexFileLoader dex_file_loader(std::move(dex_mem_maps[i]),
575*795d594fSAndroid Build Coastguard Worker DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()));
576*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(
577*795d594fSAndroid Build Coastguard Worker dex_headers[i]->checksum_,
578*795d594fSAndroid Build Coastguard Worker /* verify= */ (vdex_file == nullptr) && Runtime::Current()->IsVerificationEnabled(),
579*795d594fSAndroid Build Coastguard Worker kVerifyChecksum,
580*795d594fSAndroid Build Coastguard Worker &error_msg));
581*795d594fSAndroid Build Coastguard Worker if (dex_file != nullptr) {
582*795d594fSAndroid Build Coastguard Worker dex::tracking::RegisterDexFile(dex_file.get()); // Register for tracking.
583*795d594fSAndroid Build Coastguard Worker dex_files.push_back(std::move(dex_file));
584*795d594fSAndroid Build Coastguard Worker } else {
585*795d594fSAndroid Build Coastguard Worker error_msgs->push_back("Failed to open dex files from memory: " + error_msg);
586*795d594fSAndroid Build Coastguard Worker }
587*795d594fSAndroid Build Coastguard Worker }
588*795d594fSAndroid Build Coastguard Worker
589*795d594fSAndroid Build Coastguard Worker // Check if we should proceed to creating an OatFile instance backed by the vdex.
590*795d594fSAndroid Build Coastguard Worker // We need: (a) an existing vdex, (b) class loader (can be null if invoked via reflection),
591*795d594fSAndroid Build Coastguard Worker // and (c) no errors during dex file loading.
592*795d594fSAndroid Build Coastguard Worker if (vdex_file == nullptr || class_loader == nullptr || !error_msgs->empty()) {
593*795d594fSAndroid Build Coastguard Worker return dex_files;
594*795d594fSAndroid Build Coastguard Worker }
595*795d594fSAndroid Build Coastguard Worker
596*795d594fSAndroid Build Coastguard Worker // Attempt to create a class loader context, check OpenDexFiles succeeds (prerequisite
597*795d594fSAndroid Build Coastguard Worker // for using the context later).
598*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::CreateContextForClassLoader(
599*795d594fSAndroid Build Coastguard Worker class_loader,
600*795d594fSAndroid Build Coastguard Worker dex_elements);
601*795d594fSAndroid Build Coastguard Worker if (context == nullptr) {
602*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Could not create class loader context for " << vdex_path;
603*795d594fSAndroid Build Coastguard Worker return dex_files;
604*795d594fSAndroid Build Coastguard Worker }
605*795d594fSAndroid Build Coastguard Worker DCHECK(context->OpenDexFiles())
606*795d594fSAndroid Build Coastguard Worker << "Context created from already opened dex files should not attempt to open again";
607*795d594fSAndroid Build Coastguard Worker
608*795d594fSAndroid Build Coastguard Worker // Initialize an OatFile instance backed by the loaded vdex.
609*795d594fSAndroid Build Coastguard Worker std::unique_ptr<OatFile> oat_file(OatFile::OpenFromVdex(MakeNonOwningPointerVector(dex_files),
610*795d594fSAndroid Build Coastguard Worker std::move(vdex_file),
611*795d594fSAndroid Build Coastguard Worker dex_location,
612*795d594fSAndroid Build Coastguard Worker context.get()));
613*795d594fSAndroid Build Coastguard Worker if (oat_file != nullptr) {
614*795d594fSAndroid Build Coastguard Worker VLOG(class_linker) << "Registering " << oat_file->GetLocation();
615*795d594fSAndroid Build Coastguard Worker *out_oat_file = RegisterOatFile(std::move(oat_file));
616*795d594fSAndroid Build Coastguard Worker }
617*795d594fSAndroid Build Coastguard Worker return dex_files;
618*795d594fSAndroid Build Coastguard Worker }
619*795d594fSAndroid Build Coastguard Worker
620*795d594fSAndroid Build Coastguard Worker // Check how many vdex files exist in the same directory as the vdex file we are about
621*795d594fSAndroid Build Coastguard Worker // to write. If more than or equal to kAnonymousVdexCacheSize, unlink the least
622*795d594fSAndroid Build Coastguard Worker // recently used one(s) (according to stat-reported atime).
UnlinkLeastRecentlyUsedVdexIfNeeded(const std::string & vdex_path_to_add,std::string * error_msg)623*795d594fSAndroid Build Coastguard Worker static bool UnlinkLeastRecentlyUsedVdexIfNeeded(const std::string& vdex_path_to_add,
624*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
625*795d594fSAndroid Build Coastguard Worker std::string basename = android::base::Basename(vdex_path_to_add);
626*795d594fSAndroid Build Coastguard Worker if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
627*795d594fSAndroid Build Coastguard Worker // File is not for in memory dex files.
628*795d594fSAndroid Build Coastguard Worker return true;
629*795d594fSAndroid Build Coastguard Worker }
630*795d594fSAndroid Build Coastguard Worker
631*795d594fSAndroid Build Coastguard Worker if (OS::FileExists(vdex_path_to_add.c_str())) {
632*795d594fSAndroid Build Coastguard Worker // File already exists and will be overwritten.
633*795d594fSAndroid Build Coastguard Worker // This will not change the number of entries in the cache.
634*795d594fSAndroid Build Coastguard Worker return true;
635*795d594fSAndroid Build Coastguard Worker }
636*795d594fSAndroid Build Coastguard Worker
637*795d594fSAndroid Build Coastguard Worker auto last_slash = vdex_path_to_add.rfind('/');
638*795d594fSAndroid Build Coastguard Worker CHECK(last_slash != std::string::npos);
639*795d594fSAndroid Build Coastguard Worker std::string vdex_dir = vdex_path_to_add.substr(0, last_slash + 1);
640*795d594fSAndroid Build Coastguard Worker
641*795d594fSAndroid Build Coastguard Worker if (!OS::DirectoryExists(vdex_dir.c_str())) {
642*795d594fSAndroid Build Coastguard Worker // Folder does not exist yet. Cache has zero entries.
643*795d594fSAndroid Build Coastguard Worker return true;
644*795d594fSAndroid Build Coastguard Worker }
645*795d594fSAndroid Build Coastguard Worker
646*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<time_t, std::string>> cache;
647*795d594fSAndroid Build Coastguard Worker
648*795d594fSAndroid Build Coastguard Worker DIR* c_dir = opendir(vdex_dir.c_str());
649*795d594fSAndroid Build Coastguard Worker if (c_dir == nullptr) {
650*795d594fSAndroid Build Coastguard Worker *error_msg = "Unable to open " + vdex_dir + " to delete unused vdex files";
651*795d594fSAndroid Build Coastguard Worker return false;
652*795d594fSAndroid Build Coastguard Worker }
653*795d594fSAndroid Build Coastguard Worker for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
654*795d594fSAndroid Build Coastguard Worker if (de->d_type != DT_REG) {
655*795d594fSAndroid Build Coastguard Worker continue;
656*795d594fSAndroid Build Coastguard Worker }
657*795d594fSAndroid Build Coastguard Worker basename = de->d_name;
658*795d594fSAndroid Build Coastguard Worker if (!OatFileAssistant::IsAnonymousVdexBasename(basename)) {
659*795d594fSAndroid Build Coastguard Worker continue;
660*795d594fSAndroid Build Coastguard Worker }
661*795d594fSAndroid Build Coastguard Worker std::string fullname = vdex_dir + basename;
662*795d594fSAndroid Build Coastguard Worker
663*795d594fSAndroid Build Coastguard Worker struct stat s;
664*795d594fSAndroid Build Coastguard Worker int rc = TEMP_FAILURE_RETRY(stat(fullname.c_str(), &s));
665*795d594fSAndroid Build Coastguard Worker if (rc == -1) {
666*795d594fSAndroid Build Coastguard Worker *error_msg = "Failed to stat() anonymous vdex file " + fullname;
667*795d594fSAndroid Build Coastguard Worker return false;
668*795d594fSAndroid Build Coastguard Worker }
669*795d594fSAndroid Build Coastguard Worker
670*795d594fSAndroid Build Coastguard Worker cache.push_back(std::make_pair(s.st_atime, fullname));
671*795d594fSAndroid Build Coastguard Worker }
672*795d594fSAndroid Build Coastguard Worker CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
673*795d594fSAndroid Build Coastguard Worker
674*795d594fSAndroid Build Coastguard Worker if (cache.size() < OatFileManager::kAnonymousVdexCacheSize) {
675*795d594fSAndroid Build Coastguard Worker return true;
676*795d594fSAndroid Build Coastguard Worker }
677*795d594fSAndroid Build Coastguard Worker
678*795d594fSAndroid Build Coastguard Worker std::sort(cache.begin(),
679*795d594fSAndroid Build Coastguard Worker cache.end(),
680*795d594fSAndroid Build Coastguard Worker [](const auto& a, const auto& b) { return a.first < b.first; });
681*795d594fSAndroid Build Coastguard Worker for (size_t i = OatFileManager::kAnonymousVdexCacheSize - 1; i < cache.size(); ++i) {
682*795d594fSAndroid Build Coastguard Worker if (unlink(cache[i].second.c_str()) != 0) {
683*795d594fSAndroid Build Coastguard Worker *error_msg = "Could not unlink anonymous vdex file " + cache[i].second;
684*795d594fSAndroid Build Coastguard Worker return false;
685*795d594fSAndroid Build Coastguard Worker }
686*795d594fSAndroid Build Coastguard Worker }
687*795d594fSAndroid Build Coastguard Worker
688*795d594fSAndroid Build Coastguard Worker return true;
689*795d594fSAndroid Build Coastguard Worker }
690*795d594fSAndroid Build Coastguard Worker
691*795d594fSAndroid Build Coastguard Worker class BackgroundVerificationTask final : public Task {
692*795d594fSAndroid Build Coastguard Worker public:
BackgroundVerificationTask(const std::vector<const DexFile * > & dex_files,jobject class_loader,const std::string & vdex_path)693*795d594fSAndroid Build Coastguard Worker BackgroundVerificationTask(const std::vector<const DexFile*>& dex_files,
694*795d594fSAndroid Build Coastguard Worker jobject class_loader,
695*795d594fSAndroid Build Coastguard Worker const std::string& vdex_path)
696*795d594fSAndroid Build Coastguard Worker : dex_files_(dex_files),
697*795d594fSAndroid Build Coastguard Worker vdex_path_(vdex_path) {
698*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
699*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
700*795d594fSAndroid Build Coastguard Worker // Create a global ref for `class_loader` because it will be accessed from a different thread.
701*795d594fSAndroid Build Coastguard Worker class_loader_ = soa.Vm()->AddGlobalRef(self, soa.Decode<mirror::ClassLoader>(class_loader));
702*795d594fSAndroid Build Coastguard Worker CHECK(class_loader_ != nullptr);
703*795d594fSAndroid Build Coastguard Worker }
704*795d594fSAndroid Build Coastguard Worker
~BackgroundVerificationTask()705*795d594fSAndroid Build Coastguard Worker ~BackgroundVerificationTask() {
706*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
707*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
708*795d594fSAndroid Build Coastguard Worker soa.Vm()->DeleteGlobalRef(self, class_loader_);
709*795d594fSAndroid Build Coastguard Worker }
710*795d594fSAndroid Build Coastguard Worker
Run(Thread * self)711*795d594fSAndroid Build Coastguard Worker void Run(Thread* self) override {
712*795d594fSAndroid Build Coastguard Worker std::string error_msg;
713*795d594fSAndroid Build Coastguard Worker ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
714*795d594fSAndroid Build Coastguard Worker verifier::VerifierDeps verifier_deps(dex_files_);
715*795d594fSAndroid Build Coastguard Worker
716*795d594fSAndroid Build Coastguard Worker // Iterate over all classes and verify them.
717*795d594fSAndroid Build Coastguard Worker for (const DexFile* dex_file : dex_files_) {
718*795d594fSAndroid Build Coastguard Worker for (uint32_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); cdef_idx++) {
719*795d594fSAndroid Build Coastguard Worker const dex::ClassDef& class_def = dex_file->GetClassDef(cdef_idx);
720*795d594fSAndroid Build Coastguard Worker
721*795d594fSAndroid Build Coastguard Worker // Take handles inside the loop. The background verification is low priority
722*795d594fSAndroid Build Coastguard Worker // and we want to minimize the risk of blocking anyone else.
723*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
724*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(self);
725*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> h_loader(hs.NewHandle(
726*795d594fSAndroid Build Coastguard Worker soa.Decode<mirror::ClassLoader>(class_loader_)));
727*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_class =
728*795d594fSAndroid Build Coastguard Worker hs.NewHandle(class_linker->FindClass(self, *dex_file, class_def.class_idx_, h_loader));
729*795d594fSAndroid Build Coastguard Worker
730*795d594fSAndroid Build Coastguard Worker if (h_class == nullptr) {
731*795d594fSAndroid Build Coastguard Worker DCHECK(self->IsExceptionPending());
732*795d594fSAndroid Build Coastguard Worker self->ClearException();
733*795d594fSAndroid Build Coastguard Worker continue;
734*795d594fSAndroid Build Coastguard Worker }
735*795d594fSAndroid Build Coastguard Worker
736*795d594fSAndroid Build Coastguard Worker if (&h_class->GetDexFile() != dex_file) {
737*795d594fSAndroid Build Coastguard Worker // There is a different class in the class path or a parent class loader
738*795d594fSAndroid Build Coastguard Worker // with the same descriptor. This `h_class` is not resolvable, skip it.
739*795d594fSAndroid Build Coastguard Worker continue;
740*795d594fSAndroid Build Coastguard Worker }
741*795d594fSAndroid Build Coastguard Worker
742*795d594fSAndroid Build Coastguard Worker DCHECK(h_class->IsResolved()) << h_class->PrettyDescriptor();
743*795d594fSAndroid Build Coastguard Worker class_linker->VerifyClass(self, &verifier_deps, h_class);
744*795d594fSAndroid Build Coastguard Worker if (self->IsExceptionPending()) {
745*795d594fSAndroid Build Coastguard Worker // ClassLinker::VerifyClass can throw, but the exception isn't useful here.
746*795d594fSAndroid Build Coastguard Worker self->ClearException();
747*795d594fSAndroid Build Coastguard Worker }
748*795d594fSAndroid Build Coastguard Worker
749*795d594fSAndroid Build Coastguard Worker DCHECK(h_class->IsVerified() || h_class->IsErroneous())
750*795d594fSAndroid Build Coastguard Worker << h_class->PrettyDescriptor() << ": state=" << h_class->GetStatus();
751*795d594fSAndroid Build Coastguard Worker
752*795d594fSAndroid Build Coastguard Worker if (h_class->IsVerified()) {
753*795d594fSAndroid Build Coastguard Worker verifier_deps.RecordClassVerified(*dex_file, class_def);
754*795d594fSAndroid Build Coastguard Worker }
755*795d594fSAndroid Build Coastguard Worker }
756*795d594fSAndroid Build Coastguard Worker }
757*795d594fSAndroid Build Coastguard Worker
758*795d594fSAndroid Build Coastguard Worker // Delete old vdex files if there are too many in the folder.
759*795d594fSAndroid Build Coastguard Worker if (!UnlinkLeastRecentlyUsedVdexIfNeeded(vdex_path_, &error_msg)) {
760*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Could not unlink old vdex files " << vdex_path_ << ": " << error_msg;
761*795d594fSAndroid Build Coastguard Worker return;
762*795d594fSAndroid Build Coastguard Worker }
763*795d594fSAndroid Build Coastguard Worker
764*795d594fSAndroid Build Coastguard Worker // Construct a vdex file and write `verifier_deps` into it.
765*795d594fSAndroid Build Coastguard Worker if (!VdexFile::WriteToDisk(vdex_path_,
766*795d594fSAndroid Build Coastguard Worker dex_files_,
767*795d594fSAndroid Build Coastguard Worker verifier_deps,
768*795d594fSAndroid Build Coastguard Worker &error_msg)) {
769*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Could not write anonymous vdex " << vdex_path_ << ": " << error_msg;
770*795d594fSAndroid Build Coastguard Worker return;
771*795d594fSAndroid Build Coastguard Worker }
772*795d594fSAndroid Build Coastguard Worker }
773*795d594fSAndroid Build Coastguard Worker
Finalize()774*795d594fSAndroid Build Coastguard Worker void Finalize() override {
775*795d594fSAndroid Build Coastguard Worker delete this;
776*795d594fSAndroid Build Coastguard Worker }
777*795d594fSAndroid Build Coastguard Worker
778*795d594fSAndroid Build Coastguard Worker private:
779*795d594fSAndroid Build Coastguard Worker const std::vector<const DexFile*> dex_files_;
780*795d594fSAndroid Build Coastguard Worker jobject class_loader_;
781*795d594fSAndroid Build Coastguard Worker const std::string vdex_path_;
782*795d594fSAndroid Build Coastguard Worker
783*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(BackgroundVerificationTask);
784*795d594fSAndroid Build Coastguard Worker };
785*795d594fSAndroid Build Coastguard Worker
RunBackgroundVerification(const std::vector<const DexFile * > & dex_files,jobject class_loader)786*795d594fSAndroid Build Coastguard Worker void OatFileManager::RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
787*795d594fSAndroid Build Coastguard Worker jobject class_loader) {
788*795d594fSAndroid Build Coastguard Worker Runtime* const runtime = Runtime::Current();
789*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
790*795d594fSAndroid Build Coastguard Worker
791*795d594fSAndroid Build Coastguard Worker if (runtime->IsJavaDebuggable()) {
792*795d594fSAndroid Build Coastguard Worker // Threads created by ThreadPool ("runtime threads") are not allowed to load
793*795d594fSAndroid Build Coastguard Worker // classes when debuggable to match class-initialization semantics
794*795d594fSAndroid Build Coastguard Worker // expectations. Do not verify in the background.
795*795d594fSAndroid Build Coastguard Worker return;
796*795d594fSAndroid Build Coastguard Worker }
797*795d594fSAndroid Build Coastguard Worker
798*795d594fSAndroid Build Coastguard Worker {
799*795d594fSAndroid Build Coastguard Worker // Temporarily create a class loader context to see if we recognize the
800*795d594fSAndroid Build Coastguard Worker // chain.
801*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ClassLoaderContext> context(
802*795d594fSAndroid Build Coastguard Worker ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr));
803*795d594fSAndroid Build Coastguard Worker if (context == nullptr) {
804*795d594fSAndroid Build Coastguard Worker // We only run background verification for class loaders we know the lookup
805*795d594fSAndroid Build Coastguard Worker // chain. Because the background verification runs on runtime threads,
806*795d594fSAndroid Build Coastguard Worker // which do not call Java, we won't be able to load classes when
807*795d594fSAndroid Build Coastguard Worker // verifying, which is something the current verifier relies on.
808*795d594fSAndroid Build Coastguard Worker return;
809*795d594fSAndroid Build Coastguard Worker }
810*795d594fSAndroid Build Coastguard Worker }
811*795d594fSAndroid Build Coastguard Worker
812*795d594fSAndroid Build Coastguard Worker if (!IsSdkVersionSetAndAtLeast(runtime->GetTargetSdkVersion(), SdkVersion::kQ)) {
813*795d594fSAndroid Build Coastguard Worker // Do not run for legacy apps as they may depend on the previous class loader behaviour.
814*795d594fSAndroid Build Coastguard Worker return;
815*795d594fSAndroid Build Coastguard Worker }
816*795d594fSAndroid Build Coastguard Worker
817*795d594fSAndroid Build Coastguard Worker if (runtime->IsShuttingDown(self)) {
818*795d594fSAndroid Build Coastguard Worker // Not allowed to create new threads during runtime shutdown.
819*795d594fSAndroid Build Coastguard Worker return;
820*795d594fSAndroid Build Coastguard Worker }
821*795d594fSAndroid Build Coastguard Worker
822*795d594fSAndroid Build Coastguard Worker if (dex_files.size() < 1) {
823*795d594fSAndroid Build Coastguard Worker // Nothing to verify.
824*795d594fSAndroid Build Coastguard Worker return;
825*795d594fSAndroid Build Coastguard Worker }
826*795d594fSAndroid Build Coastguard Worker
827*795d594fSAndroid Build Coastguard Worker std::string dex_location = dex_files[0]->GetLocation();
828*795d594fSAndroid Build Coastguard Worker const std::string& data_dir = Runtime::Current()->GetProcessDataDirectory();
829*795d594fSAndroid Build Coastguard Worker if (!dex_location.starts_with(data_dir)) {
830*795d594fSAndroid Build Coastguard Worker // For now, we only run background verification for secondary dex files.
831*795d594fSAndroid Build Coastguard Worker // Running it for primary or split APKs could have some undesirable
832*795d594fSAndroid Build Coastguard Worker // side-effects, like overloading the device on app startup.
833*795d594fSAndroid Build Coastguard Worker return;
834*795d594fSAndroid Build Coastguard Worker }
835*795d594fSAndroid Build Coastguard Worker
836*795d594fSAndroid Build Coastguard Worker std::string error_msg;
837*795d594fSAndroid Build Coastguard Worker std::string odex_filename;
838*795d594fSAndroid Build Coastguard Worker if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
839*795d594fSAndroid Build Coastguard Worker kRuntimeQuickCodeISA,
840*795d594fSAndroid Build Coastguard Worker &odex_filename,
841*795d594fSAndroid Build Coastguard Worker &error_msg)) {
842*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
843*795d594fSAndroid Build Coastguard Worker return;
844*795d594fSAndroid Build Coastguard Worker }
845*795d594fSAndroid Build Coastguard Worker
846*795d594fSAndroid Build Coastguard Worker if (LocationIsOnArtApexData(odex_filename) && Runtime::Current()->DenyArtApexDataFiles()) {
847*795d594fSAndroid Build Coastguard Worker // Ignore vdex file associated with this odex file as the odex file is not trustworthy.
848*795d594fSAndroid Build Coastguard Worker return;
849*795d594fSAndroid Build Coastguard Worker }
850*795d594fSAndroid Build Coastguard Worker
851*795d594fSAndroid Build Coastguard Worker {
852*795d594fSAndroid Build Coastguard Worker WriterMutexLock mu(self, *Locks::oat_file_manager_lock_);
853*795d594fSAndroid Build Coastguard Worker if (verification_thread_pool_ == nullptr) {
854*795d594fSAndroid Build Coastguard Worker verification_thread_pool_.reset(
855*795d594fSAndroid Build Coastguard Worker ThreadPool::Create("Verification thread pool", /* num_threads= */ 1));
856*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->StartWorkers(self);
857*795d594fSAndroid Build Coastguard Worker }
858*795d594fSAndroid Build Coastguard Worker }
859*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->AddTask(self, new BackgroundVerificationTask(
860*795d594fSAndroid Build Coastguard Worker dex_files,
861*795d594fSAndroid Build Coastguard Worker class_loader,
862*795d594fSAndroid Build Coastguard Worker GetVdexFilename(odex_filename)));
863*795d594fSAndroid Build Coastguard Worker }
864*795d594fSAndroid Build Coastguard Worker
WaitForWorkersToBeCreated()865*795d594fSAndroid Build Coastguard Worker void OatFileManager::WaitForWorkersToBeCreated() {
866*795d594fSAndroid Build Coastguard Worker DCHECK(!Runtime::Current()->IsShuttingDown(Thread::Current()))
867*795d594fSAndroid Build Coastguard Worker << "Cannot create new threads during runtime shutdown";
868*795d594fSAndroid Build Coastguard Worker if (verification_thread_pool_ != nullptr) {
869*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->WaitForWorkersToBeCreated();
870*795d594fSAndroid Build Coastguard Worker }
871*795d594fSAndroid Build Coastguard Worker }
872*795d594fSAndroid Build Coastguard Worker
DeleteThreadPool()873*795d594fSAndroid Build Coastguard Worker void OatFileManager::DeleteThreadPool() {
874*795d594fSAndroid Build Coastguard Worker verification_thread_pool_.reset(nullptr);
875*795d594fSAndroid Build Coastguard Worker }
876*795d594fSAndroid Build Coastguard Worker
WaitForBackgroundVerificationTasksToFinish()877*795d594fSAndroid Build Coastguard Worker void OatFileManager::WaitForBackgroundVerificationTasksToFinish() {
878*795d594fSAndroid Build Coastguard Worker if (verification_thread_pool_ == nullptr) {
879*795d594fSAndroid Build Coastguard Worker return;
880*795d594fSAndroid Build Coastguard Worker }
881*795d594fSAndroid Build Coastguard Worker
882*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
883*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
884*795d594fSAndroid Build Coastguard Worker }
885*795d594fSAndroid Build Coastguard Worker
WaitForBackgroundVerificationTasks()886*795d594fSAndroid Build Coastguard Worker void OatFileManager::WaitForBackgroundVerificationTasks() {
887*795d594fSAndroid Build Coastguard Worker if (verification_thread_pool_ != nullptr) {
888*795d594fSAndroid Build Coastguard Worker Thread* const self = Thread::Current();
889*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->WaitForWorkersToBeCreated();
890*795d594fSAndroid Build Coastguard Worker verification_thread_pool_->Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
891*795d594fSAndroid Build Coastguard Worker }
892*795d594fSAndroid Build Coastguard Worker }
893*795d594fSAndroid Build Coastguard Worker
ClearOnlyUseTrustedOatFiles()894*795d594fSAndroid Build Coastguard Worker void OatFileManager::ClearOnlyUseTrustedOatFiles() {
895*795d594fSAndroid Build Coastguard Worker only_use_system_oat_files_ = false;
896*795d594fSAndroid Build Coastguard Worker }
897*795d594fSAndroid Build Coastguard Worker
SetOnlyUseTrustedOatFiles()898*795d594fSAndroid Build Coastguard Worker void OatFileManager::SetOnlyUseTrustedOatFiles() {
899*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
900*795d594fSAndroid Build Coastguard Worker if (!oat_files_.empty()) {
901*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected non-empty loaded oat files ";
902*795d594fSAndroid Build Coastguard Worker }
903*795d594fSAndroid Build Coastguard Worker only_use_system_oat_files_ = true;
904*795d594fSAndroid Build Coastguard Worker }
905*795d594fSAndroid Build Coastguard Worker
DumpForSigQuit(std::ostream & os)906*795d594fSAndroid Build Coastguard Worker void OatFileManager::DumpForSigQuit(std::ostream& os) {
907*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
908*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
909*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
910*795d594fSAndroid Build Coastguard Worker if (ContainsElement(boot_oat_files, oat_file.get())) {
911*795d594fSAndroid Build Coastguard Worker continue;
912*795d594fSAndroid Build Coastguard Worker }
913*795d594fSAndroid Build Coastguard Worker os << oat_file->GetLocation() << ": " << oat_file->GetCompilerFilter() << "\n";
914*795d594fSAndroid Build Coastguard Worker }
915*795d594fSAndroid Build Coastguard Worker }
916*795d594fSAndroid Build Coastguard Worker
ContainsPc(const void * code)917*795d594fSAndroid Build Coastguard Worker bool OatFileManager::ContainsPc(const void* code) {
918*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(Thread::Current(), *Locks::oat_file_manager_lock_);
919*795d594fSAndroid Build Coastguard Worker std::vector<const OatFile*> boot_oat_files = GetBootOatFiles();
920*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<const OatFile>& oat_file : oat_files_) {
921*795d594fSAndroid Build Coastguard Worker if (oat_file->Contains(code)) {
922*795d594fSAndroid Build Coastguard Worker return true;
923*795d594fSAndroid Build Coastguard Worker }
924*795d594fSAndroid Build Coastguard Worker }
925*795d594fSAndroid Build Coastguard Worker return false;
926*795d594fSAndroid Build Coastguard Worker }
927*795d594fSAndroid Build Coastguard Worker
928*795d594fSAndroid Build Coastguard Worker } // namespace art
929