summaryrefslogtreecommitdiffstats
path: root/runtime/oat_file_manager.h
blob: d09b6d6f89e7d450314af4e758365b6186b8eb2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_OAT_FILE_MANAGER_H_
#define ART_RUNTIME_OAT_FILE_MANAGER_H_

#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "base/locks.h"
#include "base/macros.h"
#include "jni.h"

namespace art {

namespace gc {
namespace space {
class ImageSpace;
}  // namespace space
}  // namespace gc

class ClassLoaderContext;
class DexFile;
class MemMap;
class OatFile;
class ThreadPool;

// Class for dealing with oat file management.
//
// This class knows about all the loaded oat files and provides utility functions. The oat file
// pointers returned from functions are always valid.
class OatFileManager {
 public:
  OatFileManager();
  ~OatFileManager();

  // Add an oat file to the internal accounting, std::aborts if there already exists an oat file
  // with the same base address. Returns the oat file pointer from oat_file.
  const OatFile* RegisterOatFile(std::unique_ptr<const OatFile> oat_file)
      REQUIRES(!Locks::oat_file_manager_lock_);

  void UnRegisterAndDeleteOatFile(const OatFile* oat_file)
      REQUIRES(!Locks::oat_file_manager_lock_);

  // Find the first opened oat file with the same location, returns null if there are none.
  const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location) const
      REQUIRES(!Locks::oat_file_manager_lock_);

  // Find the oat file which contains a dex files with the given dex base location,
  // returns null if there are none.
  const OatFile* FindOpenedOatFileFromDexLocation(const std::string& dex_base_location) const
      REQUIRES(!Locks::oat_file_manager_lock_);

  // Returns the boot image oat files.
  std::vector<const OatFile*> GetBootOatFiles() const;

  // Returns the first non-image oat file in the class path.
  const OatFile* GetPrimaryOatFile() const REQUIRES(!Locks::oat_file_manager_lock_);

  // Returns the oat files for the images, registers the oat files.
  // Takes ownership of the imagespace's underlying oat files.
  std::vector<const OatFile*> RegisterImageOatFiles(
      const std::vector<gc::space::ImageSpace*>& spaces)
      REQUIRES(!Locks::oat_file_manager_lock_);

  // Finds or creates the oat file holding dex_location. Then loads and returns
  // all corresponding dex files (there may be more than one dex file loaded
  // in the case of multidex).
  // This may return the original, unquickened dex files if the oat file could
  // not be generated.
  //
  // Returns an empty vector if the dex files could not be loaded. In this
  // case, there will be at least one error message returned describing why no
  // dex files could not be loaded. The 'error_msgs' argument must not be
  // null, regardless of whether there is an error or not.
  //
  // This method should not be called with the mutator_lock_ held, because it
  // could end up starving GC if we need to generate or relocate any oat
  // files.
  std::vector<std::unique_ptr<const DexFile>> OpenDexFilesFromOat(
      const char* dex_location,
      jobject class_loader,
      jobjectArray dex_elements,
      /*out*/ const OatFile** out_oat_file,
      /*out*/ std::vector<std::string>* error_msgs)
      REQUIRES(!Locks::oat_file_manager_lock_, !Locks::mutator_lock_);

  // Opens dex files provided in `dex_mem_maps` and attempts to find an anonymous
  // vdex file created during a previous load attempt. If found, will initialize
  // an instance of OatFile to back the DexFiles and preverify them using the
  // vdex's VerifierDeps.
  //
  // Returns an empty vector if the dex files could not be loaded. In this
  // case, there will be at least one error message returned describing why no
  // dex files could not be loaded. The 'error_msgs' argument must not be
  // null, regardless of whether there is an error or not.
  std::vector<std::unique_ptr<const DexFile>> OpenDexFilesFromOat(
      std::vector<MemMap>&& dex_mem_maps,
      jobject class_loader,
      jobjectArray dex_elements,
      /*out*/ const OatFile** out_oat_file,
      /*out*/ std::vector<std::string>* error_msgs)
      REQUIRES(!Locks::oat_file_manager_lock_, !Locks::mutator_lock_);

  void DumpForSigQuit(std::ostream& os);

  void SetOnlyUseSystemOatFiles(bool enforce, bool assert_no_files_loaded);

  // Spawn a background thread which verifies all classes in the given dex files.
  void RunBackgroundVerification(const std::vector<const DexFile*>& dex_files,
                                 jobject class_loader,
                                 const char* class_loader_context);

  // Wait for thread pool workers to be created. This is used during shutdown as
  // threads are not allowed to attach while runtime is in shutdown lock.
  void WaitForWorkersToBeCreated();

  // If allocated, delete a thread pool of background verification threads.
  void DeleteThreadPool();

  // Wait for all background verification tasks to finish. This is only used by tests.
  void WaitForBackgroundVerificationTasks();

  // Maximum number of anonymous vdex files kept in the process' data folder.
  static constexpr size_t kAnonymousVdexCacheSize = 8u;

 private:
  enum class CheckCollisionResult {
    kSkippedUnsupportedClassLoader,
    kSkippedClassLoaderContextSharedLibrary,
    kNoCollisions,
    kPerformedHasCollisions,
  };

  std::vector<std::unique_ptr<const DexFile>> OpenDexFilesFromOat_Impl(
      std::vector<MemMap>&& dex_mem_maps,
      jobject class_loader,
      jobjectArray dex_elements,
      /*out*/ const OatFile** out_oat_file,
      /*out*/ std::vector<std::string>* error_msgs)
      REQUIRES(!Locks::oat_file_manager_lock_, !Locks::mutator_lock_);

  // Check that the class loader context of the given oat file matches the given context.
  // This will perform a check that all class loaders in the chain have the same type and
  // classpath.
  // If the context is null (which means the initial class loader was null or unsupported)
  // this returns kSkippedUnsupportedClassLoader.
  // If the context does not validate the method will check for duplicate class definitions of
  // the given oat file against the oat files (either from the class loaders if possible or all
  // non-boot oat files otherwise).
  // Return kPerformedHasCollisions if there are any class definition collisions in the oat_file.
  CheckCollisionResult CheckCollision(const OatFile* oat_file,
                                      const ClassLoaderContext* context,
                                      /*out*/ std::string* error_msg) const
      REQUIRES(!Locks::oat_file_manager_lock_);

  const OatFile* FindOpenedOatFileFromOatLocationLocked(const std::string& oat_location) const
      REQUIRES(Locks::oat_file_manager_lock_);

  // Return true if we should accept the oat file.
  bool AcceptOatFile(CheckCollisionResult result) const;

  // Return true if we should attempt to load the app image.
  bool ShouldLoadAppImage(CheckCollisionResult check_collision_result,
                          const OatFile* source_oat_file,
                          ClassLoaderContext* context,
                          std::string* error_msg);

  std::set<std::unique_ptr<const OatFile>> oat_files_ GUARDED_BY(Locks::oat_file_manager_lock_);

  // Only use the compiled code in an OAT file when the file is on /system. If the OAT file
  // is not on /system, don't load it "executable".
  bool only_use_system_oat_files_;

  // Single-thread pool used to run the verifier in the background.
  std::unique_ptr<ThreadPool> verification_thread_pool_;

  DISALLOW_COPY_AND_ASSIGN(OatFileManager);
};

}  // namespace art

#endif  // ART_RUNTIME_OAT_FILE_MANAGER_H_