• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
19 #include <android-base/parseint.h>
20 #include <android-base/strings.h>
21 
22 #include "art_field-inl.h"
23 #include "base/casts.h"
24 #include "base/dchecked_vector.h"
25 #include "base/stl_util.h"
26 #include "class_linker.h"
27 #include "class_loader_utils.h"
28 #include "class_root.h"
29 #include "dex/art_dex_file_loader.h"
30 #include "dex/dex_file.h"
31 #include "dex/dex_file_loader.h"
32 #include "handle_scope-inl.h"
33 #include "jni/jni_internal.h"
34 #include "mirror/class_loader-inl.h"
35 #include "mirror/object_array-alloc-inl.h"
36 #include "nativehelper/scoped_local_ref.h"
37 #include "oat_file_assistant.h"
38 #include "obj_ptr-inl.h"
39 #include "runtime.h"
40 #include "scoped_thread_state_change-inl.h"
41 #include "thread.h"
42 #include "well_known_classes.h"
43 
44 namespace art {
45 
46 static constexpr char kPathClassLoaderString[] = "PCL";
47 static constexpr char kDelegateLastClassLoaderString[] = "DLC";
48 static constexpr char kInMemoryDexClassLoaderString[] = "IMC";
49 static constexpr char kClassLoaderOpeningMark = '[';
50 static constexpr char kClassLoaderClosingMark = ']';
51 static constexpr char kClassLoaderSharedLibraryOpeningMark = '{';
52 static constexpr char kClassLoaderSharedLibraryClosingMark = '}';
53 static constexpr char kClassLoaderSharedLibrarySeparator = '#';
54 static constexpr char kClassLoaderSeparator = ';';
55 static constexpr char kClasspathSeparator = ':';
56 static constexpr char kDexFileChecksumSeparator = '*';
57 static constexpr char kInMemoryDexClassLoaderDexLocationMagic[] = "<unknown>";
58 
ClassLoaderContext()59 ClassLoaderContext::ClassLoaderContext()
60     : special_shared_library_(false),
61       dex_files_open_attempted_(false),
62       dex_files_open_result_(false),
63       owns_the_dex_files_(true) {}
64 
ClassLoaderContext(bool owns_the_dex_files)65 ClassLoaderContext::ClassLoaderContext(bool owns_the_dex_files)
66     : special_shared_library_(false),
67       dex_files_open_attempted_(true),
68       dex_files_open_result_(true),
69       owns_the_dex_files_(owns_the_dex_files) {}
70 
71 // Utility method to add parent and shared libraries of `info` into
72 // the `work_list`.
AddToWorkList(ClassLoaderContext::ClassLoaderInfo * info,std::vector<ClassLoaderContext::ClassLoaderInfo * > & work_list)73 static void AddToWorkList(
74     ClassLoaderContext::ClassLoaderInfo* info,
75     std::vector<ClassLoaderContext::ClassLoaderInfo*>& work_list) {
76   if (info->parent != nullptr) {
77     work_list.push_back(info->parent.get());
78   }
79   for (size_t i = 0; i < info->shared_libraries.size(); ++i) {
80     work_list.push_back(info->shared_libraries[i].get());
81   }
82 }
83 
~ClassLoaderContext()84 ClassLoaderContext::~ClassLoaderContext() {
85   if (!owns_the_dex_files_ && class_loader_chain_ != nullptr) {
86     // If the context does not own the dex/oat files release the unique pointers to
87     // make sure we do not de-allocate them.
88     std::vector<ClassLoaderInfo*> work_list;
89     work_list.push_back(class_loader_chain_.get());
90     while (!work_list.empty()) {
91       ClassLoaderInfo* info = work_list.back();
92       work_list.pop_back();
93       for (std::unique_ptr<OatFile>& oat_file : info->opened_oat_files) {
94         oat_file.release();  // NOLINT b/117926937
95       }
96       for (std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
97         dex_file.release();  // NOLINT b/117926937
98       }
99       AddToWorkList(info, work_list);
100     }
101   }
102 }
103 
Default()104 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Default() {
105   return Create("");
106 }
107 
Create(const std::string & spec)108 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::Create(const std::string& spec) {
109   std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext());
110   if (result->Parse(spec)) {
111     return result;
112   } else {
113     return nullptr;
114   }
115 }
116 
FindMatchingSharedLibraryCloseMarker(const std::string & spec,size_t shared_library_open_index)117 static size_t FindMatchingSharedLibraryCloseMarker(const std::string& spec,
118                                                    size_t shared_library_open_index) {
119   // Counter of opened shared library marker we've encountered so far.
120   uint32_t counter = 1;
121   // The index at which we're operating in the loop.
122   uint32_t string_index = shared_library_open_index + 1;
123   size_t shared_library_close = std::string::npos;
124   while (counter != 0) {
125     shared_library_close =
126         spec.find_first_of(kClassLoaderSharedLibraryClosingMark, string_index);
127     size_t shared_library_open =
128         spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, string_index);
129     if (shared_library_close == std::string::npos) {
130       // No matching closing marker. Return an error.
131       break;
132     }
133 
134     if ((shared_library_open == std::string::npos) ||
135         (shared_library_close < shared_library_open)) {
136       // We have seen a closing marker. Decrement the counter.
137       --counter;
138       // Move the search index forward.
139       string_index = shared_library_close + 1;
140     } else {
141       // New nested opening marker. Increment the counter and move the search
142       // index after the marker.
143       ++counter;
144       string_index = shared_library_open + 1;
145     }
146   }
147   return shared_library_close;
148 }
149 
150 // The expected format is:
151 // "ClassLoaderType1[ClasspathElem1*Checksum1:ClasspathElem2*Checksum2...]{ClassLoaderType2[...]}".
152 // The checksum part of the format is expected only if parse_cheksums is true.
ParseClassLoaderSpec(const std::string & class_loader_spec,bool parse_checksums)153 std::unique_ptr<ClassLoaderContext::ClassLoaderInfo> ClassLoaderContext::ParseClassLoaderSpec(
154     const std::string& class_loader_spec,
155     bool parse_checksums) {
156   ClassLoaderType class_loader_type = ExtractClassLoaderType(class_loader_spec);
157   if (class_loader_type == kInvalidClassLoader) {
158     return nullptr;
159   }
160 
161   // InMemoryDexClassLoader's dex location is always bogus. Special-case it.
162   if (class_loader_type == kInMemoryDexClassLoader) {
163     if (parse_checksums) {
164       // Make sure that OpenDexFiles() will never be attempted on this context
165       // because the dex locations of IMC do not correspond to real files.
166       CHECK(!dex_files_open_attempted_ || !dex_files_open_result_)
167           << "Parsing spec not supported when context created from a ClassLoader object";
168       dex_files_open_attempted_ = true;
169       dex_files_open_result_ = false;
170     } else {
171       // Checksums are not provided and dex locations themselves have no meaning
172       // (although we keep them in the spec to simplify parsing). Treat this as
173       // an unknown class loader.
174       // We can hit this case if dex2oat is invoked with a spec containing IMC.
175       // Because the dex file data is only available at runtime, we cannot proceed.
176       return nullptr;
177     }
178   }
179 
180   const char* class_loader_type_str = GetClassLoaderTypeName(class_loader_type);
181   size_t type_str_size = strlen(class_loader_type_str);
182 
183   CHECK_EQ(0, class_loader_spec.compare(0, type_str_size, class_loader_type_str));
184 
185   // Check the opening and closing markers.
186   if (class_loader_spec[type_str_size] != kClassLoaderOpeningMark) {
187     return nullptr;
188   }
189   if ((class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderClosingMark) &&
190       (class_loader_spec[class_loader_spec.length() - 1] != kClassLoaderSharedLibraryClosingMark)) {
191     return nullptr;
192   }
193 
194   size_t closing_index = class_loader_spec.find_first_of(kClassLoaderClosingMark);
195 
196   // At this point we know the format is ok; continue and extract the classpath.
197   // Note that class loaders with an empty class path are allowed.
198   std::string classpath = class_loader_spec.substr(type_str_size + 1,
199                                                    closing_index - type_str_size - 1);
200 
201   std::unique_ptr<ClassLoaderInfo> info(new ClassLoaderInfo(class_loader_type));
202 
203   if (!parse_checksums) {
204     DCHECK(class_loader_type != kInMemoryDexClassLoader);
205     Split(classpath, kClasspathSeparator, &info->classpath);
206   } else {
207     std::vector<std::string> classpath_elements;
208     Split(classpath, kClasspathSeparator, &classpath_elements);
209     for (const std::string& element : classpath_elements) {
210       std::vector<std::string> dex_file_with_checksum;
211       Split(element, kDexFileChecksumSeparator, &dex_file_with_checksum);
212       if (dex_file_with_checksum.size() != 2) {
213         return nullptr;
214       }
215       uint32_t checksum = 0;
216       if (!android::base::ParseUint(dex_file_with_checksum[1].c_str(), &checksum)) {
217         return nullptr;
218       }
219       if ((class_loader_type == kInMemoryDexClassLoader) &&
220           (dex_file_with_checksum[0] != kInMemoryDexClassLoaderDexLocationMagic)) {
221         return nullptr;
222       }
223 
224       info->classpath.push_back(dex_file_with_checksum[0]);
225       info->checksums.push_back(checksum);
226     }
227   }
228 
229   if ((class_loader_spec[class_loader_spec.length() - 1] == kClassLoaderSharedLibraryClosingMark) &&
230       (class_loader_spec[class_loader_spec.length() - 2] != kClassLoaderSharedLibraryOpeningMark)) {
231     // Non-empty list of shared libraries.
232     size_t start_index = class_loader_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark);
233     if (start_index == std::string::npos) {
234       return nullptr;
235     }
236     std::string shared_libraries_spec =
237         class_loader_spec.substr(start_index + 1, class_loader_spec.length() - start_index - 2);
238     std::vector<std::string> shared_libraries;
239     size_t cursor = 0;
240     while (cursor != shared_libraries_spec.length()) {
241       size_t shared_library_separator =
242           shared_libraries_spec.find_first_of(kClassLoaderSharedLibrarySeparator, cursor);
243       size_t shared_library_open =
244           shared_libraries_spec.find_first_of(kClassLoaderSharedLibraryOpeningMark, cursor);
245       std::string shared_library_spec;
246       if (shared_library_separator == std::string::npos) {
247         // Only one shared library, for example:
248         // PCL[...]
249         shared_library_spec =
250             shared_libraries_spec.substr(cursor, shared_libraries_spec.length() - cursor);
251         cursor = shared_libraries_spec.length();
252       } else if ((shared_library_open == std::string::npos) ||
253                  (shared_library_open > shared_library_separator)) {
254         // We found a shared library without nested shared libraries, for example:
255         // PCL[...]#PCL[...]{...}
256         shared_library_spec =
257             shared_libraries_spec.substr(cursor, shared_library_separator - cursor);
258         cursor = shared_library_separator + 1;
259       } else {
260         // The shared library contains nested shared libraries. Find the matching closing shared
261         // marker for it.
262         size_t closing_marker =
263             FindMatchingSharedLibraryCloseMarker(shared_libraries_spec, shared_library_open);
264         if (closing_marker == std::string::npos) {
265           // No matching closing marker, return an error.
266           return nullptr;
267         }
268         shared_library_spec = shared_libraries_spec.substr(cursor, closing_marker + 1 - cursor);
269         cursor = closing_marker + 1;
270         if (cursor != shared_libraries_spec.length() &&
271             shared_libraries_spec[cursor] == kClassLoaderSharedLibrarySeparator) {
272           // Pass the shared library separator marker.
273           ++cursor;
274         }
275       }
276       std::unique_ptr<ClassLoaderInfo> shared_library(
277           ParseInternal(shared_library_spec, parse_checksums));
278       if (shared_library == nullptr) {
279         return nullptr;
280       }
281       info->shared_libraries.push_back(std::move(shared_library));
282     }
283   }
284 
285   return info;
286 }
287 
288 // Extracts the class loader type from the given spec.
289 // Return ClassLoaderContext::kInvalidClassLoader if the class loader type is not
290 // recognized.
291 ClassLoaderContext::ClassLoaderType
ExtractClassLoaderType(const std::string & class_loader_spec)292 ClassLoaderContext::ExtractClassLoaderType(const std::string& class_loader_spec) {
293   const ClassLoaderType kValidTypes[] = { kPathClassLoader,
294                                           kDelegateLastClassLoader,
295                                           kInMemoryDexClassLoader };
296   for (const ClassLoaderType& type : kValidTypes) {
297     const char* type_str = GetClassLoaderTypeName(type);
298     if (class_loader_spec.compare(0, strlen(type_str), type_str) == 0) {
299       return type;
300     }
301   }
302   return kInvalidClassLoader;
303 }
304 
305 // The format: ClassLoaderType1[ClasspathElem1:ClasspathElem2...];ClassLoaderType2[...]...
306 // ClassLoaderType is either "PCL" (PathClassLoader) or "DLC" (DelegateLastClassLoader).
307 // ClasspathElem is the path of dex/jar/apk file.
Parse(const std::string & spec,bool parse_checksums)308 bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) {
309   if (spec.empty()) {
310     // By default we load the dex files in a PathClassLoader.
311     // So an empty spec is equivalent to an empty PathClassLoader (this happens when running
312     // tests)
313     class_loader_chain_.reset(new ClassLoaderInfo(kPathClassLoader));
314     return true;
315   }
316 
317   // Stop early if we detect the special shared library, which may be passed as the classpath
318   // for dex2oat when we want to skip the shared libraries check.
319   if (spec == OatFile::kSpecialSharedLibrary) {
320     LOG(INFO) << "The ClassLoaderContext is a special shared library.";
321     special_shared_library_ = true;
322     return true;
323   }
324 
325   CHECK(class_loader_chain_ == nullptr);
326   class_loader_chain_.reset(ParseInternal(spec, parse_checksums));
327   return class_loader_chain_ != nullptr;
328 }
329 
ParseInternal(const std::string & spec,bool parse_checksums)330 ClassLoaderContext::ClassLoaderInfo* ClassLoaderContext::ParseInternal(
331     const std::string& spec, bool parse_checksums) {
332   CHECK(!spec.empty());
333   CHECK_NE(spec, OatFile::kSpecialSharedLibrary);
334   std::string remaining = spec;
335   std::unique_ptr<ClassLoaderInfo> first(nullptr);
336   ClassLoaderInfo* previous_iteration = nullptr;
337   while (!remaining.empty()) {
338     std::string class_loader_spec;
339     size_t first_class_loader_separator = remaining.find_first_of(kClassLoaderSeparator);
340     size_t first_shared_library_open =
341         remaining.find_first_of(kClassLoaderSharedLibraryOpeningMark);
342     if (first_class_loader_separator == std::string::npos) {
343       // Only one class loader, for example:
344       // PCL[...]
345       class_loader_spec = remaining;
346       remaining = "";
347     } else if ((first_shared_library_open == std::string::npos) ||
348                (first_shared_library_open > first_class_loader_separator)) {
349       // We found a class loader spec without shared libraries, for example:
350       // PCL[...];PCL[...]{...}
351       class_loader_spec = remaining.substr(0, first_class_loader_separator);
352       remaining = remaining.substr(first_class_loader_separator + 1,
353                                    remaining.size() - first_class_loader_separator - 1);
354     } else {
355       // The class loader spec contains shared libraries. Find the matching closing
356       // shared library marker for it.
357 
358       uint32_t shared_library_close =
359           FindMatchingSharedLibraryCloseMarker(remaining, first_shared_library_open);
360       if (shared_library_close == std::string::npos) {
361         LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
362         return nullptr;
363       }
364       class_loader_spec = remaining.substr(0, shared_library_close + 1);
365 
366       // Compute the remaining string to analyze.
367       if (remaining.size() == shared_library_close + 1) {
368         remaining = "";
369       } else if ((remaining.size() == shared_library_close + 2) ||
370                  (remaining.at(shared_library_close + 1) != kClassLoaderSeparator)) {
371         LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
372         return nullptr;
373       } else {
374         remaining = remaining.substr(shared_library_close + 2,
375                                      remaining.size() - shared_library_close - 2);
376       }
377     }
378 
379     std::unique_ptr<ClassLoaderInfo> info =
380         ParseClassLoaderSpec(class_loader_spec, parse_checksums);
381     if (info == nullptr) {
382       LOG(ERROR) << "Invalid class loader spec: " << class_loader_spec;
383       return nullptr;
384     }
385     if (first == nullptr) {
386       first = std::move(info);
387       previous_iteration = first.get();
388     } else {
389       CHECK(previous_iteration != nullptr);
390       previous_iteration->parent = std::move(info);
391       previous_iteration = previous_iteration->parent.get();
392     }
393   }
394   return first.release();
395 }
396 
397 // Opens requested class path files and appends them to opened_dex_files. If the dex files have
398 // been stripped, this opens them from their oat files (which get added to opened_oat_files).
OpenDexFiles(InstructionSet isa,const std::string & classpath_dir,const std::vector<int> & fds)399 bool ClassLoaderContext::OpenDexFiles(InstructionSet isa,
400                                       const std::string& classpath_dir,
401                                       const std::vector<int>& fds) {
402   if (dex_files_open_attempted_) {
403     // Do not attempt to re-open the files if we already tried.
404     return dex_files_open_result_;
405   }
406 
407   dex_files_open_attempted_ = true;
408   // Assume we can open all dex files. If not, we will set this to false as we go.
409   dex_files_open_result_ = true;
410 
411   if (special_shared_library_) {
412     // Nothing to open if the context is a special shared library.
413     return true;
414   }
415 
416   // Note that we try to open all dex files even if some fail.
417   // We may get resource-only apks which we cannot load.
418   // TODO(calin): Refine the dex opening interface to be able to tell if an archive contains
419   // no dex files. So that we can distinguish the real failures...
420   const ArtDexFileLoader dex_file_loader;
421   std::vector<ClassLoaderInfo*> work_list;
422   CHECK(class_loader_chain_ != nullptr);
423   work_list.push_back(class_loader_chain_.get());
424   size_t dex_file_index = 0;
425   while (!work_list.empty()) {
426     ClassLoaderInfo* info = work_list.back();
427     work_list.pop_back();
428     DCHECK(info->type != kInMemoryDexClassLoader) << __FUNCTION__ << " not supported for IMC";
429 
430     size_t opened_dex_files_index = info->opened_dex_files.size();
431     for (const std::string& cp_elem : info->classpath) {
432       // If path is relative, append it to the provided base directory.
433       std::string location = cp_elem;
434       if (location[0] != '/' && !classpath_dir.empty()) {
435         location = classpath_dir + (classpath_dir.back() == '/' ? "" : "/") + location;
436       }
437 
438       // If file descriptors were provided for the class loader context dex paths,
439       // get the descriptor which correponds to this dex path. We assume the `fds`
440       // vector follows the same order as a flattened class loader context.
441       int fd = -1;
442       if (!fds.empty()) {
443         if (dex_file_index >= fds.size()) {
444           LOG(WARNING) << "Number of FDs is smaller than number of dex files in the context";
445           dex_files_open_result_ = false;
446           return false;
447         }
448 
449         fd = fds[dex_file_index++];
450         DCHECK_GE(fd, 0);
451       }
452 
453       std::string error_msg;
454       // When opening the dex files from the context we expect their checksum to match their
455       // contents. So pass true to verify_checksum.
456       if (fd < 0) {
457         if (!dex_file_loader.Open(location.c_str(),
458                                   location.c_str(),
459                                   Runtime::Current()->IsVerificationEnabled(),
460                                   /*verify_checksum=*/ true,
461                                   &error_msg,
462                                   &info->opened_dex_files)) {
463           // If we fail to open the dex file because it's been stripped, try to
464           // open the dex file from its corresponding oat file.
465           // This could happen when we need to recompile a pre-build whose dex
466           // code has been stripped (for example, if the pre-build is only
467           // quicken and we want to re-compile it speed-profile).
468           // TODO(calin): Use the vdex directly instead of going through the oat file.
469           OatFileAssistant oat_file_assistant(location.c_str(), isa, false);
470           std::unique_ptr<OatFile> oat_file(oat_file_assistant.GetBestOatFile());
471           std::vector<std::unique_ptr<const DexFile>> oat_dex_files;
472           if (oat_file != nullptr &&
473               OatFileAssistant::LoadDexFiles(*oat_file, location, &oat_dex_files)) {
474             info->opened_oat_files.push_back(std::move(oat_file));
475             info->opened_dex_files.insert(info->opened_dex_files.end(),
476                                           std::make_move_iterator(oat_dex_files.begin()),
477                                           std::make_move_iterator(oat_dex_files.end()));
478           } else {
479             LOG(WARNING) << "Could not open dex files from location: " << location;
480             dex_files_open_result_ = false;
481           }
482         }
483       } else if (!dex_file_loader.Open(fd,
484                                        location.c_str(),
485                                        Runtime::Current()->IsVerificationEnabled(),
486                                        /*verify_checksum=*/ true,
487                                        &error_msg,
488                                        &info->opened_dex_files)) {
489         LOG(WARNING) << "Could not open dex files from fd " << fd << " for location: " << location;
490         dex_files_open_result_ = false;
491       }
492     }
493 
494     // We finished opening the dex files from the classpath.
495     // Now update the classpath and the checksum with the locations of the dex files.
496     //
497     // We do this because initially the classpath contains the paths of the dex files; and
498     // some of them might be multi-dexes. So in order to have a consistent view we replace all the
499     // file paths with the actual dex locations being loaded.
500     // This will allow the context to VerifyClassLoaderContextMatch which expects or multidex
501     // location in the class paths.
502     // Note that this will also remove the paths that could not be opened.
503     info->original_classpath = std::move(info->classpath);
504     info->classpath.clear();
505     info->checksums.clear();
506     for (size_t k = opened_dex_files_index; k < info->opened_dex_files.size(); k++) {
507       std::unique_ptr<const DexFile>& dex = info->opened_dex_files[k];
508       info->classpath.push_back(dex->GetLocation());
509       info->checksums.push_back(dex->GetLocationChecksum());
510     }
511     AddToWorkList(info, work_list);
512   }
513 
514   // Check that if file descriptors were provided, there were exactly as many
515   // as we have encountered while iterating over this class loader context.
516   if (dex_file_index != fds.size()) {
517     LOG(WARNING) << fds.size() << " FDs provided but only " << dex_file_index
518         << " dex files are in the class loader context";
519     dex_files_open_result_ = false;
520   }
521 
522   return dex_files_open_result_;
523 }
524 
RemoveLocationsFromClassPaths(const dchecked_vector<std::string> & locations)525 bool ClassLoaderContext::RemoveLocationsFromClassPaths(
526     const dchecked_vector<std::string>& locations) {
527   CHECK(!dex_files_open_attempted_)
528       << "RemoveLocationsFromClasspaths cannot be call after OpenDexFiles";
529 
530   if (class_loader_chain_ == nullptr) {
531     return false;
532   }
533 
534   std::set<std::string> canonical_locations;
535   for (const std::string& location : locations) {
536     canonical_locations.insert(DexFileLoader::GetDexCanonicalLocation(location.c_str()));
537   }
538   bool removed_locations = false;
539   std::vector<ClassLoaderInfo*> work_list;
540   work_list.push_back(class_loader_chain_.get());
541   while (!work_list.empty()) {
542     ClassLoaderInfo* info = work_list.back();
543     work_list.pop_back();
544     size_t initial_size = info->classpath.size();
545     auto kept_it = std::remove_if(
546         info->classpath.begin(),
547         info->classpath.end(),
548         [canonical_locations](const std::string& location) {
549             return ContainsElement(canonical_locations,
550                                    DexFileLoader::GetDexCanonicalLocation(location.c_str()));
551         });
552     info->classpath.erase(kept_it, info->classpath.end());
553     if (initial_size != info->classpath.size()) {
554       removed_locations = true;
555     }
556     AddToWorkList(info, work_list);
557   }
558   return removed_locations;
559 }
560 
EncodeContextForDex2oat(const std::string & base_dir) const561 std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const {
562   return EncodeContext(base_dir, /*for_dex2oat=*/ true, /*stored_context=*/ nullptr);
563 }
564 
EncodeContextForOatFile(const std::string & base_dir,ClassLoaderContext * stored_context) const565 std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir,
566                                                         ClassLoaderContext* stored_context) const {
567   return EncodeContext(base_dir, /*for_dex2oat=*/ false, stored_context);
568 }
569 
EncodeContext(const std::string & base_dir,bool for_dex2oat,ClassLoaderContext * stored_context) const570 std::string ClassLoaderContext::EncodeContext(const std::string& base_dir,
571                                               bool for_dex2oat,
572                                               ClassLoaderContext* stored_context) const {
573   CheckDexFilesOpened("EncodeContextForOatFile");
574   if (special_shared_library_) {
575     return OatFile::kSpecialSharedLibrary;
576   }
577 
578   if (stored_context != nullptr) {
579     DCHECK_EQ(GetParentChainSize(), stored_context->GetParentChainSize());
580   }
581 
582   std::ostringstream out;
583   if (class_loader_chain_ == nullptr) {
584     // We can get in this situation if the context was created with a class path containing the
585     // source dex files which were later removed (happens during run-tests).
586     out << GetClassLoaderTypeName(kPathClassLoader)
587         << kClassLoaderOpeningMark
588         << kClassLoaderClosingMark;
589     return out.str();
590   }
591 
592   EncodeContextInternal(
593       *class_loader_chain_,
594       base_dir,
595       for_dex2oat,
596       (stored_context == nullptr ? nullptr : stored_context->class_loader_chain_.get()),
597       out);
598   return out.str();
599 }
600 
EncodeContextInternal(const ClassLoaderInfo & info,const std::string & base_dir,bool for_dex2oat,ClassLoaderInfo * stored_info,std::ostringstream & out) const601 void ClassLoaderContext::EncodeContextInternal(const ClassLoaderInfo& info,
602                                                const std::string& base_dir,
603                                                bool for_dex2oat,
604                                                ClassLoaderInfo* stored_info,
605                                                std::ostringstream& out) const {
606   out << GetClassLoaderTypeName(info.type);
607   out << kClassLoaderOpeningMark;
608   std::set<std::string> seen_locations;
609   SafeMap<std::string, std::string> remap;
610   if (stored_info != nullptr) {
611     for (size_t k = 0; k < info.original_classpath.size(); ++k) {
612       // Note that we don't care if the same name appears twice.
613       remap.Put(info.original_classpath[k], stored_info->classpath[k]);
614     }
615   }
616   for (size_t k = 0; k < info.opened_dex_files.size(); k++) {
617     const std::unique_ptr<const DexFile>& dex_file = info.opened_dex_files[k];
618     if (for_dex2oat) {
619       // dex2oat only needs the base location. It cannot accept multidex locations.
620       // So ensure we only add each file once.
621       bool new_insert = seen_locations.insert(
622           DexFileLoader::GetBaseLocation(dex_file->GetLocation())).second;
623       if (!new_insert) {
624         continue;
625       }
626     }
627     std::string location = dex_file->GetLocation();
628     // If there is a stored class loader remap, fix up the multidex strings.
629     if (!remap.empty()) {
630       std::string base_dex_location = DexFileLoader::GetBaseLocation(location);
631       auto it = remap.find(base_dex_location);
632       CHECK(it != remap.end()) << base_dex_location;
633       location = it->second + DexFileLoader::GetMultiDexSuffix(location);
634     }
635     if (k > 0) {
636       out << kClasspathSeparator;
637     }
638     if (info.type == kInMemoryDexClassLoader) {
639       out << kInMemoryDexClassLoaderDexLocationMagic;
640     } else if (!base_dir.empty() && location.substr(0, base_dir.length()) == base_dir) {
641       // Find paths that were relative and convert them back from absolute.
642       out << location.substr(base_dir.length() + 1).c_str();
643     } else {
644       out << location.c_str();
645     }
646     // dex2oat does not need the checksums.
647     if (!for_dex2oat) {
648       out << kDexFileChecksumSeparator;
649       out << dex_file->GetLocationChecksum();
650     }
651   }
652   out << kClassLoaderClosingMark;
653 
654   if (!info.shared_libraries.empty()) {
655     out << kClassLoaderSharedLibraryOpeningMark;
656     for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
657       if (i > 0) {
658         out << kClassLoaderSharedLibrarySeparator;
659       }
660       EncodeContextInternal(
661           *info.shared_libraries[i].get(),
662           base_dir,
663           for_dex2oat,
664           (stored_info == nullptr ? nullptr : stored_info->shared_libraries[i].get()),
665           out);
666     }
667     out << kClassLoaderSharedLibraryClosingMark;
668   }
669   if (info.parent != nullptr) {
670     out << kClassLoaderSeparator;
671     EncodeContextInternal(
672         *info.parent.get(),
673         base_dir,
674         for_dex2oat,
675         (stored_info == nullptr ? nullptr : stored_info->parent.get()),
676         out);
677   }
678 }
679 
680 // Returns the WellKnownClass for the given class loader type.
GetClassLoaderClass(ClassLoaderContext::ClassLoaderType type)681 static jclass GetClassLoaderClass(ClassLoaderContext::ClassLoaderType type) {
682   switch (type) {
683     case ClassLoaderContext::kPathClassLoader:
684       return WellKnownClasses::dalvik_system_PathClassLoader;
685     case ClassLoaderContext::kDelegateLastClassLoader:
686       return WellKnownClasses::dalvik_system_DelegateLastClassLoader;
687     case ClassLoaderContext::kInMemoryDexClassLoader:
688       return WellKnownClasses::dalvik_system_InMemoryDexClassLoader;
689     case ClassLoaderContext::kInvalidClassLoader: break;  // will fail after the switch.
690   }
691   LOG(FATAL) << "Invalid class loader type " << type;
692   UNREACHABLE();
693 }
694 
FlattenClasspath(const std::vector<std::string> & classpath)695 static std::string FlattenClasspath(const std::vector<std::string>& classpath) {
696   return android::base::Join(classpath, ':');
697 }
698 
CreateClassLoaderInternal(Thread * self,ScopedObjectAccess & soa,const ClassLoaderContext::ClassLoaderInfo & info,bool for_shared_library,VariableSizedHandleScope & map_scope,std::map<std::string,Handle<mirror::ClassLoader>> & canonicalized_libraries,bool add_compilation_sources,const std::vector<const DexFile * > & compilation_sources)699 static ObjPtr<mirror::ClassLoader> CreateClassLoaderInternal(
700     Thread* self,
701     ScopedObjectAccess& soa,
702     const ClassLoaderContext::ClassLoaderInfo& info,
703     bool for_shared_library,
704     VariableSizedHandleScope& map_scope,
705     std::map<std::string, Handle<mirror::ClassLoader>>& canonicalized_libraries,
706     bool add_compilation_sources,
707     const std::vector<const DexFile*>& compilation_sources)
708       REQUIRES_SHARED(Locks::mutator_lock_) {
709   if (for_shared_library) {
710     // Check if the shared library has already been created.
711     auto search = canonicalized_libraries.find(FlattenClasspath(info.classpath));
712     if (search != canonicalized_libraries.end()) {
713       return search->second.Get();
714     }
715   }
716 
717   StackHandleScope<3> hs(self);
718   MutableHandle<mirror::ObjectArray<mirror::ClassLoader>> libraries(
719       hs.NewHandle<mirror::ObjectArray<mirror::ClassLoader>>(nullptr));
720 
721   if (!info.shared_libraries.empty()) {
722     libraries.Assign(mirror::ObjectArray<mirror::ClassLoader>::Alloc(
723         self,
724         GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
725         info.shared_libraries.size()));
726     for (uint32_t i = 0; i < info.shared_libraries.size(); ++i) {
727       // We should only add the compilation sources to the first class loader.
728       libraries->Set(i,
729                      CreateClassLoaderInternal(
730                          self,
731                          soa,
732                          *info.shared_libraries[i].get(),
733                          /* for_shared_library= */ true,
734                          map_scope,
735                          canonicalized_libraries,
736                          /* add_compilation_sources= */ false,
737                          compilation_sources));
738     }
739   }
740 
741   MutableHandle<mirror::ClassLoader> parent = hs.NewHandle<mirror::ClassLoader>(nullptr);
742   if (info.parent != nullptr) {
743     // We should only add the compilation sources to the first class loader.
744     parent.Assign(CreateClassLoaderInternal(
745         self,
746         soa,
747         *info.parent.get(),
748         /* for_shared_library= */ false,
749         map_scope,
750         canonicalized_libraries,
751         /* add_compilation_sources= */ false,
752         compilation_sources));
753   }
754   std::vector<const DexFile*> class_path_files = MakeNonOwningPointerVector(
755       info.opened_dex_files);
756   if (add_compilation_sources) {
757     // For the first class loader, its classpath comes first, followed by compilation sources.
758     // This ensures that whenever we need to resolve classes from it the classpath elements
759     // come first.
760     class_path_files.insert(class_path_files.end(),
761                             compilation_sources.begin(),
762                             compilation_sources.end());
763   }
764   Handle<mirror::Class> loader_class = hs.NewHandle<mirror::Class>(
765       soa.Decode<mirror::Class>(GetClassLoaderClass(info.type)));
766   ObjPtr<mirror::ClassLoader> loader =
767       Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
768           self,
769           class_path_files,
770           loader_class,
771           parent,
772           libraries);
773   if (for_shared_library) {
774     canonicalized_libraries[FlattenClasspath(info.classpath)] =
775         map_scope.NewHandle<mirror::ClassLoader>(loader);
776   }
777   return loader;
778 }
779 
CreateClassLoader(const std::vector<const DexFile * > & compilation_sources) const780 jobject ClassLoaderContext::CreateClassLoader(
781     const std::vector<const DexFile*>& compilation_sources) const {
782   CheckDexFilesOpened("CreateClassLoader");
783 
784   Thread* self = Thread::Current();
785   ScopedObjectAccess soa(self);
786 
787   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
788 
789   if (class_loader_chain_ == nullptr) {
790     CHECK(special_shared_library_);
791     return class_linker->CreatePathClassLoader(self, compilation_sources);
792   }
793 
794   // Create a map of canonicalized shared libraries. As we're holding objects,
795   // we're creating a variable size handle scope to put handles in the map.
796   VariableSizedHandleScope map_scope(self);
797   std::map<std::string, Handle<mirror::ClassLoader>> canonicalized_libraries;
798 
799   // Create the class loader.
800   ObjPtr<mirror::ClassLoader> loader =
801       CreateClassLoaderInternal(self,
802                                 soa,
803                                 *class_loader_chain_.get(),
804                                 /* for_shared_library= */ false,
805                                 map_scope,
806                                 canonicalized_libraries,
807                                 /* add_compilation_sources= */ true,
808                                 compilation_sources);
809   // Make it a global ref and return.
810   ScopedLocalRef<jobject> local_ref(
811       soa.Env(), soa.Env()->AddLocalReference<jobject>(loader));
812   return soa.Env()->NewGlobalRef(local_ref.get());
813 }
814 
FlattenOpenedDexFiles() const815 std::vector<const DexFile*> ClassLoaderContext::FlattenOpenedDexFiles() const {
816   CheckDexFilesOpened("FlattenOpenedDexFiles");
817 
818   std::vector<const DexFile*> result;
819   if (class_loader_chain_ == nullptr) {
820     return result;
821   }
822   std::vector<ClassLoaderInfo*> work_list;
823   work_list.push_back(class_loader_chain_.get());
824   while (!work_list.empty()) {
825     ClassLoaderInfo* info = work_list.back();
826     work_list.pop_back();
827     for (const std::unique_ptr<const DexFile>& dex_file : info->opened_dex_files) {
828       result.push_back(dex_file.get());
829     }
830     AddToWorkList(info, work_list);
831   }
832   return result;
833 }
834 
FlattenDexPaths() const835 std::string ClassLoaderContext::FlattenDexPaths() const {
836   if (class_loader_chain_ == nullptr) {
837     return "";
838   }
839 
840   std::vector<std::string> result;
841   std::vector<ClassLoaderInfo*> work_list;
842   work_list.push_back(class_loader_chain_.get());
843   while (!work_list.empty()) {
844     ClassLoaderInfo* info = work_list.back();
845     work_list.pop_back();
846     for (const std::string& dex_path : info->classpath) {
847       result.push_back(dex_path);
848     }
849     AddToWorkList(info, work_list);
850   }
851   return FlattenClasspath(result);
852 }
853 
GetClassLoaderTypeName(ClassLoaderType type)854 const char* ClassLoaderContext::GetClassLoaderTypeName(ClassLoaderType type) {
855   switch (type) {
856     case kPathClassLoader: return kPathClassLoaderString;
857     case kDelegateLastClassLoader: return kDelegateLastClassLoaderString;
858     case kInMemoryDexClassLoader: return kInMemoryDexClassLoaderString;
859     default:
860       LOG(FATAL) << "Invalid class loader type " << type;
861       UNREACHABLE();
862   }
863 }
864 
CheckDexFilesOpened(const std::string & calling_method) const865 void ClassLoaderContext::CheckDexFilesOpened(const std::string& calling_method) const {
866   CHECK(dex_files_open_attempted_)
867       << "Dex files were not successfully opened before the call to " << calling_method
868       << "attempt=" << dex_files_open_attempted_ << ", result=" << dex_files_open_result_;
869 }
870 
871 // Collects the dex files from the give Java dex_file object. Only the dex files with
872 // at least 1 class are collected. If a null java_dex_file is passed this method does nothing.
CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file,ArtField * const cookie_field,std::vector<const DexFile * > * out_dex_files)873 static bool CollectDexFilesFromJavaDexFile(ObjPtr<mirror::Object> java_dex_file,
874                                            ArtField* const cookie_field,
875                                            std::vector<const DexFile*>* out_dex_files)
876       REQUIRES_SHARED(Locks::mutator_lock_) {
877   if (java_dex_file == nullptr) {
878     return true;
879   }
880   // On the Java side, the dex files are stored in the cookie field.
881   ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(java_dex_file)->AsLongArray();
882   if (long_array == nullptr) {
883     // This should never happen so log a warning.
884     LOG(ERROR) << "Unexpected null cookie";
885     return false;
886   }
887   int32_t long_array_size = long_array->GetLength();
888   // Index 0 from the long array stores the oat file. The dex files start at index 1.
889   for (int32_t j = 1; j < long_array_size; ++j) {
890     const DexFile* cp_dex_file =
891         reinterpret_cast64<const DexFile*>(long_array->GetWithoutChecks(j));
892     if (cp_dex_file != nullptr && cp_dex_file->NumClassDefs() > 0) {
893       // TODO(calin): It's unclear why the dex files with no classes are skipped here and when
894       // cp_dex_file can be null.
895       out_dex_files->push_back(cp_dex_file);
896     }
897   }
898   return true;
899 }
900 
901 // Collects all the dex files loaded by the given class loader.
902 // Returns true for success or false if an unexpected state is discovered (e.g. a null dex cookie,
903 // a null list of dex elements or a null dex element).
CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRunnable & soa,Handle<mirror::ClassLoader> class_loader,std::vector<const DexFile * > * out_dex_files)904 static bool CollectDexFilesFromSupportedClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
905                                                     Handle<mirror::ClassLoader> class_loader,
906                                                     std::vector<const DexFile*>* out_dex_files)
907       REQUIRES_SHARED(Locks::mutator_lock_) {
908   CHECK(IsPathOrDexClassLoader(soa, class_loader) ||
909         IsDelegateLastClassLoader(soa, class_loader) ||
910         IsInMemoryDexClassLoader(soa, class_loader));
911 
912   // All supported class loaders inherit from BaseDexClassLoader.
913   // We need to get the DexPathList and loop through it.
914   ArtField* const cookie_field =
915       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
916   ArtField* const dex_file_field =
917       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
918   ObjPtr<mirror::Object> dex_path_list =
919       jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
920           GetObject(class_loader.Get());
921   CHECK(cookie_field != nullptr);
922   CHECK(dex_file_field != nullptr);
923   if (dex_path_list == nullptr) {
924     // This may be null if the current class loader is under construction and it does not
925     // have its fields setup yet.
926     return true;
927   }
928   // DexPathList has an array dexElements of Elements[] which each contain a dex file.
929   ObjPtr<mirror::Object> dex_elements_obj =
930       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
931           GetObject(dex_path_list);
932   // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
933   // at the mCookie which is a DexFile vector.
934   if (dex_elements_obj == nullptr) {
935     // TODO(calin): It's unclear if we should just assert here. For now be prepared for the worse
936     // and assume we have no elements.
937     return true;
938   } else {
939     StackHandleScope<1> hs(soa.Self());
940     Handle<mirror::ObjectArray<mirror::Object>> dex_elements(
941         hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()));
942     for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
943       ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
944       if (element == nullptr) {
945         // Should never happen, log an error and break.
946         // TODO(calin): It's unclear if we should just assert here.
947         // This code was propagated to oat_file_manager from the class linker where it would
948         // throw a NPE. For now, return false which will mark this class loader as unsupported.
949         LOG(ERROR) << "Unexpected null in the dex element list";
950         return false;
951       }
952       ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
953       if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
954         return false;
955       }
956     }
957   }
958 
959   return true;
960 }
961 
GetDexFilesFromDexElementsArray(ScopedObjectAccessAlreadyRunnable & soa,Handle<mirror::ObjectArray<mirror::Object>> dex_elements,std::vector<const DexFile * > * out_dex_files)962 static bool GetDexFilesFromDexElementsArray(
963     ScopedObjectAccessAlreadyRunnable& soa,
964     Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
965     std::vector<const DexFile*>* out_dex_files) REQUIRES_SHARED(Locks::mutator_lock_) {
966   DCHECK(dex_elements != nullptr);
967 
968   ArtField* const cookie_field =
969       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
970   ArtField* const dex_file_field =
971       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
972   const ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(
973       WellKnownClasses::dalvik_system_DexPathList__Element);
974   const ObjPtr<mirror::Class> dexfile_class = soa.Decode<mirror::Class>(
975       WellKnownClasses::dalvik_system_DexFile);
976 
977   for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
978     ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
979     // We can hit a null element here because this is invoked with a partially filled dex_elements
980     // array from DexPathList. DexPathList will open each dex sequentially, each time passing the
981     // list of dex files which were opened before.
982     if (element == nullptr) {
983       continue;
984     }
985 
986     // We support this being dalvik.system.DexPathList$Element and dalvik.system.DexFile.
987     // TODO(calin): Code caried over oat_file_manager: supporting both classes seem to be
988     // a historical glitch. All the java code opens dex files using an array of Elements.
989     ObjPtr<mirror::Object> dex_file;
990     if (element_class == element->GetClass()) {
991       dex_file = dex_file_field->GetObject(element);
992     } else if (dexfile_class == element->GetClass()) {
993       dex_file = element;
994     } else {
995       LOG(ERROR) << "Unsupported element in dex_elements: "
996                  << mirror::Class::PrettyClass(element->GetClass());
997       return false;
998     }
999 
1000     if (!CollectDexFilesFromJavaDexFile(dex_file, cookie_field, out_dex_files)) {
1001       return false;
1002     }
1003   }
1004   return true;
1005 }
1006 
1007 // Adds the `class_loader` info to the `context`.
1008 // The dex file present in `dex_elements` array (if not null) will be added at the end of
1009 // the classpath.
1010 // This method is recursive (w.r.t. the class loader parent) and will stop once it reaches the
1011 // BootClassLoader. Note that the class loader chain is expected to be short.
CreateInfoFromClassLoader(ScopedObjectAccessAlreadyRunnable & soa,Handle<mirror::ClassLoader> class_loader,Handle<mirror::ObjectArray<mirror::Object>> dex_elements,ClassLoaderInfo * child_info,bool is_shared_library)1012 bool ClassLoaderContext::CreateInfoFromClassLoader(
1013       ScopedObjectAccessAlreadyRunnable& soa,
1014       Handle<mirror::ClassLoader> class_loader,
1015       Handle<mirror::ObjectArray<mirror::Object>> dex_elements,
1016       ClassLoaderInfo* child_info,
1017       bool is_shared_library)
1018     REQUIRES_SHARED(Locks::mutator_lock_) {
1019   if (ClassLinker::IsBootClassLoader(soa, class_loader.Get())) {
1020     // Nothing to do for the boot class loader as we don't add its dex files to the context.
1021     return true;
1022   }
1023 
1024   ClassLoaderContext::ClassLoaderType type;
1025   if (IsPathOrDexClassLoader(soa, class_loader)) {
1026     type = kPathClassLoader;
1027   } else if (IsDelegateLastClassLoader(soa, class_loader)) {
1028     type = kDelegateLastClassLoader;
1029   } else if (IsInMemoryDexClassLoader(soa, class_loader)) {
1030     type = kInMemoryDexClassLoader;
1031   } else {
1032     LOG(WARNING) << "Unsupported class loader";
1033     return false;
1034   }
1035 
1036   // Inspect the class loader for its dex files.
1037   std::vector<const DexFile*> dex_files_loaded;
1038   CollectDexFilesFromSupportedClassLoader(soa, class_loader, &dex_files_loaded);
1039 
1040   // If we have a dex_elements array extract its dex elements now.
1041   // This is used in two situations:
1042   //   1) when a new ClassLoader is created DexPathList will open each dex file sequentially
1043   //      passing the list of already open dex files each time. This ensures that we see the
1044   //      correct context even if the ClassLoader under construction is not fully build.
1045   //   2) when apk splits are loaded on the fly, the framework will load their dex files by
1046   //      appending them to the current class loader. When the new code paths are loaded in
1047   //      BaseDexClassLoader, the paths already present in the class loader will be passed
1048   //      in the dex_elements array.
1049   if (dex_elements != nullptr) {
1050     GetDexFilesFromDexElementsArray(soa, dex_elements, &dex_files_loaded);
1051   }
1052 
1053   ClassLoaderInfo* info = new ClassLoaderContext::ClassLoaderInfo(type);
1054   // Attach the `ClassLoaderInfo` now, before populating dex files, as only the
1055   // `ClassLoaderContext` knows whether these dex files should be deleted or not.
1056   if (child_info == nullptr) {
1057     class_loader_chain_.reset(info);
1058   } else if (is_shared_library) {
1059     child_info->shared_libraries.push_back(std::unique_ptr<ClassLoaderInfo>(info));
1060   } else {
1061     child_info->parent.reset(info);
1062   }
1063 
1064   // Now that `info` is in the chain, populate dex files.
1065   for (const DexFile* dex_file : dex_files_loaded) {
1066     // Dex location of dex files loaded with InMemoryDexClassLoader is always bogus.
1067     // Use a magic value for the classpath instead.
1068     info->classpath.push_back((type == kInMemoryDexClassLoader)
1069         ? kInMemoryDexClassLoaderDexLocationMagic
1070         : dex_file->GetLocation());
1071     info->checksums.push_back(dex_file->GetLocationChecksum());
1072     info->opened_dex_files.emplace_back(dex_file);
1073   }
1074 
1075   // Note that dex_elements array is null here. The elements are considered to be part of the
1076   // current class loader and are not passed to the parents.
1077   ScopedNullHandle<mirror::ObjectArray<mirror::Object>> null_dex_elements;
1078 
1079   // Add the shared libraries.
1080   StackHandleScope<3> hs(Thread::Current());
1081   ArtField* field =
1082       jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
1083   ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader.Get());
1084   if (raw_shared_libraries != nullptr) {
1085     Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries =
1086         hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>());
1087     MutableHandle<mirror::ClassLoader> temp_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
1088     for (int32_t i = 0; i < shared_libraries->GetLength(); ++i) {
1089       temp_loader.Assign(shared_libraries->Get(i));
1090       if (!CreateInfoFromClassLoader(
1091               soa, temp_loader, null_dex_elements, info, /*is_shared_library=*/ true)) {
1092         return false;
1093       }
1094     }
1095   }
1096 
1097   // We created the ClassLoaderInfo for the current loader. Move on to its parent.
1098   Handle<mirror::ClassLoader> parent = hs.NewHandle(class_loader->GetParent());
1099   if (!CreateInfoFromClassLoader(
1100           soa, parent, null_dex_elements, info, /*is_shared_library=*/ false)) {
1101     return false;
1102   }
1103   return true;
1104 }
1105 
CreateContextForClassLoader(jobject class_loader,jobjectArray dex_elements)1106 std::unique_ptr<ClassLoaderContext> ClassLoaderContext::CreateContextForClassLoader(
1107     jobject class_loader,
1108     jobjectArray dex_elements) {
1109   CHECK(class_loader != nullptr);
1110 
1111   ScopedObjectAccess soa(Thread::Current());
1112   StackHandleScope<2> hs(soa.Self());
1113   Handle<mirror::ClassLoader> h_class_loader =
1114       hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader));
1115   Handle<mirror::ObjectArray<mirror::Object>> h_dex_elements =
1116       hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(dex_elements));
1117   std::unique_ptr<ClassLoaderContext> result(new ClassLoaderContext(/*owns_the_dex_files=*/ false));
1118   if (!result->CreateInfoFromClassLoader(
1119           soa, h_class_loader, h_dex_elements, nullptr, /*is_shared_library=*/ false)) {
1120     return nullptr;
1121   }
1122   return result;
1123 }
1124 
VerifyClassLoaderContextMatch(const std::string & context_spec,bool verify_names,bool verify_checksums) const1125 ClassLoaderContext::VerificationResult ClassLoaderContext::VerifyClassLoaderContextMatch(
1126     const std::string& context_spec,
1127     bool verify_names,
1128     bool verify_checksums) const {
1129   if (verify_names || verify_checksums) {
1130     DCHECK(dex_files_open_attempted_);
1131     DCHECK(dex_files_open_result_);
1132   }
1133 
1134   ClassLoaderContext expected_context;
1135   if (!expected_context.Parse(context_spec, verify_checksums)) {
1136     LOG(WARNING) << "Invalid class loader context: " << context_spec;
1137     return VerificationResult::kMismatch;
1138   }
1139 
1140   // Special shared library contexts always match. They essentially instruct the runtime
1141   // to ignore the class path check because the oat file is known to be loaded in different
1142   // contexts. OatFileManager will further verify if the oat file can be loaded based on the
1143   // collision check.
1144   if (expected_context.special_shared_library_) {
1145     // Special case where we are the only entry in the class path.
1146     if (class_loader_chain_ != nullptr &&
1147         class_loader_chain_->parent == nullptr &&
1148         class_loader_chain_->classpath.size() == 0) {
1149       return VerificationResult::kVerifies;
1150     }
1151     return VerificationResult::kForcedToSkipChecks;
1152   } else if (special_shared_library_) {
1153     return VerificationResult::kForcedToSkipChecks;
1154   }
1155 
1156   ClassLoaderInfo* info = class_loader_chain_.get();
1157   ClassLoaderInfo* expected = expected_context.class_loader_chain_.get();
1158   CHECK(info != nullptr);
1159   CHECK(expected != nullptr);
1160   if (!ClassLoaderInfoMatch(*info, *expected, context_spec, verify_names, verify_checksums)) {
1161     return VerificationResult::kMismatch;
1162   }
1163   return VerificationResult::kVerifies;
1164 }
1165 
ClassLoaderInfoMatch(const ClassLoaderInfo & info,const ClassLoaderInfo & expected_info,const std::string & context_spec,bool verify_names,bool verify_checksums) const1166 bool ClassLoaderContext::ClassLoaderInfoMatch(
1167     const ClassLoaderInfo& info,
1168     const ClassLoaderInfo& expected_info,
1169     const std::string& context_spec,
1170     bool verify_names,
1171     bool verify_checksums) const {
1172   if (info.type != expected_info.type) {
1173     LOG(WARNING) << "ClassLoaderContext type mismatch"
1174         << ". expected=" << GetClassLoaderTypeName(expected_info.type)
1175         << ", found=" << GetClassLoaderTypeName(info.type)
1176         << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1177     return false;
1178   }
1179   if (info.classpath.size() != expected_info.classpath.size()) {
1180     LOG(WARNING) << "ClassLoaderContext classpath size mismatch"
1181           << ". expected=" << expected_info.classpath.size()
1182           << ", found=" << info.classpath.size()
1183           << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1184     return false;
1185   }
1186 
1187   if (verify_checksums) {
1188     DCHECK_EQ(info.classpath.size(), info.checksums.size());
1189     DCHECK_EQ(expected_info.classpath.size(), expected_info.checksums.size());
1190   }
1191 
1192   if (verify_names) {
1193     for (size_t k = 0; k < info.classpath.size(); k++) {
1194       // Compute the dex location that must be compared.
1195       // We shouldn't do a naive comparison `info.classpath[k] == expected_info.classpath[k]`
1196       // because even if they refer to the same file, one could be encoded as a relative location
1197       // and the other as an absolute one.
1198       bool is_dex_name_absolute = IsAbsoluteLocation(info.classpath[k]);
1199       bool is_expected_dex_name_absolute = IsAbsoluteLocation(expected_info.classpath[k]);
1200       std::string dex_name;
1201       std::string expected_dex_name;
1202 
1203       if (is_dex_name_absolute == is_expected_dex_name_absolute) {
1204         // If both locations are absolute or relative then compare them as they are.
1205         // This is usually the case for: shared libraries and secondary dex files.
1206         dex_name = info.classpath[k];
1207         expected_dex_name = expected_info.classpath[k];
1208       } else if (is_dex_name_absolute) {
1209         // The runtime name is absolute but the compiled name (the expected one) is relative.
1210         // This is the case for split apks which depend on base or on other splits.
1211         dex_name = info.classpath[k];
1212         OatFile::ResolveRelativeEncodedDexLocation(info.classpath[k].c_str(),
1213                                                    expected_info.classpath[k],
1214                                                    &expected_dex_name);
1215       } else if (is_expected_dex_name_absolute) {
1216         // The runtime name is relative but the compiled name is absolute.
1217         // There is no expected use case that would end up here as dex files are always loaded
1218         // with their absolute location. However, be tolerant and do the best effort (in case
1219         // there are unexpected new use case...).
1220         OatFile::ResolveRelativeEncodedDexLocation(expected_info.classpath[k].c_str(),
1221                                                    info.classpath[k],
1222                                                    &dex_name);
1223         expected_dex_name = expected_info.classpath[k];
1224       } else {
1225         // Both locations are relative. In this case there's not much we can be sure about
1226         // except that the names are the same. The checksum will ensure that the files are
1227         // are same. This should not happen outside testing and manual invocations.
1228         dex_name = info.classpath[k];
1229         expected_dex_name = expected_info.classpath[k];
1230       }
1231 
1232       // Compare the locations.
1233       if (dex_name != expected_dex_name) {
1234         LOG(WARNING) << "ClassLoaderContext classpath element mismatch"
1235             << ". expected=" << expected_info.classpath[k]
1236             << ", found=" << info.classpath[k]
1237             << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1238         return false;
1239       }
1240 
1241       // Compare the checksums.
1242       if (info.checksums[k] != expected_info.checksums[k]) {
1243         LOG(WARNING) << "ClassLoaderContext classpath element checksum mismatch"
1244                      << ". expected=" << expected_info.checksums[k]
1245                      << ", found=" << info.checksums[k]
1246                      << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1247         return false;
1248       }
1249     }
1250   }
1251 
1252   if (info.shared_libraries.size() != expected_info.shared_libraries.size()) {
1253     LOG(WARNING) << "ClassLoaderContext shared library size mismatch. "
1254           << "Expected=" << expected_info.shared_libraries.size()
1255           << ", found=" << info.shared_libraries.size()
1256           << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1257     return false;
1258   }
1259   for (size_t i = 0; i < info.shared_libraries.size(); ++i) {
1260     if (!ClassLoaderInfoMatch(*info.shared_libraries[i].get(),
1261                               *expected_info.shared_libraries[i].get(),
1262                               context_spec,
1263                               verify_names,
1264                               verify_checksums)) {
1265       return false;
1266     }
1267   }
1268   if (info.parent.get() == nullptr) {
1269     if (expected_info.parent.get() != nullptr) {
1270       LOG(WARNING) << "ClassLoaderContext parent mismatch. "
1271             << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1272       return false;
1273     }
1274     return true;
1275   } else if (expected_info.parent.get() == nullptr) {
1276     LOG(WARNING) << "ClassLoaderContext parent mismatch. "
1277           << " (" << context_spec << " | " << EncodeContextForOatFile("") << ")";
1278     return false;
1279   } else {
1280     return ClassLoaderInfoMatch(*info.parent.get(),
1281                                 *expected_info.parent.get(),
1282                                 context_spec,
1283                                 verify_names,
1284                                 verify_checksums);
1285   }
1286 }
1287 
1288 }  // namespace art
1289