blob: 7809095a271dcddd2b9c8c93c1b294063b17ff74 [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
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100176 bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
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:
193 DISALLOW_COPY_AND_ASSIGN(OatFileBase);
194};
195
196template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100197OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
198 const std::string& vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100199 const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800200 const std::string& location,
Andreas Gampe049cff02015-12-01 23:27:12 -0800201 bool writable,
202 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800203 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000204 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -0700205 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100206 /*inout*/MemMap* reservation,
207 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800208 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
Andreas Gampe4075f832016-05-18 13:09:54 -0700209
210 ret->PreLoad();
211
Andreas Gampe049cff02015-12-01 23:27:12 -0800212 if (!ret->Load(elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -0800213 writable,
214 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800215 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100216 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -0800217 error_msg)) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800218 return nullptr;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800219 }
Elliott Hughes956af0f2014-12-11 14:34:28 -0800220
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100221 if (!ret->ComputeFields(elf_filename, error_msg)) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800222 return nullptr;
223 }
Andreas Gampe4075f832016-05-18 13:09:54 -0700224
David Sehr2300b2d2018-05-10 14:20:10 -0700225 ret->PreSetup(elf_filename);
226
David Srbeckyec2cdf42017-12-08 16:21:25 +0000227 if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
228 return nullptr;
229 }
230
Victor Hsiehf667c332021-05-27 11:35:44 -0700231 if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800232 return nullptr;
233 }
234
Dave Allison69dfe512014-07-11 17:11:58 +0000235 return ret.release();
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800236}
237
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700238template <typename kOatFileBaseSubType>
Nicolas Geoffray30025092018-04-19 14:43:29 +0100239OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
240 int vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700241 int oat_fd,
242 const std::string& vdex_location,
243 const std::string& oat_location,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700244 bool writable,
245 bool executable,
246 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000247 ArrayRef<const std::string> dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -0700248 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100249 /*inout*/MemMap* reservation,
250 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700251 std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
252
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700253 if (!ret->Load(oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700254 writable,
255 executable,
256 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100257 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700258 error_msg)) {
259 return nullptr;
260 }
261
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100262 if (!ret->ComputeFields(oat_location, error_msg)) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700263 return nullptr;
264 }
265
David Sehr2300b2d2018-05-10 14:20:10 -0700266 ret->PreSetup(oat_location);
267
David Srbeckyec2cdf42017-12-08 16:21:25 +0000268 if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
269 return nullptr;
270 }
271
Victor Hsiehce9b9022021-07-21 10:44:06 -0700272 if (!ret->Setup(zip_fd, dex_filenames, dex_fds, error_msg)) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700273 return nullptr;
274 }
275
276 return ret.release();
277}
278
David Brazdil7b49e6c2016-09-01 11:06:18 +0100279bool OatFileBase::LoadVdex(const std::string& vdex_filename,
280 bool writable,
281 bool low_4gb,
282 std::string* error_msg) {
David Srbeckyec2cdf42017-12-08 16:21:25 +0000283 vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
284 vdex_end_ - vdex_begin_,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100285 /*mmap_reuse=*/ vdex_begin_ != nullptr,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000286 vdex_filename,
287 writable,
288 low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000289 error_msg);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100290 if (vdex_.get() == nullptr) {
291 *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
292 vdex_filename.c_str(),
293 error_msg->c_str());
294 return false;
295 }
296 return true;
297}
298
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700299bool OatFileBase::LoadVdex(int vdex_fd,
300 const std::string& vdex_filename,
301 bool writable,
302 bool low_4gb,
303 std::string* error_msg) {
304 if (vdex_fd != -1) {
305 struct stat s;
306 int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd, &s));
307 if (rc == -1) {
308 PLOG(WARNING) << "Failed getting length of vdex file";
309 } else {
Alex Lightabd8f052019-12-06 10:49:17 -0800310 vdex_ = VdexFile::OpenAtAddress(
311 vdex_begin_,
312 vdex_end_ - vdex_begin_,
313 /*mmap_reuse=*/ vdex_begin_ != nullptr,
314 vdex_fd,
315 s.st_size,
316 vdex_filename,
317 writable,
318 low_4gb,
Alex Lightabd8f052019-12-06 10:49:17 -0800319 error_msg);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700320 if (vdex_.get() == nullptr) {
321 *error_msg = "Failed opening vdex file.";
322 return false;
323 }
324 }
325 }
326 return true;
327}
328
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100329bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800330 std::string symbol_error_msg;
331 begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700332 if (begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800333 *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
334 file_path.c_str(),
335 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700336 return false;
337 }
Andreas Gampe049cff02015-12-01 23:27:12 -0800338 end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
Andreas Gampefa8429b2015-04-07 18:34:42 -0700339 if (end_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800340 *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
341 file_path.c_str(),
342 symbol_error_msg.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700343 return false;
344 }
345 // Readjust to be non-inclusive upper bound.
346 end_ += sizeof(uint32_t);
347
Vladimir Markob066d432018-01-03 13:14:37 +0000348 data_bimg_rel_ro_begin_ = FindDynamicSymbolAddress("oatdatabimgrelro", &symbol_error_msg);
349 if (data_bimg_rel_ro_begin_ != nullptr) {
350 data_bimg_rel_ro_end_ =
351 FindDynamicSymbolAddress("oatdatabimgrelrolastword", &symbol_error_msg);
352 if (data_bimg_rel_ro_end_ == nullptr) {
353 *error_msg =
354 StringPrintf("Failed to find oatdatabimgrelrolastword symbol in '%s'", file_path.c_str());
355 return false;
356 }
357 // Readjust to be non-inclusive upper bound.
358 data_bimg_rel_ro_end_ += sizeof(uint32_t);
359 }
360
Andreas Gampe049cff02015-12-01 23:27:12 -0800361 bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700362 if (bss_begin_ == nullptr) {
Andreas Gampe049cff02015-12-01 23:27:12 -0800363 // No .bss section.
Andreas Gampefa8429b2015-04-07 18:34:42 -0700364 bss_end_ = nullptr;
Andreas Gampefa8429b2015-04-07 18:34:42 -0700365 } else {
Andreas Gampe049cff02015-12-01 23:27:12 -0800366 bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700367 if (bss_end_ == nullptr) {
David Srbeckyec2cdf42017-12-08 16:21:25 +0000368 *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
Andreas Gampefa8429b2015-04-07 18:34:42 -0700369 return false;
370 }
371 // Readjust to be non-inclusive upper bound.
372 bss_end_ += sizeof(uint32_t);
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100373 // Find bss methods if present.
374 bss_methods_ =
375 const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
Vladimir Markoaad75c62016-10-03 08:46:48 +0000376 // Find bss roots if present.
377 bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
Andreas Gampefa8429b2015-04-07 18:34:42 -0700378 }
379
David Srbeckyec2cdf42017-12-08 16:21:25 +0000380 vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
381 if (vdex_begin_ == nullptr) {
382 // No .vdex section.
383 vdex_end_ = nullptr;
384 } else {
385 vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
386 if (vdex_end_ == nullptr) {
387 *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
388 return false;
389 }
390 // Readjust to be non-inclusive upper bound.
391 vdex_end_ += sizeof(uint32_t);
392 }
393
Andreas Gampe049cff02015-12-01 23:27:12 -0800394 return true;
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800395}
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800396
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100397// Read an unaligned entry from the OatDexFile data in OatFile and advance the read
398// position by the number of bytes read, i.e. sizeof(T).
399// Return true on success, false if the read would go beyond the end of the OatFile.
400template <typename T>
Vladimir Marko722fa982015-10-19 18:18:27 +0100401inline static bool ReadOatDexFileData(const OatFile& oat_file,
402 /*inout*/const uint8_t** oat,
403 /*out*/T* value) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100404 DCHECK(oat != nullptr);
405 DCHECK(value != nullptr);
406 DCHECK_LE(*oat, oat_file.End());
407 if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
408 return false;
409 }
410 static_assert(std::is_trivial<T>::value, "T must be a trivial type");
Andreas Gampec55bb392018-09-21 00:02:02 +0000411 using unaligned_type __attribute__((__aligned__(1))) = T;
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100412 *value = *reinterpret_cast<const unaligned_type*>(*oat);
413 *oat += sizeof(T);
414 return true;
415}
416
Vladimir Markof3c52b42017-11-17 17:32:12 +0000417static bool ReadIndexBssMapping(OatFile* oat_file,
418 /*inout*/const uint8_t** oat,
419 size_t dex_file_index,
420 const std::string& dex_file_location,
421 const char* tag,
422 /*out*/const IndexBssMapping** mapping,
423 std::string* error_msg) {
424 uint32_t index_bss_mapping_offset;
425 if (UNLIKELY(!ReadOatDexFileData(*oat_file, oat, &index_bss_mapping_offset))) {
426 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
427 "after %s bss mapping offset",
428 oat_file->GetLocation().c_str(),
429 dex_file_index,
430 dex_file_location.c_str(),
431 tag);
432 return false;
433 }
434 const bool readable_index_bss_mapping_size =
435 index_bss_mapping_offset != 0u &&
436 index_bss_mapping_offset <= oat_file->Size() &&
437 IsAligned<alignof(IndexBssMapping)>(index_bss_mapping_offset) &&
438 oat_file->Size() - index_bss_mapping_offset >= IndexBssMapping::ComputeSize(0);
439 const IndexBssMapping* index_bss_mapping = readable_index_bss_mapping_size
440 ? reinterpret_cast<const IndexBssMapping*>(oat_file->Begin() + index_bss_mapping_offset)
441 : nullptr;
442 if (index_bss_mapping_offset != 0u &&
443 (UNLIKELY(index_bss_mapping == nullptr) ||
444 UNLIKELY(index_bss_mapping->size() == 0u) ||
445 UNLIKELY(oat_file->Size() - index_bss_mapping_offset <
446 IndexBssMapping::ComputeSize(index_bss_mapping->size())))) {
447 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned or "
448 " truncated %s bss mapping, offset %u of %zu, length %zu",
449 oat_file->GetLocation().c_str(),
450 dex_file_index,
451 dex_file_location.c_str(),
452 tag,
453 index_bss_mapping_offset,
454 oat_file->Size(),
455 index_bss_mapping != nullptr ? index_bss_mapping->size() : 0u);
456 return false;
457 }
458
459 *mapping = index_bss_mapping;
460 return true;
461}
462
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100463static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
464 const uint8_t* type_lookup_table_start,
465 const VdexFile* vdex_file,
466 const uint8_t** type_lookup_table_data,
467 std::string* error_msg) {
468 if (type_lookup_table_start == nullptr ||
469 reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0] == 0) {
470 *type_lookup_table_data = nullptr;
471 return true;
472 }
473
474 *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
475 size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
476 size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
477 if (UNLIKELY(found_size != expected_table_size)) {
478 *error_msg =
479 StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
480 vdex_file->GetName().c_str(),
481 found_size,
482 expected_table_size);
483 return false;
484 }
485 if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data))) {
486 *error_msg =
487 StringPrintf("In vdex file '%s' found invalid type lookup table pointer %p not in [%p, %p]",
488 vdex_file->GetName().c_str(),
489 type_lookup_table_data,
490 vdex_file->Begin(),
491 vdex_file->End());
492 return false;
493 }
494 if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data + expected_table_size - 1))) {
495 *error_msg =
496 StringPrintf("In vdex file '%s' found overflowing type lookup table %p not in [%p, %p]",
497 vdex_file->GetName().c_str(),
498 type_lookup_table_data + expected_table_size,
499 vdex_file->Begin(),
500 vdex_file->End());
501 return false;
502 }
503 if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
504 *error_msg =
505 StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
506 vdex_file->GetName().c_str(),
507 type_lookup_table_start);
508 return false;
509 }
510 return true;
511}
512
513bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000514 uint32_t i = 0;
515 const uint8_t* type_lookup_table_start = nullptr;
David Brazdil7126c5b2019-03-05 00:02:51 +0000516 for (const DexFile* dex_file : dex_files) {
517 std::string dex_location = dex_file->GetLocation();
518 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
519
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100520 type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000521 const uint8_t* type_lookup_table_data = nullptr;
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100522 if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
523 type_lookup_table_start,
524 vdex_.get(),
525 &type_lookup_table_data,
526 error_msg)) {
527 return false;
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000528 }
David Brazdil7126c5b2019-03-05 00:02:51 +0000529 // Create an OatDexFile and add it to the owning container.
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000530 OatDexFile* oat_dex_file = new OatDexFile(
531 this,
532 dex_file->Begin(),
533 dex_file->GetLocationChecksum(),
534 dex_location,
535 canonical_location,
536 type_lookup_table_data);
David Brazdil7126c5b2019-03-05 00:02:51 +0000537 oat_dex_files_storage_.push_back(oat_dex_file);
538
539 // Add the location and canonical location (if different) to the oat_dex_files_ table.
540 std::string_view key(oat_dex_file->GetDexFileLocation());
541 oat_dex_files_.Put(key, oat_dex_file);
542 if (canonical_location != dex_location) {
543 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
544 oat_dex_files_.Put(canonical_key, oat_dex_file);
545 }
546 }
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100547 // Now that we've created all the OatDexFile, update the dex files.
548 for (i = 0; i < dex_files.size(); ++i) {
549 dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
550 }
551 return true;
David Brazdil7126c5b2019-03-05 00:02:51 +0000552}
553
Vladimir Markob7bf8432019-12-03 13:18:50 +0000554bool OatFileBase::Setup(int zip_fd,
555 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -0700556 ArrayRef<const int> dex_fds,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000557 std::string* error_msg) {
Brian Carlstromf1b30302013-03-28 10:35:32 -0700558 if (!GetOatHeader().IsValid()) {
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800559 std::string cause = GetOatHeader().GetValidationErrorMessage();
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100560 *error_msg = StringPrintf("Invalid oat header for '%s': %s",
561 GetLocation().c_str(),
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800562 cause.c_str());
Brian Carlstromf1b30302013-03-28 10:35:32 -0700563 return false;
564 }
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100565 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
566 size_t key_value_store_size =
567 (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
568 if (Size() < sizeof(OatHeader) + key_value_store_size) {
569 *error_msg = StringPrintf("In oat file '%s' found truncated OatHeader, "
570 "size = %zu < %zu + %zu",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100571 GetLocation().c_str(),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100572 Size(),
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100573 sizeof(OatHeader),
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100574 key_value_store_size);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700575 return false;
576 }
577
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100578 size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
579 if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
580 *error_msg = StringPrintf("In oat file '%s' found invalid oat dex files offset: "
581 "%zu is not in [%zu, %zu]",
582 GetLocation().c_str(),
583 oat_dex_files_offset,
584 GetOatHeader().GetHeaderSize(),
585 Size());
586 return false;
587 }
588 const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records.
589
Vladimir Markob066d432018-01-03 13:14:37 +0000590 if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) ||
591 !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) ||
592 data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) {
593 *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro "
594 "symbol(s): begin = %p, end = %p",
595 GetLocation().c_str(),
596 data_bimg_rel_ro_begin_,
597 data_bimg_rel_ro_end_);
598 return false;
599 }
600
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100601 DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
602 if (!IsAligned<kPageSize>(bss_begin_) ||
603 !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
604 !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
Vladimir Markoaad75c62016-10-03 08:46:48 +0000605 !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
606 *error_msg = StringPrintf("In oat file '%s' found unaligned bss symbol(s): "
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100607 "begin = %p, methods_ = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000608 GetLocation().c_str(),
609 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100610 bss_methods_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000611 bss_roots_,
612 bss_end_);
613 return false;
614 }
615
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100616 if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
617 (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
618 (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
619 *error_msg = StringPrintf("In oat file '%s' found bss symbol(s) outside .bss or unordered: "
Vladimir Marko0f3c7002017-09-07 14:15:56 +0100620 "begin = %p, methods = %p, roots = %p, end = %p",
Vladimir Markoaad75c62016-10-03 08:46:48 +0000621 GetLocation().c_str(),
Vladimir Markoaad75c62016-10-03 08:46:48 +0000622 bss_begin_,
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100623 bss_methods_,
624 bss_roots_,
Vladimir Markoaad75c62016-10-03 08:46:48 +0000625 bss_end_);
626 return false;
627 }
628
Vladimir Markoe47f60c2018-02-21 13:43:28 +0000629 if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
630 *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': "
631 "begin = %p, methods = %p",
632 GetLocation().c_str(),
633 bss_begin_,
634 bss_methods_);
635 return false;
636 }
637
Vladimir Markob7bf8432019-12-03 13:18:50 +0000638 std::string_view primary_location;
639 std::string_view primary_location_replacement;
Victor Hsiehf667c332021-05-27 11:35:44 -0700640 int dex_fd = -1;
Vladimir Markob7bf8432019-12-03 13:18:50 +0000641 size_t dex_filenames_pos = 0u;
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100642 uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
643 oat_dex_files_storage_.reserve(dex_file_count);
644 for (size_t i = 0; i < dex_file_count; i++) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100645 uint32_t dex_file_location_size;
646 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
647 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu truncated after dex file "
648 "location size",
649 GetLocation().c_str(),
650 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700651 return false;
652 }
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100653 if (UNLIKELY(dex_file_location_size == 0U)) {
654 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with empty location name",
655 GetLocation().c_str(),
656 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700657 return false;
658 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000659 if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100660 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu with truncated dex file "
661 "location",
662 GetLocation().c_str(),
663 i);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700664 return false;
665 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000666 const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
667 oat += dex_file_location_size;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700668
Vladimir Markob7bf8432019-12-03 13:18:50 +0000669 // Location encoded in the oat file. We will use this for multidex naming.
670 std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
671 std::string dex_file_location(oat_dex_file_location);
672 bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location.c_str());
Vladimir Marko69944682019-12-09 15:16:39 +0000673 // Check that `is_multidex` does not clash with other indicators. The first dex location
674 // must be primary location and, if we're opening external dex files, the location must
675 // be multi-dex if and only if we already have a dex file opened for it.
676 if ((i == 0 && is_multidex) ||
677 (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
678 *error_msg = StringPrintf("In oat file '%s' found unexpected %s location '%s'",
679 GetLocation().c_str(),
680 is_multidex ? "multi-dex" : "primary",
681 dex_file_location.c_str());
682 return false;
683 }
684 // Remember the primary location and, if provided, the replacement from `dex_filenames`.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000685 if (!is_multidex) {
686 primary_location = oat_dex_file_location;
687 if (!dex_filenames.empty()) {
688 if (dex_filenames_pos == dex_filenames.size()) {
689 *error_msg = StringPrintf("In oat file '%s' found excessive primary location '%s'"
690 ", expected only %zu primary locations",
691 GetLocation().c_str(),
692 dex_file_location.c_str(),
693 dex_filenames.size());
694 return false;
695 }
696 primary_location_replacement = dex_filenames[dex_filenames_pos];
Victor Hsiehf667c332021-05-27 11:35:44 -0700697 dex_fd = dex_filenames_pos < dex_fds.size() ? dex_fds[dex_filenames_pos] : -1;
Vladimir Markob7bf8432019-12-03 13:18:50 +0000698 ++dex_filenames_pos;
699 }
700 }
Vladimir Marko69944682019-12-09 15:16:39 +0000701 // Check that the base location of a multidex location matches the last seen primary location.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000702 if (is_multidex &&
703 (!StartsWith(dex_file_location, primary_location) ||
704 dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
705 *error_msg = StringPrintf("In oat file '%s' found unexpected multidex location '%s',"
706 " unrelated to '%s'",
707 GetLocation().c_str(),
708 dex_file_location.c_str(),
709 std::string(primary_location).c_str());
710 return false;
711 }
712 std::string dex_file_name = dex_file_location;
713 if (!dex_filenames.empty()) {
714 dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
715 // If the location does not contain path and matches the file name component,
716 // use the provided file name also as the location.
717 // TODO: Do we need this for anything other than tests?
718 if (dex_file_location.find('/') == std::string::npos &&
719 dex_file_name.size() > dex_file_location.size() &&
720 dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
721 EndsWith(dex_file_name, dex_file_location)) {
722 dex_file_location = dex_file_name;
723 }
724 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700725
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100726 uint32_t dex_file_checksum;
727 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
728 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated after "
729 "dex file checksum",
730 GetLocation().c_str(),
731 i,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700732 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700733 return false;
734 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700735
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100736 uint32_t dex_file_offset;
737 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
738 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
739 "after dex file offsets",
740 GetLocation().c_str(),
741 i,
742 dex_file_location.c_str());
743 return false;
744 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100745 if (UNLIKELY(dex_file_offset > DexSize())) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100746 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
747 "offset %u > %zu",
748 GetLocation().c_str(),
749 i,
750 dex_file_location.c_str(),
751 dex_file_offset,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100752 DexSize());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700753 return false;
754 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000755 const uint8_t* dex_file_pointer = nullptr;
756 if (UNLIKELY(dex_file_offset == 0U)) {
Vladimir Markob7bf8432019-12-03 13:18:50 +0000757 // Do not support mixed-mode oat files.
758 if (i != 0u && external_dex_files_.empty()) {
759 *error_msg = StringPrintf("In oat file '%s', unsupported uncompressed-dex-file for dex "
760 "file %zu (%s)",
761 GetLocation().c_str(),
762 i,
763 dex_file_location.c_str());
764 return false;
765 }
766 DCHECK_LE(i, external_dex_files_.size());
767 if (i == external_dex_files_.size()) {
768 std::vector<std::unique_ptr<const DexFile>> new_dex_files;
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000769 // No dex files, load it from location.
770 const ArtDexFileLoader dex_file_loader;
Nicolas Geoffray30025092018-04-19 14:43:29 +0100771 bool loaded = false;
Victor Hsiehf667c332021-05-27 11:35:44 -0700772 CHECK(zip_fd == -1 || dex_fds.empty()); // Allow only the supported combinations.
Victor Hsieh9060ebe2021-06-17 12:57:12 -0700773 if (zip_fd != -1) {
774 loaded = dex_file_loader.OpenZip(zip_fd,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100775 dex_file_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100776 /*verify=*/ false,
777 /*verify_checksum=*/ false,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100778 error_msg,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000779 &new_dex_files);
Victor Hsieh9060ebe2021-06-17 12:57:12 -0700780 } else if (dex_fd != -1) {
781 // Note that we assume dex_fds are backing by jars.
782 loaded = dex_file_loader.OpenZipFromOwnedFd(dex_fd,
783 dex_file_location,
784 /*verify=*/ false,
785 /*verify_checksum=*/ false,
786 error_msg,
787 &new_dex_files);
Nicolas Geoffray30025092018-04-19 14:43:29 +0100788 } else {
David Brazdil3e8aae02019-03-26 18:48:02 +0000789 loaded = dex_file_loader.Open(dex_file_name.c_str(),
Nicolas Geoffray30025092018-04-19 14:43:29 +0100790 dex_file_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100791 /*verify=*/ false,
792 /*verify_checksum=*/ false,
Nicolas Geoffray30025092018-04-19 14:43:29 +0100793 error_msg,
Vladimir Markob7bf8432019-12-03 13:18:50 +0000794 &new_dex_files);
Nicolas Geoffray30025092018-04-19 14:43:29 +0100795 }
796 if (!loaded) {
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000797 if (Runtime::Current() == nullptr) {
798 // If there's no runtime, we're running oatdump, so return
799 // a half constructed oat file that oatdump knows how to deal with.
800 LOG(WARNING) << "Could not find associated dex files of oat file. "
801 << "Oatdump will only dump the header.";
802 return true;
803 } else {
804 return false;
805 }
806 }
Andreas Gampefc604a72018-02-08 15:43:37 -0800807 // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
808 // here and ensure that at least the number of dex files still matches.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000809 // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
810 // load all dex files from that file, otherwise we may open multiple files.
Andreas Gampefc604a72018-02-08 15:43:37 -0800811 // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
812 // done after loading the OatFile.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000813 size_t max_dex_files = dex_file_count - external_dex_files_.size();
814 bool expect_all =
815 (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
816 if (expect_all ? new_dex_files.size() != max_dex_files
817 : new_dex_files.size() > max_dex_files) {
818 *error_msg = StringPrintf("In oat file '%s', expected %s%zu uncompressed dex files, but "
Andreas Gampefc604a72018-02-08 15:43:37 -0800819 "found %zu in '%s'",
820 GetLocation().c_str(),
Vladimir Markob7bf8432019-12-03 13:18:50 +0000821 (expect_all ? "" : "<="),
822 max_dex_files,
823 new_dex_files.size(),
Andreas Gampefc604a72018-02-08 15:43:37 -0800824 dex_file_location.c_str());
825 return false;
826 }
Vladimir Markob7bf8432019-12-03 13:18:50 +0000827 for (std::unique_ptr<const DexFile>& dex_file : new_dex_files) {
828 external_dex_files_.push_back(std::move(dex_file));
829 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000830 }
Vladimir Markob7bf8432019-12-03 13:18:50 +0000831 dex_file_pointer = external_dex_files_[i]->Begin();
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000832 } else {
Andreas Gampefc604a72018-02-08 15:43:37 -0800833 // Do not support mixed-mode oat files.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000834 if (!external_dex_files_.empty()) {
Andreas Gampefc604a72018-02-08 15:43:37 -0800835 *error_msg = StringPrintf("In oat file '%s', unsupported embedded dex-file for dex file "
836 "%zu (%s)",
837 GetLocation().c_str(),
838 i,
839 dex_file_location.c_str());
840 return false;
841 }
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000842 if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
843 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
844 "offset %u of %zu but the size of dex file header is %zu",
845 GetLocation().c_str(),
846 i,
847 dex_file_location.c_str(),
848 dex_file_offset,
849 DexSize(),
850 sizeof(DexFile::Header));
851 return false;
852 }
853 dex_file_pointer = DexBegin() + dex_file_offset;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000854 }
Brian Carlstrom89521892011-12-07 22:05:07 -0800855
Mathieu Chartiercf76bf82017-09-25 16:22:36 -0700856 const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
Mathieu Chartier7b074bf2017-09-25 16:22:36 -0700857 if (UNLIKELY(!valid_magic)) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100858 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100859 "dex file magic",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100860 GetLocation().c_str(),
861 i,
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100862 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700863 return false;
864 }
Mathieu Chartiercf76bf82017-09-25 16:22:36 -0700865 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100866 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with invalid "
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100867 "dex file version",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100868 GetLocation().c_str(),
869 i,
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +0100870 dex_file_location.c_str());
Brian Carlstromfb331d72013-07-25 22:00:16 -0700871 return false;
872 }
Brian Carlstrom6e3b1d92012-01-11 01:36:32 -0800873 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
Nicolas Geoffrayf3075272018-01-08 12:41:19 +0000874 if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000875 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with dex file "
876 "offset %u and size %u truncated at %zu",
877 GetLocation().c_str(),
878 i,
879 dex_file_location.c_str(),
880 dex_file_offset,
881 header->file_size_,
David Brazdil7b49e6c2016-09-01 11:06:18 +0100882 DexSize());
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000883 return false;
884 }
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300885
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000886 uint32_t class_offsets_offset;
887 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
888 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' truncated "
889 "after class offsets offset",
890 GetLocation().c_str(),
891 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300892 dex_file_location.c_str());
893 return false;
894 }
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000895 if (UNLIKELY(class_offsets_offset > Size()) ||
896 UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
897 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
898 "class offsets, offset %u of %zu, class defs %u",
899 GetLocation().c_str(),
900 i,
901 dex_file_location.c_str(),
902 class_offsets_offset,
903 Size(),
904 header->class_defs_size_);
905 return false;
906 }
907 if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
908 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with unaligned "
909 "class offsets, offset %u",
910 GetLocation().c_str(),
911 i,
912 dex_file_location.c_str(),
913 class_offsets_offset);
914 return false;
915 }
916 const uint32_t* class_offsets_pointer =
917 reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
918
919 uint32_t lookup_table_offset;
920 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
921 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
922 "after lookup table offset",
923 GetLocation().c_str(),
924 i,
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300925 dex_file_location.c_str());
926 return false;
927 }
928 const uint8_t* lookup_table_data = lookup_table_offset != 0u
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000929 ? DexBegin() + lookup_table_offset
Artem Udovichenkod9786b02015-10-14 16:36:55 +0300930 : nullptr;
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000931 if (lookup_table_offset != 0u &&
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000932 (UNLIKELY(lookup_table_offset > DexSize()) ||
933 UNLIKELY(DexSize() - lookup_table_offset <
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000934 TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100935 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zu for '%s' with truncated "
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000936 "type lookup table, offset %u of %zu, class defs %u",
Vladimir Marko06d7aaa2015-10-16 11:23:41 +0100937 GetLocation().c_str(),
938 i,
Vladimir Marko9bdf1082016-01-21 12:15:52 +0000939 dex_file_location.c_str(),
940 lookup_table_offset,
941 Size(),
942 header->class_defs_size_);
Brian Carlstromfb331d72013-07-25 22:00:16 -0700943 return false;
944 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700945
Mathieu Chartier120aa282017-08-05 16:03:03 -0700946 uint32_t dex_layout_sections_offset;
947 if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
948 *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' truncated "
949 "after dex layout sections offset",
950 GetLocation().c_str(),
951 i,
952 dex_file_location.c_str());
953 return false;
954 }
955 const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
956 ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
957 : nullptr;
958
Vladimir Markof3c52b42017-11-17 17:32:12 +0000959 const IndexBssMapping* method_bss_mapping;
960 const IndexBssMapping* type_bss_mapping;
Vladimir Marko8f63f102020-09-28 12:10:28 +0100961 const IndexBssMapping* public_type_bss_mapping;
962 const IndexBssMapping* package_type_bss_mapping;
Vladimir Markof3c52b42017-11-17 17:32:12 +0000963 const IndexBssMapping* string_bss_mapping;
964 if (!ReadIndexBssMapping(
965 this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) ||
966 !ReadIndexBssMapping(
967 this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) ||
968 !ReadIndexBssMapping(
Vladimir Marko8f63f102020-09-28 12:10:28 +0100969 this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) ||
970 !ReadIndexBssMapping(
971 this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) ||
972 !ReadIndexBssMapping(
Vladimir Markof3c52b42017-11-17 17:32:12 +0000973 this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) {
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100974 return false;
975 }
Vladimir Marko0eb882b2017-05-15 13:39:18 +0100976
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100977 // Create the OatDexFile and add it to the owning container.
David Brazdil3e8aae02019-03-26 18:48:02 +0000978 OatDexFile* oat_dex_file = new OatDexFile(
979 this,
980 dex_file_location,
981 DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
982 dex_file_checksum,
983 dex_file_pointer,
984 lookup_table_data,
985 method_bss_mapping,
986 type_bss_mapping,
Vladimir Marko8f63f102020-09-28 12:10:28 +0100987 public_type_bss_mapping,
988 package_type_bss_mapping,
David Brazdil3e8aae02019-03-26 18:48:02 +0000989 string_bss_mapping,
990 class_offsets_pointer,
991 dex_layout_sections);
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100992 oat_dex_files_storage_.push_back(oat_dex_file);
993
994 // Add the location and canonical location (if different) to the oat_dex_files_ table.
Vladimir Markob7bf8432019-12-03 13:18:50 +0000995 // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
996 // the location and canonical location, GetOatDexFile() shall canonicalize it when
997 // requested and match the canonical path.
998 std::string_view key = oat_dex_file_location; // References oat file data.
David Brazdil3e8aae02019-03-26 18:48:02 +0000999 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
Vladimir Marko539690a2014-06-05 18:36:42 +01001000 oat_dex_files_.Put(key, oat_dex_file);
David Brazdil3e8aae02019-03-26 18:48:02 +00001001 if (canonical_key != key) {
Vladimir Markoaa4497d2014-09-05 14:01:17 +01001002 oat_dex_files_.Put(canonical_key, oat_dex_file);
1003 }
Brian Carlstrome24fa612011-09-29 00:53:55 -07001004 }
Santiago Aboy Solanesb7404382022-02-02 16:00:52 +00001005
1006 size_t bcp_info_offset = GetOatHeader().GetBcpBssInfoOffset();
1007 // `bcp_info_offset` will be 0 for multi-image, or for the case of no mappings.
1008 if (bcp_info_offset != 0) {
1009 // Consistency check.
1010 if (bcp_info_offset < GetOatHeader().GetHeaderSize() || bcp_info_offset > Size()) {
1011 *error_msg = StringPrintf(
1012 "In oat file '%s' found invalid bcp info offset: "
1013 "%zu is not in [%zu, %zu]",
1014 GetLocation().c_str(),
1015 bcp_info_offset,
1016 GetOatHeader().GetHeaderSize(),
1017 Size());
1018 return false;
1019 }
1020 const uint8_t* bcp_info_begin = Begin() + bcp_info_offset; // Jump to the BCP_info records.
1021
1022 uint32_t number_of_bcp_dexfiles;
1023 if (UNLIKELY(!ReadOatDexFileData(*this, &bcp_info_begin, &number_of_bcp_dexfiles))) {
1024 *error_msg = StringPrintf("Failed to read the number of BCP dex files");
1025 return false;
1026 }
1027 Runtime* const runtime = Runtime::Current();
1028 ClassLinker* const linker = runtime != nullptr ? runtime->GetClassLinker() : nullptr;
1029 if (linker != nullptr && UNLIKELY(number_of_bcp_dexfiles > linker->GetBootClassPath().size())) {
1030 // If we compiled with more DexFiles than what we have at runtime, we expect to discard this
1031 // OatFile after verifying its checksum in OatFileAssistant. Therefore, we set
1032 // `number_of_bcp_dexfiles` to 0 to avoid reading data that will ultimately be discarded.
1033 number_of_bcp_dexfiles = 0;
1034 }
1035
1036 DCHECK(bcp_bss_info_.empty());
1037 bcp_bss_info_.resize(number_of_bcp_dexfiles);
1038 // At runtime, there might be more DexFiles added to the BCP that we didn't compile with.
1039 // We only care about the ones in [0..number_of_bcp_dexfiles).
1040 for (size_t i = 0, size = number_of_bcp_dexfiles; i != size; ++i) {
1041 const std::string& dex_file_location = linker != nullptr ?
1042 linker->GetBootClassPath()[i]->GetLocation() :
1043 "No runtime/linker therefore no DexFile location";
1044 if (!ReadIndexBssMapping(this,
1045 &bcp_info_begin,
1046 i,
1047 dex_file_location,
1048 "method",
1049 &bcp_bss_info_[i].method_bss_mapping,
1050 error_msg) ||
1051 !ReadIndexBssMapping(this,
1052 &bcp_info_begin,
1053 i,
1054 dex_file_location,
1055 "type",
1056 &bcp_bss_info_[i].type_bss_mapping,
1057 error_msg) ||
1058 !ReadIndexBssMapping(this,
1059 &bcp_info_begin,
1060 i,
1061 dex_file_location,
1062 "type",
1063 &bcp_bss_info_[i].public_type_bss_mapping,
1064 error_msg) ||
1065 !ReadIndexBssMapping(this,
1066 &bcp_info_begin,
1067 i,
1068 dex_file_location,
1069 "type",
1070 &bcp_bss_info_[i].package_type_bss_mapping,
1071 error_msg) ||
1072 !ReadIndexBssMapping(this,
1073 &bcp_info_begin,
1074 i,
1075 dex_file_location,
1076 "string",
1077 &bcp_bss_info_[i].string_bss_mapping,
1078 error_msg)) {
1079 return false;
1080 }
1081 }
1082 }
1083
Vladimir Markob7bf8432019-12-03 13:18:50 +00001084 if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
1085 *error_msg = StringPrintf("Oat file '%s' contains only %zu primary dex locations, expected %zu",
1086 GetLocation().c_str(),
1087 dex_filenames_pos,
1088 dex_filenames.size());
1089 return false;
1090 }
Vladimir Marko09d09432015-09-08 13:47:48 +01001091
Vladimir Markob066d432018-01-03 13:14:37 +00001092 if (DataBimgRelRoBegin() != nullptr) {
Vladimir Markoe80ecf32019-08-01 15:20:58 +01001093 // Make .data.bimg.rel.ro read only. ClassLinker shall temporarily make it writable for
1094 // relocation when we register a dex file from this oat file. We do not do the relocation
1095 // here to avoid dirtying the pages if the code is never actually ready to be executed.
Vladimir Markob066d432018-01-03 13:14:37 +00001096 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
1097 CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ);
Vladimir Markoe80ecf32019-08-01 15:20:58 +01001098 // Make sure the file lists a boot image dependency, otherwise the .data.bimg.rel.ro
1099 // section is bogus. The full dependency is checked before the code is executed.
Vladimir Marko21910692019-11-06 13:27:03 +00001100 // We cannot do this check if we do not have a key-value store, i.e. for secondary
1101 // oat files for boot image extensions.
1102 if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
1103 const char* boot_class_path_checksum =
1104 GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1105 if (boot_class_path_checksum == nullptr ||
1106 boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
1107 *error_msg = StringPrintf("Oat file '%s' contains .data.bimg.rel.ro section "
1108 "without boot image dependency.",
1109 GetLocation().c_str());
1110 return false;
1111 }
Vladimir Markob066d432018-01-03 13:14:37 +00001112 }
1113 }
1114
Brian Carlstromf1b30302013-03-28 10:35:32 -07001115 return true;
Brian Carlstrome24fa612011-09-29 00:53:55 -07001116}
1117
Andreas Gampe049cff02015-12-01 23:27:12 -08001118////////////////////////
1119// OatFile via dlopen //
1120////////////////////////
1121
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001122class DlOpenOatFile final : public OatFileBase {
Andreas Gampe049cff02015-12-01 23:27:12 -08001123 public:
1124 DlOpenOatFile(const std::string& filename, bool executable)
1125 : OatFileBase(filename, executable),
1126 dlopen_handle_(nullptr),
Richard Uhlera206c742016-05-24 15:04:22 -07001127 shared_objects_before_(0) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001128 }
1129
1130 ~DlOpenOatFile() {
1131 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -07001132 if (!kIsTargetBuild) {
1133 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1134 host_dlopen_handles_.erase(dlopen_handle_);
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -07001135 dlclose(dlopen_handle_);
1136 } else {
1137 dlclose(dlopen_handle_);
Richard Uhlera206c742016-05-24 15:04:22 -07001138 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001139 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001140 }
1141
1142 protected:
1143 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001144 std::string* error_msg) const override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001145 const uint8_t* ptr =
1146 reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1147 if (ptr == nullptr) {
1148 *error_msg = dlerror();
1149 }
1150 return ptr;
1151 }
1152
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001153 void PreLoad() override;
Andreas Gampe4075f832016-05-18 13:09:54 -07001154
Andreas Gampe049cff02015-12-01 23:27:12 -08001155 bool Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001156 bool writable,
1157 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001158 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001159 /*inout*/MemMap* reservation, // Where to load if not null.
1160 /*out*/std::string* error_msg) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001161
Vladimir Markoc09cd052018-08-23 16:36:36 +01001162 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1163 bool writable ATTRIBUTE_UNUSED,
1164 bool executable ATTRIBUTE_UNUSED,
1165 bool low_4gb ATTRIBUTE_UNUSED,
1166 /*inout*/MemMap* reservation ATTRIBUTE_UNUSED,
1167 /*out*/std::string* error_msg ATTRIBUTE_UNUSED) override {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001168 return false;
1169 }
1170
Andreas Gampe049cff02015-12-01 23:27:12 -08001171 // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001172 void PreSetup(const std::string& elf_filename) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001173
1174 private:
1175 bool Dlopen(const std::string& elf_filename,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001176 /*inout*/MemMap* reservation, // Where to load if not null.
1177 /*out*/std::string* error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001178
Richard Uhlera206c742016-05-24 15:04:22 -07001179 // On the host, if the same library is loaded again with dlopen the same
1180 // file handle is returned. This differs from the behavior of dlopen on the
1181 // target, where dlopen reloads the library at a different address every
1182 // time you load it. The runtime relies on the target behavior to ensure
1183 // each instance of the loaded library has a unique dex cache. To avoid
1184 // problems, we fall back to our own linker in the case when the same
1185 // library is opened multiple times on host. dlopen_handles_ is used to
1186 // detect that case.
1187 // Guarded by host_dlopen_handles_lock_;
1188 static std::unordered_set<void*> host_dlopen_handles_;
1189
Vladimir Marko07f78902020-07-27 11:35:12 +00001190 // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
Vladimir Markoc09cd052018-08-23 16:36:36 +01001191 // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1192 std::vector<MemMap> dlopen_mmaps_;
1193
Andreas Gampe049cff02015-12-01 23:27:12 -08001194 // dlopen handle during runtime.
1195 void* dlopen_handle_; // TODO: Unique_ptr with custom deleter.
1196
Andreas Gampe4075f832016-05-18 13:09:54 -07001197 // The number of shared objects the linker told us about before loading. Used to
1198 // (optimistically) optimize the PreSetup stage (see comment there).
1199 size_t shared_objects_before_;
1200
Andreas Gampe049cff02015-12-01 23:27:12 -08001201 DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1202};
1203
Richard Uhlera206c742016-05-24 15:04:22 -07001204std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1205
Andreas Gampe4075f832016-05-18 13:09:54 -07001206void DlOpenOatFile::PreLoad() {
1207#ifdef __APPLE__
Andreas Gampe39004a62016-05-18 21:27:00 -07001208 UNUSED(shared_objects_before_);
Andreas Gampe4075f832016-05-18 13:09:54 -07001209 LOG(FATAL) << "Should not reach here.";
1210 UNREACHABLE();
1211#else
1212 // Count the entries in dl_iterate_phdr we get at this point in time.
1213 struct dl_iterate_context {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001214 static int callback(dl_phdr_info* info ATTRIBUTE_UNUSED,
Andreas Gampe4075f832016-05-18 13:09:54 -07001215 size_t size ATTRIBUTE_UNUSED,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001216 void* data) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001217 reinterpret_cast<dl_iterate_context*>(data)->count++;
1218 return 0; // Continue iteration.
1219 }
1220 size_t count = 0;
1221 } context;
1222
1223 dl_iterate_phdr(dl_iterate_context::callback, &context);
1224 shared_objects_before_ = context.count;
1225#endif
1226}
1227
Andreas Gampe049cff02015-12-01 23:27:12 -08001228bool DlOpenOatFile::Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001229 bool writable,
1230 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001231 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001232 /*inout*/MemMap* reservation, // Where to load if not null.
1233 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001234 // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1235 // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1236 // !executable is a sign that we may want to patch), which may not be allowed for
1237 // various reasons.
1238 if (!kUseDlopen) {
1239 *error_msg = "DlOpen is disabled.";
1240 return false;
1241 }
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001242 if (low_4gb) {
1243 *error_msg = "DlOpen does not support low 4gb loading.";
1244 return false;
1245 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001246 if (writable) {
1247 *error_msg = "DlOpen does not support writable loading.";
1248 return false;
1249 }
1250 if (!executable) {
1251 *error_msg = "DlOpen does not support non-executable loading.";
1252 return false;
1253 }
1254
1255 // dlopen always returns the same library if it is already opened on the host. For this reason
1256 // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1257 // the same library loaded multiple times at different addresses is required for class unloading
1258 // and for having dex caches arrays in the .bss section.
1259 if (!kIsTargetBuild) {
1260 if (!kUseDlopenOnHost) {
1261 *error_msg = "DlOpen disabled for host.";
1262 return false;
1263 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001264 }
1265
Vladimir Markoc09cd052018-08-23 16:36:36 +01001266 bool success = Dlopen(elf_filename, reservation, error_msg);
Santiago Aboy Solanes6cdabe12022-02-18 15:27:43 +00001267 DCHECK_IMPLIES(dlopen_handle_ == nullptr, !success);
Andreas Gampe049cff02015-12-01 23:27:12 -08001268
1269 return success;
1270}
1271
Martin Stjernholm93c28ed2021-05-14 14:11:42 +01001272#ifdef ART_TARGET_ANDROID
1273static struct android_namespace_t* GetSystemLinkerNamespace() {
1274 static struct android_namespace_t* system_ns = []() {
1275 // The system namespace is called "default" for binaries in /system and
1276 // "system" for those in the ART APEX. Try "system" first since "default"
1277 // always exists.
1278 // TODO(b/185587109): Get rid of this error prone logic.
1279 struct android_namespace_t* ns = android_get_exported_namespace("system");
1280 if (ns == nullptr) {
1281 ns = android_get_exported_namespace("default");
1282 if (ns == nullptr) {
1283 LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1284 }
1285 }
1286 return ns;
1287 }();
1288 return system_ns;
1289}
1290#endif // ART_TARGET_ANDROID
1291
Andreas Gampe049cff02015-12-01 23:27:12 -08001292bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001293 /*inout*/MemMap* reservation,
1294 /*out*/std::string* error_msg) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001295#ifdef __APPLE__
1296 // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
1297 // but let's fallback to the custom loading code for the time being.
Vladimir Marko3ec8fb62018-08-31 17:47:38 +01001298 UNUSED(elf_filename, reservation);
Andreas Gampe049cff02015-12-01 23:27:12 -08001299 *error_msg = "Dlopen unsupported on Mac.";
1300 return false;
1301#else
1302 {
1303 UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1304 if (absolute_path == nullptr) {
1305 *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1306 return false;
1307 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +01001308#ifdef ART_TARGET_ANDROID
Anton Kirilov3a2e78e2017-01-06 13:33:42 +00001309 android_dlextinfo extinfo = {};
Vladimir Markof6cfd002018-11-01 16:53:31 +00001310 extinfo.flags = ANDROID_DLEXT_FORCE_LOAD; // Force-load, don't reuse handle
1311 // (open oat files multiple times).
Vladimir Markoc09cd052018-08-23 16:36:36 +01001312 if (reservation != nullptr) {
1313 if (!reservation->IsValid()) {
1314 *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1315 return false;
1316 }
1317 extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS; // Use the reserved memory range.
1318 extinfo.reserved_addr = reservation->Begin();
1319 extinfo.reserved_size = reservation->Size();
1320 }
Martin Stjernholm93c28ed2021-05-14 14:11:42 +01001321
1322 if (strncmp(kAndroidArtApexDefaultPath,
1323 absolute_path.get(),
1324 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1325 absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1326 // Use the system namespace for OAT files outside the ART APEX. Search
1327 // paths and links don't matter here, but permitted paths do, and the
1328 // system namespace is configured to allow loading from all appropriate
1329 // locations.
1330 extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1331 extinfo.library_namespace = GetSystemLinkerNamespace();
1332 }
1333
Andreas Gampe049cff02015-12-01 23:27:12 -08001334 dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001335 if (reservation != nullptr && dlopen_handle_ != nullptr) {
1336 // Find used pages from the reservation.
1337 struct dl_iterate_context {
1338 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
1339 auto* context = reinterpret_cast<dl_iterate_context*>(data);
1340 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1341 using Elf_Half = Elf64_Half;
1342
1343 // See whether this callback corresponds to the file which we have just loaded.
1344 uint8_t* reservation_begin = context->reservation->Begin();
1345 bool contained_in_reservation = false;
1346 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1347 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1348 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1349 info->dlpi_phdr[i].p_vaddr);
1350 size_t memsz = info->dlpi_phdr[i].p_memsz;
1351 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1352 if (offset < context->reservation->Size()) {
1353 contained_in_reservation = true;
1354 DCHECK_LE(memsz, context->reservation->Size() - offset);
1355 } else if (vaddr < reservation_begin) {
1356 // Check that there's no overlap with the reservation.
1357 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1358 }
1359 break; // It is sufficient to check the first PT_LOAD header.
1360 }
1361 }
1362
1363 if (contained_in_reservation) {
1364 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1365 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1366 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1367 info->dlpi_phdr[i].p_vaddr);
1368 size_t memsz = info->dlpi_phdr[i].p_memsz;
1369 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1370 DCHECK_LT(offset, context->reservation->Size());
1371 DCHECK_LE(memsz, context->reservation->Size() - offset);
1372 context->max_size = std::max(context->max_size, offset + memsz);
1373 }
1374 }
1375
1376 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1377 }
1378 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1379 }
1380
1381 const MemMap* const reservation;
1382 size_t max_size = 0u;
1383 };
1384 dl_iterate_context context = { reservation };
1385
1386 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1387 LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1388 UNREACHABLE();
1389 }
1390
1391 // Take ownership of the memory used by the shared object. dlopen() does not assume
1392 // full ownership of this memory and dlclose() shall just remap it as zero pages with
1393 // PROT_NONE. We need to unmap the memory when destroying this oat file.
1394 dlopen_mmaps_.push_back(reservation->TakeReservedMemory(context.max_size));
1395 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001396#else
Steve Austin882ed6b2018-06-08 11:40:38 -07001397 static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1398 "host_dlopen_handles_ will leak handles");
Vladimir Markoc09cd052018-08-23 16:36:36 +01001399 if (reservation != nullptr) {
1400 *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1401 elf_filename.c_str());
1402 return false;
1403 }
Mathieu Chartierc7d3f4b2016-06-01 10:48:19 -07001404 MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
Richard Uhlera206c742016-05-24 15:04:22 -07001405 dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1406 if (dlopen_handle_ != nullptr) {
Richard Uhlera206c742016-05-24 15:04:22 -07001407 if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1408 dlclose(dlopen_handle_);
1409 dlopen_handle_ = nullptr;
1410 *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1411 return false;
1412 }
1413 }
Bilyan Borisovbb661c02016-04-04 16:27:32 +01001414#endif // ART_TARGET_ANDROID
Andreas Gampe049cff02015-12-01 23:27:12 -08001415 }
1416 if (dlopen_handle_ == nullptr) {
1417 *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1418 return false;
1419 }
1420 return true;
1421#endif
1422}
1423
1424void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
Andreas Gampe74f07b52015-12-02 11:53:26 -08001425#ifdef __APPLE__
1426 UNUSED(elf_filename);
1427 LOG(FATAL) << "Should not reach here.";
1428 UNREACHABLE();
1429#else
Vladimir Marko07f78902020-07-27 11:35:12 +00001430 struct PlaceholderMapData {
Vladimir Marko211f9d32020-05-21 16:10:44 +01001431 const char* name;
1432 uint8_t* vaddr;
1433 size_t memsz;
1434 };
Andreas Gampe049cff02015-12-01 23:27:12 -08001435 struct dl_iterate_context {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001436 static int callback(dl_phdr_info* info, size_t size ATTRIBUTE_UNUSED, void* data) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001437 auto* context = reinterpret_cast<dl_iterate_context*>(data);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001438 static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1439 using Elf_Half = Elf64_Half;
1440
Andreas Gampe4075f832016-05-18 13:09:54 -07001441 context->shared_objects_seen++;
1442 if (context->shared_objects_seen < context->shared_objects_before) {
1443 // We haven't been called yet for anything we haven't seen before. Just continue.
1444 // Note: this is aggressively optimistic. If another thread was unloading a library,
1445 // we may miss out here. However, this does not happen often in practice.
1446 return 0;
1447 }
1448
Andreas Gampe049cff02015-12-01 23:27:12 -08001449 // See whether this callback corresponds to the file which we have just loaded.
1450 bool contains_begin = false;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001451 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001452 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1453 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1454 info->dlpi_phdr[i].p_vaddr);
1455 size_t memsz = info->dlpi_phdr[i].p_memsz;
1456 if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1457 contains_begin = true;
1458 break;
1459 }
1460 }
1461 }
Vladimir Marko07f78902020-07-27 11:35:12 +00001462 // Add placeholder mmaps for this file.
Andreas Gampe049cff02015-12-01 23:27:12 -08001463 if (contains_begin) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001464 for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
Andreas Gampe049cff02015-12-01 23:27:12 -08001465 if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1466 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1467 info->dlpi_phdr[i].p_vaddr);
1468 size_t memsz = info->dlpi_phdr[i].p_memsz;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001469 size_t name_size = strlen(info->dlpi_name) + 1u;
Vladimir Marko07f78902020-07-27 11:35:12 +00001470 std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001471 // We must not allocate any memory in the callback, see b/156312036 .
Vladimir Marko07f78902020-07-27 11:35:12 +00001472 if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1473 context->placeholder_maps_data_->size() <
1474 context->placeholder_maps_data_->capacity()) {
1475 placeholder_maps_names->insert(
1476 placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1477 const char* name =
1478 &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1479 context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
Vladimir Marko211f9d32020-05-21 16:10:44 +01001480 }
Vladimir Marko07f78902020-07-27 11:35:12 +00001481 context->num_placeholder_maps_ += 1u;
1482 context->placeholder_maps_names_size_ += name_size;
Andreas Gampe049cff02015-12-01 23:27:12 -08001483 }
1484 }
1485 return 1; // Stop iteration and return 1 from dl_iterate_phdr.
1486 }
1487 return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
1488 }
1489 const uint8_t* const begin_;
Vladimir Marko07f78902020-07-27 11:35:12 +00001490 std::vector<PlaceholderMapData>* placeholder_maps_data_;
1491 size_t num_placeholder_maps_;
1492 std::vector<char>* placeholder_maps_names_;
1493 size_t placeholder_maps_names_size_;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001494 size_t shared_objects_before;
Andreas Gampe4075f832016-05-18 13:09:54 -07001495 size_t shared_objects_seen;
1496 };
Vladimir Marko211f9d32020-05-21 16:10:44 +01001497
1498 // We must not allocate any memory in the callback, see b/156312036 .
Vladimir Marko07f78902020-07-27 11:35:12 +00001499 // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1500 std::vector<PlaceholderMapData> placeholder_maps_data;
1501 placeholder_maps_data.reserve(32); // 32 should be enough. If not, we'll retry.
1502 std::vector<char> placeholder_maps_names;
1503 placeholder_maps_names.reserve(4 * KB); // 4KiB should be enough. If not, we'll retry.
Vladimir Marko211f9d32020-05-21 16:10:44 +01001504
1505 dl_iterate_context context = {
1506 Begin(),
Vladimir Marko07f78902020-07-27 11:35:12 +00001507 &placeholder_maps_data,
1508 /*num_placeholder_maps_*/ 0u,
1509 &placeholder_maps_names,
1510 /*placeholder_maps_names_size_*/ 0u,
Vladimir Marko211f9d32020-05-21 16:10:44 +01001511 shared_objects_before_,
1512 /*shared_objects_seen*/ 0u
1513 };
Andreas Gampe049cff02015-12-01 23:27:12 -08001514
1515 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001516 // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1517 // before giving up. This should be unusual.
1518 VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1519 << shared_objects_before_;
Vladimir Marko07f78902020-07-27 11:35:12 +00001520 DCHECK(placeholder_maps_data.empty());
1521 DCHECK_EQ(context.num_placeholder_maps_, 0u);
1522 DCHECK(placeholder_maps_names.empty());
1523 DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
Vladimir Marko211f9d32020-05-21 16:10:44 +01001524 context.shared_objects_before = 0u;
1525 context.shared_objects_seen = 0u;
1526 if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
Andreas Gampe4075f832016-05-18 13:09:54 -07001527 // OK, give up and print an error.
Andreas Gampe170331f2017-12-07 18:41:03 -08001528 PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
Andreas Gampe4075f832016-05-18 13:09:54 -07001529 LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1530 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001531 }
Vladimir Marko211f9d32020-05-21 16:10:44 +01001532
Vladimir Marko07f78902020-07-27 11:35:12 +00001533 if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
Vladimir Marko211f9d32020-05-21 16:10:44 +01001534 // Insufficient capacity. Reserve more space and retry.
Vladimir Marko07f78902020-07-27 11:35:12 +00001535 placeholder_maps_data.clear();
1536 placeholder_maps_data.reserve(context.num_placeholder_maps_);
1537 context.num_placeholder_maps_ = 0u;
1538 placeholder_maps_names.clear();
1539 placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1540 context.placeholder_maps_names_size_ = 0u;
Vladimir Marko211f9d32020-05-21 16:10:44 +01001541 context.shared_objects_before = 0u;
1542 context.shared_objects_seen = 0u;
1543 bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1544 CHECK(success);
1545 }
1546
Vladimir Marko07f78902020-07-27 11:35:12 +00001547 CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1548 CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1549 DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1550 placeholder_maps_names.end(), '\0')),
1551 context.num_placeholder_maps_);
1552 for (const PlaceholderMapData& data : placeholder_maps_data) {
1553 MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
Vladimir Marko211f9d32020-05-21 16:10:44 +01001554 dlopen_mmaps_.push_back(std::move(mmap));
1555 }
Andreas Gampe74f07b52015-12-02 11:53:26 -08001556#endif
Andreas Gampe049cff02015-12-01 23:27:12 -08001557}
1558
1559////////////////////////////////////////////////
1560// OatFile via our own ElfFile implementation //
1561////////////////////////////////////////////////
1562
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001563class ElfOatFile final : public OatFileBase {
Andreas Gampe049cff02015-12-01 23:27:12 -08001564 public:
1565 ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1566
Nicolas Geoffray30025092018-04-19 14:43:29 +01001567 bool InitializeFromElfFile(int zip_fd,
1568 ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001569 VdexFile* vdex_file,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001570 ArrayRef<const std::string> dex_filenames,
Andreas Gampe049cff02015-12-01 23:27:12 -08001571 std::string* error_msg);
1572
1573 protected:
1574 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001575 std::string* error_msg) const override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001576 const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1577 if (ptr == nullptr) {
1578 *error_msg = "(Internal implementation could not find symbol)";
1579 }
1580 return ptr;
1581 }
1582
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001583 void PreLoad() override {
Andreas Gampe4075f832016-05-18 13:09:54 -07001584 }
1585
Andreas Gampe049cff02015-12-01 23:27:12 -08001586 bool Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001587 bool writable,
1588 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001589 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001590 /*inout*/MemMap* reservation, // Where to load if not null.
1591 /*out*/std::string* error_msg) override;
Andreas Gampe049cff02015-12-01 23:27:12 -08001592
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001593 bool Load(int oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001594 bool writable,
1595 bool executable,
1596 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001597 /*inout*/MemMap* reservation, // Where to load if not null.
1598 /*out*/std::string* error_msg) override;
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001599
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001600 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {
Andreas Gampe049cff02015-12-01 23:27:12 -08001601 }
1602
1603 private:
1604 bool ElfFileOpen(File* file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001605 bool writable,
1606 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001607 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001608 /*inout*/MemMap* reservation, // Where to load if not null.
1609 /*out*/std::string* error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001610
1611 private:
1612 // Backing memory map for oat file during cross compilation.
1613 std::unique_ptr<ElfFile> elf_file_;
1614
1615 DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1616};
1617
Nicolas Geoffray30025092018-04-19 14:43:29 +01001618bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1619 ElfFile* elf_file,
David Brazdilc93b3be2016-09-12 18:49:58 +01001620 VdexFile* vdex_file,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001621 ArrayRef<const std::string> dex_filenames,
Andreas Gampe049cff02015-12-01 23:27:12 -08001622 std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001623 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001624 if (IsExecutable()) {
1625 *error_msg = "Cannot initialize from elf file in executable mode.";
1626 return false;
1627 }
1628 elf_file_.reset(elf_file);
David Brazdilc93b3be2016-09-12 18:49:58 +01001629 SetVdex(vdex_file);
Andreas Gampe049cff02015-12-01 23:27:12 -08001630 uint64_t offset, size;
1631 bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1632 CHECK(has_section);
1633 SetBegin(elf_file->Begin() + offset);
1634 SetEnd(elf_file->Begin() + size + offset);
1635 // Ignore the optional .bss section when opening non-executable.
Victor Hsiehf667c332021-05-27 11:35:44 -07001636 return Setup(zip_fd, dex_filenames, /*dex_fds=*/ArrayRef<const int>(), error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001637}
1638
1639bool ElfOatFile::Load(const std::string& elf_filename,
Andreas Gampe049cff02015-12-01 23:27:12 -08001640 bool writable,
1641 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001642 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001643 /*inout*/MemMap* reservation,
1644 /*out*/std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001645 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001646 std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1647 if (file == nullptr) {
1648 *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1649 return false;
1650 }
1651 return ElfOatFile::ElfFileOpen(file.get(),
Andreas Gampe049cff02015-12-01 23:27:12 -08001652 writable,
1653 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001654 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001655 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001656 error_msg);
1657}
1658
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001659bool ElfOatFile::Load(int oat_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001660 bool writable,
1661 bool executable,
1662 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001663 /*inout*/MemMap* reservation,
1664 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001665 ScopedTrace trace(__PRETTY_FUNCTION__);
1666 if (oat_fd != -1) {
Josh Gaoafeec9f2018-08-30 14:05:56 -07001667 int duped_fd = DupCloexec(oat_fd);
1668 std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001669 if (file == nullptr) {
1670 *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1671 strerror(errno));
1672 return false;
1673 }
1674 return ElfOatFile::ElfFileOpen(file.get(),
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001675 writable,
1676 executable,
1677 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001678 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001679 error_msg);
1680 }
1681 return false;
1682}
1683
Andreas Gampe049cff02015-12-01 23:27:12 -08001684bool ElfOatFile::ElfFileOpen(File* file,
Andreas Gampe049cff02015-12-01 23:27:12 -08001685 bool writable,
1686 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001687 bool low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001688 /*inout*/MemMap* reservation,
1689 /*out*/std::string* error_msg) {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08001690 ScopedTrace trace(__PRETTY_FUNCTION__);
Andreas Gampe049cff02015-12-01 23:27:12 -08001691 elf_file_.reset(ElfFile::Open(file,
1692 writable,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001693 /*program_header_only=*/ true,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001694 low_4gb,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001695 error_msg));
Andreas Gampe049cff02015-12-01 23:27:12 -08001696 if (elf_file_ == nullptr) {
1697 DCHECK(!error_msg->empty());
1698 return false;
1699 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001700 bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
Andreas Gampe049cff02015-12-01 23:27:12 -08001701 DCHECK(loaded || !error_msg->empty());
1702 return loaded;
1703}
1704
David Brazdil7126c5b2019-03-05 00:02:51 +00001705class OatFileBackedByVdex final : public OatFileBase {
1706 public:
1707 explicit OatFileBackedByVdex(const std::string& filename)
1708 : OatFileBase(filename, /*executable=*/ false) {}
1709
1710 static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1711 std::unique_ptr<VdexFile>&& vdex_file,
1712 const std::string& location) {
1713 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001714 // SetVdex will take ownership of the VdexFile.
1715 oat_file->SetVdex(vdex_file.release());
1716 oat_file->SetupHeader(dex_files.size());
1717 // Initialize OatDexFiles.
Nicolas Geoffraya74a7072021-09-09 17:06:46 +01001718 std::string error_msg;
1719 if (!oat_file->Setup(dex_files, &error_msg)) {
1720 LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
1721 return nullptr;
1722 }
David Brazdil7126c5b2019-03-05 00:02:51 +00001723 return oat_file.release();
1724 }
1725
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001726 static OatFileBackedByVdex* Open(int zip_fd,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001727 std::unique_ptr<VdexFile>&& unique_vdex_file,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001728 const std::string& dex_location,
1729 std::string* error_msg) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001730 VdexFile* vdex_file = unique_vdex_file.get();
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001731 std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001732 // SetVdex will take ownership of the VdexFile.
1733 oat_file->SetVdex(unique_vdex_file.release());
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001734 if (vdex_file->HasDexSection()) {
1735 uint32_t i = 0;
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001736 const uint8_t* type_lookup_table_start = nullptr;
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +00001737 for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001738 dex_file_start != nullptr;
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +00001739 dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
Nicolas Geoffraya74a7072021-09-09 17:06:46 +01001740 const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
1741 if (UNLIKELY(!vdex_file->Contains(dex_file_start))) {
1742 *error_msg =
1743 StringPrintf("In vdex file '%s' found invalid dex file pointer %p not in [%p, %p]",
1744 dex_location.c_str(),
1745 dex_file_start,
1746 vdex_file->Begin(),
1747 vdex_file->End());
1748 return nullptr;
1749 }
1750 if (UNLIKELY(!vdex_file->Contains(dex_file_start + header->file_size_ - 1))) {
1751 *error_msg =
1752 StringPrintf("In vdex file '%s' found overflowing dex file %p not in [%p, %p]",
1753 dex_location.c_str(),
1754 dex_file_start + header->file_size_,
1755 vdex_file->Begin(),
1756 vdex_file->End());
1757 return nullptr;
1758 }
Nicolas Geoffrayf5690ca2021-06-16 14:27:34 +01001759 if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1760 *error_msg =
1761 StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1762 dex_location.c_str());
1763 return nullptr;
1764 }
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001765 // Create the OatDexFile and add it to the owning container.
1766 std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1767 std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001768 type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1769 const uint8_t* type_lookup_table_data = nullptr;
Nicolas Geoffraya74a7072021-09-09 17:06:46 +01001770 if (!ComputeAndCheckTypeLookupTableData(*header,
1771 type_lookup_table_start,
1772 vdex_file,
1773 &type_lookup_table_data,
1774 error_msg)) {
1775 return nullptr;
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001776 }
Nicolas Geoffraya74a7072021-09-09 17:06:46 +01001777
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001778 OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1779 dex_file_start,
1780 vdex_file->GetLocationChecksum(i),
1781 location,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00001782 canonical_location,
1783 type_lookup_table_data);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001784 oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1785
1786 std::string_view key(oat_dex_file->GetDexFileLocation());
1787 oat_file->oat_dex_files_.Put(key, oat_dex_file);
1788 if (canonical_location != location) {
1789 std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1790 oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1791 }
1792 }
1793 oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size());
1794 } else {
1795 // No need for any verification when loading dex files as we already have
1796 // a vdex file.
1797 const ArtDexFileLoader dex_file_loader;
1798 bool loaded = false;
1799 if (zip_fd != -1) {
1800 loaded = dex_file_loader.OpenZip(zip_fd,
1801 dex_location,
1802 /*verify=*/ false,
1803 /*verify_checksum=*/ false,
1804 error_msg,
1805 &oat_file->external_dex_files_);
1806 } else {
1807 loaded = dex_file_loader.Open(dex_location.c_str(),
1808 dex_location,
1809 /*verify=*/ false,
1810 /*verify_checksum=*/ false,
1811 error_msg,
1812 &oat_file->external_dex_files_);
1813 }
1814 if (!loaded) {
1815 return nullptr;
1816 }
1817 oat_file->SetupHeader(oat_file->external_dex_files_.size());
Nicolas Geoffraya74a7072021-09-09 17:06:46 +01001818 if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
1819 return nullptr;
1820 }
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001821 }
David Brazdil7126c5b2019-03-05 00:02:51 +00001822
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001823 return oat_file.release();
1824 }
1825
1826 void SetupHeader(size_t number_of_dex_files) {
1827 DCHECK(!IsExecutable());
David Brazdil7126c5b2019-03-05 00:02:51 +00001828
Nicolas Geoffrayb17c9082021-07-07 08:27:45 +01001829 // Create a fake OatHeader with a key store to help debugging.
David Brazdil7126c5b2019-03-05 00:02:51 +00001830 std::unique_ptr<const InstructionSetFeatures> isa_features =
1831 InstructionSetFeatures::FromCppDefines();
Nicolas Geoffraydee09f92019-10-23 15:18:20 +01001832 SafeMap<std::string, std::string> store;
1833 store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
Nicolas Geoffrayb17c9082021-07-07 08:27:45 +01001834 store.Put(OatHeader::kCompilationReasonKey, "vdex");
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001835 store.Put(OatHeader::kConcurrentCopying,
1836 kUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
David Brazdil7126c5b2019-03-05 00:02:51 +00001837 oat_header_.reset(OatHeader::Create(kRuntimeISA,
1838 isa_features.get(),
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001839 number_of_dex_files,
Nicolas Geoffraydee09f92019-10-23 15:18:20 +01001840 &store));
David Brazdil7126c5b2019-03-05 00:02:51 +00001841 const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1842 SetBegin(begin);
1843 SetEnd(begin + oat_header_->GetHeaderSize());
David Brazdil7126c5b2019-03-05 00:02:51 +00001844 }
1845
1846 protected:
1847 void PreLoad() override {}
1848
1849 bool Load(const std::string& elf_filename ATTRIBUTE_UNUSED,
1850 bool writable ATTRIBUTE_UNUSED,
1851 bool executable ATTRIBUTE_UNUSED,
1852 bool low_4gb ATTRIBUTE_UNUSED,
1853 MemMap* reservation ATTRIBUTE_UNUSED,
1854 std::string* error_msg ATTRIBUTE_UNUSED) override {
1855 LOG(FATAL) << "Unsupported";
1856 UNREACHABLE();
1857 }
1858
1859 bool Load(int oat_fd ATTRIBUTE_UNUSED,
1860 bool writable ATTRIBUTE_UNUSED,
1861 bool executable ATTRIBUTE_UNUSED,
1862 bool low_4gb ATTRIBUTE_UNUSED,
1863 MemMap* reservation ATTRIBUTE_UNUSED,
1864 std::string* error_msg ATTRIBUTE_UNUSED) override {
1865 LOG(FATAL) << "Unsupported";
1866 UNREACHABLE();
1867 }
1868
1869 void PreSetup(const std::string& elf_filename ATTRIBUTE_UNUSED) override {}
1870
1871 const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name ATTRIBUTE_UNUSED,
1872 std::string* error_msg) const override {
1873 *error_msg = "Unsupported";
1874 return nullptr;
1875 }
1876
1877 private:
1878 std::unique_ptr<OatHeader> oat_header_;
David Brazdil7126c5b2019-03-05 00:02:51 +00001879
1880 DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1881};
1882
Andreas Gampe049cff02015-12-01 23:27:12 -08001883//////////////////////////
1884// General OatFile code //
1885//////////////////////////
1886
Andreas Gampe049cff02015-12-01 23:27:12 -08001887static void CheckLocation(const std::string& location) {
1888 CHECK(!location.empty());
1889}
1890
Nicolas Geoffray30025092018-04-19 14:43:29 +01001891OatFile* OatFile::Open(int zip_fd,
1892 const std::string& oat_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001893 const std::string& oat_location,
Andreas Gampe049cff02015-12-01 23:27:12 -08001894 bool executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001895 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001896 ArrayRef<const std::string> dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001897 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001898 /*inout*/MemMap* reservation,
1899 /*out*/std::string* error_msg) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001900 ScopedTrace trace("Open oat file " + oat_location);
1901 CHECK(!oat_filename.empty()) << oat_location;
1902 CheckLocation(oat_location);
Andreas Gampe54315c72016-05-18 21:10:42 -07001903
Calin Juravle367b9d82017-05-15 18:18:39 -07001904 std::string vdex_filename = GetVdexFilename(oat_filename);
David Brazdil7b49e6c2016-09-01 11:06:18 +01001905
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001906 // Check that the vdex file even exists, fast-fail. We don't check the odex
1907 // file as we use the absence of an odex file for test the functionality of
1908 // vdex-only.
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00001909 if (!OS::FileExists(vdex_filename.c_str())) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001910 *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1911 return nullptr;
Andreas Gampe54315c72016-05-18 21:10:42 -07001912 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001913
1914 // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1915 // disabled.
Nicolas Geoffray30025092018-04-19 14:43:29 +01001916 OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1917 vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001918 oat_filename,
1919 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001920 /*writable=*/ false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001921 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001922 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001923 dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001924 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001925 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001926 error_msg);
1927 if (with_dlopen != nullptr) {
Jagadeesh Pakaravoor06541532021-02-22 21:19:09 -08001928 Runtime* runtime = Runtime::Current();
1929 // The runtime might not be available at this point if we're running
1930 // dex2oat or oatdump.
1931 if (runtime != nullptr) {
1932 size_t madvise_size_limit = runtime->GetMadviseWillNeedSizeOdex();
1933 Runtime::MadviseFileForRange(madvise_size_limit,
1934 with_dlopen->Size(),
1935 with_dlopen->Begin(),
1936 with_dlopen->End(),
1937 oat_location);
1938 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001939 return with_dlopen;
1940 }
1941 if (kPrintDlOpenErrorMessage) {
David Brazdil7b49e6c2016-09-01 11:06:18 +01001942 LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
Andreas Gampe049cff02015-12-01 23:27:12 -08001943 }
Andreas Gampe049cff02015-12-01 23:27:12 -08001944 // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1945 //
1946 // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1947 //
1948 // We use our own ELF loader for Quick to deal with legacy apps that
1949 // open a generated dex file by name, remove the file, then open
1950 // another generated dex file with the same name. http://b/10614658
1951 //
Vladimir Marko13fcc3e2020-01-24 12:40:56 +00001952 // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
Andreas Gampe049cff02015-12-01 23:27:12 -08001953 //
1954 //
1955 // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1956 // 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 +01001957 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1958 vdex_filename,
David Brazdil7b49e6c2016-09-01 11:06:18 +01001959 oat_filename,
1960 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001961 /*writable=*/ false,
Andreas Gampe049cff02015-12-01 23:27:12 -08001962 executable,
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -08001963 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001964 dex_filenames,
Victor Hsiehf667c332021-05-27 11:35:44 -07001965 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001966 reservation,
Andreas Gampe049cff02015-12-01 23:27:12 -08001967 error_msg);
1968 return with_internal;
1969}
1970
Nicolas Geoffray30025092018-04-19 14:43:29 +01001971OatFile* OatFile::Open(int zip_fd,
1972 int vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001973 int oat_fd,
1974 const std::string& oat_location,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001975 bool executable,
1976 bool low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001977 ArrayRef<const std::string> dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -07001978 ArrayRef<const int> dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001979 /*inout*/MemMap* reservation,
1980 /*out*/std::string* error_msg) {
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001981 CHECK(!oat_location.empty()) << oat_location;
1982
1983 std::string vdex_location = GetVdexFilename(oat_location);
1984
Nicolas Geoffray30025092018-04-19 14:43:29 +01001985 OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1986 vdex_fd,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001987 oat_fd,
1988 vdex_location,
1989 oat_location,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001990 /*writable=*/ false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001991 executable,
1992 low_4gb,
Vladimir Markob7bf8432019-12-03 13:18:50 +00001993 dex_filenames,
Victor Hsiehce9b9022021-07-21 10:44:06 -07001994 dex_fds,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001995 reservation,
Shubham Ajmerab22dea02017-10-04 18:36:41 -07001996 error_msg);
1997 return with_internal;
1998}
1999
David Brazdil7126c5b2019-03-05 00:02:51 +00002000OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
2001 std::unique_ptr<VdexFile>&& vdex_file,
2002 const std::string& location) {
2003 CheckLocation(location);
2004 return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location);
2005}
2006
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002007OatFile* OatFile::OpenFromVdex(int zip_fd,
2008 std::unique_ptr<VdexFile>&& vdex_file,
2009 const std::string& location,
2010 std::string* error_msg) {
2011 CheckLocation(location);
2012 return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, error_msg);
2013}
2014
Andreas Gampe049cff02015-12-01 23:27:12 -08002015OatFile::OatFile(const std::string& location, bool is_executable)
2016 : location_(location),
David Brazdil7b49e6c2016-09-01 11:06:18 +01002017 vdex_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08002018 begin_(nullptr),
2019 end_(nullptr),
Vladimir Markob066d432018-01-03 13:14:37 +00002020 data_bimg_rel_ro_begin_(nullptr),
2021 data_bimg_rel_ro_end_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08002022 bss_begin_(nullptr),
2023 bss_end_(nullptr),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01002024 bss_methods_(nullptr),
Vladimir Markoaad75c62016-10-03 08:46:48 +00002025 bss_roots_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08002026 is_executable_(is_executable),
David Srbeckyec2cdf42017-12-08 16:21:25 +00002027 vdex_begin_(nullptr),
2028 vdex_end_(nullptr),
Andreas Gampe049cff02015-12-01 23:27:12 -08002029 secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
2030 CHECK(!location_.empty());
2031}
2032
2033OatFile::~OatFile() {
2034 STLDeleteElements(&oat_dex_files_storage_);
2035}
2036
Brian Carlstrome24fa612011-09-29 00:53:55 -07002037const OatHeader& OatFile::GetOatHeader() const {
Ian Rogers30fab402012-01-23 15:43:46 -08002038 return *reinterpret_cast<const OatHeader*>(Begin());
Brian Carlstrome24fa612011-09-29 00:53:55 -07002039}
2040
Ian Rogers13735952014-10-08 12:43:28 -07002041const uint8_t* OatFile::Begin() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07002042 CHECK(begin_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08002043 return begin_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07002044}
2045
Ian Rogers13735952014-10-08 12:43:28 -07002046const uint8_t* OatFile::End() const {
Andreas Gampefa8429b2015-04-07 18:34:42 -07002047 CHECK(end_ != nullptr);
Brian Carlstrom700c8d32012-11-05 10:42:02 -08002048 return end_;
Brian Carlstrome24fa612011-09-29 00:53:55 -07002049}
2050
David Brazdil7b49e6c2016-09-01 11:06:18 +01002051const uint8_t* OatFile::DexBegin() const {
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00002052 return vdex_->Begin();
David Brazdil7b49e6c2016-09-01 11:06:18 +01002053}
2054
2055const uint8_t* OatFile::DexEnd() const {
Nicolas Geoffray8eaa8e52017-11-13 17:47:50 +00002056 return vdex_->End();
David Brazdil7b49e6c2016-09-01 11:06:18 +01002057}
2058
Vladimir Markob066d432018-01-03 13:14:37 +00002059ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
2060 if (data_bimg_rel_ro_begin_ != nullptr) {
2061 const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_);
2062 const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_);
2063 return ArrayRef<const uint32_t>(relocations, relocations_end - relocations);
2064 } else {
2065 return ArrayRef<const uint32_t>();
2066 }
2067}
2068
Vladimir Marko0eb882b2017-05-15 13:39:18 +01002069ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
2070 if (bss_methods_ != nullptr) {
2071 ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
2072 ArtMethod** methods_end =
2073 reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
2074 return ArrayRef<ArtMethod*>(methods, methods_end - methods);
2075 } else {
2076 return ArrayRef<ArtMethod*>();
2077 }
2078}
2079
Vladimir Markoaad75c62016-10-03 08:46:48 +00002080ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
2081 if (bss_roots_ != nullptr) {
2082 auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
2083 auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
2084 return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
2085 } else {
2086 return ArrayRef<GcRoot<mirror::Object>>();
2087 }
2088}
2089
Andreas Gampeb40d3612018-06-26 15:49:42 -07002090const OatDexFile* OatFile::GetOatDexFile(const char* dex_location,
2091 const uint32_t* dex_location_checksum,
2092 std::string* error_msg) const {
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002093 // NOTE: We assume here that the canonical location for a given dex_location never
2094 // changes. If it does (i.e. some symlink used by the filename changes) we may return
2095 // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
2096 // an identical file or fail; otherwise we may see some unpredictable failures.
Calin Juravle4e1d5792014-07-15 23:56:47 +01002097
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002098 // TODO: Additional analysis of usage patterns to see if this can be simplified
2099 // without any performance loss, for example by not doing the first lock-free lookup.
2100
Andreas Gampeb40d3612018-06-26 15:49:42 -07002101 const OatDexFile* oat_dex_file = nullptr;
Vladimir Marko59ae4f92019-02-04 14:06:02 +00002102 std::string_view key(dex_location);
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002103 // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
2104 // directly mentioned in the oat file and doesn't require locking.
2105 auto primary_it = oat_dex_files_.find(key);
2106 if (primary_it != oat_dex_files_.end()) {
2107 oat_dex_file = primary_it->second;
2108 DCHECK(oat_dex_file != nullptr);
2109 } else {
2110 // This dex_location is not one of the dex locations directly mentioned in the
2111 // oat file. The correct lookup is via the canonical location but first see in
2112 // the secondary_oat_dex_files_ whether we've looked up this location before.
2113 MutexLock mu(Thread::Current(), secondary_lookup_lock_);
2114 auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
2115 if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002116 oat_dex_file = secondary_lb->second; // May be null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002117 } else {
2118 // We haven't seen this dex_location before, we must check the canonical location.
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002119 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Vladimir Markoaa4497d2014-09-05 14:01:17 +01002120 if (dex_canonical_location != dex_location) {
Vladimir Marko59ae4f92019-02-04 14:06:02 +00002121 std::string_view canonical_key(dex_canonical_location);
Vladimir Markoaa4497d2014-09-05 14:01:17 +01002122 auto canonical_it = oat_dex_files_.find(canonical_key);
2123 if (canonical_it != oat_dex_files_.end()) {
2124 oat_dex_file = canonical_it->second;
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002125 } // else keep null.
2126 } // else keep null.
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002127
2128 // Copy the key to the string_cache_ and store the result in secondary map.
2129 string_cache_.emplace_back(key.data(), key.length());
Vladimir Marko59ae4f92019-02-04 14:06:02 +00002130 std::string_view key_copy(string_cache_.back());
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002131 secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07002132 }
2133 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07002134
2135 if (oat_dex_file == nullptr) {
2136 if (error_msg != nullptr) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002137 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -07002138 *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
2139 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
2140 }
2141 return nullptr;
Vladimir Marko3f5838d2014-08-07 18:07:18 +01002142 }
Brian Carlstrom756ee4e2013-10-03 15:46:12 -07002143
Richard Uhler9a37efc2016-08-05 16:32:55 -07002144 if (dex_location_checksum != nullptr &&
2145 oat_dex_file->GetDexFileLocationChecksum() != *dex_location_checksum) {
2146 if (error_msg != nullptr) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002147 std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -07002148 std::string checksum = StringPrintf("0x%08x", oat_dex_file->GetDexFileLocationChecksum());
2149 std::string required_checksum = StringPrintf("0x%08x", *dex_location_checksum);
2150 *error_msg = "OatDexFile for DexFile " + std::string(dex_location)
2151 + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation()
2152 + " has checksum " + checksum + " but " + required_checksum + " was required";
Brian Carlstrom0d6adac2014-02-05 17:39:16 -08002153 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07002154 return nullptr;
Brian Carlstrome24fa612011-09-29 00:53:55 -07002155 }
Richard Uhler9a37efc2016-08-05 16:32:55 -07002156 return oat_dex_file;
Brian Carlstromaded5f72011-10-07 17:15:04 -07002157}
2158
Andreas Gampeb40d3612018-06-26 15:49:42 -07002159OatDexFile::OatDexFile(const OatFile* oat_file,
2160 const std::string& dex_file_location,
2161 const std::string& canonical_dex_file_location,
2162 uint32_t dex_file_location_checksum,
2163 const uint8_t* dex_file_pointer,
2164 const uint8_t* lookup_table_data,
2165 const IndexBssMapping* method_bss_mapping_data,
2166 const IndexBssMapping* type_bss_mapping_data,
Vladimir Marko8f63f102020-09-28 12:10:28 +01002167 const IndexBssMapping* public_type_bss_mapping_data,
2168 const IndexBssMapping* package_type_bss_mapping_data,
Andreas Gampeb40d3612018-06-26 15:49:42 -07002169 const IndexBssMapping* string_bss_mapping_data,
2170 const uint32_t* oat_class_offsets_pointer,
2171 const DexLayoutSections* dex_layout_sections)
Brian Carlstrome24fa612011-09-29 00:53:55 -07002172 : oat_file_(oat_file),
2173 dex_file_location_(dex_file_location),
Vladimir Markoaa4497d2014-09-05 14:01:17 +01002174 canonical_dex_file_location_(canonical_dex_file_location),
Brian Carlstrom5b332c82012-02-01 15:02:31 -08002175 dex_file_location_checksum_(dex_file_location_checksum),
Brian Carlstrom89521892011-12-07 22:05:07 -08002176 dex_file_pointer_(dex_file_pointer),
Artem Udovichenkod9786b02015-10-14 16:36:55 +03002177 lookup_table_data_(lookup_table_data),
Vladimir Marko0eb882b2017-05-15 13:39:18 +01002178 method_bss_mapping_(method_bss_mapping_data),
Vladimir Markof3c52b42017-11-17 17:32:12 +00002179 type_bss_mapping_(type_bss_mapping_data),
Vladimir Marko8f63f102020-09-28 12:10:28 +01002180 public_type_bss_mapping_(public_type_bss_mapping_data),
2181 package_type_bss_mapping_(package_type_bss_mapping_data),
Vladimir Markof3c52b42017-11-17 17:32:12 +00002182 string_bss_mapping_(string_bss_mapping_data),
Vladimir Marko09d09432015-09-08 13:47:48 +01002183 oat_class_offsets_pointer_(oat_class_offsets_pointer),
Vladimir Markoea341d22018-05-11 10:33:37 +01002184 lookup_table_(),
Mathieu Chartier120aa282017-08-05 16:03:03 -07002185 dex_layout_sections_(dex_layout_sections) {
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002186 InitializeTypeLookupTable();
2187 DCHECK(!IsBackedByVdexOnly());
2188}
2189
2190void OatDexFile::InitializeTypeLookupTable() {
David Sehr9aa352e2016-09-15 18:13:52 -07002191 // Initialize TypeLookupTable.
2192 if (lookup_table_data_ != nullptr) {
2193 // Peek the number of classes from the DexFile.
2194 const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2195 const uint32_t num_class_defs = dex_header->class_defs_size_;
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002196 if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2197 GetOatFile()->DexEnd()) {
David Sehr9aa352e2016-09-15 18:13:52 -07002198 LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2199 } else {
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002200 const uint8_t* dex_data = dex_file_pointer_;
2201 // TODO: Clean this up to create the type lookup table after the dex file has been created?
2202 if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2203 dex_data += dex_header->data_off_;
2204 }
2205 lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
David Sehr9aa352e2016-09-15 18:13:52 -07002206 }
2207 }
David Brazdil7126c5b2019-03-05 00:02:51 +00002208}
2209
2210OatDexFile::OatDexFile(const OatFile* oat_file,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002211 const uint8_t* dex_file_pointer,
2212 uint32_t dex_file_location_checksum,
David Brazdil7126c5b2019-03-05 00:02:51 +00002213 const std::string& dex_file_location,
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002214 const std::string& canonical_dex_file_location,
2215 const uint8_t* lookup_table_data)
David Brazdil7126c5b2019-03-05 00:02:51 +00002216 : oat_file_(oat_file),
2217 dex_file_location_(dex_file_location),
2218 canonical_dex_file_location_(canonical_dex_file_location),
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002219 dex_file_location_checksum_(dex_file_location_checksum),
Nicolas Geoffray0b943282021-04-16 09:16:00 +00002220 dex_file_pointer_(dex_file_pointer),
2221 lookup_table_data_(lookup_table_data) {
2222 InitializeTypeLookupTable();
David Brazdil7126c5b2019-03-05 00:02:51 +00002223 DCHECK(IsBackedByVdexOnly());
David Sehr9aa352e2016-09-15 18:13:52 -07002224}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002225
Andreas Gampe875b4f22018-11-19 12:59:15 -08002226OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
David Srbeckyb5649f92019-05-14 15:27:52 +01002227 // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
Nicolas Geoffraydc2fbb62019-04-11 22:55:50 +01002228 CHECK(Runtime::Current() == nullptr ||
2229 Runtime::Current()->IsAotCompiler() ||
David Srbeckyb5649f92019-05-14 15:27:52 +01002230 Runtime::Current()->IsZygote() ||
2231 Runtime::Current()->IsSystemServer());
Andreas Gampe875b4f22018-11-19 12:59:15 -08002232}
Mathieu Chartier1b868492016-11-16 16:22:37 -08002233
Andreas Gampeb40d3612018-06-26 15:49:42 -07002234OatDexFile::~OatDexFile() {}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002235
Andreas Gampeb40d3612018-06-26 15:49:42 -07002236size_t OatDexFile::FileSize() const {
Andreas Gampe875b4f22018-11-19 12:59:15 -08002237 DCHECK(dex_file_pointer_ != nullptr);
Ian Rogers05f28c62012-10-23 18:12:13 -07002238 return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2239}
2240
Andreas Gampeb40d3612018-06-26 15:49:42 -07002241std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -08002242 ScopedTrace trace(__PRETTY_FUNCTION__);
Aart Bik37d6a3b2016-06-21 18:30:10 -07002243 static constexpr bool kVerify = false;
2244 static constexpr bool kVerifyChecksum = false;
David Sehr013fd802018-01-11 22:55:24 -08002245 const ArtDexFileLoader dex_file_loader;
2246 return dex_file_loader.Open(dex_file_pointer_,
2247 FileSize(),
2248 dex_file_location_,
2249 dex_file_location_checksum_,
2250 this,
2251 kVerify,
2252 kVerifyChecksum,
2253 error_msg);
Brian Carlstrom89521892011-12-07 22:05:07 -08002254}
2255
Andreas Gampeb40d3612018-06-26 15:49:42 -07002256uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
Andreas Gampe875b4f22018-11-19 12:59:15 -08002257 DCHECK(oat_class_offsets_pointer_ != nullptr);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002258 return oat_class_offsets_pointer_[class_def_index];
2259}
2260
David Brazdil7126c5b2019-03-05 00:02:51 +00002261bool OatDexFile::IsBackedByVdexOnly() const {
2262 return oat_class_offsets_pointer_ == nullptr;
2263}
2264
Andreas Gampeb40d3612018-06-26 15:49:42 -07002265OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
David Brazdil7126c5b2019-03-05 00:02:51 +00002266 if (IsBackedByVdexOnly()) {
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002267 // If there is only a vdex file, return that the class is not ready. The
2268 // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2269 // actual class status, because we need to do the assignability type checks.
David Brazdil7126c5b2019-03-05 00:02:51 +00002270 return OatFile::OatClass(oat_file_,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002271 ClassStatus::kNotReady,
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002272 /* type= */ OatClassType::kNoneCompiled,
David Brazdil7126c5b2019-03-05 00:02:51 +00002273 /* bitmap_size= */ 0u,
2274 /* bitmap_pointer= */ nullptr,
2275 /* methods_pointer= */ nullptr);
2276 }
2277
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002278 uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002279 CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2280 CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2281 CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2282 oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2283 const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002284
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002285 uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2286 current_pointer += sizeof(uint16_t);
2287 uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2288 current_pointer += sizeof(uint16_t);
2289 CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2290 << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2291 CHECK_LT(type_value, enum_cast<uint8_t>(OatClassType::kOatClassMax)) << oat_file_->GetLocation();
2292 ClassStatus status = enum_cast<ClassStatus>(status_value);
2293 OatClassType type = enum_cast<OatClassType>(type_value);
Brian Carlstromba150c32013-08-27 17:31:03 -07002294
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002295 uint32_t num_methods = 0;
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002296 const uint32_t* bitmap_pointer = nullptr;
2297 const OatMethodOffsets* methods_pointer = nullptr;
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002298 if (type != OatClassType::kNoneCompiled) {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002299 CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2300 << oat_file_->GetLocation();
2301 num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2302 current_pointer += sizeof(uint32_t);
2303 CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2304 uint32_t num_method_offsets;
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002305 if (type == OatClassType::kSomeCompiled) {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002306 uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002307 CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2308 << oat_file_->GetLocation();
2309 bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2310 current_pointer += bitmap_size;
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002311 // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2312 // should be zero but we're not verifying that.
2313 num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
Ian Rogers97b52f82014-08-14 11:34:07 -07002314 } else {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002315 num_method_offsets = num_methods;
Ian Rogers97b52f82014-08-14 11:34:07 -07002316 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002317 CHECK_LE(num_method_offsets,
2318 static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2319 << oat_file_->GetLocation();
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002320 methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
Brian Carlstromcd937a92014-03-04 22:53:23 -08002321 }
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002322
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002323 return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
Brian Carlstrome24fa612011-09-29 00:53:55 -07002324}
2325
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002326const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2327 const char* descriptor,
2328 size_t hash) {
Andreas Gampeb40d3612018-06-26 15:49:42 -07002329 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
David Sehr9aa352e2016-09-15 18:13:52 -07002330 DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002331 bool used_lookup_table = false;
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002332 const dex::ClassDef* lookup_table_classdef = nullptr;
Vladimir Markoea341d22018-05-11 10:33:37 +01002333 if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002334 used_lookup_table = true;
Vladimir Markoea341d22018-05-11 10:33:37 +01002335 const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
Vladimir Marko1c7d0ce2021-04-19 14:00:14 +00002336 if (class_def_idx != dex::kDexNoIndex) {
2337 CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2338 lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2339 }
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002340 if (!kIsDebugBuild) {
2341 return lookup_table_classdef;
2342 }
David Sehr9aa352e2016-09-15 18:13:52 -07002343 }
2344 // Fast path for rare no class defs case.
2345 const uint32_t num_class_defs = dex_file.NumClassDefs();
2346 if (num_class_defs == 0) {
Vladimir Markoea341d22018-05-11 10:33:37 +01002347 DCHECK(!used_lookup_table);
David Sehr9aa352e2016-09-15 18:13:52 -07002348 return nullptr;
2349 }
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002350 const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
David Sehr9aa352e2016-09-15 18:13:52 -07002351 if (type_id != nullptr) {
Andreas Gampea5b09a62016-11-17 15:21:22 -08002352 dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
Andreas Gampe3f1dcd32018-12-28 09:39:56 -08002353 const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
Mathieu Chartierc3a22aa2018-01-19 18:58:34 -08002354 if (kIsDebugBuild && used_lookup_table) {
2355 DCHECK_EQ(found_class_def, lookup_table_classdef);
2356 }
2357 return found_class_def;
David Sehr9aa352e2016-09-15 18:13:52 -07002358 }
2359 return nullptr;
2360}
2361
Mathieu Chartier120aa282017-08-05 16:03:03 -07002362// Madvise the dex file based on the state we are moving to.
Jared Duke95bb9952021-08-11 15:07:25 -07002363void OatDexFile::MadviseDexFileAtLoad(const DexFile& dex_file) {
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002364 Runtime* const runtime = Runtime::Current();
2365 const bool low_ram = runtime->GetHeap()->IsLowMemoryMode();
Jared Duke95bb9952021-08-11 15:07:25 -07002366 // TODO(b/196052575): Revisit low-ram madvise behavior in light of vdex/odex/art madvise hints.
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002367 if (!low_ram) {
Mathieu Chartierbe8303d2017-08-17 17:39:39 -07002368 return;
2369 }
Jared Duke95bb9952021-08-11 15:07:25 -07002370 if (runtime->MAdviseRandomAccess()) {
Mathieu Chartierc42cb0e2017-10-13 11:35:00 -07002371 // Default every dex file to MADV_RANDOM when its loaded by default for low ram devices.
2372 // Other devices have enough page cache to get performance benefits from loading more pages
2373 // into the page cache.
David Sehrc431b9d2018-03-02 12:01:51 -08002374 DexLayoutSection::MadviseLargestPageAlignedRegion(dex_file.Begin(),
2375 dex_file.Begin() + dex_file.Size(),
2376 MADV_RANDOM);
Mathieu Chartier120aa282017-08-05 16:03:03 -07002377 }
Andreas Gampeb40d3612018-06-26 15:49:42 -07002378 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
Mathieu Chartier120aa282017-08-05 16:03:03 -07002379 if (oat_dex_file != nullptr) {
2380 // Should always be there.
2381 const DexLayoutSections* const sections = oat_dex_file->GetDexLayoutSections();
Nicolas Geoffray50419f22021-04-01 18:10:21 +01002382 if (sections != nullptr) {
Jared Duke95bb9952021-08-11 15:07:25 -07002383 sections->MadviseAtLoad(&dex_file);
Nicolas Geoffray50419f22021-04-01 18:10:21 +01002384 } else {
2385 DCHECK(oat_dex_file->IsBackedByVdexOnly());
2386 }
Mathieu Chartier120aa282017-08-05 16:03:03 -07002387 }
2388}
2389
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002390OatFile::OatClass::OatClass(const OatFile* oat_file,
Vladimir Marko2c64a832018-01-04 11:31:56 +00002391 ClassStatus status,
Brian Carlstromba150c32013-08-27 17:31:03 -07002392 OatClassType type,
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002393 uint32_t num_methods,
Brian Carlstromba150c32013-08-27 17:31:03 -07002394 const uint32_t* bitmap_pointer,
Brian Carlstrom0755ec52012-01-11 15:19:46 -08002395 const OatMethodOffsets* methods_pointer)
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002396 : oat_file_(oat_file),
2397 status_(status),
2398 type_(type),
2399 num_methods_(num_methods),
2400 bitmap_(bitmap_pointer),
2401 methods_pointer_(methods_pointer) {
2402 DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2403 DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2404 DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
Brian Carlstromba150c32013-08-27 17:31:03 -07002405}
Brian Carlstrome24fa612011-09-29 00:53:55 -07002406
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002407uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2408 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2409 if (oat_method_offsets == nullptr) {
2410 return 0u;
2411 }
2412 return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2413}
2414
2415const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002416 // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2417 // a bounds check for `method_index` in that case.
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002418 if (methods_pointer_ == nullptr) {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002419 CHECK_EQ(OatClassType::kNoneCompiled, type_);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002420 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07002421 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002422 CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
Brian Carlstromba150c32013-08-27 17:31:03 -07002423 size_t methods_pointer_index;
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002424 if (bitmap_ == nullptr) {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002425 CHECK_EQ(OatClassType::kAllCompiled, type_);
Brian Carlstromba150c32013-08-27 17:31:03 -07002426 methods_pointer_index = method_index;
2427 } else {
Vladimir Marko3d76ebe2021-04-19 15:07:50 +00002428 CHECK_EQ(OatClassType::kSomeCompiled, type_);
Vladimir Markod3c5beb2014-04-11 16:32:51 +01002429 if (!BitVector::IsBitSet(bitmap_, method_index)) {
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002430 return nullptr;
Brian Carlstromba150c32013-08-27 17:31:03 -07002431 }
Vladimir Markod3c5beb2014-04-11 16:32:51 +01002432 size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2433 methods_pointer_index = num_set_bits;
Brian Carlstromba150c32013-08-27 17:31:03 -07002434 }
Vladimir Marko2cca1e02021-04-21 09:21:16 +00002435 if (kIsDebugBuild) {
2436 size_t size_until_end = dchecked_integral_cast<size_t>(
2437 oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2438 CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2439 << oat_file_->GetLocation();
2440 }
Brian Carlstromba150c32013-08-27 17:31:03 -07002441 const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002442 return &oat_method_offsets;
2443}
2444
2445const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2446 const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2447 if (oat_method_offsets == nullptr) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08002448 return OatMethod(nullptr, 0);
Brian Carlstrom2cbaccb2014-09-14 20:34:17 -07002449 }
2450 if (oat_file_->IsExecutable() ||
2451 Runtime::Current() == nullptr || // This case applies for oatdump.
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08002452 Runtime::Current()->IsAotCompiler()) {
Mathieu Chartier957ca1c2014-11-21 16:51:29 -08002453 return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
Alex Light9dcc4572014-08-14 14:16:26 -07002454 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -08002455 // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2456 // version.
2457 return OatMethod(oat_file_->Begin(), 0);
Brian Carlstrom3320cf42011-10-04 14:58:28 -07002458}
2459
Sebastien Hertz0de11332015-05-13 12:14:05 +02002460bool OatFile::IsDebuggable() const {
2461 return GetOatHeader().IsDebuggable();
2462}
2463
Andreas Gampe29d38e72016-03-23 15:31:51 +00002464CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2465 return GetOatHeader().GetCompilerFilter();
Calin Juravleb077e152016-02-18 18:47:37 +00002466}
2467
Calin Juravle44e5efa2017-09-12 00:54:26 -07002468std::string OatFile::GetClassLoaderContext() const {
2469 return GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
Igor Murashkin2ffb7032017-11-08 13:35:21 -08002470}
Calin Juravle44e5efa2017-09-12 00:54:26 -07002471
Calin Juravle0e09dfc2018-02-12 19:01:09 -08002472const char* OatFile::GetCompilationReason() const {
2473 return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2474}
2475
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01002476OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2477 uint16_t class_def_idx,
2478 bool* found) {
2479 DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
Andreas Gampeb40d3612018-06-26 15:49:42 -07002480 const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
Mathieu Chartier1b868492016-11-16 16:22:37 -08002481 if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
Vladimir Marko97d7e1c2016-10-04 14:44:28 +01002482 *found = false;
2483 return OatFile::OatClass::Invalid();
2484 }
2485 *found = true;
2486 return oat_dex_file->GetOatClass(class_def_idx);
2487}
2488
Eric Holkbc89ed42020-04-29 19:59:24 +00002489bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2490
Vladimir Marko1cedb4a2019-02-06 14:13:28 +00002491static void DCheckIndexToBssMapping(const OatFile* oat_file,
2492 uint32_t number_of_indexes,
2493 size_t slot_size,
2494 const IndexBssMapping* index_bss_mapping) {
2495 if (kIsDebugBuild && index_bss_mapping != nullptr) {
2496 size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2497 const IndexBssMappingEntry* prev_entry = nullptr;
2498 for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2499 CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2500 CHECK_LT(entry.bss_offset, oat_file->BssSize());
2501 uint32_t mask = entry.GetMask(index_bits);
2502 CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2503 size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2504 CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2505 if (prev_entry != nullptr) {
2506 CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2507 }
2508 prev_entry = &entry;
2509 }
2510 CHECK(prev_entry != nullptr);
2511 CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2512 }
2513}
2514
2515void OatFile::InitializeRelocations() const {
2516 DCHECK(IsExecutable());
2517
2518 // Initialize the .data.bimg.rel.ro section.
2519 if (!GetBootImageRelocations().empty()) {
2520 uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin());
2521 CheckedCall(mprotect,
2522 "un-protect boot image relocations",
2523 reloc_begin,
2524 DataBimgRelRoSize(),
2525 PROT_READ | PROT_WRITE);
Vladimir Marko7cde4582019-07-05 13:26:11 +01002526 uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
Vladimir Marko1cedb4a2019-02-06 14:13:28 +00002527 for (const uint32_t& relocation : GetBootImageRelocations()) {
2528 const_cast<uint32_t&>(relocation) += boot_image_begin;
2529 }
2530 CheckedCall(mprotect,
2531 "protect boot image relocations",
2532 reloc_begin,
2533 DataBimgRelRoSize(),
2534 PROT_READ);
2535 }
2536
2537 // Before initializing .bss, check the .bss mappings in debug mode.
2538 if (kIsDebugBuild) {
2539 PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2540 for (const OatDexFile* odf : GetOatDexFiles()) {
2541 const DexFile::Header* header =
2542 reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2543 DCheckIndexToBssMapping(this,
2544 header->method_ids_size_,
2545 static_cast<size_t>(pointer_size),
2546 odf->GetMethodBssMapping());
2547 DCheckIndexToBssMapping(this,
2548 header->type_ids_size_,
2549 sizeof(GcRoot<mirror::Class>),
2550 odf->GetTypeBssMapping());
2551 DCheckIndexToBssMapping(this,
2552 header->string_ids_size_,
2553 sizeof(GcRoot<mirror::String>),
2554 odf->GetStringBssMapping());
2555 }
2556 }
2557
2558 // Initialize the .bss section.
2559 // TODO: Pre-initialize from boot/app image?
2560 ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2561 for (ArtMethod*& entry : GetBssMethods()) {
2562 entry = resolution_method;
2563 }
2564}
2565
Andreas Gampeb40d3612018-06-26 15:49:42 -07002566void OatDexFile::AssertAotCompiler() {
Mathieu Chartier1b868492016-11-16 16:22:37 -08002567 CHECK(Runtime::Current()->IsAotCompiler());
2568}
2569
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00002570bool OatFile::IsBackedByVdexOnly() const {
2571 return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2572}
2573
Brian Carlstrome24fa612011-09-29 00:53:55 -07002574} // namespace art