blob: 347b58fee6ce985a05aa83a823f5560732abe70c [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrome24fa612011-09-29 00:53:55 -070016
17#include "oat_file.h"
18
Brian Carlstrom700c8d32012-11-05 10:42:02 -080019#include <dlfcn.h>
David Srbecky1baabf02015-06-16 17:12:34 +000020#ifndef __APPLE__
21#include <link.h> // for dl_iterate_phdr.
22#endif
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include <unistd.h>
24
25#include <cstdlib>
26#include <cstring>
Richard Uhlere5fed032015-03-18 08:21:11 -070027#include <sstream>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070028#include <type_traits>
Shubham Ajmerab22dea02017-10-04 18:36:41 -070029#include <sys/stat.h>
Richard Uhlere5fed032015-03-18 08:21:11 -070030
Andreas Gampefa8429b2015-04-07 18:34:42 -070031// dlopen_ext support from bionic.
Bilyan Borisovbb661c02016-04-04 16:27:32 +010032#ifdef ART_TARGET_ANDROID
Andreas Gampefa8429b2015-04-07 18:34:42 -070033#include "android/dlext.h"
Martin Stjernholm93c28ed2021-05-14 14:11:42 +010034#include "nativeloader/dlext_namespaces.h"
Andreas Gampefa8429b2015-04-07 18:34:42 -070035#endif
36
Andreas Gampe875b4f22018-11-19 12:59:15 -080037#include <android-base/logging.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080038#include "android-base/stringprintf.h"
39
David Brazdil7126c5b2019-03-05 00:02:51 +000040#include "arch/instruction_set_features.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080041#include "art_method.h"
Brian Carlstromba150c32013-08-27 17:31:03 -070042#include "base/bit_vector.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070043#include "base/enums.h"
David Sehr891a50e2017-10-27 17:01:07 -070044#include "base/file_utils.h"
Andreas Gampe170331f2017-12-07 18:41:03 -080045#include "base/logging.h" // For VLOG_IS_ON.
David Sehr79e26072018-04-06 17:58:50 -070046#include "base/mem_map.h"
David Sehrc431b9d2018-03-02 12:01:51 -080047#include "base/os.h"
Elliott Hughes1aa246d2012-12-13 09:29:36 -080048#include "base/stl_util.h"
Vladimir Markob7bf8432019-12-03 13:18:50 +000049#include "base/string_view_cpp20.h"
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -080050#include "base/systrace.h"
Elliott Hughes76160052012-12-12 16:31:20 -080051#include "base/unix_file/fd_file.h"
David Sehrc431b9d2018-03-02 12:01:51 -080052#include "base/utils.h"
David Sehr013fd802018-01-11 22:55:24 -080053#include "dex/art_dex_file_loader.h"
Andreas Gampe3f1dcd32018-12-28 09:39:56 -080054#include "dex/dex_file.h"
David Sehr9e734c72018-01-04 17:56:19 -080055#include "dex/dex_file_loader.h"
Andreas Gampe3f1dcd32018-12-28 09:39:56 -080056#include "dex/dex_file_structs.h"
David Sehr9e734c72018-01-04 17:56:19 -080057#include "dex/dex_file_types.h"
58#include "dex/standard_dex_file.h"
David Sehr9c4a0152018-04-05 12:23:54 -070059#include "dex/type_lookup_table.h"
David Sehr0225f8e2018-01-31 08:52:24 +000060#include "dex/utf-inl.h"
David Srbecky50928112019-03-22 17:06:28 +000061#include "elf/elf_utils.h"
Brian Carlstrom700c8d32012-11-05 10:42:02 -080062#include "elf_file.h"
Vladimir Markoaad75c62016-10-03 08:46:48 +000063#include "gc_root.h"
Vladimir Marko1cedb4a2019-02-06 14:13:28 +000064#include "gc/heap.h"
Vladimir Marko6cfbdbc2017-07-25 13:26:39 +010065#include "gc/space/image_space.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080066#include "mirror/class.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070067#include "mirror/object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070068#include "oat.h"
Nicolas Geoffrayc04c8002015-07-14 11:37:54 +010069#include "oat_file-inl.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070070#include "oat_file_manager.h"
Vladimir Marko1cedb4a2019-02-06 14:13:28 +000071#include "runtime-inl.h"
Vladimir Marko97d7e1c2016-10-04 14:44:28 +010072#include "vdex_file.h"
David Brazdil7126c5b2019-03-05 00:02:51 +000073#include "verifier/verifier_deps.h"
Brian Carlstrome24fa612011-09-29 00:53:55 -070074
75namespace art {
76
Andreas Gampe46ee31b2016-12-14 10:11:49 -080077using android::base::StringPrintf;
78
Andreas Gampe049cff02015-12-01 23:27:12 -080079// Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
David Srbecky1baabf02015-06-16 17:12:34 +000080static constexpr bool kUseDlopen = true;
Andreas Gampefa8429b2015-04-07 18:34:42 -070081
Andreas Gampe049cff02015-12-01 23:27:12 -080082// Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
Andreas Gampefa8429b2015-04-07 18:34:42 -070083// bionic, so cannot take advantage of the support for changed semantics (loading the same soname
84// multiple times). However, if/when we switch the above, we likely want to switch this, too,
85// to get test coverage of the code paths.
David Srbecky1baabf02015-06-16 17:12:34 +000086static constexpr bool kUseDlopenOnHost = true;
Andreas Gampefa8429b2015-04-07 18:34:42 -070087
88// For debugging, Open will print DlOpen error message if set to true.
89static constexpr bool kPrintDlOpenErrorMessage = false;
90
Andreas Gampe049cff02015-12-01 23:27:12 -080091// Note for OatFileBase and descendents:
92//
93// These are used in OatFile::Open to try all our loaders.
94//
95// The process is simple:
96//
97// 1) Allocate an instance through the standard constructor (location, executable)
98// 2) Load() to try to open the file.
99// 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
100// 4) PreSetup() for any steps that should be done before the final setup.
101// 5) Setup() to complete the procedure.
Richard Uhlere5fed032015-03-18 08:21:11 -0700102
Andreas Gampe049cff02015-12-01 23:27:12 -0800103class OatFileBase : public OatFile {
104 public:
105 virtual ~OatFileBase() {}
Richard Uhlere5fed032015-03-18 08:21:11 -0700106
Andreas Gampe049cff02015-12-01 23:27:12 -0800107 template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100108 static OatFileBase* OpenOatFile(int zip_fd,
109 const std::string& vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100110 const std::string& elf_filename,
Alex Light84d76052014-08-22 17:49:35 -0700111 const std::string& location,
Andreas Gampe049cff02015-12-01 23:27:12 -0800112 bool writable,
113 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800114 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000115 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -0700116 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100117 /*inout*/MemMap* reservation, // Where to load if not null.
118 /*out*/std::string* error_msg);
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800119
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700120 template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100121 static OatFileBase* OpenOatFile(int zip_fd,
122 int vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700123 int oat_fd,
124 const std::string& vdex_filename,
125 const std::string& oat_filename,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700126 bool writable,
127 bool executable,
128 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000129 ArrayRef<const std::string> dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -0700130 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100131 /*inout*/MemMap* reservation, // Where to load if not null.
132 /*out*/std::string* error_msg);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700133
Andreas Gampe049cff02015-12-01 23:27:12 -0800134 protected:
135 OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
Andreas Gampefa8429b2015-04-07 18:34:42 -0700136
Andreas Gampe049cff02015-12-01 23:27:12 -0800137 virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
138 std::string* error_msg) const = 0;
139
Andreas Gampe4075f832016-05-18 13:09:54 -0700140 virtual void PreLoad() = 0;
141
David Brazdil7b49e6c2016-09-01 11:06:18 +0100142 bool LoadVdex(const std::string& vdex_filename,
143 bool writable,
144 bool low_4gb,
145 std::string* error_msg);
146
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700147 bool LoadVdex(int vdex_fd,
148 const std::string& vdex_filename,
149 bool writable,
150 bool low_4gb,
151 std::string* error_msg);
152
Andreas Gampe049cff02015-12-01 23:27:12 -0800153 virtual bool Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800154 bool writable,
155 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800156 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100157 /*inout*/MemMap* reservation, // Where to load if not null.
158 /*out*/std::string* error_msg) = 0;
Andreas Gampe049cff02015-12-01 23:27:12 -0800159
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700160 virtual bool Load(int oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700161 bool writable,
162 bool executable,
163 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100164 /*inout*/MemMap* reservation, // Where to load if not null.
165 /*out*/std::string* error_msg) = 0;
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700166
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100167 bool ComputeFields(const std::string& file_path, std::string* error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -0800168
169 virtual void PreSetup(const std::string& elf_filename) = 0;
170
Victor Hsiehf667c332021-05-27 11:35:44 -0700171 bool Setup(int zip_fd,
172 ArrayRef<const std::string> dex_filenames,
173 ArrayRef<const int> dex_fds,
174 std::string* error_msg);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000175
176 void Setup(const std::vector<const DexFile*>& dex_files);
Andreas Gampe049cff02015-12-01 23:27:12 -0800177
178 // Setters exposed for ElfOatFile.
179
180 void SetBegin(const uint8_t* begin) {
181 begin_ = begin;
Andreas Gampefa8429b2015-04-07 18:34:42 -0700182 }
183
Andreas Gampe049cff02015-12-01 23:27:12 -0800184 void SetEnd(const uint8_t* end) {
185 end_ = end;
186 }
187
David Brazdilc93b3be2016-09-12 18:49:58 +0100188 void SetVdex(VdexFile* vdex) {
189 vdex_.reset(vdex);
190 }
191
Andreas Gampe049cff02015-12-01 23:27:12 -0800192 private:
Alex Lightabd8f052019-12-06 10:49:17 -0800193 // Returns true if we want to remove quickened opcodes before loading the VDEX file, false
194 // otherwise.
195 bool ShouldUnquickenVDex() const;
196
Andreas Gampe049cff02015-12-01 23:27:12 -0800197 DISALLOW_COPY_AND_ASSIGN(OatFileBase);
198};
199
200template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100201OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
202 const std::string& vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100203 const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800204 const std::string& location,
Andreas Gampe049cff02015-12-01 23:27:12 -0800205 bool writable,
206 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800207 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000208 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -0700209 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100210 /*inout*/MemMap* reservation,
211 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800212 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
Andreas Gampe4075f832016-05-18 13:09:54 -0700213
214 ret->PreLoad();
215
Andreas Gampe049cff02015-12-01 23:27:12 -0800216 if (!ret->Load(elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800217 writable,
218 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800219 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100220 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -0800221 error_msg)) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800222 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800223 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800224
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100225 if (!ret->ComputeFields(elf_filename, error_msg)) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800226 return nullptr;
227 }
Andreas Gampe4075f832016-05-18 13:09:54 -0700228
David Sehr2300b2d2018-05-10 14:20:10 -0700229 ret->PreSetup(elf_filename);
230
David Srbeckyec2cdf42017-12-08 16:21:25 +0000231 if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
232 return nullptr;
233 }
234
Victor Hsiehf667c332021-05-27 11:35:44 -0700235 if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800236 return nullptr;
237 }
238
Dave Allison69dfe512014-07-11 17:11:58 +0000239 return ret.release();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800240}
241
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700242template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100243OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
244 int vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700245 int oat_fd,
246 const std::string& vdex_location,
247 const std::string& oat_location,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700248 bool writable,
249 bool executable,
250 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000251 ArrayRef<const std::string> dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -0700252 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100253 /*inout*/MemMap* reservation,
254 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700255 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
256
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700257 if (!ret->Load(oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700258 writable,
259 executable,
260 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100261 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700262 error_msg)) {
263 return nullptr;
264 }
265
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100266 if (!ret->ComputeFields(oat_location, error_msg)) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700267 return nullptr;
268 }
269
David Sehr2300b2d2018-05-10 14:20:10 -0700270 ret->PreSetup(oat_location);
271
David Srbeckyec2cdf42017-12-08 16:21:25 +0000272 if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
273 return nullptr;
274 }
275
Victor Hsiehce9b9022021-07-21 10:44:06 -0700276 if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700277 return nullptr;
278 }
279
280 return ret.release();
281}
282
Alex Lightabd8f052019-12-06 10:49:17 -0800283bool OatFileBase::ShouldUnquickenVDex() const {
284 // We sometimes load oat files without a runtime (eg oatdump) and don't want to do anything in
285 // that case. If we are debuggable there are no -quick opcodes to unquicken. If the runtime is not
286 // debuggable we don't care whether there are -quick opcodes or not so no need to do anything.
Vladimir Markoef8c3372021-03-17 15:01:42 +0000287 Runtime* runtime = Runtime::Current();
288 return (runtime != nullptr && runtime->IsJavaDebuggable()) &&
289 // Note: This is called before `OatFileBase::Setup()` where we validate the
290 // oat file contents. Check that we have at least a valid header, including
291 // oat file version, to avoid parsing the key-value store for a different
292 // version (out-of-date oat file) which can lead to crashes. b/179221298.
293 // TODO: While this is a poor workaround and the correct solution would be
294 // to postpone the unquickening check until after `OatFileBase::Setup()`,
295 // we prefer to avoid larger rewrites because quickening is deprecated and
296 // should be removed completely anyway. b/170086509
297 (GetOatHeader().IsValid() && !IsDebuggable());
Alex Lightabd8f052019-12-06 10:49:17 -0800298}
299
David Brazdil7b49e6c2016-09-01 11:06:18 +0100300bool OatFileBase::LoadVdex(const std::string& vdex_filename,
301 bool writable,
302 bool low_4gb,
303 std::string* error_msg) {
David Srbeckyec2cdf42017-12-08 16:21:25 +0000304 vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
305 vdex_end_ - vdex_begin_,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100306 /*mmap_reuse=*/ vdex_begin_ != nullptr,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000307 vdex_filename,
308 writable,
309 low_4gb,
Alex Lightabd8f052019-12-06 10:49:17 -0800310 ShouldUnquickenVDex(),
David Srbeckyec2cdf42017-12-08 16:21:25 +0000311 error_msg);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100312 if (vdex_.get() == nullptr) {
313 *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
314 vdex_filename.c_str(),
315 error_msg->c_str());
316 return false;
317 }
318 return true;
319}
320
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700321bool OatFileBase::LoadVdex(int vdex_fd,
322 const std::string& vdex_filename,
323 bool writable,
324 bool low_4gb,
325 std::string* error_msg) {
326 if (vdex_fd != -1) {
327 struct stat s;
328 int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd, &s));
329 if (rc == -1) {
330 PLOG(WARNING) << "Failed getting length of vdex file";
331 } else {
Alex Lightabd8f052019-12-06 10:49:17 -0800332 vdex_ = VdexFile::OpenAtAddress(
333 vdex_begin_,
334 vdex_end_ - vdex_begin_,
335 /*mmap_reuse=*/ vdex_begin_ != nullptr,
336 vdex_fd,
337 s.st_size,
338 vdex_filename,
339 writable,
340 low_4gb,
341 ShouldUnquickenVDex(),
342 error_msg);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700343 if (vdex_.get() == nullptr) {
344 *error_msg = "Failed opening vdex file.";
345 return false;
346 }
347 }
348 }
349 return true;
350}
351
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100352bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800353 std::string symbol_error_msg;
354 begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700355 if (begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800356 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
357 file_path.c_str(),
358 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700359 return false;
360 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800361 end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700362 if (end_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800363 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
364 file_path.c_str(),
365 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700366 return false;
367 }
368 // Readjust to be non-inclusive upper bound.
369 end_ += sizeof(uint32_t);
370
Vladimir Markob066d432018-01-03 13:14:37 +0000371 data_bimg_rel_ro_begin_ = FindDynamicSymbolAddress("oatdatabimgrelro", &symbol_error_msg);
372 if (data_bimg_rel_ro_begin_ != nullptr) {
373 data_bimg_rel_ro_end_ =
374 FindDynamicSymbolAddress("oatdatabimgrelrolastword", &symbol_error_msg);
375 if (data_bimg_rel_ro_end_ == nullptr) {
376 *error_msg =
377 StringPrintf("Failed to find oatdatabimgrelrolastword symbol in '%s'", file_path.c_str());
378 return false;
379 }
380 // Readjust to be non-inclusive upper bound.
381 data_bimg_rel_ro_end_ += sizeof(uint32_t);
382 }
383
Andreas Gampe049cff02015-12-01 23:27:12 -0800384 bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700385 if (bss_begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800386 // No .bss section.
Andreas Gampefa8429b2015-04-07 18:34:42 -0700387 bss_end_ = nullptr;
Andreas Gampefa8429b2015-04-07 18:34:42 -0700388 } else {
Andreas Gampe049cff02015-12-01 23:27:12 -0800389 bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700390 if (bss_end_ == nullptr) {
David Srbeckyec2cdf42017-12-08 16:21:25 +0000391 *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700392 return false;
393 }
394 // Readjust to be non-inclusive upper bound.
395 bss_end_ += sizeof(uint32_t);
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100396 // Find bss methods if present.
397 bss_methods_ =
398 const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
Vladimir Markoaad75c62016-10-03 08:46:48 +0000399 // Find bss roots if present.
400 bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700401 }
402
David Srbeckyec2cdf42017-12-08 16:21:25 +0000403 vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
404 if (vdex_begin_ == nullptr) {
405 // No .vdex section.
406 vdex_end_ = nullptr;
407 } else {
408 vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
409 if (vdex_end_ == nullptr) {
410 *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
411 return false;
412 }
413 // Readjust to be non-inclusive upper bound.
414 vdex_end_ += sizeof(uint32_t);
415 }
416
Andreas Gampe049cff02015-12-01 23:27:12 -0800417 return true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800418}
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800419
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100420// Read an unaligned entry from the OatDexFile data in OatFile and advance the read
421// position by the number of bytes read, i.e. sizeof(T).
422// Return true on success, false if the read would go beyond the end of the OatFile.
423template <typename T>
Vladimir Marko722fa982015-10-19 18:18:27 +0100424inline static bool ReadOatDexFileData(const OatFile& oat_file,
425 /*inout*/const uint8_t** oat,
426 /*out*/T* value) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100427 DCHECK(oat != nullptr);
428 DCHECK(value != nullptr);
429 DCHECK_LE(*oat, oat_file.End());
430 if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
431 return false;
432 }
433 static_assert(std::is_trivial<T>::value, "T must be a trivial type");
Andreas Gampec55bb392018-09-21 00:02:02 +0000434 using unaligned_type __attribute__((__aligned__(1))) = T;
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100435 *value = *reinterpret_cast<const unaligned_type*>(*oat);
436 *oat += sizeof(T);
437 return true;
438}
439
Vladimir Markof3c52b42017-11-17 17:32:12 +0000440static bool ReadIndexBssMapping(OatFile* oat_file,
441 /*inout*/const uint8_t** oat,
442 size_t dex_file_index,
443 const std::string& dex_file_location,
444 const char* tag,
445 /*out*/const IndexBssMapping** mapping,
446 std::string* error_msg) {
447 uint32_t index_bss_mapping_offset;
448 if (UNLIKELY(!ReadOatDexFileData(*oat_file, oat, &index_bss_mapping_offset))) {
449 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
450 "after %s bss mapping offset",
451 oat_file->GetLocation().c_str(),
452 dex_file_index,
453 dex_file_location.c_str(),
454 tag);
455 return false;
456 }
457 const bool readable_index_bss_mapping_size =
458 index_bss_mapping_offset != 0u &&
459 index_bss_mapping_offset <= oat_file->Size() &&
460 IsAligned<alignof(IndexBssMapping)>(index_bss_mapping_offset) &&
461 oat_file->Size() - index_bss_mapping_offset >= IndexBssMapping::ComputeSize(0);
462 const IndexBssMapping* index_bss_mapping = readable_index_bss_mapping_size
463 ? reinterpret_cast<const IndexBssMapping*>(oat_file->Begin() + index_bss_mapping_offset)
464 : nullptr;
465 if (index_bss_mapping_offset != 0u &&
466 (UNLIKELY(index_bss_mapping == nullptr) ||
467 UNLIKELY(index_bss_mapping->size() == 0u) ||
468 UNLIKELY(oat_file->Size() - index_bss_mapping_offset <
469 IndexBssMapping::ComputeSize(index_bss_mapping->size())))) {
470 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
471 " truncated %s bss mapping, offset %u of %zu, length %zu",
472 oat_file->GetLocation().c_str(),
473 dex_file_index,
474 dex_file_location.c_str(),
475 tag,
476 index_bss_mapping_offset,
477 oat_file->Size(),
478 index_bss_mapping != nullptr ? index_bss_mapping->size() : 0u);
479 return false;
480 }
481
482 *mapping = index_bss_mapping;
483 return true;
484}
485
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000486void OatFileBase::Setup(const std::vector<const DexFile*>& dex_files) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000487 uint32_t i = 0;
488 const uint8_t* type_lookup_table_start = nullptr;
David Brazdil7126c5b2019-03-05 00:02:51 +0000489 for (const DexFile* dex_file : dex_files) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000490 type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
David Brazdil7126c5b2019-03-05 00:02:51 +0000491 std::string dex_location = dex_file->GetLocation();
492 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
493
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000494 const uint8_t* type_lookup_table_data = nullptr;
495 if (type_lookup_table_start != nullptr &&
496 (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
497 type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
498 }
David Brazdil7126c5b2019-03-05 00:02:51 +0000499 // Create an OatDexFile and add it to the owning container.
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000500 OatDexFile* oat_dex_file = new OatDexFile(
501 this,
502 dex_file->Begin(),
503 dex_file->GetLocationChecksum(),
504 dex_location,
505 canonical_location,
506 type_lookup_table_data);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000507 dex_file->SetOatDexFile(oat_dex_file);
David Brazdil7126c5b2019-03-05 00:02:51 +0000508 oat_dex_files_storage_.push_back(oat_dex_file);
509
510 // Add the location and canonical location (if different) to the oat_dex_files_ table.
511 std::string_view key(oat_dex_file->GetDexFileLocation());
512 oat_dex_files_.Put(key, oat_dex_file);
513 if (canonical_location != dex_location) {
514 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
515 oat_dex_files_.Put(canonical_key, oat_dex_file);
516 }
517 }
David Brazdil7126c5b2019-03-05 00:02:51 +0000518}
519
Vladimir Markob7bf8432019-12-03 13:18:50 +0000520bool OatFileBase::Setup(int zip_fd,
521 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -0700522 ArrayRef<const int> dex_fds,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000523 std::string* error_msg) {
Brian Carlstromf1b30302013-03-28 10:35:32 -0700524 if (!GetOatHeader().IsValid()) {
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800525 std::string cause = GetOatHeader().GetValidationErrorMessage();
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100526 *error_msg = StringPrintf("Invalid oat header for '%s': %s",
527 GetLocation().c_str(),
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800528 cause.c_str());
Brian Carlstromf1b30302013-03-28 10:35:32 -0700529 return false;
530 }
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100531 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
532 size_t key_value_store_size =
533 (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
534 if (Size() < sizeof(OatHeader) + key_value_store_size) {
535 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
536 "size = %zu < %zu + %zu",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100537 GetLocation().c_str(),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100538 Size(),
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100539 sizeof(OatHeader),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100540 key_value_store_size);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700541 return false;
542 }
543
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100544 size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
545 if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
546 *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
547 "%zu is not in [%zu, %zu]",
548 GetLocation().c_str(),
549 oat_dex_files_offset,
550 GetOatHeader().GetHeaderSize(),
551 Size());
552 return false;
553 }
554 const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
555
Vladimir Markob066d432018-01-03 13:14:37 +0000556 if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
557 !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
558 data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
559 *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
560 "symbol(s): begin = %p, end = %p",
561 GetLocation().c_str(),
562 data_bimg_rel_ro_begin_,
563 data_bimg_rel_ro_end_);
564 return false;
565 }
566
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100567 DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
568 if (!IsAligned<kPageSize>(bss_begin_) ||
569 !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
570 !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
Vladimir Markoaad75c62016-10-03 08:46:48 +0000571 !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
572 *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100573 "begin = %p, methods_ = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000574 GetLocation().c_str(),
575 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100576 bss_methods_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000577 bss_roots_,
578 bss_end_);
579 return false;
580 }
581
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100582 if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
583 (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
584 (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
585 *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
Vladimir Marko0f3c7002017-09-07 14:15:56 +0100586 "begin = %p, methods = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000587 GetLocation().c_str(),
Vladimir Markoaad75c62016-10-03 08:46:48 +0000588 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100589 bss_methods_,
590 bss_roots_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000591 bss_end_);
592 return false;
593 }
594
Vladimir Markoe47f60c2018-02-21 13:43:28 +0000595 if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
596 *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
597 "begin = %p, methods = %p",
598 GetLocation().c_str(),
599 bss_begin_,
600 bss_methods_);
601 return false;
602 }
603
Vladimir Markob7bf8432019-12-03 13:18:50 +0000604 std::string_view primary_location;
605 std::string_view primary_location_replacement;
Victor Hsiehf667c332021-05-27 11:35:44 -0700606 int dex_fd = -1;
Vladimir Markob7bf8432019-12-03 13:18:50 +0000607 size_t dex_filenames_pos = 0u;
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100608 uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
609 oat_dex_files_storage_.reserve(dex_file_count);
610 for (size_t i = 0; i < dex_file_count; i++) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100611 uint32_t dex_file_location_size;
612 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
613 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
614 "location size",
615 GetLocation().c_str(),
616 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700617 return false;
618 }
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100619 if (UNLIKELY(dex_file_location_size == 0U)) {
620 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
621 GetLocation().c_str(),
622 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700623 return false;
624 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000625 if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100626 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
627 "location",
628 GetLocation().c_str(),
629 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700630 return false;
631 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000632 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
633 oat += dex_file_location_size;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700634
Vladimir Markob7bf8432019-12-03 13:18:50 +0000635 // Location encoded in the oat file. We will use this for multidex naming.
636 std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
637 std::string dex_file_location(oat_dex_file_location);
638 bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
Vladimir Marko69944682019-12-09 15:16:39 +0000639 // Check that `is_multidex` does not clash with other indicators. The first dex location
640 // must be primary location and, if we're opening external dex files, the location must
641 // be multi-dex if and only if we already have a dex file opened for it.
642 if ((i == 0 && is_multidex) ||
643 (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
644 *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
645 GetLocation().c_str(),
646 is_multidex ? "multi-dex" : "primary",
647 dex_file_location.c_str());
648 return false;
649 }
650 // Remember the primary location and, if provided, the replacement from `dex_filenames`.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000651 if (!is_multidex) {
652 primary_location = oat_dex_file_location;
653 if (!dex_filenames.empty()) {
654 if (dex_filenames_pos == dex_filenames.size()) {
655 *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
656 ", expected only %zu primary locations",
657 GetLocation().c_str(),
658 dex_file_location.c_str(),
659 dex_filenames.size());
660 return false;
661 }
662 primary_location_replacement = dex_filenames[dex_filenames_pos];
Victor Hsiehf667c332021-05-27 11:35:44 -0700663 dex_fd = dex_filenames_pos < dex_fds.size() ? dex_fds[dex_filenames_pos] : -1;
Vladimir Markob7bf8432019-12-03 13:18:50 +0000664 ++dex_filenames_pos;
665 }
666 }
Vladimir Marko69944682019-12-09 15:16:39 +0000667 // Check that the base location of a multidex location matches the last seen primary location.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000668 if (is_multidex &&
669 (!StartsWith(dex_file_location, primary_location) ||
670 dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
671 *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
672 " unrelated to '%s'",
673 GetLocation().c_str(),
674 dex_file_location.c_str(),
675 std::string(primary_location).c_str());
676 return false;
677 }
678 std::string dex_file_name = dex_file_location;
679 if (!dex_filenames.empty()) {
680 dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
681 // If the location does not contain path and matches the file name component,
682 // use the provided file name also as the location.
683 // TODO: Do we need this for anything other than tests?
684 if (dex_file_location.find('/') == std::string::npos &&
685 dex_file_name.size() > dex_file_location.size() &&
686 dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
687 EndsWith(dex_file_name, dex_file_location)) {
688 dex_file_location = dex_file_name;
689 }
690 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700691
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100692 uint32_t dex_file_checksum;
693 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
694 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
695 "dex file checksum",
696 GetLocation().c_str(),
697 i,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700698 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700699 return false;
700 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700701
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100702 uint32_t dex_file_offset;
703 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
704 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
705 "after dex file offsets",
706 GetLocation().c_str(),
707 i,
708 dex_file_location.c_str());
709 return false;
710 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100711 if (UNLIKELY(dex_file_offset > DexSize())) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100712 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
713 "offset %u > %zu",
714 GetLocation().c_str(),
715 i,
716 dex_file_location.c_str(),
717 dex_file_offset,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100718 DexSize());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700719 return false;
720 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000721 const uint8_t* dex_file_pointer = nullptr;
722 if (UNLIKELY(dex_file_offset == 0U)) {
Vladimir Markob7bf8432019-12-03 13:18:50 +0000723 // Do not support mixed-mode oat files.
724 if (i != 0u && external_dex_files_.empty()) {
725 *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
726 "file %zu (%s)",
727 GetLocation().c_str(),
728 i,
729 dex_file_location.c_str());
730 return false;
731 }
732 DCHECK_LE(i, external_dex_files_.size());
733 if (i == external_dex_files_.size()) {
734 std::vector<std::unique_ptr<const DexFile>> new_dex_files;
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000735 // No dex files, load it from location.
736 const ArtDexFileLoader dex_file_loader;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100737 bool loaded = false;
Victor Hsiehf667c332021-05-27 11:35:44 -0700738 CHECK(zip_fd == -1 || dex_fds.empty()); // Allow only the supported combinations.
Victor Hsieh9060ebe2021-06-17 12:57:12 -0700739 if (zip_fd != -1) {
740 loaded = dex_file_loader.OpenZip(zip_fd,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100741 dex_file_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100742 /*verify=*/ false,
743 /*verify_checksum=*/ false,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100744 error_msg,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000745 &new_dex_files);
Victor Hsieh9060ebe2021-06-17 12:57:12 -0700746 } else if (dex_fd != -1) {
747 // Note that we assume dex_fds are backing by jars.
748 loaded = dex_file_loader.OpenZipFromOwnedFd(dex_fd,
749 dex_file_location,
750 /*verify=*/ false,
751 /*verify_checksum=*/ false,
752 error_msg,
753 &new_dex_files);
Nicolas Geoffray30025092018-04-19 14:43:29 +0100754 } else {
David Brazdil3e8aae02019-03-26 18:48:02 +0000755 loaded = dex_file_loader.Open(dex_file_name.c_str(),
Nicolas Geoffray30025092018-04-19 14:43:29 +0100756 dex_file_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100757 /*verify=*/ false,
758 /*verify_checksum=*/ false,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100759 error_msg,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000760 &new_dex_files);
Nicolas Geoffray30025092018-04-19 14:43:29 +0100761 }
762 if (!loaded) {
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000763 if (Runtime::Current() == nullptr) {
764 // If there's no runtime, we're running oatdump, so return
765 // a half constructed oat file that oatdump knows how to deal with.
766 LOG(WARNING) << "Could not find associated dex files of oat file. "
767 << "Oatdump will only dump the header.";
768 return true;
769 } else {
770 return false;
771 }
772 }
Andreas Gampefc604a72018-02-08 15:43:37 -0800773 // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
774 // here and ensure that at least the number of dex files still matches.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000775 // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
776 // load all dex files from that file, otherwise we may open multiple files.
Andreas Gampefc604a72018-02-08 15:43:37 -0800777 // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
778 // done after loading the OatFile.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000779 size_t max_dex_files = dex_file_count - external_dex_files_.size();
780 bool expect_all =
781 (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
782 if (expect_all ? new_dex_files.size() != max_dex_files
783 : new_dex_files.size() > max_dex_files) {
784 *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
Andreas Gampefc604a72018-02-08 15:43:37 -0800785 "found %zu in '%s'",
786 GetLocation().c_str(),
Vladimir Markob7bf8432019-12-03 13:18:50 +0000787 (expect_all ? "" : "<="),
788 max_dex_files,
789 new_dex_files.size(),
Andreas Gampefc604a72018-02-08 15:43:37 -0800790 dex_file_location.c_str());
791 return false;
792 }
Vladimir Markob7bf8432019-12-03 13:18:50 +0000793 for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
794 external_dex_files_.push_back(std::move(dex_file));
795 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000796 }
Vladimir Markob7bf8432019-12-03 13:18:50 +0000797 dex_file_pointer = external_dex_files_[i]->Begin();
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000798 } else {
Andreas Gampefc604a72018-02-08 15:43:37 -0800799 // Do not support mixed-mode oat files.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000800 if (!external_dex_files_.empty()) {
Andreas Gampefc604a72018-02-08 15:43:37 -0800801 *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
802 "%zu (%s)",
803 GetLocation().c_str(),
804 i,
805 dex_file_location.c_str());
806 return false;
807 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000808 if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
809 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
810 "offset %u of %zu but the size of dex file header is %zu",
811 GetLocation().c_str(),
812 i,
813 dex_file_location.c_str(),
814 dex_file_offset,
815 DexSize(),
816 sizeof(DexFile::Header));
817 return false;
818 }
819 dex_file_pointer = DexBegin() + dex_file_offset;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000820 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800821
Mathieu Chartiercf76bf82017-09-25 16:22:36 -0700822 const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
Mathieu Chartier7b074bf2017-09-25 16:22:36 -0700823 if (UNLIKELY(!valid_magic)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100824 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100825 "dex file magic",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100826 GetLocation().c_str(),
827 i,
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100828 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700829 return false;
830 }
Mathieu Chartiercf76bf82017-09-25 16:22:36 -0700831 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100832 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100833 "dex file version",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100834 GetLocation().c_str(),
835 i,
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100836 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700837 return false;
838 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800839 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000840 if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000841 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
842 "offset %u and size %u truncated at %zu",
843 GetLocation().c_str(),
844 i,
845 dex_file_location.c_str(),
846 dex_file_offset,
847 header->file_size_,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100848 DexSize());
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000849 return false;
850 }
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300851
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000852 uint32_t class_offsets_offset;
853 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
854 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
855 "after class offsets offset",
856 GetLocation().c_str(),
857 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300858 dex_file_location.c_str());
859 return false;
860 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000861 if (UNLIKELY(class_offsets_offset > Size()) ||
862 UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
863 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
864 "class offsets, offset %u of %zu, class defs %u",
865 GetLocation().c_str(),
866 i,
867 dex_file_location.c_str(),
868 class_offsets_offset,
869 Size(),
870 header->class_defs_size_);
871 return false;
872 }
873 if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
874 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
875 "class offsets, offset %u",
876 GetLocation().c_str(),
877 i,
878 dex_file_location.c_str(),
879 class_offsets_offset);
880 return false;
881 }
882 const uint32_t* class_offsets_pointer =
883 reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
884
885 uint32_t lookup_table_offset;
886 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
887 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
888 "after lookup table offset",
889 GetLocation().c_str(),
890 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300891 dex_file_location.c_str());
892 return false;
893 }
894 const uint8_t* lookup_table_data = lookup_table_offset != 0u
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000895 ? DexBegin() + lookup_table_offset
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300896 : nullptr;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000897 if (lookup_table_offset != 0u &&
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000898 (UNLIKELY(lookup_table_offset > DexSize()) ||
899 UNLIKELY(DexSize() - lookup_table_offset <
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000900 TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100901 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000902 "type lookup table, offset %u of %zu, class defs %u",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100903 GetLocation().c_str(),
904 i,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000905 dex_file_location.c_str(),
906 lookup_table_offset,
907 Size(),
908 header->class_defs_size_);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700909 return false;
910 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700911
Mathieu Chartier120aa282017-08-05 16:03:03 -0700912 uint32_t dex_layout_sections_offset;
913 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
914 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
915 "after dex layout sections offset",
916 GetLocation().c_str(),
917 i,
918 dex_file_location.c_str());
919 return false;
920 }
921 const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
922 ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
923 : nullptr;
924
Vladimir Markof3c52b42017-11-17 17:32:12 +0000925 const IndexBssMapping* method_bss_mapping;
926 const IndexBssMapping* type_bss_mapping;
Vladimir Marko8f63f102020-09-28 12:10:28 +0100927 const IndexBssMapping* public_type_bss_mapping;
928 const IndexBssMapping* package_type_bss_mapping;
Vladimir Markof3c52b42017-11-17 17:32:12 +0000929 const IndexBssMapping* string_bss_mapping;
930 if (!ReadIndexBssMapping(
931 this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
932 !ReadIndexBssMapping(
933 this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
934 !ReadIndexBssMapping(
Vladimir Marko8f63f102020-09-28 12:10:28 +0100935 this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
936 !ReadIndexBssMapping(
937 this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
938 !ReadIndexBssMapping(
Vladimir Markof3c52b42017-11-17 17:32:12 +0000939 this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100940 return false;
941 }
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100942
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100943 // Create the OatDexFile and add it to the owning container.
David Brazdil3e8aae02019-03-26 18:48:02 +0000944 OatDexFile* oat_dex_file = new OatDexFile(
945 this,
946 dex_file_location,
947 DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
948 dex_file_checksum,
949 dex_file_pointer,
950 lookup_table_data,
951 method_bss_mapping,
952 type_bss_mapping,
Vladimir Marko8f63f102020-09-28 12:10:28 +0100953 public_type_bss_mapping,
954 package_type_bss_mapping,
David Brazdil3e8aae02019-03-26 18:48:02 +0000955 string_bss_mapping,
956 class_offsets_pointer,
957 dex_layout_sections);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100958 oat_dex_files_storage_.push_back(oat_dex_file);
959
960 // Add the location and canonical location (if different) to the oat_dex_files_ table.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000961 // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
962 // the location and canonical location, GetOatDexFile() shall canonicalize it when
963 // requested and match the canonical path.
964 std::string_view key = oat_dex_file_location; // References oat file data.
David Brazdil3e8aae02019-03-26 18:48:02 +0000965 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
Vladimir Marko539690a2014-06-05 18:36:42 +0100966 oat_dex_files_.Put(key, oat_dex_file);
David Brazdil3e8aae02019-03-26 18:48:02 +0000967 if (canonical_key != key) {
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100968 oat_dex_files_.Put(canonical_key, oat_dex_file);
969 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700970 }
Vladimir Markob7bf8432019-12-03 13:18:50 +0000971 if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
972 *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
973 GetLocation().c_str(),
974 dex_filenames_pos,
975 dex_filenames.size());
976 return false;
977 }
Vladimir Marko09d09432015-09-08 13:47:48 +0100978
Vladimir Markob066d432018-01-03 13:14:37 +0000979 if (DataBimgRelRoBegin() != nullptr) {
Vladimir Markoe80ecf32019-08-01 15:20:58 +0100980 // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
981 // relocation when we register a dex file from this oat file. We do not do the relocation
982 // here to avoid dirtying the pages if the code is never actually ready to be executed.
Vladimir Markob066d432018-01-03 13:14:37 +0000983 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
984 CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
Vladimir Markoe80ecf32019-08-01 15:20:58 +0100985 // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
986 // section is bogus. The full dependency is checked before the code is executed.
Vladimir Marko21910692019-11-06 13:27:03 +0000987 // We cannot do this check if we do not have a key-value store, i.e. for secondary
988 // oat files for boot image extensions.
989 if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
990 const char* boot_class_path_checksum =
991 GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
992 if (boot_class_path_checksum == nullptr ||
993 boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
994 *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
995 "without boot image dependency.",
996 GetLocation().c_str());
997 return false;
998 }
Vladimir Markob066d432018-01-03 13:14:37 +0000999 }
1000 }
1001
Brian Carlstromf1b30302013-03-28 10:35:32 -07001002 return true;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001003}
1004
Andreas Gampe049cff02015-12-01 23:27:12 -08001005////////////////////////
1006// OatFile via dlopen //
1007////////////////////////
1008
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001009class DlOpenOatFile final : public OatFileBase {
Andreas Gampe049cff02015-12-01 23:27:12 -08001010 public:
1011 DlOpenOatFile(const std::string& filename, bool executable)
1012 : OatFileBase(filename, executable),
1013 dlopen_handle_(nullptr),
Richard Uhlera206c742016-05-24 15:04:22 -07001014 shared_objects_before_(0) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001015 }
1016
1017 ~DlOpenOatFile() {
1018 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -07001019 if (!kIsTargetBuild) {
1020 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1021 host_dlopen_handles_.erase(dlopen_handle_);
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -07001022 dlclose(dlopen_handle_);
1023 } else {
1024 dlclose(dlopen_handle_);
Richard Uhlera206c742016-05-24 15:04:22 -07001025 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001026 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001027 }
1028
1029 protected:
1030 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001031 std::string* error_msg) const override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001032 const uint8_t* ptr =
1033 reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1034 if (ptr == nullptr) {
1035 *error_msg = dlerror();
1036 }
1037 return ptr;
1038 }
1039
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001040 void PreLoad() override;
Andreas Gampe4075f832016-05-18 13:09:54 -07001041
Andreas Gampe049cff02015-12-01 23:27:12 -08001042 bool Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001043 bool writable,
1044 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001045 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001046 /*inout*/MemMap* reservation, // Where to load if not null.
1047 /*out*/std::string* error_msg) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001048
Vladimir Markoc09cd052018-08-23 16:36:36 +01001049 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1050 bool writable ATTRIBUTE_UNUSED,
1051 bool executable ATTRIBUTE_UNUSED,
1052 bool low_4gb ATTRIBUTE_UNUSED,
1053 /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1054 /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001055 return false;
1056 }
1057
Andreas Gampe049cff02015-12-01 23:27:12 -08001058 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001059 void PreSetup(const std::string& elf_filename) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001060
1061 private:
1062 bool Dlopen(const std::string& elf_filename,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001063 /*inout*/MemMap* reservation, // Where to load if not null.
1064 /*out*/std::string* error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001065
Richard Uhlera206c742016-05-24 15:04:22 -07001066 // On the host, if the same library is loaded again with dlopen the same
1067 // file handle is returned. This differs from the behavior of dlopen on the
1068 // target, where dlopen reloads the library at a different address every
1069 // time you load it. The runtime relies on the target behavior to ensure
1070 // each instance of the loaded library has a unique dex cache. To avoid
1071 // problems, we fall back to our own linker in the case when the same
1072 // library is opened multiple times on host. dlopen_handles_ is used to
1073 // detect that case.
1074 // Guarded by host_dlopen_handles_lock_;
1075 static std::unordered_set<void*> host_dlopen_handles_;
1076
Vladimir Marko07f78902020-07-27 11:35:12 +00001077 // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
Vladimir Markoc09cd052018-08-23 16:36:36 +01001078 // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1079 std::vector<MemMap> dlopen_mmaps_;
1080
Andreas Gampe049cff02015-12-01 23:27:12 -08001081 // dlopen handle during runtime.
1082 void* dlopen_handle_; // TODO: Unique_ptr with custom deleter.
1083
Andreas Gampe4075f832016-05-18 13:09:54 -07001084 // The number of shared objects the linker told us about before loading. Used to
1085 // (optimistically) optimize the PreSetup stage (see comment there).
1086 size_t shared_objects_before_;
1087
Andreas Gampe049cff02015-12-01 23:27:12 -08001088 DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1089};
1090
Richard Uhlera206c742016-05-24 15:04:22 -07001091std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1092
Andreas Gampe4075f832016-05-18 13:09:54 -07001093void DlOpenOatFile::PreLoad() {
1094#ifdef __APPLE__
Andreas Gampe39004a62016-05-18 21:27:00 -07001095 UNUSED(shared_objects_before_);
Andreas Gampe4075f832016-05-18 13:09:54 -07001096 LOG(FATAL) << "Should not reach here.";
1097 UNREACHABLE();
1098#else
1099 // Count the entries in dl_iterate_phdr we get at this point in time.
1100 struct dl_iterate_context {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001101 static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
Andreas Gampe4075f832016-05-18 13:09:54 -07001102 size_t size ATTRIBUTE_UNUSED,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001103 void* data) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001104 reinterpret_cast<dl_iterate_context*>(data)->count++;
1105 return 0; // Continue iteration.
1106 }
1107 size_t count = 0;
1108 } context;
1109
1110 dl_iterate_phdr(dl_iterate_context::callback, &context);
1111 shared_objects_before_ = context.count;
1112#endif
1113}
1114
Andreas Gampe049cff02015-12-01 23:27:12 -08001115bool DlOpenOatFile::Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001116 bool writable,
1117 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001118 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001119 /*inout*/MemMap* reservation, // Where to load if not null.
1120 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001121 // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1122 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1123 // !executable is a sign that we may want to patch), which may not be allowed for
1124 // various reasons.
1125 if (!kUseDlopen) {
1126 *error_msg = "DlOpen is disabled.";
1127 return false;
1128 }
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001129 if (low_4gb) {
1130 *error_msg = "DlOpen does not support low 4gb loading.";
1131 return false;
1132 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001133 if (writable) {
1134 *error_msg = "DlOpen does not support writable loading.";
1135 return false;
1136 }
1137 if (!executable) {
1138 *error_msg = "DlOpen does not support non-executable loading.";
1139 return false;
1140 }
1141
1142 // dlopen always returns the same library if it is already opened on the host. For this reason
1143 // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1144 // the same library loaded multiple times at different addresses is required for class unloading
1145 // and for having dex caches arrays in the .bss section.
1146 if (!kIsTargetBuild) {
1147 if (!kUseDlopenOnHost) {
1148 *error_msg = "DlOpen disabled for host.";
1149 return false;
1150 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001151 }
1152
Vladimir Markoc09cd052018-08-23 16:36:36 +01001153 bool success = Dlopen(elf_filename, reservation, error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001154 DCHECK(dlopen_handle_ != nullptr || !success);
1155
1156 return success;
1157}
1158
Martin Stjernholm93c28ed2021-05-14 14:11:42 +01001159#ifdef ART_TARGET_ANDROID
1160static struct android_namespace_t* GetSystemLinkerNamespace() {
1161 static struct android_namespace_t* system_ns = []() {
1162 // The system namespace is called "default" for binaries in /system and
1163 // "system" for those in the ART APEX. Try "system" first since "default"
1164 // always exists.
1165 // TODO(b/185587109): Get rid of this error prone logic.
1166 struct android_namespace_t* ns = android_get_exported_namespace("system");
1167 if (ns == nullptr) {
1168 ns = android_get_exported_namespace("default");
1169 if (ns == nullptr) {
1170 LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1171 }
1172 }
1173 return ns;
1174 }();
1175 return system_ns;
1176}
1177#endif // ART_TARGET_ANDROID
1178
Andreas Gampe049cff02015-12-01 23:27:12 -08001179bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001180 /*inout*/MemMap* reservation,
1181 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001182#ifdef __APPLE__
1183 // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
1184 // but let's fallback to the custom loading code for the time being.
Vladimir Marko3ec8fb62018-08-31 17:47:38 +01001185 UNUSED(elf_filename, reservation);
Andreas Gampe049cff02015-12-01 23:27:12 -08001186 *error_msg = "Dlopen unsupported on Mac.";
1187 return false;
1188#else
1189 {
1190 UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1191 if (absolute_path == nullptr) {
1192 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1193 return false;
1194 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +01001195#ifdef ART_TARGET_ANDROID
Anton Kirilov3a2e78e2017-01-06 13:33:42 +00001196 android_dlextinfo extinfo = {};
Vladimir Markof6cfd002018-11-01 16:53:31 +00001197 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD; // Force-load, don't reuse handle
1198 // (open oat files multiple times).
Vladimir Markoc09cd052018-08-23 16:36:36 +01001199 if (reservation != nullptr) {
1200 if (!reservation->IsValid()) {
1201 *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1202 return false;
1203 }
1204 extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS; // Use the reserved memory range.
1205 extinfo.reserved_addr = reservation->Begin();
1206 extinfo.reserved_size = reservation->Size();
1207 }
Martin Stjernholm93c28ed2021-05-14 14:11:42 +01001208
1209 if (strncmp(kAndroidArtApexDefaultPath,
1210 absolute_path.get(),
1211 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1212 absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1213 // Use the system namespace for OAT files outside the ART APEX. Search
1214 // paths and links don't matter here, but permitted paths do, and the
1215 // system namespace is configured to allow loading from all appropriate
1216 // locations.
1217 extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1218 extinfo.library_namespace = GetSystemLinkerNamespace();
1219 }
1220
Andreas Gampe049cff02015-12-01 23:27:12 -08001221 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001222 if (reservation != nullptr && dlopen_handle_ != nullptr) {
1223 // Find used pages from the reservation.
1224 struct dl_iterate_context {
1225 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1226 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1227 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1228 using Elf_Half = Elf64_Half;
1229
1230 // See whether this callback corresponds to the file which we have just loaded.
1231 uint8_t* reservation_begin = context->reservation->Begin();
1232 bool contained_in_reservation = false;
1233 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1234 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1235 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1236 info->dlpi_phdr[i].p_vaddr);
1237 size_t memsz = info->dlpi_phdr[i].p_memsz;
1238 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1239 if (offset < context->reservation->Size()) {
1240 contained_in_reservation = true;
1241 DCHECK_LE(memsz, context->reservation->Size() - offset);
1242 } else if (vaddr < reservation_begin) {
1243 // Check that there's no overlap with the reservation.
1244 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1245 }
1246 break; // It is sufficient to check the first PT_LOAD header.
1247 }
1248 }
1249
1250 if (contained_in_reservation) {
1251 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1252 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1253 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1254 info->dlpi_phdr[i].p_vaddr);
1255 size_t memsz = info->dlpi_phdr[i].p_memsz;
1256 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1257 DCHECK_LT(offset, context->reservation->Size());
1258 DCHECK_LE(memsz, context->reservation->Size() - offset);
1259 context->max_size = std::max(context->max_size, offset + memsz);
1260 }
1261 }
1262
1263 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1264 }
1265 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1266 }
1267
1268 const MemMap* const reservation;
1269 size_t max_size = 0u;
1270 };
1271 dl_iterate_context context = { reservation };
1272
1273 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1274 LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1275 UNREACHABLE();
1276 }
1277
1278 // Take ownership of the memory used by the shared object. dlopen() does not assume
1279 // full ownership of this memory and dlclose() shall just remap it as zero pages with
1280 // PROT_NONE. We need to unmap the memory when destroying this oat file.
1281 dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1282 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001283#else
Steve Austin882ed6b2018-06-08 11:40:38 -07001284 static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1285 "host_dlopen_handles_ will leak handles");
Vladimir Markoc09cd052018-08-23 16:36:36 +01001286 if (reservation != nullptr) {
1287 *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1288 elf_filename.c_str());
1289 return false;
1290 }
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -07001291 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
Richard Uhlera206c742016-05-24 15:04:22 -07001292 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1293 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -07001294 if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1295 dlclose(dlopen_handle_);
1296 dlopen_handle_ = nullptr;
1297 *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1298 return false;
1299 }
1300 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +01001301#endif // ART_TARGET_ANDROID
Andreas Gampe049cff02015-12-01 23:27:12 -08001302 }
1303 if (dlopen_handle_ == nullptr) {
1304 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1305 return false;
1306 }
1307 return true;
1308#endif
1309}
1310
1311void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
Andreas Gampe74f07b52015-12-02 11:53:26 -08001312#ifdef __APPLE__
1313 UNUSED(elf_filename);
1314 LOG(FATAL) << "Should not reach here.";
1315 UNREACHABLE();
1316#else
Vladimir Marko07f78902020-07-27 11:35:12 +00001317 struct PlaceholderMapData {
Vladimir Marko211f9d32020-05-21 16:10:44 +01001318 const char* name;
1319 uint8_t* vaddr;
1320 size_t memsz;
1321 };
Andreas Gampe049cff02015-12-01 23:27:12 -08001322 struct dl_iterate_context {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001323 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001324 auto* context = reinterpret_cast<dl_iterate_context*>(data);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001325 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1326 using Elf_Half = Elf64_Half;
1327
Andreas Gampe4075f832016-05-18 13:09:54 -07001328 context->shared_objects_seen++;
1329 if (context->shared_objects_seen < context->shared_objects_before) {
1330 // We haven't been called yet for anything we haven't seen before. Just continue.
1331 // Note: this is aggressively optimistic. If another thread was unloading a library,
1332 // we may miss out here. However, this does not happen often in practice.
1333 return 0;
1334 }
1335
Andreas Gampe049cff02015-12-01 23:27:12 -08001336 // See whether this callback corresponds to the file which we have just loaded.
1337 bool contains_begin = false;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001338 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001339 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1340 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1341 info->dlpi_phdr[i].p_vaddr);
1342 size_t memsz = info->dlpi_phdr[i].p_memsz;
1343 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1344 contains_begin = true;
1345 break;
1346 }
1347 }
1348 }
Vladimir Marko07f78902020-07-27 11:35:12 +00001349 // Add placeholder mmaps for this file.
Andreas Gampe049cff02015-12-01 23:27:12 -08001350 if (contains_begin) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001351 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001352 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1353 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1354 info->dlpi_phdr[i].p_vaddr);
1355 size_t memsz = info->dlpi_phdr[i].p_memsz;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001356 size_t name_size = strlen(info->dlpi_name) + 1u;
Vladimir Marko07f78902020-07-27 11:35:12 +00001357 std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001358 // We must not allocate any memory in the callback, see b/156312036 .
Vladimir Marko07f78902020-07-27 11:35:12 +00001359 if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1360 context->placeholder_maps_data_->size() <
1361 context->placeholder_maps_data_->capacity()) {
1362 placeholder_maps_names->insert(
1363 placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1364 const char* name =
1365 &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1366 context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
Vladimir Marko211f9d32020-05-21 16:10:44 +01001367 }
Vladimir Marko07f78902020-07-27 11:35:12 +00001368 context->num_placeholder_maps_ += 1u;
1369 context->placeholder_maps_names_size_ += name_size;
Andreas Gampe049cff02015-12-01 23:27:12 -08001370 }
1371 }
1372 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1373 }
1374 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1375 }
1376 const uint8_t* const begin_;
Vladimir Marko07f78902020-07-27 11:35:12 +00001377 std::vector<PlaceholderMapData>* placeholder_maps_data_;
1378 size_t num_placeholder_maps_;
1379 std::vector<char>* placeholder_maps_names_;
1380 size_t placeholder_maps_names_size_;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001381 size_t shared_objects_before;
Andreas Gampe4075f832016-05-18 13:09:54 -07001382 size_t shared_objects_seen;
1383 };
Vladimir Marko211f9d32020-05-21 16:10:44 +01001384
1385 // We must not allocate any memory in the callback, see b/156312036 .
Vladimir Marko07f78902020-07-27 11:35:12 +00001386 // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1387 std::vector<PlaceholderMapData> placeholder_maps_data;
1388 placeholder_maps_data.reserve(32); // 32 should be enough. If not, we'll retry.
1389 std::vector<char> placeholder_maps_names;
1390 placeholder_maps_names.reserve(4 * KB); // 4KiB should be enough. If not, we'll retry.
Vladimir Marko211f9d32020-05-21 16:10:44 +01001391
1392 dl_iterate_context context = {
1393 Begin(),
Vladimir Marko07f78902020-07-27 11:35:12 +00001394 &placeholder_maps_data,
1395 /*num_placeholder_maps_*/ 0u,
1396 &placeholder_maps_names,
1397 /*placeholder_maps_names_size_*/ 0u,
Vladimir Marko211f9d32020-05-21 16:10:44 +01001398 shared_objects_before_,
1399 /*shared_objects_seen*/ 0u
1400 };
Andreas Gampe049cff02015-12-01 23:27:12 -08001401
1402 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001403 // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1404 // before giving up. This should be unusual.
1405 VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1406 << shared_objects_before_;
Vladimir Marko07f78902020-07-27 11:35:12 +00001407 DCHECK(placeholder_maps_data.empty());
1408 DCHECK_EQ(context.num_placeholder_maps_, 0u);
1409 DCHECK(placeholder_maps_names.empty());
1410 DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
Vladimir Marko211f9d32020-05-21 16:10:44 +01001411 context.shared_objects_before = 0u;
1412 context.shared_objects_seen = 0u;
1413 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001414 // OK, give up and print an error.
Andreas Gampe170331f2017-12-07 18:41:03 -08001415 PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
Andreas Gampe4075f832016-05-18 13:09:54 -07001416 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1417 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001418 }
Vladimir Marko211f9d32020-05-21 16:10:44 +01001419
Vladimir Marko07f78902020-07-27 11:35:12 +00001420 if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
Vladimir Marko211f9d32020-05-21 16:10:44 +01001421 // Insufficient capacity. Reserve more space and retry.
Vladimir Marko07f78902020-07-27 11:35:12 +00001422 placeholder_maps_data.clear();
1423 placeholder_maps_data.reserve(context.num_placeholder_maps_);
1424 context.num_placeholder_maps_ = 0u;
1425 placeholder_maps_names.clear();
1426 placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1427 context.placeholder_maps_names_size_ = 0u;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001428 context.shared_objects_before = 0u;
1429 context.shared_objects_seen = 0u;
1430 bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1431 CHECK(success);
1432 }
1433
Vladimir Marko07f78902020-07-27 11:35:12 +00001434 CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1435 CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1436 DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1437 placeholder_maps_names.end(), '\0')),
1438 context.num_placeholder_maps_);
1439 for (const PlaceholderMapData& data : placeholder_maps_data) {
1440 MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
Vladimir Marko211f9d32020-05-21 16:10:44 +01001441 dlopen_mmaps_.push_back(std::move(mmap));
1442 }
Andreas Gampe74f07b52015-12-02 11:53:26 -08001443#endif
Andreas Gampe049cff02015-12-01 23:27:12 -08001444}
1445
1446////////////////////////////////////////////////
1447// OatFile via our own ElfFile implementation //
1448////////////////////////////////////////////////
1449
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001450class ElfOatFile final : public OatFileBase {
Andreas Gampe049cff02015-12-01 23:27:12 -08001451 public:
1452 ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1453
Nicolas Geoffray30025092018-04-19 14:43:29 +01001454 bool InitializeFromElfFile(int zip_fd,
1455 ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001456 VdexFile* vdex_file,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001457 ArrayRef<const std::string> dex_filenames,
Andreas Gampe049cff02015-12-01 23:27:12 -08001458 std::string* error_msg);
1459
1460 protected:
1461 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001462 std::string* error_msg) const override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001463 const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1464 if (ptr == nullptr) {
1465 *error_msg = "(Internal implementation could not find symbol)";
1466 }
1467 return ptr;
1468 }
1469
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001470 void PreLoad() override {
Andreas Gampe4075f832016-05-18 13:09:54 -07001471 }
1472
Andreas Gampe049cff02015-12-01 23:27:12 -08001473 bool Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001474 bool writable,
1475 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001476 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001477 /*inout*/MemMap* reservation, // Where to load if not null.
1478 /*out*/std::string* error_msg) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001479
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001480 bool Load(int oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001481 bool writable,
1482 bool executable,
1483 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001484 /*inout*/MemMap* reservation, // Where to load if not null.
1485 /*out*/std::string* error_msg) override;
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001486
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001487 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001488 }
1489
1490 private:
1491 bool ElfFileOpen(File* file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001492 bool writable,
1493 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001494 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001495 /*inout*/MemMap* reservation, // Where to load if not null.
1496 /*out*/std::string* error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001497
1498 private:
1499 // Backing memory map for oat file during cross compilation.
1500 std::unique_ptr<ElfFile> elf_file_;
1501
1502 DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1503};
1504
Nicolas Geoffray30025092018-04-19 14:43:29 +01001505bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1506 ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001507 VdexFile* vdex_file,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001508 ArrayRef<const std::string> dex_filenames,
Andreas Gampe049cff02015-12-01 23:27:12 -08001509 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001510 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001511 if (IsExecutable()) {
1512 *error_msg = "Cannot initialize from elf file in executable mode.";
1513 return false;
1514 }
1515 elf_file_.reset(elf_file);
David Brazdilc93b3be2016-09-12 18:49:58 +01001516 SetVdex(vdex_file);
Andreas Gampe049cff02015-12-01 23:27:12 -08001517 uint64_t offset, size;
1518 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1519 CHECK(has_section);
1520 SetBegin(elf_file->Begin() + offset);
1521 SetEnd(elf_file->Begin() + size + offset);
1522 // Ignore the optional .bss section when opening non-executable.
Victor Hsiehf667c332021-05-27 11:35:44 -07001523 return Setup(zip_fd, dex_filenames, /*dex_fds=*/ArrayRef<const int>(), error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001524}
1525
1526bool ElfOatFile::Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001527 bool writable,
1528 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001529 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001530 /*inout*/MemMap* reservation,
1531 /*out*/std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001532 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001533 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1534 if (file == nullptr) {
1535 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1536 return false;
1537 }
1538 return ElfOatFile::ElfFileOpen(file.get(),
Andreas Gampe049cff02015-12-01 23:27:12 -08001539 writable,
1540 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001541 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001542 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001543 error_msg);
1544}
1545
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001546bool ElfOatFile::Load(int oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001547 bool writable,
1548 bool executable,
1549 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001550 /*inout*/MemMap* reservation,
1551 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001552 ScopedTrace trace(__PRETTY_FUNCTION__);
1553 if (oat_fd != -1) {
Josh Gaoafeec9f2018-08-30 14:05:56 -07001554 int duped_fd = DupCloexec(oat_fd);
1555 std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001556 if (file == nullptr) {
1557 *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1558 strerror(errno));
1559 return false;
1560 }
1561 return ElfOatFile::ElfFileOpen(file.get(),
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001562 writable,
1563 executable,
1564 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001565 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001566 error_msg);
1567 }
1568 return false;
1569}
1570
Andreas Gampe049cff02015-12-01 23:27:12 -08001571bool ElfOatFile::ElfFileOpen(File* file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001572 bool writable,
1573 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001574 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001575 /*inout*/MemMap* reservation,
1576 /*out*/std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001577 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001578 elf_file_.reset(ElfFile::Open(file,
1579 writable,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001580 /*program_header_only=*/ true,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001581 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001582 error_msg));
Andreas Gampe049cff02015-12-01 23:27:12 -08001583 if (elf_file_ == nullptr) {
1584 DCHECK(!error_msg->empty());
1585 return false;
1586 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001587 bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001588 DCHECK(loaded || !error_msg->empty());
1589 return loaded;
1590}
1591
David Brazdil7126c5b2019-03-05 00:02:51 +00001592class OatFileBackedByVdex final : public OatFileBase {
1593 public:
1594 explicit OatFileBackedByVdex(const std::string& filename)
1595 : OatFileBase(filename, /*executable=*/ false) {}
1596
1597 static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1598 std::unique_ptr<VdexFile>&& vdex_file,
1599 const std::string& location) {
1600 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001601 // SetVdex will take ownership of the VdexFile.
1602 oat_file->SetVdex(vdex_file.release());
1603 oat_file->SetupHeader(dex_files.size());
1604 // Initialize OatDexFiles.
1605 oat_file->Setup(dex_files);
David Brazdil7126c5b2019-03-05 00:02:51 +00001606 return oat_file.release();
1607 }
1608
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001609 static OatFileBackedByVdex* Open(int zip_fd,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001610 std::unique_ptr<VdexFile>&& unique_vdex_file,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001611 const std::string& dex_location,
1612 std::string* error_msg) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001613 VdexFile* vdex_file = unique_vdex_file.get();
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001614 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001615 // SetVdex will take ownership of the VdexFile.
1616 oat_file->SetVdex(unique_vdex_file.release());
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001617 if (vdex_file->HasDexSection()) {
1618 uint32_t i = 0;
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001619 const uint8_t* type_lookup_table_start = nullptr;
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +00001620 for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001621 dex_file_start != nullptr;
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +00001622 dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +01001623 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1624 *error_msg =
1625 StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1626 dex_location.c_str());
1627 return nullptr;
1628 }
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001629 // Create the OatDexFile and add it to the owning container.
1630 std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1631 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001632 type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1633 const uint8_t* type_lookup_table_data = nullptr;
1634 if (type_lookup_table_start != nullptr &&
1635 (reinterpret_cast<uint32_t*>(type_lookup_table_start[0]) != 0)) {
1636 type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
1637 }
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001638 OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1639 dex_file_start,
1640 vdex_file->GetLocationChecksum(i),
1641 location,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001642 canonical_location,
1643 type_lookup_table_data);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001644 oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1645
1646 std::string_view key(oat_dex_file->GetDexFileLocation());
1647 oat_file->oat_dex_files_.Put(key, oat_dex_file);
1648 if (canonical_location != location) {
1649 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1650 oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1651 }
1652 }
1653 oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
1654 } else {
1655 // No need for any verification when loading dex files as we already have
1656 // a vdex file.
1657 const ArtDexFileLoader dex_file_loader;
1658 bool loaded = false;
1659 if (zip_fd != -1) {
1660 loaded = dex_file_loader.OpenZip(zip_fd,
1661 dex_location,
1662 /*verify=*/ false,
1663 /*verify_checksum=*/ false,
1664 error_msg,
1665 &oat_file->external_dex_files_);
1666 } else {
1667 loaded = dex_file_loader.Open(dex_location.c_str(),
1668 dex_location,
1669 /*verify=*/ false,
1670 /*verify_checksum=*/ false,
1671 error_msg,
1672 &oat_file->external_dex_files_);
1673 }
1674 if (!loaded) {
1675 return nullptr;
1676 }
1677 oat_file->SetupHeader(oat_file->external_dex_files_.size());
1678 oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_));
1679 }
David Brazdil7126c5b2019-03-05 00:02:51 +00001680
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001681 return oat_file.release();
1682 }
1683
1684 void SetupHeader(size_t number_of_dex_files) {
1685 DCHECK(!IsExecutable());
David Brazdil7126c5b2019-03-05 00:02:51 +00001686
Nicolas Geoffrayb17c9082021-07-07 08:27:45 +01001687 // Create a fake OatHeader with a key store to help debugging.
David Brazdil7126c5b2019-03-05 00:02:51 +00001688 std::unique_ptr<const InstructionSetFeatures> isa_features =
1689 InstructionSetFeatures::FromCppDefines();
Nicolas Geoffraydee09f92019-10-23 15:18:20 +01001690 SafeMap<std::string, std::string> store;
1691 store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
Nicolas Geoffrayb17c9082021-07-07 08:27:45 +01001692 store.Put(OatHeader::kCompilationReasonKey, "vdex");
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001693 store.Put(OatHeader::kConcurrentCopying,
1694 kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
David Brazdil7126c5b2019-03-05 00:02:51 +00001695 oat_header_.reset(OatHeader::Create(kRuntimeISA,
1696 isa_features.get(),
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001697 number_of_dex_files,
Nicolas Geoffraydee09f92019-10-23 15:18:20 +01001698 &store));
David Brazdil7126c5b2019-03-05 00:02:51 +00001699 const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1700 SetBegin(begin);
1701 SetEnd(begin + oat_header_->GetHeaderSize());
David Brazdil7126c5b2019-03-05 00:02:51 +00001702 }
1703
1704 protected:
1705 void PreLoad() override {}
1706
1707 bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1708 bool writable ATTRIBUTE_UNUSED,
1709 bool executable ATTRIBUTE_UNUSED,
1710 bool low_4gb ATTRIBUTE_UNUSED,
1711 MemMap* reservation ATTRIBUTE_UNUSED,
1712 std::string* error_msg ATTRIBUTE_UNUSED) override {
1713 LOG(FATAL) << "Unsupported";
1714 UNREACHABLE();
1715 }
1716
1717 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1718 bool writable ATTRIBUTE_UNUSED,
1719 bool executable ATTRIBUTE_UNUSED,
1720 bool low_4gb ATTRIBUTE_UNUSED,
1721 MemMap* reservation ATTRIBUTE_UNUSED,
1722 std::string* error_msg ATTRIBUTE_UNUSED) override {
1723 LOG(FATAL) << "Unsupported";
1724 UNREACHABLE();
1725 }
1726
1727 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1728
1729 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1730 std::string* error_msg) const override {
1731 *error_msg = "Unsupported";
1732 return nullptr;
1733 }
1734
1735 private:
1736 std::unique_ptr<OatHeader> oat_header_;
David Brazdil7126c5b2019-03-05 00:02:51 +00001737
1738 DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1739};
1740
Andreas Gampe049cff02015-12-01 23:27:12 -08001741//////////////////////////
1742// General OatFile code //
1743//////////////////////////
1744
Andreas Gampe049cff02015-12-01 23:27:12 -08001745static void CheckLocation(const std::string& location) {
1746 CHECK(!location.empty());
1747}
1748
Nicolas Geoffray30025092018-04-19 14:43:29 +01001749OatFile* OatFile::Open(int zip_fd,
1750 const std::string& oat_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001751 const std::string& oat_location,
Andreas Gampe049cff02015-12-01 23:27:12 -08001752 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001753 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001754 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001755 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001756 /*inout*/MemMap* reservation,
1757 /*out*/std::string* error_msg) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001758 ScopedTrace trace("Open oat file " + oat_location);
1759 CHECK(!oat_filename.empty()) << oat_location;
1760 CheckLocation(oat_location);
Andreas Gampe54315c72016-05-18 21:10:42 -07001761
Calin Juravle367b9d82017-05-15 18:18:39 -07001762 std::string vdex_filename = GetVdexFilename(oat_filename);
David Brazdil7b49e6c2016-09-01 11:06:18 +01001763
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001764 // Check that the vdex file even exists, fast-fail. We don't check the odex
1765 // file as we use the absence of an odex file for test the functionality of
1766 // vdex-only.
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00001767 if (!OS::FileExists(vdex_filename.c_str())) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001768 *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1769 return nullptr;
Andreas Gampe54315c72016-05-18 21:10:42 -07001770 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001771
1772 // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1773 // disabled.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001774 OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1775 vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001776 oat_filename,
1777 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001778 /*writable=*/ false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001779 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001780 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001781 dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001782 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001783 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001784 error_msg);
1785 if (with_dlopen != nullptr) {
Jagadeesh Pakaravoor06541532021-02-22 21:19:09 -08001786 Runtime* runtime = Runtime::Current();
1787 // The runtime might not be available at this point if we're running
1788 // dex2oat or oatdump.
1789 if (runtime != nullptr) {
1790 size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
1791 Runtime::MadviseFileForRange(madvise_size_limit,
1792 with_dlopen->Size(),
1793 with_dlopen->Begin(),
1794 with_dlopen->End(),
1795 oat_location);
1796 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001797 return with_dlopen;
1798 }
1799 if (kPrintDlOpenErrorMessage) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001800 LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
Andreas Gampe049cff02015-12-01 23:27:12 -08001801 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001802 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1803 //
1804 // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1805 //
1806 // We use our own ELF loader for Quick to deal with legacy apps that
1807 // open a generated dex file by name, remove the file, then open
1808 // another generated dex file with the same name. http://b/10614658
1809 //
Vladimir Marko13fcc3e2020-01-24 12:40:56 +00001810 // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
Andreas Gampe049cff02015-12-01 23:27:12 -08001811 //
1812 //
1813 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1814 // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001815 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1816 vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001817 oat_filename,
1818 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001819 /*writable=*/ false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001820 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001821 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001822 dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001823 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001824 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001825 error_msg);
1826 return with_internal;
1827}
1828
Nicolas Geoffray30025092018-04-19 14:43:29 +01001829OatFile* OatFile::Open(int zip_fd,
1830 int vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001831 int oat_fd,
1832 const std::string& oat_location,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001833 bool executable,
1834 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001835 ArrayRef<const std::string> dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -07001836 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001837 /*inout*/MemMap* reservation,
1838 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001839 CHECK(!oat_location.empty()) << oat_location;
1840
1841 std::string vdex_location = GetVdexFilename(oat_location);
1842
Nicolas Geoffray30025092018-04-19 14:43:29 +01001843 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1844 vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001845 oat_fd,
1846 vdex_location,
1847 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001848 /*writable=*/ false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001849 executable,
1850 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001851 dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -07001852 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001853 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001854 error_msg);
1855 return with_internal;
1856}
1857
David Brazdil7126c5b2019-03-05 00:02:51 +00001858OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
1859 std::unique_ptr<VdexFile>&& vdex_file,
1860 const std::string& location) {
1861 CheckLocation(location);
1862 return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
1863}
1864
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001865OatFile* OatFile::OpenFromVdex(int zip_fd,
1866 std::unique_ptr<VdexFile>&& vdex_file,
1867 const std::string& location,
1868 std::string* error_msg) {
1869 CheckLocation(location);
1870 return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
1871}
1872
Andreas Gampe049cff02015-12-01 23:27:12 -08001873OatFile::OatFile(const std::string& location, bool is_executable)
1874 : location_(location),
David Brazdil7b49e6c2016-09-01 11:06:18 +01001875 vdex_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001876 begin_(nullptr),
1877 end_(nullptr),
Vladimir Markob066d432018-01-03 13:14:37 +00001878 data_bimg_rel_ro_begin_(nullptr),
1879 data_bimg_rel_ro_end_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001880 bss_begin_(nullptr),
1881 bss_end_(nullptr),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001882 bss_methods_(nullptr),
Vladimir Markoaad75c62016-10-03 08:46:48 +00001883 bss_roots_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001884 is_executable_(is_executable),
David Srbeckyec2cdf42017-12-08 16:21:25 +00001885 vdex_begin_(nullptr),
1886 vdex_end_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08001887 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
1888 CHECK(!location_.empty());
1889}
1890
1891OatFile::~OatFile() {
1892 STLDeleteElements(&oat_dex_files_storage_);
1893}
1894
Brian Carlstrome24fa612011-09-29 00:53:55 -07001895const OatHeader& OatFile::GetOatHeader() const {
Ian Rogers30fab402012-01-23 15:43:46 -08001896 return *reinterpret_cast<const OatHeader*>(Begin());
Brian Carlstrome24fa612011-09-29 00:53:55 -07001897}
1898
Ian Rogers13735952014-10-08 12:43:28 -07001899const uint8_t* OatFile::Begin() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07001900 CHECK(begin_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001901 return begin_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001902}
1903
Ian Rogers13735952014-10-08 12:43:28 -07001904const uint8_t* OatFile::End() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07001905 CHECK(end_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08001906 return end_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001907}
1908
David Brazdil7b49e6c2016-09-01 11:06:18 +01001909const uint8_t* OatFile::DexBegin() const {
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00001910 return vdex_->Begin();
David Brazdil7b49e6c2016-09-01 11:06:18 +01001911}
1912
1913const uint8_t* OatFile::DexEnd() const {
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00001914 return vdex_->End();
David Brazdil7b49e6c2016-09-01 11:06:18 +01001915}
1916
Vladimir Markob066d432018-01-03 13:14:37 +00001917ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
1918 if (data_bimg_rel_ro_begin_ != nullptr) {
1919 const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
1920 const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
1921 return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
1922 } else {
1923 return ArrayRef<const uint32_t>();
1924 }
1925}
1926
Vladimir Marko0eb882b2017-05-15 13:39:18 +01001927ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
1928 if (bss_methods_ != nullptr) {
1929 ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
1930 ArtMethod** methods_end =
1931 reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
1932 return ArrayRef<ArtMethod*>(methods, methods_end - methods);
1933 } else {
1934 return ArrayRef<ArtMethod*>();
1935 }
1936}
1937
Vladimir Markoaad75c62016-10-03 08:46:48 +00001938ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
1939 if (bss_roots_ != nullptr) {
1940 auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
1941 auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
1942 return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
1943 } else {
1944 return ArrayRef<GcRoot<mirror::Object>>();
1945 }
1946}
1947
Andreas Gampeb40d3612018-06-26 15:49:42 -07001948const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
1949 const uint32_t* dex_location_checksum,
1950 std::string* error_msg) const {
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001951 // NOTE: We assume here that the canonical location for a given dex_location never
1952 // changes. If it does (i.e. some symlink used by the filename changes) we may return
1953 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
1954 // an identical file or fail; otherwise we may see some unpredictable failures.
Calin Juravle4e1d5792014-07-15 23:56:47 +01001955
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001956 // TODO: Additional analysis of usage patterns to see if this can be simplified
1957 // without any performance loss, for example by not doing the first lock-free lookup.
1958
Andreas Gampeb40d3612018-06-26 15:49:42 -07001959 const OatDexFile* oat_dex_file = nullptr;
Vladimir Marko59ae4f92019-02-04 14:06:02 +00001960 std::string_view key(dex_location);
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001961 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
1962 // directly mentioned in the oat file and doesn't require locking.
1963 auto primary_it = oat_dex_files_.find(key);
1964 if (primary_it != oat_dex_files_.end()) {
1965 oat_dex_file = primary_it->second;
1966 DCHECK(oat_dex_file != nullptr);
1967 } else {
1968 // This dex_location is not one of the dex locations directly mentioned in the
1969 // oat file. The correct lookup is via the canonical location but first see in
1970 // the secondary_oat_dex_files_ whether we've looked up this location before.
1971 MutexLock mu(Thread::Current(), secondary_lookup_lock_);
1972 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
1973 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001974 oat_dex_file = secondary_lb->second; // May be null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001975 } else {
1976 // We haven't seen this dex_location before, we must check the canonical location.
Mathieu Chartier79c87da2017-10-10 11:54:29 -07001977 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001978 if (dex_canonical_location != dex_location) {
Vladimir Marko59ae4f92019-02-04 14:06:02 +00001979 std::string_view canonical_key(dex_canonical_location);
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001980 auto canonical_it = oat_dex_files_.find(canonical_key);
1981 if (canonical_it != oat_dex_files_.end()) {
1982 oat_dex_file = canonical_it->second;
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001983 } // else keep null.
1984 } // else keep null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001985
1986 // Copy the key to the string_cache_ and store the result in secondary map.
1987 string_cache_.emplace_back(key.data(), key.length());
Vladimir Marko59ae4f92019-02-04 14:06:02 +00001988 std::string_view key_copy(string_cache_.back());
Vladimir Marko3f5838d2014-08-07 18:07:18 +01001989 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07001990 }
1991 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07001992
1993 if (oat_dex_file == nullptr) {
1994 if (error_msg != nullptr) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07001995 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -07001996 *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
1997 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
1998 }
1999 return nullptr;
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002000 }
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07002001
Richard Uhler9a37efc2016-08-05 16:32:55 -07002002 if (dex_location_checksum != nullptr &&
2003 oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
2004 if (error_msg != nullptr) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002005 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -07002006 std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
2007 std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
2008 *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
2009 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
2010 + " has checksum " + checksum + " but " + required_checksum + " was required";
Brian Carlstrom0d6adac2014-02-05 17:39:16 -08002011 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07002012 return nullptr;
Brian Carlstrome24fa612011-09-29 00:53:55 -07002013 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07002014 return oat_dex_file;
Brian Carlstromaded5f72011-10-07 17:15:04 -07002015}
2016
Andreas Gampeb40d3612018-06-26 15:49:42 -07002017OatDexFile::OatDexFile(const OatFile* oat_file,
2018 const std::string& dex_file_location,
2019 const std::string& canonical_dex_file_location,
2020 uint32_t dex_file_location_checksum,
2021 const uint8_t* dex_file_pointer,
2022 const uint8_t* lookup_table_data,
2023 const IndexBssMapping* method_bss_mapping_data,
2024 const IndexBssMapping* type_bss_mapping_data,
Vladimir Marko8f63f102020-09-28 12:10:28 +01002025 const IndexBssMapping* public_type_bss_mapping_data,
2026 const IndexBssMapping* package_type_bss_mapping_data,
Andreas Gampeb40d3612018-06-26 15:49:42 -07002027 const IndexBssMapping* string_bss_mapping_data,
2028 const uint32_t* oat_class_offsets_pointer,
2029 const DexLayoutSections* dex_layout_sections)
Brian Carlstrome24fa612011-09-29 00:53:55 -07002030 : oat_file_(oat_file),
2031 dex_file_location_(dex_file_location),
Vladimir Markoaa4497d2014-09-05 14:01:17 +01002032 canonical_dex_file_location_(canonical_dex_file_location),
Brian Carlstrom5b332c82012-02-01 15:02:31 -08002033 dex_file_location_checksum_(dex_file_location_checksum),
Brian Carlstrom89521892011-12-07 22:05:07 -08002034 dex_file_pointer_(dex_file_pointer),
Artem Udovichenkod9786b02015-10-14 16:36:55 +03002035 lookup_table_data_(lookup_table_data),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01002036 method_bss_mapping_(method_bss_mapping_data),
Vladimir Markof3c52b42017-11-17 17:32:12 +00002037 type_bss_mapping_(type_bss_mapping_data),
Vladimir Marko8f63f102020-09-28 12:10:28 +01002038 public_type_bss_mapping_(public_type_bss_mapping_data),
2039 package_type_bss_mapping_(package_type_bss_mapping_data),
Vladimir Markof3c52b42017-11-17 17:32:12 +00002040 string_bss_mapping_(string_bss_mapping_data),
Vladimir Marko09d09432015-09-08 13:47:48 +01002041 oat_class_offsets_pointer_(oat_class_offsets_pointer),
Vladimir Markoea341d22018-05-11 10:33:37 +01002042 lookup_table_(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07002043 dex_layout_sections_(dex_layout_sections) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002044 InitializeTypeLookupTable();
2045 DCHECK(!IsBackedByVdexOnly());
2046}
2047
2048void OatDexFile::InitializeTypeLookupTable() {
David Sehr9aa352e2016-09-15 18:13:52 -07002049 // Initialize TypeLookupTable.
2050 if (lookup_table_data_ != nullptr) {
2051 // Peek the number of classes from the DexFile.
2052 const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2053 const uint32_t num_class_defs = dex_header->class_defs_size_;
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002054 if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2055 GetOatFile()->DexEnd()) {
David Sehr9aa352e2016-09-15 18:13:52 -07002056 LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2057 } else {
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002058 const uint8_t* dex_data = dex_file_pointer_;
2059 // TODO: Clean this up to create the type lookup table after the dex file has been created?
2060 if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2061 dex_data += dex_header->data_off_;
2062 }
2063 lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
David Sehr9aa352e2016-09-15 18:13:52 -07002064 }
2065 }
David Brazdil7126c5b2019-03-05 00:02:51 +00002066}
2067
2068OatDexFile::OatDexFile(const OatFile* oat_file,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002069 const uint8_t* dex_file_pointer,
2070 uint32_t dex_file_location_checksum,
David Brazdil7126c5b2019-03-05 00:02:51 +00002071 const std::string& dex_file_location,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002072 const std::string& canonical_dex_file_location,
2073 const uint8_t* lookup_table_data)
David Brazdil7126c5b2019-03-05 00:02:51 +00002074 : oat_file_(oat_file),
2075 dex_file_location_(dex_file_location),
2076 canonical_dex_file_location_(canonical_dex_file_location),
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002077 dex_file_location_checksum_(dex_file_location_checksum),
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002078 dex_file_pointer_(dex_file_pointer),
2079 lookup_table_data_(lookup_table_data) {
2080 InitializeTypeLookupTable();
David Brazdil7126c5b2019-03-05 00:02:51 +00002081 DCHECK(IsBackedByVdexOnly());
David Sehr9aa352e2016-09-15 18:13:52 -07002082}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002083
Andreas Gampe875b4f22018-11-19 12:59:15 -08002084OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
David Srbeckyb5649f92019-05-14 15:27:52 +01002085 // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
Nicolas Geoffraydc2fbb62019-04-11 22:55:50 +01002086 CHECK(Runtime::Current() == nullptr ||
2087 Runtime::Current()->IsAotCompiler() ||
David Srbeckyb5649f92019-05-14 15:27:52 +01002088 Runtime::Current()->IsZygote() ||
2089 Runtime::Current()->IsSystemServer());
Andreas Gampe875b4f22018-11-19 12:59:15 -08002090}
Mathieu Chartier1b868492016-11-16 16:22:37 -08002091
Andreas Gampeb40d3612018-06-26 15:49:42 -07002092OatDexFile::~OatDexFile() {}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002093
Andreas Gampeb40d3612018-06-26 15:49:42 -07002094size_t OatDexFile::FileSize() const {
Andreas Gampe875b4f22018-11-19 12:59:15 -08002095 DCHECK(dex_file_pointer_ != nullptr);
Ian Rogers05f28c62012-10-23 18:12:13 -07002096 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2097}
2098
Andreas Gampeb40d3612018-06-26 15:49:42 -07002099std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08002100 ScopedTrace trace(__PRETTY_FUNCTION__);
Aart Bik37d6a3b2016-06-21 18:30:10 -07002101 static constexpr bool kVerify = false;
2102 static constexpr bool kVerifyChecksum = false;
David Sehr013fd802018-01-11 22:55:24 -08002103 const ArtDexFileLoader dex_file_loader;
2104 return dex_file_loader.Open(dex_file_pointer_,
2105 FileSize(),
2106 dex_file_location_,
2107 dex_file_location_checksum_,
2108 this,
2109 kVerify,
2110 kVerifyChecksum,
2111 error_msg);
Brian Carlstrom89521892011-12-07 22:05:07 -08002112}
2113
Andreas Gampeb40d3612018-06-26 15:49:42 -07002114uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
Andreas Gampe875b4f22018-11-19 12:59:15 -08002115 DCHECK(oat_class_offsets_pointer_ != nullptr);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002116 return oat_class_offsets_pointer_[class_def_index];
2117}
2118
David Brazdil7126c5b2019-03-05 00:02:51 +00002119bool OatDexFile::IsBackedByVdexOnly() const {
2120 return oat_class_offsets_pointer_ == nullptr;
2121}
2122
Andreas Gampeb40d3612018-06-26 15:49:42 -07002123OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
David Brazdil7126c5b2019-03-05 00:02:51 +00002124 if (IsBackedByVdexOnly()) {
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002125 // If there is only a vdex file, return that the class is not ready. The
2126 // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2127 // actual class status, because we need to do the assignability type checks.
David Brazdil7126c5b2019-03-05 00:02:51 +00002128 return OatFile::OatClass(oat_file_,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002129 ClassStatus::kNotReady,
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002130 /* type= */ OatClassType::kNoneCompiled,
David Brazdil7126c5b2019-03-05 00:02:51 +00002131 /* bitmap_size= */ 0u,
2132 /* bitmap_pointer= */ nullptr,
2133 /* methods_pointer= */ nullptr);
2134 }
2135
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002136 uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002137 CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2138 CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2139 CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2140 oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2141 const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002142
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002143 uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2144 current_pointer += sizeof(uint16_t);
2145 uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2146 current_pointer += sizeof(uint16_t);
2147 CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2148 << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2149 CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2150 ClassStatus status = enum_cast<ClassStatus>(status_value);
2151 OatClassType type = enum_cast<OatClassType>(type_value);
Brian Carlstromba150c32013-08-27 17:31:03 -07002152
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002153 uint32_t num_methods = 0;
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002154 const uint32_t* bitmap_pointer = nullptr;
2155 const OatMethodOffsets* methods_pointer = nullptr;
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002156 if (type != OatClassType::kNoneCompiled) {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002157 CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2158 << oat_file_->GetLocation();
2159 num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2160 current_pointer += sizeof(uint32_t);
2161 CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2162 uint32_t num_method_offsets;
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002163 if (type == OatClassType::kSomeCompiled) {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002164 uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002165 CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2166 << oat_file_->GetLocation();
2167 bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2168 current_pointer += bitmap_size;
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002169 // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2170 // should be zero but we're not verifying that.
2171 num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
Ian Rogers97b52f82014-08-14 11:34:07 -07002172 } else {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002173 num_method_offsets = num_methods;
Ian Rogers97b52f82014-08-14 11:34:07 -07002174 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002175 CHECK_LE(num_method_offsets,
2176 static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2177 << oat_file_->GetLocation();
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002178 methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
Brian Carlstromcd937a92014-03-04 22:53:23 -08002179 }
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002180
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002181 return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
Brian Carlstrome24fa612011-09-29 00:53:55 -07002182}
2183
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002184const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2185 const char* descriptor,
2186 size_t hash) {
Andreas Gampeb40d3612018-06-26 15:49:42 -07002187 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
David Sehr9aa352e2016-09-15 18:13:52 -07002188 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002189 bool used_lookup_table = false;
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002190 const dex::ClassDef* lookup_table_classdef = nullptr;
Vladimir Markoea341d22018-05-11 10:33:37 +01002191 if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002192 used_lookup_table = true;
Vladimir Markoea341d22018-05-11 10:33:37 +01002193 const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002194 if (class_def_idx != dex::kDexNoIndex) {
2195 CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2196 lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2197 }
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002198 if (!kIsDebugBuild) {
2199 return lookup_table_classdef;
2200 }
David Sehr9aa352e2016-09-15 18:13:52 -07002201 }
2202 // Fast path for rare no class defs case.
2203 const uint32_t num_class_defs = dex_file.NumClassDefs();
2204 if (num_class_defs == 0) {
Vladimir Markoea341d22018-05-11 10:33:37 +01002205 DCHECK(!used_lookup_table);
David Sehr9aa352e2016-09-15 18:13:52 -07002206 return nullptr;
2207 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002208 const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
David Sehr9aa352e2016-09-15 18:13:52 -07002209 if (type_id != nullptr) {
Andreas Gampea5b09a62016-11-17 15:21:22 -08002210 dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002211 const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002212 if (kIsDebugBuild && used_lookup_table) {
2213 DCHECK_EQ(found_class_def, lookup_table_classdef);
2214 }
2215 return found_class_def;
David Sehr9aa352e2016-09-15 18:13:52 -07002216 }
2217 return nullptr;
2218}
2219
Mathieu Chartier120aa282017-08-05 16:03:03 -07002220// Madvise the dex file based on the state we are moving to.
2221void OatDexFile::MadviseDexFile(const DexFile& dex_file, MadviseState state) {
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002222 Runtime* const runtime = Runtime::Current();
2223 const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
Mathieu Chartier150d25d2017-08-28 09:52:55 -07002224 // TODO: Also do madvise hints for non low ram devices.
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002225 if (!low_ram) {
Mathieu Chartierbe8303d2017-08-17 17:39:39 -07002226 return;
2227 }
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002228 if (state == MadviseState::kMadviseStateAtLoad && runtime->MAdviseRandomAccess()) {
2229 // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
2230 // Other devices have enough page cache to get performance benefits from loading more pages
2231 // into the page cache.
David Sehrc431b9d2018-03-02 12:01:51 -08002232 DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
2233 dex_file.Begin() + dex_file.Size(),
2234 MADV_RANDOM);
Mathieu Chartier120aa282017-08-05 16:03:03 -07002235 }
Andreas Gampeb40d3612018-06-26 15:49:42 -07002236 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
Mathieu Chartier120aa282017-08-05 16:03:03 -07002237 if (oat_dex_file != nullptr) {
2238 // Should always be there.
2239 const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
Nicolas Geoffray50419f22021-04-01 18:10:21 +01002240 if (sections != nullptr) {
2241 sections->Madvise(&dex_file, state);
2242 } else {
2243 DCHECK(oat_dex_file->IsBackedByVdexOnly());
2244 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07002245 }
2246}
2247
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002248OatFile::OatClass::OatClass(const OatFile* oat_file,
Vladimir Marko2c64a832018-01-04 11:31:56 +00002249 ClassStatus status,
Brian Carlstromba150c32013-08-27 17:31:03 -07002250 OatClassType type,
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002251 uint32_t num_methods,
Brian Carlstromba150c32013-08-27 17:31:03 -07002252 const uint32_t* bitmap_pointer,
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002253 const OatMethodOffsets* methods_pointer)
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002254 : oat_file_(oat_file),
2255 status_(status),
2256 type_(type),
2257 num_methods_(num_methods),
2258 bitmap_(bitmap_pointer),
2259 methods_pointer_(methods_pointer) {
2260 DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2261 DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2262 DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
Brian Carlstromba150c32013-08-27 17:31:03 -07002263}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002264
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002265uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2266 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2267 if (oat_method_offsets == nullptr) {
2268 return 0u;
2269 }
2270 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2271}
2272
2273const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002274 // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2275 // a bounds check for `method_index` in that case.
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002276 if (methods_pointer_ == nullptr) {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002277 CHECK_EQ(OatClassType::kNoneCompiled, type_);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002278 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07002279 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002280 CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
Brian Carlstromba150c32013-08-27 17:31:03 -07002281 size_t methods_pointer_index;
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002282 if (bitmap_ == nullptr) {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002283 CHECK_EQ(OatClassType::kAllCompiled, type_);
Brian Carlstromba150c32013-08-27 17:31:03 -07002284 methods_pointer_index = method_index;
2285 } else {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002286 CHECK_EQ(OatClassType::kSomeCompiled, type_);
Vladimir Markod3c5beb2014-04-11 16:32:51 +01002287 if (!BitVector::IsBitSet(bitmap_, method_index)) {
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002288 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07002289 }
Vladimir Markod3c5beb2014-04-11 16:32:51 +01002290 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2291 methods_pointer_index = num_set_bits;
Brian Carlstromba150c32013-08-27 17:31:03 -07002292 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002293 if (kIsDebugBuild) {
2294 size_t size_until_end = dchecked_integral_cast<size_t>(
2295 oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2296 CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2297 << oat_file_->GetLocation();
2298 }
Brian Carlstromba150c32013-08-27 17:31:03 -07002299 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002300 return &oat_method_offsets;
2301}
2302
2303const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2304 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2305 if (oat_method_offsets == nullptr) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08002306 return OatMethod(nullptr, 0);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002307 }
2308 if (oat_file_->IsExecutable() ||
2309 Runtime::Current() == nullptr || // This case applies for oatdump.
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08002310 Runtime::Current()->IsAotCompiler()) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08002311 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
Alex Light9dcc4572014-08-14 14:16:26 -07002312 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08002313 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2314 // version.
2315 return OatMethod(oat_file_->Begin(), 0);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07002316}
2317
Sebastien Hertz0de11332015-05-13 12:14:05 +02002318bool OatFile::IsDebuggable() const {
2319 return GetOatHeader().IsDebuggable();
2320}
2321
Andreas Gampe29d38e72016-03-23 15:31:51 +00002322CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2323 return GetOatHeader().GetCompilerFilter();
Calin Juravleb077e152016-02-18 18:47:37 +00002324}
2325
Calin Juravle44e5efa2017-09-12 00:54:26 -07002326std::string OatFile::GetClassLoaderContext() const {
2327 return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
Igor Murashkin2ffb7032017-11-08 13:35:21 -08002328}
Calin Juravle44e5efa2017-09-12 00:54:26 -07002329
Calin Juravle0e09dfc2018-02-12 19:01:09 -08002330const char* OatFile::GetCompilationReason() const {
2331 return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2332}
2333
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01002334OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2335 uint16_t class_def_idx,
2336 bool* found) {
2337 DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
Andreas Gampeb40d3612018-06-26 15:49:42 -07002338 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
Mathieu Chartier1b868492016-11-16 16:22:37 -08002339 if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01002340 *found = false;
2341 return OatFile::OatClass::Invalid();
2342 }
2343 *found = true;
2344 return oat_dex_file->GetOatClass(class_def_idx);
2345}
2346
Eric Holkbc89ed42020-04-29 19:59:24 +00002347bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2348
Vladimir Marko1cedb4a2019-02-06 14:13:28 +00002349static void DCheckIndexToBssMapping(const OatFile* oat_file,
2350 uint32_t number_of_indexes,
2351 size_t slot_size,
2352 const IndexBssMapping* index_bss_mapping) {
2353 if (kIsDebugBuild && index_bss_mapping != nullptr) {
2354 size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2355 const IndexBssMappingEntry* prev_entry = nullptr;
2356 for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2357 CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2358 CHECK_LT(entry.bss_offset, oat_file->BssSize());
2359 uint32_t mask = entry.GetMask(index_bits);
2360 CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2361 size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2362 CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2363 if (prev_entry != nullptr) {
2364 CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2365 }
2366 prev_entry = &entry;
2367 }
2368 CHECK(prev_entry != nullptr);
2369 CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2370 }
2371}
2372
2373void OatFile::InitializeRelocations() const {
2374 DCHECK(IsExecutable());
2375
2376 // Initialize the .data.bimg.rel.ro section.
2377 if (!GetBootImageRelocations().empty()) {
2378 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2379 CheckedCall(mprotect,
2380 "un-protect boot image relocations",
2381 reloc_begin,
2382 DataBimgRelRoSize(),
2383 PROT_READ | PROT_WRITE);
Vladimir Marko7cde4582019-07-05 13:26:11 +01002384 uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
Vladimir Marko1cedb4a2019-02-06 14:13:28 +00002385 for (const uint32_t& relocation : GetBootImageRelocations()) {
2386 const_cast<uint32_t&>(relocation) += boot_image_begin;
2387 }
2388 CheckedCall(mprotect,
2389 "protect boot image relocations",
2390 reloc_begin,
2391 DataBimgRelRoSize(),
2392 PROT_READ);
2393 }
2394
2395 // Before initializing .bss, check the .bss mappings in debug mode.
2396 if (kIsDebugBuild) {
2397 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2398 for (const OatDexFile* odf : GetOatDexFiles()) {
2399 const DexFile::Header* header =
2400 reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2401 DCheckIndexToBssMapping(this,
2402 header->method_ids_size_,
2403 static_cast<size_t>(pointer_size),
2404 odf->GetMethodBssMapping());
2405 DCheckIndexToBssMapping(this,
2406 header->type_ids_size_,
2407 sizeof(GcRoot<mirror::Class>),
2408 odf->GetTypeBssMapping());
2409 DCheckIndexToBssMapping(this,
2410 header->string_ids_size_,
2411 sizeof(GcRoot<mirror::String>),
2412 odf->GetStringBssMapping());
2413 }
2414 }
2415
2416 // Initialize the .bss section.
2417 // TODO: Pre-initialize from boot/app image?
2418 ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2419 for (ArtMethod*& entry : GetBssMethods()) {
2420 entry = resolution_method;
2421 }
2422}
2423
Andreas Gampeb40d3612018-06-26 15:49:42 -07002424void OatDexFile::AssertAotCompiler() {
Mathieu Chartier1b868492016-11-16 16:22:37 -08002425 CHECK(Runtime::Current()->IsAotCompiler());
2426}
2427
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002428bool OatFile::IsBackedByVdexOnly() const {
2429 return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2430}
2431
Brian Carlstrome24fa612011-09-29 00:53:55 -07002432} // namespace art