1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 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 #ifndef ART_RUNTIME_CLASS_LOADER_UTILS_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_CLASS_LOADER_UTILS_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
23*795d594fSAndroid Build Coastguard Worker #include "handle_scope.h"
24*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
28*795d594fSAndroid Build Coastguard Worker #include "native/dalvik_system_DexFile.h"
29*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker // Returns true if the given class loader derives from BaseDexClassLoader.
IsInstanceOfBaseDexClassLoader(Handle<mirror::ClassLoader> class_loader)35*795d594fSAndroid Build Coastguard Worker inline bool IsInstanceOfBaseDexClassLoader(Handle<mirror::ClassLoader> class_loader)
36*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
37*795d594fSAndroid Build Coastguard Worker return class_loader->InstanceOf(WellKnownClasses::dalvik_system_BaseDexClassLoader.Get());
38*795d594fSAndroid Build Coastguard Worker }
39*795d594fSAndroid Build Coastguard Worker
40*795d594fSAndroid Build Coastguard Worker // Returns true if the given class loader is either a PathClassLoader or a DexClassLoader.
41*795d594fSAndroid Build Coastguard Worker // (they both have the same behaviour with respect to class lookup order)
IsPathOrDexClassLoader(Handle<mirror::ClassLoader> class_loader)42*795d594fSAndroid Build Coastguard Worker inline bool IsPathOrDexClassLoader(Handle<mirror::ClassLoader> class_loader)
43*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
44*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
45*795d594fSAndroid Build Coastguard Worker return (class_loader_class == WellKnownClasses::dalvik_system_PathClassLoader) ||
46*795d594fSAndroid Build Coastguard Worker (class_loader_class == WellKnownClasses::dalvik_system_DexClassLoader);
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker
49*795d594fSAndroid Build Coastguard Worker // Returns true if the given class loader is an InMemoryDexClassLoader.
IsInMemoryDexClassLoader(Handle<mirror::ClassLoader> class_loader)50*795d594fSAndroid Build Coastguard Worker inline bool IsInMemoryDexClassLoader(Handle<mirror::ClassLoader> class_loader)
51*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
52*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
53*795d594fSAndroid Build Coastguard Worker return (class_loader_class == WellKnownClasses::dalvik_system_InMemoryDexClassLoader);
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
IsDelegateLastClassLoader(Handle<mirror::ClassLoader> class_loader)56*795d594fSAndroid Build Coastguard Worker inline bool IsDelegateLastClassLoader(Handle<mirror::ClassLoader> class_loader)
57*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
58*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> class_loader_class = class_loader->GetClass();
59*795d594fSAndroid Build Coastguard Worker return class_loader_class == WellKnownClasses::dalvik_system_DelegateLastClassLoader;
60*795d594fSAndroid Build Coastguard Worker }
61*795d594fSAndroid Build Coastguard Worker
62*795d594fSAndroid Build Coastguard Worker // Visit the DexPathList$Element instances in the given classloader with the given visitor.
63*795d594fSAndroid Build Coastguard Worker // Constraints on the visitor:
64*795d594fSAndroid Build Coastguard Worker // * The visitor should return true to continue visiting more Elements.
65*795d594fSAndroid Build Coastguard Worker // * The last argument of the visitor is an out argument of RetType. It will be returned
66*795d594fSAndroid Build Coastguard Worker // when the visitor ends the visit (by returning false).
67*795d594fSAndroid Build Coastguard Worker // This function assumes that the given classloader is a subclass of BaseDexClassLoader!
68*795d594fSAndroid Build Coastguard Worker template <typename Visitor, typename RetType>
VisitClassLoaderDexElements(Thread * self,Handle<mirror::ClassLoader> class_loader,Visitor fn,RetType defaultReturn)69*795d594fSAndroid Build Coastguard Worker inline RetType VisitClassLoaderDexElements(Thread* self,
70*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader,
71*795d594fSAndroid Build Coastguard Worker Visitor fn,
72*795d594fSAndroid Build Coastguard Worker RetType defaultReturn)
73*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
74*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> dex_path_list =
75*795d594fSAndroid Build Coastguard Worker WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList->GetObject(class_loader.Get());
76*795d594fSAndroid Build Coastguard Worker if (dex_path_list != nullptr) {
77*795d594fSAndroid Build Coastguard Worker // DexPathList has an array dexElements of Elements[] which each contain a dex file.
78*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> dex_elements_obj =
79*795d594fSAndroid Build Coastguard Worker WellKnownClasses::dalvik_system_DexPathList_dexElements->GetObject(dex_path_list);
80*795d594fSAndroid Build Coastguard Worker // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
81*795d594fSAndroid Build Coastguard Worker // at the mCookie which is a DexFile vector.
82*795d594fSAndroid Build Coastguard Worker if (dex_elements_obj != nullptr) {
83*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self);
84*795d594fSAndroid Build Coastguard Worker Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
85*795d594fSAndroid Build Coastguard Worker hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
86*795d594fSAndroid Build Coastguard Worker for (auto element : dex_elements.Iterate<mirror::Object>()) {
87*795d594fSAndroid Build Coastguard Worker if (element == nullptr) {
88*795d594fSAndroid Build Coastguard Worker // Should never happen, fail.
89*795d594fSAndroid Build Coastguard Worker break;
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker RetType ret_value;
92*795d594fSAndroid Build Coastguard Worker if (!fn(element, &ret_value)) {
93*795d594fSAndroid Build Coastguard Worker return ret_value;
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker }
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker return defaultReturn;
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker // Visit the DexFiles in the given classloader with the given visitor.
102*795d594fSAndroid Build Coastguard Worker // Constraints on the visitor:
103*795d594fSAndroid Build Coastguard Worker // * The visitor should return true to continue visiting more DexFiles.
104*795d594fSAndroid Build Coastguard Worker // * The last argument of the visitor is an out argument of RetType. It will be returned
105*795d594fSAndroid Build Coastguard Worker // when the visitor ends the visit (by returning false).
106*795d594fSAndroid Build Coastguard Worker // This function assumes that the given classloader is a subclass of BaseDexClassLoader!
107*795d594fSAndroid Build Coastguard Worker template <typename Visitor, typename RetType>
VisitClassLoaderDexFiles(Thread * self,Handle<mirror::ClassLoader> class_loader,Visitor fn,RetType defaultReturn)108*795d594fSAndroid Build Coastguard Worker inline RetType VisitClassLoaderDexFiles(Thread* self,
109*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader,
110*795d594fSAndroid Build Coastguard Worker Visitor fn,
111*795d594fSAndroid Build Coastguard Worker RetType defaultReturn)
112*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
113*795d594fSAndroid Build Coastguard Worker ArtField* const cookie_field = WellKnownClasses::dalvik_system_DexFile_cookie;
114*795d594fSAndroid Build Coastguard Worker ArtField* const dex_file_field = WellKnownClasses::dalvik_system_DexPathList__Element_dexFile;
115*795d594fSAndroid Build Coastguard Worker if (dex_file_field == nullptr || cookie_field == nullptr) {
116*795d594fSAndroid Build Coastguard Worker return defaultReturn;
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker auto visit_dex_files = [&](ObjPtr<mirror::Object> element, RetType* ret)
119*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
120*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
121*795d594fSAndroid Build Coastguard Worker if (dex_file != nullptr) {
122*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self);
123*795d594fSAndroid Build Coastguard Worker Handle<mirror::LongArray> long_array =
124*795d594fSAndroid Build Coastguard Worker hs.NewHandle(cookie_field->GetObject(dex_file)->AsLongArray());
125*795d594fSAndroid Build Coastguard Worker if (long_array == nullptr) {
126*795d594fSAndroid Build Coastguard Worker // This should never happen so log a warning.
127*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Null DexFile::mCookie";
128*795d594fSAndroid Build Coastguard Worker *ret = defaultReturn;
129*795d594fSAndroid Build Coastguard Worker return true;
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker int32_t long_array_size = long_array->GetLength();
132*795d594fSAndroid Build Coastguard Worker // First element is the oat file.
133*795d594fSAndroid Build Coastguard Worker for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
134*795d594fSAndroid Build Coastguard Worker const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
135*795d594fSAndroid Build Coastguard Worker long_array->GetWithoutChecks(j)));
136*795d594fSAndroid Build Coastguard Worker RetType ret_value;
137*795d594fSAndroid Build Coastguard Worker if (!fn(cp_dex_file, /* out */ &ret_value)) {
138*795d594fSAndroid Build Coastguard Worker *ret = ret_value;
139*795d594fSAndroid Build Coastguard Worker return false;
140*795d594fSAndroid Build Coastguard Worker }
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker return true;
144*795d594fSAndroid Build Coastguard Worker };
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker return VisitClassLoaderDexElements(self, class_loader, visit_dex_files, defaultReturn);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker // Simplified version of the above, w/o out argument.
150*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitClassLoaderDexFiles(Thread * self,Handle<mirror::ClassLoader> class_loader,Visitor fn)151*795d594fSAndroid Build Coastguard Worker inline void VisitClassLoaderDexFiles(Thread* self,
152*795d594fSAndroid Build Coastguard Worker Handle<mirror::ClassLoader> class_loader,
153*795d594fSAndroid Build Coastguard Worker Visitor fn)
154*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
155*795d594fSAndroid Build Coastguard Worker auto helper = [&fn](const art::DexFile* dex_file, void** ret)
156*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
157*795d594fSAndroid Build Coastguard Worker #ifdef __clang_analyzer__
158*795d594fSAndroid Build Coastguard Worker *ret = nullptr;
159*795d594fSAndroid Build Coastguard Worker #else
160*795d594fSAndroid Build Coastguard Worker UNUSED(ret);
161*795d594fSAndroid Build Coastguard Worker #endif
162*795d594fSAndroid Build Coastguard Worker
163*795d594fSAndroid Build Coastguard Worker return fn(dex_file);
164*795d594fSAndroid Build Coastguard Worker };
165*795d594fSAndroid Build Coastguard Worker VisitClassLoaderDexFiles<decltype(helper), void*>(self,
166*795d594fSAndroid Build Coastguard Worker class_loader,
167*795d594fSAndroid Build Coastguard Worker helper,
168*795d594fSAndroid Build Coastguard Worker /* defaultReturn= */ nullptr);
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker
171*795d594fSAndroid Build Coastguard Worker } // namespace art
172*795d594fSAndroid Build Coastguard Worker
173*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_CLASS_LOADER_UTILS_H_
174