blob: c5988f6ce08f26b81700aaf28b4b6fbbd46dbbda [file] [log] [blame]
Calin Juravle87e2cb62017-06-13 21:48:45 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "class_loader_context.h"
18
Andreas Gampef9411702018-09-06 17:16:57 -070019#include <android-base/parseint.h>
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +000020#include <android-base/strings.h>
Andreas Gampef9411702018-09-06 17:16:57 -070021
Calin Juravle57d0acc2017-07-11 17:41:30 -070022#include "art_field-inl.h"
Vladimir Marko78baed52018-10-11 10:44:58 +010023#include "base/casts.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070024#include "base/dchecked_vector.h"
25#include "base/stl_util.h"
26#include "class_linker.h"
Calin Juravle57d0acc2017-07-11 17:41:30 -070027#include "class_loader_utils.h"
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +000028#include "class_root.h"
David Sehr013fd802018-01-11 22:55:24 -080029#include "dex/art_dex_file_loader.h"
David Sehr9e734c72018-01-04 17:56:19 -080030#include "dex/dex_file.h"
31#include "dex/dex_file_loader.h"
Calin Juravle57d0acc2017-07-11 17:41:30 -070032#include "handle_scope-inl.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010033#include "jni/jni_internal.h"
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +000034#include "mirror/object_array-alloc-inl.h"
35#include "nativehelper/scoped_local_ref.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070036#include "oat_file_assistant.h"
Calin Juravle57d0acc2017-07-11 17:41:30 -070037#include "obj_ptr-inl.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070038#include "runtime.h"
39#include "scoped_thread_state_change-inl.h"
40#include "thread.h"
Calin Juravle57d0acc2017-07-11 17:41:30 -070041#include "well_known_classes.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070042
43namespace art {
44
45static constexpr char kPathClassLoaderString[] = "PCL";
46static constexpr char kDelegateLastClassLoaderString[] = "DLC";
47static constexpr char kClassLoaderOpeningMark = '[';
48static constexpr char kClassLoaderClosingMark = ']';
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000049static constexpr char kClassLoaderSharedLibraryOpeningMark = '{';
50static constexpr char kClassLoaderSharedLibraryClosingMark = '}';
51static constexpr char kClassLoaderSharedLibrarySeparator = '#';
Calin Juravle7b0648a2017-07-07 18:40:50 -070052static constexpr char kClassLoaderSeparator = ';';
53static constexpr char kClasspathSeparator = ':';
54static constexpr char kDexFileChecksumSeparator = '*';
Calin Juravle87e2cb62017-06-13 21:48:45 -070055
56ClassLoaderContext::ClassLoaderContext()
57 : special_shared_library_(false),
58 dex_files_open_attempted_(false),
Calin Juravle57d0acc2017-07-11 17:41:30 -070059 dex_files_open_result_(false),
Calin Juravle41acdc12017-07-18 17:45:32 -070060 owns_the_dex_files_(true) {}
Calin Juravle57d0acc2017-07-11 17:41:30 -070061
62ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files)
63 : special_shared_library_(false),
64 dex_files_open_attempted_(true),
65 dex_files_open_result_(true),
66 owns_the_dex_files_(owns_the_dex_files) {}
67
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000068// Utility method to add parent and shared libraries of `info` into
69// the `work_list`.
70static void AddToWorkList(
71 ClassLoaderContext::ClassLoaderInfo* info,
72 std::vector<ClassLoaderContext::ClassLoaderInfo*>& work_list) {
73 if (info->parent != nullptr) {
74 work_list.push_back(info->parent.get());
75 }
76 for (size_t i = 0; i < info->shared_libraries.size(); ++i) {
77 work_list.push_back(info->shared_libraries[i].get());
78 }
79}
80
Calin Juravle57d0acc2017-07-11 17:41:30 -070081ClassLoaderContext::~ClassLoaderContext() {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000082 if (!owns_the_dex_files_ && class_loader_chain_ != nullptr) {
Calin Juravle57d0acc2017-07-11 17:41:30 -070083 // If the context does not own the dex/oat files release the unique pointers to
84 // make sure we do not de-allocate them.
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000085 std::vector<ClassLoaderInfo*> work_list;
86 work_list.push_back(class_loader_chain_.get());
87 while (!work_list.empty()) {
88 ClassLoaderInfo* info = work_list.back();
89 work_list.pop_back();
90 for (std::unique_ptr<OatFile>& oat_file : info->opened_oat_files) {
Andreas Gampeafaf7f82018-10-16 11:32:38 -070091 oat_file.release(); // NOLINT b/117926937
Calin Juravle57d0acc2017-07-11 17:41:30 -070092 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000093 for (std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
Andreas Gampeafaf7f82018-10-16 11:32:38 -070094 dex_file.release(); // NOLINT b/117926937
Calin Juravle57d0acc2017-07-11 17:41:30 -070095 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +000096 AddToWorkList(info, work_list);
Calin Juravle57d0acc2017-07-11 17:41:30 -070097 }
98 }
99}
Calin Juravle87e2cb62017-06-13 21:48:45 -0700100
Calin Juravle19915892017-08-03 17:10:36 +0000101std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Default() {
102 return Create("");
103}
104
Calin Juravle87e2cb62017-06-13 21:48:45 -0700105std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Create(const std::string& spec) {
106 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext());
107 if (result->Parse(spec)) {
108 return result;
109 } else {
110 return nullptr;
111 }
112}
113
Nicolas Geoffrayf378fff2018-11-19 12:52:26 +0000114static size_t FindMatchingSharedLibraryCloseMarker(const std::string& spec,
115 size_t shared_library_open_index) {
116 // Counter of opened shared library marker we've encountered so far.
117 uint32_t counter = 1;
118 // The index at which we're operating in the loop.
119 uint32_t string_index = shared_library_open_index + 1;
120 size_t shared_library_close = std::string::npos;
121 while (counter != 0) {
122 shared_library_close =
123 spec.find_first_of(kClassLoaderSharedLibraryClosingMark, string_index);
124 size_t shared_library_open =
125 spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, string_index);
126 if (shared_library_close == std::string::npos) {
127 // No matching closing marker. Return an error.
128 break;
129 }
130
131 if ((shared_library_open == std::string::npos) ||
132 (shared_library_close < shared_library_open)) {
133 // We have seen a closing marker. Decrement the counter.
134 --counter;
135 // Move the search index forward.
136 string_index = shared_library_close + 1;
137 } else {
138 // New nested opening marker. Increment the counter and move the search
139 // index after the marker.
140 ++counter;
141 string_index = shared_library_open + 1;
142 }
143 }
144 return shared_library_close;
145}
146
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000147// The expected format is:
148// "ClassLoaderType1[ClasspathElem1*Checksum1:ClasspathElem2*Checksum2...]{ClassLoaderType2[...]}".
Calin Juravle7b0648a2017-07-07 18:40:50 -0700149// The checksum part of the format is expected only if parse_cheksums is true.
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000150std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseClassLoaderSpec(
151 const std::string& class_loader_spec,
152 bool parse_checksums) {
153 ClassLoaderType class_loader_type = ExtractClassLoaderType(class_loader_spec);
154 if (class_loader_type == kInvalidClassLoader) {
155 return nullptr;
156 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700157 const char* class_loader_type_str = GetClassLoaderTypeName(class_loader_type);
158 size_t type_str_size = strlen(class_loader_type_str);
159
160 CHECK_EQ(0, class_loader_spec.compare(0, type_str_size, class_loader_type_str));
161
162 // Check the opening and closing markers.
163 if (class_loader_spec[type_str_size] != kClassLoaderOpeningMark) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000164 return nullptr;
Calin Juravle87e2cb62017-06-13 21:48:45 -0700165 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000166 if ((class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderClosingMark) &&
167 (class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderSharedLibraryClosingMark)) {
168 return nullptr;
Calin Juravle87e2cb62017-06-13 21:48:45 -0700169 }
170
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000171 size_t closing_index = class_loader_spec.find_first_of(kClassLoaderClosingMark);
172
Calin Juravle87e2cb62017-06-13 21:48:45 -0700173 // At this point we know the format is ok; continue and extract the classpath.
174 // Note that class loaders with an empty class path are allowed.
175 std::string classpath = class_loader_spec.substr(type_str_size + 1,
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000176 closing_index - type_str_size - 1);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700177
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000178 std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderInfo(class_loader_type));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700179
180 if (!parse_checksums) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000181 Split(classpath, kClasspathSeparator, &info->classpath);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700182 } else {
183 std::vector<std::string> classpath_elements;
184 Split(classpath, kClasspathSeparator, &classpath_elements);
185 for (const std::string& element : classpath_elements) {
186 std::vector<std::string> dex_file_with_checksum;
187 Split(element, kDexFileChecksumSeparator, &dex_file_with_checksum);
188 if (dex_file_with_checksum.size() != 2) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000189 return nullptr;
Calin Juravle7b0648a2017-07-07 18:40:50 -0700190 }
191 uint32_t checksum = 0;
Tom Cherry7bc8e8f2018-10-05 14:34:13 -0700192 if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000193 return nullptr;
Calin Juravle7b0648a2017-07-07 18:40:50 -0700194 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000195 info->classpath.push_back(dex_file_with_checksum[0]);
196 info->checksums.push_back(checksum);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700197 }
198 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700199
Nicolas Geoffrayf378fff2018-11-19 12:52:26 +0000200 if ((class_loader_spec[class_loader_spec.length() - 1] == kClassLoaderSharedLibraryClosingMark) &&
201 (class_loader_spec[class_loader_spec.length() - 2] != kClassLoaderSharedLibraryOpeningMark)) {
202 // Non-empty list of shared libraries.
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000203 size_t start_index = class_loader_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark);
204 if (start_index == std::string::npos) {
205 return nullptr;
206 }
207 std::string shared_libraries_spec =
208 class_loader_spec.substr(start_index + 1, class_loader_spec.length() - start_index - 2);
209 std::vector<std::string> shared_libraries;
Nicolas Geoffrayf378fff2018-11-19 12:52:26 +0000210 size_t cursor = 0;
211 while (cursor != shared_libraries_spec.length()) {
212 size_t shared_library_separator =
213 shared_libraries_spec.find_first_of(kClassLoaderSharedLibrarySeparator, cursor);
214 size_t shared_library_open =
215 shared_libraries_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, cursor);
216 std::string shared_library_spec;
217 if (shared_library_separator == std::string::npos) {
218 // Only one shared library, for example:
219 // PCL[...]
220 shared_library_spec =
221 shared_libraries_spec.substr(cursor, shared_libraries_spec.length() - cursor);
222 cursor = shared_libraries_spec.length();
223 } else if ((shared_library_open == std::string::npos) ||
224 (shared_library_open > shared_library_separator)) {
225 // We found a shared library without nested shared libraries, for example:
226 // PCL[...]#PCL[...]{...}
227 shared_library_spec =
228 shared_libraries_spec.substr(cursor, shared_library_separator - cursor);
229 cursor = shared_library_separator + 1;
230 } else {
231 // The shared library contains nested shared libraries. Find the matching closing shared
232 // marker for it.
233 size_t closing_marker =
234 FindMatchingSharedLibraryCloseMarker(shared_libraries_spec, shared_library_open);
235 if (closing_marker == std::string::npos) {
236 // No matching closing marker, return an error.
237 return nullptr;
238 }
239 shared_library_spec = shared_libraries_spec.substr(cursor, closing_marker + 1 - cursor);
240 cursor = closing_marker + 1;
241 if (cursor != shared_libraries_spec.length() &&
242 shared_libraries_spec[cursor] == kClassLoaderSharedLibrarySeparator) {
243 // Pass the shared library separator marker.
244 ++cursor;
245 }
246 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000247 std::unique_ptr<ClassLoaderInfo> shared_library(
248 ParseInternal(shared_library_spec, parse_checksums));
249 if (shared_library == nullptr) {
250 return nullptr;
251 }
252 info->shared_libraries.push_back(std::move(shared_library));
253 }
254 }
255
256 return info;
Calin Juravle87e2cb62017-06-13 21:48:45 -0700257}
258
259// Extracts the class loader type from the given spec.
260// Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not
261// recognized.
262ClassLoaderContext::ClassLoaderType
263ClassLoaderContext::ExtractClassLoaderType(const std::string& class_loader_spec) {
264 const ClassLoaderType kValidTypes[] = {kPathClassLoader, kDelegateLastClassLoader};
265 for (const ClassLoaderType& type : kValidTypes) {
266 const char* type_str = GetClassLoaderTypeName(type);
267 if (class_loader_spec.compare(0, strlen(type_str), type_str) == 0) {
268 return type;
269 }
270 }
271 return kInvalidClassLoader;
272}
273
274// The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]...
275// ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader).
276// ClasspathElem is the path of dex/jar/apk file.
Calin Juravle7b0648a2017-07-07 18:40:50 -0700277bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700278 if (spec.empty()) {
Calin Juravle1a509c82017-07-24 16:51:21 -0700279 // By default we load the dex files in a PathClassLoader.
280 // So an empty spec is equivalent to an empty PathClassLoader (this happens when running
281 // tests)
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000282 class_loader_chain_.reset(new ClassLoaderInfo(kPathClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700283 return true;
Calin Juravle87e2cb62017-06-13 21:48:45 -0700284 }
Calin Juravle7b0648a2017-07-07 18:40:50 -0700285
Calin Juravle87e2cb62017-06-13 21:48:45 -0700286 // Stop early if we detect the special shared library, which may be passed as the classpath
287 // for dex2oat when we want to skip the shared libraries check.
288 if (spec == OatFile::kSpecialSharedLibrary) {
289 LOG(INFO) << "The ClassLoaderContext is a special shared library.";
290 special_shared_library_ = true;
291 return true;
292 }
293
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000294 CHECK(class_loader_chain_ == nullptr);
295 class_loader_chain_.reset(ParseInternal(spec, parse_checksums));
296 return class_loader_chain_ != nullptr;
297}
Calin Juravle87e2cb62017-06-13 21:48:45 -0700298
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000299ClassLoaderContext::ClassLoaderInfo* ClassLoaderContext::ParseInternal(
300 const std::string& spec, bool parse_checksums) {
301 CHECK(!spec.empty());
302 CHECK_NE(spec, OatFile::kSpecialSharedLibrary);
303 std::string remaining = spec;
304 std::unique_ptr<ClassLoaderInfo> first(nullptr);
305 ClassLoaderInfo* previous_iteration = nullptr;
306 while (!remaining.empty()) {
307 std::string class_loader_spec;
308 size_t first_class_loader_separator = remaining.find_first_of(kClassLoaderSeparator);
309 size_t first_shared_library_open =
310 remaining.find_first_of(kClassLoaderSharedLibraryOpeningMark);
311 if (first_class_loader_separator == std::string::npos) {
312 // Only one class loader, for example:
313 // PCL[...]
314 class_loader_spec = remaining;
315 remaining = "";
316 } else if ((first_shared_library_open == std::string::npos) ||
317 (first_shared_library_open > first_class_loader_separator)) {
318 // We found a class loader spec without shared libraries, for example:
319 // PCL[...];PCL[...]{...}
320 class_loader_spec = remaining.substr(0, first_class_loader_separator);
321 remaining = remaining.substr(first_class_loader_separator + 1,
322 remaining.size() - first_class_loader_separator - 1);
323 } else {
324 // The class loader spec contains shared libraries. Find the matching closing
325 // shared library marker for it.
326
Nicolas Geoffrayf378fff2018-11-19 12:52:26 +0000327 uint32_t shared_library_close =
328 FindMatchingSharedLibraryCloseMarker(remaining, first_shared_library_open);
329 if (shared_library_close == std::string::npos) {
330 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
331 return nullptr;
332 }
333 class_loader_spec = remaining.substr(0, shared_library_close + 1);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000334
Nicolas Geoffrayf378fff2018-11-19 12:52:26 +0000335 // Compute the remaining string to analyze.
336 if (remaining.size() == shared_library_close + 1) {
337 remaining = "";
338 } else if ((remaining.size() == shared_library_close + 2) ||
339 (remaining.at(shared_library_close + 1) != kClassLoaderSeparator)) {
340 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
341 return nullptr;
342 } else {
343 remaining = remaining.substr(shared_library_close + 2,
344 remaining.size() - shared_library_close - 2);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000345 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700346 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000347
348 std::unique_ptr<ClassLoaderInfo> info =
349 ParseClassLoaderSpec(class_loader_spec, parse_checksums);
350 if (info == nullptr) {
351 LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
352 return nullptr;
353 }
354 if (first == nullptr) {
Andreas Gampe41c911f2018-11-19 11:34:16 -0800355 first = std::move(info);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000356 previous_iteration = first.get();
357 } else {
358 CHECK(previous_iteration != nullptr);
Andreas Gampe41c911f2018-11-19 11:34:16 -0800359 previous_iteration->parent = std::move(info);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000360 previous_iteration = previous_iteration->parent.get();
Calin Juravle87e2cb62017-06-13 21:48:45 -0700361 }
362 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000363 return first.release();
Calin Juravle87e2cb62017-06-13 21:48:45 -0700364}
365
366// Opens requested class path files and appends them to opened_dex_files. If the dex files have
367// been stripped, this opens them from their oat files (which get added to opened_oat_files).
368bool ClassLoaderContext::OpenDexFiles(InstructionSet isa, const std::string& classpath_dir) {
Calin Juravlec5b215f2017-09-12 14:49:37 -0700369 if (dex_files_open_attempted_) {
370 // Do not attempt to re-open the files if we already tried.
371 return dex_files_open_result_;
372 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700373
374 dex_files_open_attempted_ = true;
375 // Assume we can open all dex files. If not, we will set this to false as we go.
376 dex_files_open_result_ = true;
377
378 if (special_shared_library_) {
379 // Nothing to open if the context is a special shared library.
380 return true;
381 }
382
383 // Note that we try to open all dex files even if some fail.
384 // We may get resource-only apks which we cannot load.
385 // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains
386 // no dex files. So that we can distinguish the real failures...
David Sehr013fd802018-01-11 22:55:24 -0800387 const ArtDexFileLoader dex_file_loader;
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000388 std::vector<ClassLoaderInfo*> work_list;
Nicolas Geoffray9893c472018-11-13 15:39:53 +0000389 CHECK(class_loader_chain_ != nullptr);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000390 work_list.push_back(class_loader_chain_.get());
391 while (!work_list.empty()) {
392 ClassLoaderInfo* info = work_list.back();
393 work_list.pop_back();
394 size_t opened_dex_files_index = info->opened_dex_files.size();
395 for (const std::string& cp_elem : info->classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700396 // If path is relative, append it to the provided base directory.
Calin Juravle92003fe2017-09-06 02:22:57 +0000397 std::string location = cp_elem;
398 if (location[0] != '/' && !classpath_dir.empty()) {
Nicolas Geoffray06ffecf2017-11-14 10:31:54 +0000399 location = classpath_dir + (classpath_dir.back() == '/' ? "" : "/") + location;
Calin Juravle821a2592017-08-11 14:33:38 -0700400 }
401
Calin Juravle87e2cb62017-06-13 21:48:45 -0700402 std::string error_msg;
403 // When opening the dex files from the context we expect their checksum to match their
404 // contents. So pass true to verify_checksum.
David Sehr013fd802018-01-11 22:55:24 -0800405 if (!dex_file_loader.Open(location.c_str(),
406 location.c_str(),
407 Runtime::Current()->IsVerificationEnabled(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700408 /*verify_checksum=*/ true,
David Sehr013fd802018-01-11 22:55:24 -0800409 &error_msg,
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000410 &info->opened_dex_files)) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700411 // If we fail to open the dex file because it's been stripped, try to open the dex file
412 // from its corresponding oat file.
413 // This could happen when we need to recompile a pre-build whose dex code has been stripped.
414 // (for example, if the pre-build is only quicken and we want to re-compile it
415 // speed-profile).
416 // TODO(calin): Use the vdex directly instead of going through the oat file.
417 OatFileAssistant oat_file_assistant(location.c_str(), isa, false);
418 std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
419 std::vector<std::unique_ptr<const DexFile>> oat_dex_files;
420 if (oat_file != nullptr &&
421 OatFileAssistant::LoadDexFiles(*oat_file, location, &oat_dex_files)) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000422 info->opened_oat_files.push_back(std::move(oat_file));
423 info->opened_dex_files.insert(info->opened_dex_files.end(),
424 std::make_move_iterator(oat_dex_files.begin()),
425 std::make_move_iterator(oat_dex_files.end()));
Calin Juravle87e2cb62017-06-13 21:48:45 -0700426 } else {
427 LOG(WARNING) << "Could not open dex files from location: " << location;
428 dex_files_open_result_ = false;
429 }
430 }
431 }
Calin Juravlec5b215f2017-09-12 14:49:37 -0700432
433 // We finished opening the dex files from the classpath.
434 // Now update the classpath and the checksum with the locations of the dex files.
435 //
436 // We do this because initially the classpath contains the paths of the dex files; and
437 // some of them might be multi-dexes. So in order to have a consistent view we replace all the
438 // file paths with the actual dex locations being loaded.
439 // This will allow the context to VerifyClassLoaderContextMatch which expects or multidex
440 // location in the class paths.
441 // Note that this will also remove the paths that could not be opened.
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000442 info->original_classpath = std::move(info->classpath);
443 info->classpath.clear();
444 info->checksums.clear();
445 for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) {
446 std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k];
447 info->classpath.push_back(dex->GetLocation());
448 info->checksums.push_back(dex->GetLocationChecksum());
Calin Juravlec5b215f2017-09-12 14:49:37 -0700449 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000450 AddToWorkList(info, work_list);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700451 }
452
453 return dex_files_open_result_;
454}
455
456bool ClassLoaderContext::RemoveLocationsFromClassPaths(
457 const dchecked_vector<std::string>& locations) {
458 CHECK(!dex_files_open_attempted_)
459 << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles";
460
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000461 if (class_loader_chain_ == nullptr) {
462 return false;
463 }
464
Calin Juravle87e2cb62017-06-13 21:48:45 -0700465 std::set<std::string> canonical_locations;
466 for (const std::string& location : locations) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -0700467 canonical_locations.insert(DexFileLoader::GetDexCanonicalLocation(location.c_str()));
Calin Juravle87e2cb62017-06-13 21:48:45 -0700468 }
469 bool removed_locations = false;
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000470 std::vector<ClassLoaderInfo*> work_list;
471 work_list.push_back(class_loader_chain_.get());
472 while (!work_list.empty()) {
473 ClassLoaderInfo* info = work_list.back();
474 work_list.pop_back();
475 size_t initial_size = info->classpath.size();
Calin Juravle87e2cb62017-06-13 21:48:45 -0700476 auto kept_it = std::remove_if(
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000477 info->classpath.begin(),
478 info->classpath.end(),
Calin Juravle87e2cb62017-06-13 21:48:45 -0700479 [canonical_locations](const std::string& location) {
480 return ContainsElement(canonical_locations,
Mathieu Chartier79c87da2017-10-10 11:54:29 -0700481 DexFileLoader::GetDexCanonicalLocation(location.c_str()));
Calin Juravle87e2cb62017-06-13 21:48:45 -0700482 });
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000483 info->classpath.erase(kept_it, info->classpath.end());
484 if (initial_size != info->classpath.size()) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700485 removed_locations = true;
486 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000487 AddToWorkList(info, work_list);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700488 }
489 return removed_locations;
490}
491
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700492std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const {
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700493 return EncodeContext(base_dir, /*for_dex2oat=*/ true, /*stored_context=*/ nullptr);
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700494}
495
Mathieu Chartierc4440772018-04-16 14:40:56 -0700496std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir,
497 ClassLoaderContext* stored_context) const {
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700498 return EncodeContext(base_dir, /*for_dex2oat=*/ false, stored_context);
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700499}
500
501std::string ClassLoaderContext::EncodeContext(const std::string& base_dir,
Mathieu Chartierc4440772018-04-16 14:40:56 -0700502 bool for_dex2oat,
503 ClassLoaderContext* stored_context) const {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700504 CheckDexFilesOpened("EncodeContextForOatFile");
505 if (special_shared_library_) {
506 return OatFile::kSpecialSharedLibrary;
507 }
508
Mathieu Chartierc4440772018-04-16 14:40:56 -0700509 if (stored_context != nullptr) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000510 DCHECK_EQ(GetParentChainSize(), stored_context->GetParentChainSize());
Mathieu Chartierc4440772018-04-16 14:40:56 -0700511 }
512
Calin Juravle7b0648a2017-07-07 18:40:50 -0700513 std::ostringstream out;
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000514 if (class_loader_chain_ == nullptr) {
Calin Juravle1a509c82017-07-24 16:51:21 -0700515 // We can get in this situation if the context was created with a class path containing the
516 // source dex files which were later removed (happens during run-tests).
517 out << GetClassLoaderTypeName(kPathClassLoader)
518 << kClassLoaderOpeningMark
519 << kClassLoaderClosingMark;
520 return out.str();
521 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700522
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000523 EncodeContextInternal(
524 *class_loader_chain_,
525 base_dir,
526 for_dex2oat,
527 (stored_context == nullptr ? nullptr : stored_context->class_loader_chain_.get()),
528 out);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700529 return out.str();
Calin Juravle87e2cb62017-06-13 21:48:45 -0700530}
531
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000532void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info,
533 const std::string& base_dir,
534 bool for_dex2oat,
535 ClassLoaderInfo* stored_info,
536 std::ostringstream& out) const {
537 out << GetClassLoaderTypeName(info.type);
538 out << kClassLoaderOpeningMark;
539 std::set<std::string> seen_locations;
540 SafeMap<std::string, std::string> remap;
541 if (stored_info != nullptr) {
542 for (size_t k = 0; k < info.original_classpath.size(); ++k) {
543 // Note that we don't care if the same name appears twice.
544 remap.Put(info.original_classpath[k], stored_info->classpath[k]);
545 }
546 }
547 for (size_t k = 0; k < info.opened_dex_files.size(); k++) {
548 const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k];
549 if (for_dex2oat) {
550 // dex2oat only needs the base location. It cannot accept multidex locations.
551 // So ensure we only add each file once.
552 bool new_insert = seen_locations.insert(
553 DexFileLoader::GetBaseLocation(dex_file->GetLocation())).second;
554 if (!new_insert) {
555 continue;
556 }
557 }
558 std::string location = dex_file->GetLocation();
559 // If there is a stored class loader remap, fix up the multidex strings.
560 if (!remap.empty()) {
561 std::string base_dex_location = DexFileLoader::GetBaseLocation(location);
562 auto it = remap.find(base_dex_location);
563 CHECK(it != remap.end()) << base_dex_location;
564 location = it->second + DexFileLoader::GetMultiDexSuffix(location);
565 }
566 if (k > 0) {
567 out << kClasspathSeparator;
568 }
569 // Find paths that were relative and convert them back from absolute.
570 if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) {
571 out << location.substr(base_dir.length() + 1).c_str();
572 } else {
573 out << location.c_str();
574 }
575 // dex2oat does not need the checksums.
576 if (!for_dex2oat) {
577 out << kDexFileChecksumSeparator;
578 out << dex_file->GetLocationChecksum();
579 }
580 }
581 out << kClassLoaderClosingMark;
582
583 if (!info.shared_libraries.empty()) {
584 out << kClassLoaderSharedLibraryOpeningMark;
585 for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
586 if (i > 0) {
587 out << kClassLoaderSharedLibrarySeparator;
588 }
589 EncodeContextInternal(
590 *info.shared_libraries[i].get(),
591 base_dir,
592 for_dex2oat,
593 (stored_info == nullptr ? nullptr : stored_info->shared_libraries[i].get()),
594 out);
595 }
596 out << kClassLoaderSharedLibraryClosingMark;
597 }
598 if (info.parent != nullptr) {
599 out << kClassLoaderSeparator;
600 EncodeContextInternal(
601 *info.parent.get(),
602 base_dir,
603 for_dex2oat,
604 (stored_info == nullptr ? nullptr : stored_info->parent.get()),
605 out);
606 }
607}
608
609// Returns the WellKnownClass for the given class loader type.
610static jclass GetClassLoaderClass(ClassLoaderContext::ClassLoaderType type) {
611 switch (type) {
612 case ClassLoaderContext::kPathClassLoader:
613 return WellKnownClasses::dalvik_system_PathClassLoader;
614 case ClassLoaderContext::kDelegateLastClassLoader:
615 return WellKnownClasses::dalvik_system_DelegateLastClassLoader;
616 case ClassLoaderContext::kInvalidClassLoader: break; // will fail after the switch.
617 }
618 LOG(FATAL) << "Invalid class loader type " << type;
619 UNREACHABLE();
620}
621
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000622static std::string FlattenClasspath(const std::vector<std::string>& classpath) {
623 return android::base::Join(classpath, ':');
624}
625
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000626static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal(
627 Thread* self,
628 ScopedObjectAccess& soa,
629 const ClassLoaderContext::ClassLoaderInfo& info,
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000630 bool for_shared_library,
631 VariableSizedHandleScope& map_scope,
632 std::map<std::string, Handle<mirror::ClassLoader>>& canonicalized_libraries,
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000633 bool add_compilation_sources,
634 const std::vector<const DexFile*>& compilation_sources)
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000635 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000636 if (for_shared_library) {
637 // Check if the shared library has already been created.
638 auto search = canonicalized_libraries.find(FlattenClasspath(info.classpath));
639 if (search != canonicalized_libraries.end()) {
640 return search->second.Get();
641 }
642 }
643
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000644 StackHandleScope<3> hs(self);
645 MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries(
646 hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
647
648 if (!info.shared_libraries.empty()) {
649 libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
650 self,
651 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
652 info.shared_libraries.size()));
653 for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
654 // We should only add the compilation sources to the first class loader.
655 libraries->Set(i,
656 CreateClassLoaderInternal(
657 self,
658 soa,
659 *info.shared_libraries[i].get(),
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000660 /* for_shared_library= */ true,
661 map_scope,
662 canonicalized_libraries,
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000663 /* add_compilation_sources= */ false,
664 compilation_sources));
665 }
666 }
667
668 MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr);
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000669 if (info.parent != nullptr) {
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000670 // We should only add the compilation sources to the first class loader.
671 parent.Assign(CreateClassLoaderInternal(
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000672 self,
673 soa,
674 *info.parent.get(),
675 /* for_shared_library= */ false,
676 map_scope,
677 canonicalized_libraries,
678 /* add_compilation_sources= */ false,
679 compilation_sources));
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000680 }
681 std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(
682 info.opened_dex_files);
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000683 if (add_compilation_sources) {
684 // For the first class loader, its classpath comes first, followed by compilation sources.
685 // This ensures that whenever we need to resolve classes from it the classpath elements
686 // come first.
687 class_path_files.insert(class_path_files.end(),
688 compilation_sources.begin(),
689 compilation_sources.end());
690 }
691 Handle<mirror::Class> loader_class = hs.NewHandle<mirror::Class>(
692 soa.Decode<mirror::Class>(GetClassLoaderClass(info.type)));
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000693 ObjPtr<mirror::ClassLoader> loader =
694 Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
695 self,
696 class_path_files,
697 loader_class,
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000698 parent,
699 libraries);
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000700 if (for_shared_library) {
701 canonicalized_libraries[FlattenClasspath(info.classpath)] =
702 map_scope.NewHandle<mirror::ClassLoader>(loader);
703 }
704 return loader;
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000705}
706
Calin Juravle87e2cb62017-06-13 21:48:45 -0700707jobject ClassLoaderContext::CreateClassLoader(
708 const std::vector<const DexFile*>& compilation_sources) const {
709 CheckDexFilesOpened("CreateClassLoader");
710
711 Thread* self = Thread::Current();
712 ScopedObjectAccess soa(self);
713
Calin Juravlec79470d2017-07-12 17:37:42 -0700714 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
Calin Juravle87e2cb62017-06-13 21:48:45 -0700715
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000716 if (class_loader_chain_ == nullptr) {
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000717 CHECK(special_shared_library_);
Calin Juravlec79470d2017-07-12 17:37:42 -0700718 return class_linker->CreatePathClassLoader(self, compilation_sources);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700719 }
720
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000721 // Create a map of canonicalized shared libraries. As we're holding objects,
722 // we're creating a variable size handle scope to put handles in the map.
723 VariableSizedHandleScope map_scope(self);
724 std::map<std::string, Handle<mirror::ClassLoader>> canonicalized_libraries;
725
726 // Create the class loader.
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000727 ObjPtr<mirror::ClassLoader> loader =
728 CreateClassLoaderInternal(self,
729 soa,
730 *class_loader_chain_.get(),
Nicolas Geoffraycb2e1dd2018-11-20 11:15:13 +0000731 /* for_shared_library= */ false,
732 map_scope,
733 canonicalized_libraries,
Nicolas Geoffray6b9fd8c2018-11-16 10:25:42 +0000734 /* add_compilation_sources= */ true,
735 compilation_sources);
736 // Make it a global ref and return.
737 ScopedLocalRef<jobject> local_ref(
738 soa.Env(), soa.Env()->AddLocalReference<jobject>(loader));
739 return soa.Env()->NewGlobalRef(local_ref.get());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700740}
741
742std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const {
743 CheckDexFilesOpened("FlattenOpenedDexFiles");
744
745 std::vector<const DexFile*> result;
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000746 if (class_loader_chain_ == nullptr) {
747 return result;
748 }
749 std::vector<ClassLoaderInfo*> work_list;
750 work_list.push_back(class_loader_chain_.get());
751 while (!work_list.empty()) {
752 ClassLoaderInfo* info = work_list.back();
753 work_list.pop_back();
754 for (const std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700755 result.push_back(dex_file.get());
756 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000757 AddToWorkList(info, work_list);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700758 }
759 return result;
760}
761
762const char* ClassLoaderContext::GetClassLoaderTypeName(ClassLoaderType type) {
763 switch (type) {
764 case kPathClassLoader: return kPathClassLoaderString;
765 case kDelegateLastClassLoader: return kDelegateLastClassLoaderString;
766 default:
767 LOG(FATAL) << "Invalid class loader type " << type;
768 UNREACHABLE();
769 }
770}
771
772void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const {
773 CHECK(dex_files_open_attempted_)
774 << "Dex files were not successfully opened before the call to " << calling_method
775 << "attempt=" << dex_files_open_attempted_ << ", result=" << dex_files_open_result_;
776}
Calin Juravle7b0648a2017-07-07 18:40:50 -0700777
Calin Juravle57d0acc2017-07-11 17:41:30 -0700778// Collects the dex files from the give Java dex_file object. Only the dex files with
779// at least 1 class are collected. If a null java_dex_file is passed this method does nothing.
780static bool CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file,
781 ArtField* const cookie_field,
782 std::vector<const DexFile*>* out_dex_files)
783 REQUIRES_SHARED(Locks::mutator_lock_) {
784 if (java_dex_file == nullptr) {
785 return true;
786 }
787 // On the Java side, the dex files are stored in the cookie field.
788 mirror::LongArray* long_array = cookie_field->GetObject(java_dex_file)->AsLongArray();
789 if (long_array == nullptr) {
790 // This should never happen so log a warning.
791 LOG(ERROR) << "Unexpected null cookie";
792 return false;
793 }
794 int32_t long_array_size = long_array->GetLength();
795 // Index 0 from the long array stores the oat file. The dex files start at index 1.
796 for (int32_t j = 1; j < long_array_size; ++j) {
Vladimir Marko78baed52018-10-11 10:44:58 +0100797 const DexFile* cp_dex_file =
798 reinterpret_cast64<const DexFile*>(long_array->GetWithoutChecks(j));
Calin Juravle57d0acc2017-07-11 17:41:30 -0700799 if (cp_dex_file != nullptr && cp_dex_file->NumClassDefs() > 0) {
800 // TODO(calin): It's unclear why the dex files with no classes are skipped here and when
801 // cp_dex_file can be null.
802 out_dex_files->push_back(cp_dex_file);
803 }
804 }
805 return true;
806}
807
808// Collects all the dex files loaded by the given class loader.
809// Returns true for success or false if an unexpected state is discovered (e.g. a null dex cookie,
810// a null list of dex elements or a null dex element).
811static bool CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
812 Handle<mirror::ClassLoader> class_loader,
813 std::vector<const DexFile*>* out_dex_files)
814 REQUIRES_SHARED(Locks::mutator_lock_) {
815 CHECK(IsPathOrDexClassLoader(soa, class_loader) || IsDelegateLastClassLoader(soa, class_loader));
816
817 // All supported class loaders inherit from BaseDexClassLoader.
818 // We need to get the DexPathList and loop through it.
819 ArtField* const cookie_field =
820 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
821 ArtField* const dex_file_field =
822 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
823 ObjPtr<mirror::Object> dex_path_list =
824 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
825 GetObject(class_loader.Get());
826 CHECK(cookie_field != nullptr);
827 CHECK(dex_file_field != nullptr);
828 if (dex_path_list == nullptr) {
829 // This may be null if the current class loader is under construction and it does not
830 // have its fields setup yet.
831 return true;
832 }
833 // DexPathList has an array dexElements of Elements[] which each contain a dex file.
834 ObjPtr<mirror::Object> dex_elements_obj =
835 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
836 GetObject(dex_path_list);
837 // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
838 // at the mCookie which is a DexFile vector.
839 if (dex_elements_obj == nullptr) {
840 // TODO(calin): It's unclear if we should just assert here. For now be prepared for the worse
841 // and assume we have no elements.
842 return true;
843 } else {
844 StackHandleScope<1> hs(soa.Self());
845 Handle<mirror::ObjectArray<mirror::Object>> dex_elements(
846 hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()));
847 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
848 mirror::Object* element = dex_elements->GetWithoutChecks(i);
849 if (element == nullptr) {
850 // Should never happen, log an error and break.
851 // TODO(calin): It's unclear if we should just assert here.
852 // This code was propagated to oat_file_manager from the class linker where it would
853 // throw a NPE. For now, return false which will mark this class loader as unsupported.
854 LOG(ERROR) << "Unexpected null in the dex element list";
855 return false;
856 }
857 ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
858 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
859 return false;
860 }
861 }
862 }
863
864 return true;
865}
866
867static bool GetDexFilesFromDexElementsArray(
868 ScopedObjectAccessAlreadyRunnable& soa,
869 Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
870 std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) {
871 DCHECK(dex_elements != nullptr);
872
873 ArtField* const cookie_field =
874 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
875 ArtField* const dex_file_field =
876 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
877 ObjPtr<mirror::Class> const element_class = soa.Decode<mirror::Class>(
878 WellKnownClasses::dalvik_system_DexPathList__Element);
879 ObjPtr<mirror::Class> const dexfile_class = soa.Decode<mirror::Class>(
880 WellKnownClasses::dalvik_system_DexFile);
881
882 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
883 mirror::Object* element = dex_elements->GetWithoutChecks(i);
884 // We can hit a null element here because this is invoked with a partially filled dex_elements
885 // array from DexPathList. DexPathList will open each dex sequentially, each time passing the
886 // list of dex files which were opened before.
887 if (element == nullptr) {
888 continue;
889 }
890
891 // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile.
892 // TODO(calin): Code caried over oat_file_manager: supporting both classes seem to be
893 // a historical glitch. All the java code opens dex files using an array of Elements.
894 ObjPtr<mirror::Object> dex_file;
895 if (element_class == element->GetClass()) {
896 dex_file = dex_file_field->GetObject(element);
897 } else if (dexfile_class == element->GetClass()) {
898 dex_file = element;
899 } else {
900 LOG(ERROR) << "Unsupported element in dex_elements: "
901 << mirror::Class::PrettyClass(element->GetClass());
902 return false;
903 }
904
905 if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
906 return false;
907 }
908 }
909 return true;
910}
911
912// Adds the `class_loader` info to the `context`.
913// The dex file present in `dex_elements` array (if not null) will be added at the end of
914// the classpath.
915// This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the
916// BootClassLoader. Note that the class loader chain is expected to be short.
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000917bool ClassLoaderContext::CreateInfoFromClassLoader(
Calin Juravle57d0acc2017-07-11 17:41:30 -0700918 ScopedObjectAccessAlreadyRunnable& soa,
919 Handle<mirror::ClassLoader> class_loader,
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000920 Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
921 ClassLoaderInfo* child_info,
922 bool is_shared_library)
Calin Juravle57d0acc2017-07-11 17:41:30 -0700923 REQUIRES_SHARED(Locks::mutator_lock_) {
924 if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) {
925 // Nothing to do for the boot class loader as we don't add its dex files to the context.
926 return true;
927 }
928
929 ClassLoaderContext::ClassLoaderType type;
930 if (IsPathOrDexClassLoader(soa, class_loader)) {
931 type = kPathClassLoader;
932 } else if (IsDelegateLastClassLoader(soa, class_loader)) {
933 type = kDelegateLastClassLoader;
934 } else {
935 LOG(WARNING) << "Unsupported class loader";
936 return false;
937 }
938
939 // Inspect the class loader for its dex files.
940 std::vector<const DexFile*> dex_files_loaded;
941 CollectDexFilesFromSupportedClassLoader(soa, class_loader, &dex_files_loaded);
942
943 // If we have a dex_elements array extract its dex elements now.
944 // This is used in two situations:
945 // 1) when a new ClassLoader is created DexPathList will open each dex file sequentially
946 // passing the list of already open dex files each time. This ensures that we see the
947 // correct context even if the ClassLoader under construction is not fully build.
948 // 2) when apk splits are loaded on the fly, the framework will load their dex files by
949 // appending them to the current class loader. When the new code paths are loaded in
950 // BaseDexClassLoader, the paths already present in the class loader will be passed
951 // in the dex_elements array.
952 if (dex_elements != nullptr) {
953 GetDexFilesFromDexElementsArray(soa, dex_elements, &dex_files_loaded);
954 }
955
Nicolas Geoffray1717a492018-11-30 01:02:50 +0000956 ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type);
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000957 // Attach the `ClassLoaderInfo` now, before populating dex files, as only the
958 // `ClassLoaderContext` knows whether these dex files should be deleted or not.
959 if (child_info == nullptr) {
Nicolas Geoffray1717a492018-11-30 01:02:50 +0000960 class_loader_chain_.reset(info);
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000961 } else if (is_shared_library) {
962 child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
Nicolas Geoffray1717a492018-11-30 01:02:50 +0000963 } else {
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000964 child_info->parent.reset(info);
Nicolas Geoffray1717a492018-11-30 01:02:50 +0000965 }
966
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000967 // Now that `info` is in the chain, populate dex files.
Calin Juravle57d0acc2017-07-11 17:41:30 -0700968 for (const DexFile* dex_file : dex_files_loaded) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +0000969 info->classpath.push_back(dex_file->GetLocation());
970 info->checksums.push_back(dex_file->GetLocationChecksum());
971 info->opened_dex_files.emplace_back(dex_file);
Calin Juravle57d0acc2017-07-11 17:41:30 -0700972 }
973
Calin Juravle57d0acc2017-07-11 17:41:30 -0700974 // Note that dex_elements array is null here. The elements are considered to be part of the
975 // current class loader and are not passed to the parents.
976 ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements;
Nicolas Geoffraye1672732018-11-30 01:09:49 +0000977
978 // Add the shared libraries.
979 StackHandleScope<3> hs(Thread::Current());
980 ArtField* field =
981 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
982 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
983 if (raw_shared_libraries != nullptr) {
984 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries =
985 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>());
986 MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
987 for (int32_t i = 0; i < shared_libraries->GetLength(); ++i) {
988 temp_loader.Assign(shared_libraries->Get(i));
989 if (!CreateInfoFromClassLoader(
990 soa, temp_loader, null_dex_elements, info, /*is_shared_library=*/ true)) {
991 return false;
992 }
993 }
994 }
995
996 // We created the ClassLoaderInfo for the current loader. Move on to its parent.
997 Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
998 if (!CreateInfoFromClassLoader(
999 soa, parent, null_dex_elements, info, /*is_shared_library=*/ false)) {
1000 return false;
1001 }
1002 return true;
Calin Juravle57d0acc2017-07-11 17:41:30 -07001003}
1004
1005std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader(
1006 jobject class_loader,
1007 jobjectArray dex_elements) {
Calin Juravle3f918642017-07-11 19:04:20 -07001008 CHECK(class_loader != nullptr);
1009
Calin Juravle57d0acc2017-07-11 17:41:30 -07001010 ScopedObjectAccess soa(Thread::Current());
1011 StackHandleScope<2> hs(soa.Self());
1012 Handle<mirror::ClassLoader> h_class_loader =
1013 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
1014 Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
1015 hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
Nicolas Geoffray1717a492018-11-30 01:02:50 +00001016 std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false));
Nicolas Geoffraye1672732018-11-30 01:09:49 +00001017 if (!result->CreateInfoFromClassLoader(
1018 soa, h_class_loader, h_dex_elements, nullptr, /*is_shared_library=*/ false)) {
Calin Juravle57d0acc2017-07-11 17:41:30 -07001019 return nullptr;
1020 }
Nicolas Geoffraye1672732018-11-30 01:09:49 +00001021 return result;
Calin Juravle57d0acc2017-07-11 17:41:30 -07001022}
1023
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001024static bool IsAbsoluteLocation(const std::string& location) {
1025 return !location.empty() && location[0] == '/';
1026}
1027
Mathieu Chartieradc90862018-05-11 13:03:06 -07001028ClassLoaderContext::VerificationResult ClassLoaderContext::VerifyClassLoaderContextMatch(
1029 const std::string& context_spec,
1030 bool verify_names,
1031 bool verify_checksums) const {
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07001032 if (verify_names || verify_checksums) {
1033 DCHECK(dex_files_open_attempted_);
1034 DCHECK(dex_files_open_result_);
1035 }
Calin Juravlec5b215f2017-09-12 14:49:37 -07001036
Calin Juravle3f918642017-07-11 19:04:20 -07001037 ClassLoaderContext expected_context;
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07001038 if (!expected_context.Parse(context_spec, verify_checksums)) {
Calin Juravle3f918642017-07-11 19:04:20 -07001039 LOG(WARNING) << "Invalid class loader context: " << context_spec;
Mathieu Chartieradc90862018-05-11 13:03:06 -07001040 return VerificationResult::kMismatch;
Calin Juravle3f918642017-07-11 19:04:20 -07001041 }
1042
Calin Juravlec5b215f2017-09-12 14:49:37 -07001043 // Special shared library contexts always match. They essentially instruct the runtime
1044 // to ignore the class path check because the oat file is known to be loaded in different
1045 // contexts. OatFileManager will further verify if the oat file can be loaded based on the
1046 // collision check.
Mathieu Chartieradc90862018-05-11 13:03:06 -07001047 if (expected_context.special_shared_library_) {
1048 // Special case where we are the only entry in the class path.
Nicolas Geoffray9893c472018-11-13 15:39:53 +00001049 if (class_loader_chain_ != nullptr &&
1050 class_loader_chain_->parent == nullptr &&
1051 class_loader_chain_->classpath.size() == 0) {
Mathieu Chartieradc90862018-05-11 13:03:06 -07001052 return VerificationResult::kVerifies;
1053 }
1054 return VerificationResult::kForcedToSkipChecks;
1055 } else if (special_shared_library_) {
1056 return VerificationResult::kForcedToSkipChecks;
Calin Juravle3f918642017-07-11 19:04:20 -07001057 }
1058
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001059 ClassLoaderInfo* info = class_loader_chain_.get();
1060 ClassLoaderInfo* expected = expected_context.class_loader_chain_.get();
1061 CHECK(info != nullptr);
1062 CHECK(expected != nullptr);
1063 if (!ClassLoaderInfoMatch(*info, *expected, context_spec, verify_names, verify_checksums)) {
Mathieu Chartieradc90862018-05-11 13:03:06 -07001064 return VerificationResult::kMismatch;
Calin Juravle3f918642017-07-11 19:04:20 -07001065 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001066 return VerificationResult::kVerifies;
1067}
Calin Juravle3f918642017-07-11 19:04:20 -07001068
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001069bool ClassLoaderContext::ClassLoaderInfoMatch(
1070 const ClassLoaderInfo& info,
1071 const ClassLoaderInfo& expected_info,
1072 const std::string& context_spec,
1073 bool verify_names,
1074 bool verify_checksums) const {
1075 if (info.type != expected_info.type) {
1076 LOG(WARNING) << "ClassLoaderContext type mismatch"
1077 << ". expected=" << GetClassLoaderTypeName(expected_info.type)
1078 << ", found=" << GetClassLoaderTypeName(info.type)
1079 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1080 return false;
1081 }
1082 if (info.classpath.size() != expected_info.classpath.size()) {
1083 LOG(WARNING) << "ClassLoaderContext classpath size mismatch"
1084 << ". expected=" << expected_info.classpath.size()
1085 << ", found=" << info.classpath.size()
Andreas Gampe7d0f81c2017-07-25 18:25:41 -07001086 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001087 return false;
1088 }
Calin Juravle3f918642017-07-11 19:04:20 -07001089
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001090 if (verify_checksums) {
1091 DCHECK_EQ(info.classpath.size(), info.checksums.size());
1092 DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size());
1093 }
Mathieu Chartierf5abfc42018-03-23 21:51:54 -07001094
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001095 if (verify_names) {
Calin Juravle3f918642017-07-11 19:04:20 -07001096 for (size_t k = 0; k < info.classpath.size(); k++) {
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001097 // Compute the dex location that must be compared.
1098 // We shouldn't do a naive comparison `info.classpath[k] == expected_info.classpath[k]`
1099 // because even if they refer to the same file, one could be encoded as a relative location
1100 // and the other as an absolute one.
1101 bool is_dex_name_absolute = IsAbsoluteLocation(info.classpath[k]);
1102 bool is_expected_dex_name_absolute = IsAbsoluteLocation(expected_info.classpath[k]);
1103 std::string dex_name;
1104 std::string expected_dex_name;
1105
1106 if (is_dex_name_absolute == is_expected_dex_name_absolute) {
1107 // If both locations are absolute or relative then compare them as they are.
1108 // This is usually the case for: shared libraries and secondary dex files.
1109 dex_name = info.classpath[k];
1110 expected_dex_name = expected_info.classpath[k];
1111 } else if (is_dex_name_absolute) {
1112 // The runtime name is absolute but the compiled name (the expected one) is relative.
1113 // This is the case for split apks which depend on base or on other splits.
1114 dex_name = info.classpath[k];
1115 expected_dex_name = OatFile::ResolveRelativeEncodedDexLocation(
1116 info.classpath[k].c_str(), expected_info.classpath[k]);
Calin Juravle92003fe2017-09-06 02:22:57 +00001117 } else if (is_expected_dex_name_absolute) {
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001118 // The runtime name is relative but the compiled name is absolute.
1119 // There is no expected use case that would end up here as dex files are always loaded
1120 // with their absolute location. However, be tolerant and do the best effort (in case
1121 // there are unexpected new use case...).
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001122 dex_name = OatFile::ResolveRelativeEncodedDexLocation(
1123 expected_info.classpath[k].c_str(), info.classpath[k]);
1124 expected_dex_name = expected_info.classpath[k];
Calin Juravle92003fe2017-09-06 02:22:57 +00001125 } else {
1126 // Both locations are relative. In this case there's not much we can be sure about
1127 // except that the names are the same. The checksum will ensure that the files are
1128 // are same. This should not happen outside testing and manual invocations.
1129 dex_name = info.classpath[k];
1130 expected_dex_name = expected_info.classpath[k];
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001131 }
1132
1133 // Compare the locations.
1134 if (dex_name != expected_dex_name) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001135 LOG(WARNING) << "ClassLoaderContext classpath element mismatch"
Calin Juravle3f918642017-07-11 19:04:20 -07001136 << ". expected=" << expected_info.classpath[k]
Andreas Gampe7d0f81c2017-07-25 18:25:41 -07001137 << ", found=" << info.classpath[k]
1138 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001139 return false;
Calin Juravle3f918642017-07-11 19:04:20 -07001140 }
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001141
1142 // Compare the checksums.
Calin Juravle3f918642017-07-11 19:04:20 -07001143 if (info.checksums[k] != expected_info.checksums[k]) {
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001144 LOG(WARNING) << "ClassLoaderContext classpath element checksum mismatch"
Calin Juravle1e96a5d2017-09-05 17:10:48 -07001145 << ". expected=" << expected_info.checksums[k]
1146 << ", found=" << info.checksums[k]
1147 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001148 return false;
Calin Juravle3f918642017-07-11 19:04:20 -07001149 }
1150 }
1151 }
Calin Juravle3f918642017-07-11 19:04:20 -07001152
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001153 if (info.shared_libraries.size() != expected_info.shared_libraries.size()) {
1154 LOG(WARNING) << "ClassLoaderContext shared library size mismatch. "
Nicolas Geoffraye1672732018-11-30 01:09:49 +00001155 << "Expected=" << expected_info.shared_libraries.size()
1156 << ", found=" << info.shared_libraries.size()
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001157 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1158 return false;
Calin Juravlec79470d2017-07-12 17:37:42 -07001159 }
Nicolas Geoffray06af3b42018-10-29 10:39:04 +00001160 for (size_t i = 0; i < info.shared_libraries.size(); ++i) {
1161 if (!ClassLoaderInfoMatch(*info.shared_libraries[i].get(),
1162 *expected_info.shared_libraries[i].get(),
1163 context_spec,
1164 verify_names,
1165 verify_checksums)) {
1166 return false;
1167 }
1168 }
1169 if (info.parent.get() == nullptr) {
1170 if (expected_info.parent.get() != nullptr) {
1171 LOG(WARNING) << "ClassLoaderContext parent mismatch. "
1172 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1173 return false;
1174 }
1175 return true;
1176 } else if (expected_info.parent.get() == nullptr) {
1177 LOG(WARNING) << "ClassLoaderContext parent mismatch. "
1178 << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1179 return false;
1180 } else {
1181 return ClassLoaderInfoMatch(*info.parent.get(),
1182 *expected_info.parent.get(),
1183 context_spec,
1184 verify_names,
1185 verify_checksums);
1186 }
Calin Juravlec79470d2017-07-12 17:37:42 -07001187}
1188
Calin Juravle87e2cb62017-06-13 21:48:45 -07001189} // namespace art