blob: 760acc7cabeedcbf66be6b6aec394832aa84b8cf [file] [log] [blame]
Ian Rogers1d54e732013-05-02 21:10:01 -07001/*
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 */
16
17#include "image_space.h"
18
Andreas Gampe70be1fb2014-10-31 16:45:19 -070019#include <sys/statvfs.h>
Alex Light25396132014-08-27 15:37:23 -070020#include <sys/types.h>
Narayan Kamath5a2be3f2015-02-16 13:51:51 +000021#include <unistd.h>
Alex Light25396132014-08-27 15:37:23 -070022
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include <random>
24
Andreas Gampe46ee31b2016-12-14 10:11:49 -080025#include "android-base/stringprintf.h"
Andreas Gampe9186ced2016-12-12 14:28:21 -080026#include "android-base/strings.h"
27
Andreas Gampe639b2b12019-01-08 10:32:50 -080028#include "arch/instruction_set.h"
Andreas Gampea1d2f952017-04-20 22:53:58 -070029#include "art_field-inl.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080030#include "art_method-inl.h"
Vladimir Marko0ace5632018-12-14 11:11:47 +000031#include "base/array_ref.h"
Vladimir Marko4df2d802018-09-27 16:42:44 +000032#include "base/bit_memory_region.h"
Andreas Gampe8228cdf2017-05-30 15:03:54 -070033#include "base/callee_save_type.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070034#include "base/enums.h"
David Sehr891a50e2017-10-27 17:01:07 -070035#include "base/file_utils.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070036#include "base/macros.h"
David Sehrc431b9d2018-03-02 12:01:51 -080037#include "base/os.h"
Narayan Kamathd1c606f2014-06-09 16:50:19 +010038#include "base/scoped_flock.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070039#include "base/stl_util.h"
Vladimir Marko436c6f52019-07-25 14:50:14 +010040#include "base/string_view_cpp20.h"
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -080041#include "base/systrace.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010042#include "base/time_utils.h"
David Sehrc431b9d2018-03-02 12:01:51 -080043#include "base/utils.h"
Vladimir Marko4df2d802018-09-27 16:42:44 +000044#include "class_root.h"
David Sehr013fd802018-01-11 22:55:24 -080045#include "dex/art_dex_file_loader.h"
David Sehr9e734c72018-01-04 17:56:19 -080046#include "dex/dex_file_loader.h"
David Sehr97c381e2017-02-01 15:09:58 -080047#include "exec_utils.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070048#include "gc/accounting/space_bitmap-inl.h"
Mathieu Chartier93c21ba2018-12-10 13:08:30 -080049#include "gc/task_processor.h"
Mathieu Chartier4a26f172016-01-26 14:26:18 -080050#include "image-inl.h"
Andreas Gampebec63582015-11-20 19:26:51 -080051#include "image_space_fs.h"
Mathieu Chartier74ccee62018-10-10 10:30:29 -070052#include "intern_table-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070053#include "mirror/class-inl.h"
Vladimir Marko0eefb9b2019-03-27 15:04:31 +000054#include "mirror/executable-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070055#include "mirror/object-inl.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080056#include "mirror/object-refvisitor-inl.h"
Brian Carlstrom56d947f2013-07-15 13:14:23 -070057#include "oat_file.h"
Andreas Gamped482e732017-04-24 17:59:09 -070058#include "runtime.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070059#include "space-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070060
61namespace art {
62namespace gc {
63namespace space {
64
Vladimir Marko0ace5632018-12-14 11:11:47 +000065using android::base::StringAppendF;
Andreas Gampe46ee31b2016-12-14 10:11:49 -080066using android::base::StringPrintf;
67
Ian Rogersef7d42f2014-01-06 12:55:46 -080068Atomic<uint32_t> ImageSpace::bitmap_index_(0);
Ian Rogers1d54e732013-05-02 21:10:01 -070069
Jeff Haodcdc85b2015-12-04 14:06:18 -080070ImageSpace::ImageSpace(const std::string& image_filename,
71 const char* image_location,
Vladimir Markoc34bebf2018-08-16 16:12:49 +010072 MemMap&& mem_map,
Mathieu Chartier6f382012019-07-30 09:47:35 -070073 accounting::ContinuousSpaceBitmap&& live_bitmap,
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080074 uint8_t* end)
75 : MemMapSpace(image_filename,
Vladimir Markoc34bebf2018-08-16 16:12:49 +010076 std::move(mem_map),
77 mem_map.Begin(),
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080078 end,
79 end,
Narayan Kamath52f84882014-05-02 10:10:39 +010080 kGcRetentionPolicyNeverCollect),
Vladimir Markoc09cd052018-08-23 16:36:36 +010081 live_bitmap_(std::move(live_bitmap)),
Jeff Haodcdc85b2015-12-04 14:06:18 -080082 oat_file_non_owned_(nullptr),
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080083 image_location_(image_location) {
Mathieu Chartier6f382012019-07-30 09:47:35 -070084 DCHECK(live_bitmap_.IsValid());
Ian Rogers1d54e732013-05-02 21:10:01 -070085}
86
Alex Lightcf4bf382014-07-24 11:29:14 -070087static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
88 CHECK_ALIGNED(min_delta, kPageSize);
89 CHECK_ALIGNED(max_delta, kPageSize);
90 CHECK_LT(min_delta, max_delta);
91
Alex Light15324762015-11-19 11:03:10 -080092 int32_t r = GetRandomNumber<int32_t>(min_delta, max_delta);
Alex Lightcf4bf382014-07-24 11:29:14 -070093 if (r % 2 == 0) {
94 r = RoundUp(r, kPageSize);
95 } else {
96 r = RoundDown(r, kPageSize);
97 }
98 CHECK_LE(min_delta, r);
99 CHECK_GE(max_delta, r);
100 CHECK_ALIGNED(r, kPageSize);
101 return r;
102}
103
Andreas Gampea463b6a2016-08-12 21:53:32 -0700104static int32_t ChooseRelocationOffsetDelta() {
105 return ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, ART_BASE_ADDRESS_MAX_DELTA);
106}
107
108static bool GenerateImage(const std::string& image_filename,
109 InstructionSet image_isa,
Alex Light25396132014-08-27 15:37:23 -0700110 std::string* error_msg) {
Vladimir Marko91f10322018-12-07 18:04:10 +0000111 Runtime* runtime = Runtime::Current();
112 const std::vector<std::string>& boot_class_path = runtime->GetBootClassPath();
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700113 if (boot_class_path.empty()) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700114 *error_msg = "Failed to generate image because no boot class path specified";
115 return false;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700116 }
Alex Light25396132014-08-27 15:37:23 -0700117 // We should clean up so we are more likely to have room for the image.
118 if (Runtime::Current()->IsZygote()) {
Andreas Gampe3c13a792014-09-18 20:56:04 -0700119 LOG(INFO) << "Pruning dalvik-cache since we are generating an image and will need to recompile";
Narayan Kamath28bc9872014-11-07 17:46:28 +0000120 PruneDalvikCache(image_isa);
Alex Light25396132014-08-27 15:37:23 -0700121 }
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700122
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700123 std::vector<std::string> arg_vector;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700124
Tsu Chiang Chuang12e6d742014-05-22 10:22:25 -0700125 std::string dex2oat(Runtime::Current()->GetCompilerExecutable());
Mathieu Chartier08d7d442013-07-31 18:08:51 -0700126 arg_vector.push_back(dex2oat);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700127
wangshumind6d878e2019-05-08 12:52:39 +0800128 char* dex2oat_bcp = getenv("DEX2OATBOOTCLASSPATH");
129 std::vector<std::string> dex2oat_bcp_vector;
130 if (dex2oat_bcp != nullptr) {
131 arg_vector.push_back("--runtime-arg");
132 arg_vector.push_back(StringPrintf("-Xbootclasspath:%s", dex2oat_bcp));
133 Split(dex2oat_bcp, ':', &dex2oat_bcp_vector);
134 }
135
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700136 std::string image_option_string("--image=");
Narayan Kamath52f84882014-05-02 10:10:39 +0100137 image_option_string += image_filename;
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700138 arg_vector.push_back(image_option_string);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700139
wangshumind6d878e2019-05-08 12:52:39 +0800140 if (!dex2oat_bcp_vector.empty()) {
141 for (size_t i = 0u; i < dex2oat_bcp_vector.size(); i++) {
142 arg_vector.push_back(std::string("--dex-file=") + dex2oat_bcp_vector[i]);
143 arg_vector.push_back(std::string("--dex-location=") + dex2oat_bcp_vector[i]);
144 }
145 } else {
146 const std::vector<std::string>& boot_class_path_locations =
147 runtime->GetBootClassPathLocations();
148 DCHECK_EQ(boot_class_path.size(), boot_class_path_locations.size());
149 for (size_t i = 0u; i < boot_class_path.size(); i++) {
150 arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
151 arg_vector.push_back(std::string("--dex-location=") + boot_class_path_locations[i]);
152 }
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700153 }
154
155 std::string oat_file_option_string("--oat-file=");
Brian Carlstrom2f1e15c2014-10-27 16:27:06 -0700156 oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename);
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700157 arg_vector.push_back(oat_file_option_string);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700158
Sebastien Hertz0de11332015-05-13 12:14:05 +0200159 // Note: we do not generate a fully debuggable boot image so we do not pass the
160 // compiler flag --debuggable here.
161
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700162 Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector);
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700163 CHECK_EQ(image_isa, kRuntimeISA)
164 << "We should always be generating an image for the current isa.";
Ian Rogers8afeb852014-04-02 14:55:49 -0700165
Andreas Gampea463b6a2016-08-12 21:53:32 -0700166 int32_t base_offset = ChooseRelocationOffsetDelta();
Alex Lightcf4bf382014-07-24 11:29:14 -0700167 LOG(INFO) << "Using an offset of 0x" << std::hex << base_offset << " from default "
168 << "art base address of 0x" << std::hex << ART_BASE_ADDRESS;
169 arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700170
Brian Carlstrom57309db2014-07-30 15:13:25 -0700171 if (!kIsTargetBuild) {
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700172 arg_vector.push_back("--host");
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700173 }
174
Brian Carlstrom6449c622014-02-10 23:48:36 -0800175 const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions();
Brian Carlstrom2ec65202014-03-03 15:16:37 -0800176 for (size_t i = 0; i < compiler_options.size(); ++i) {
Brian Carlstrom6449c622014-02-10 23:48:36 -0800177 arg_vector.push_back(compiler_options[i].c_str());
178 }
179
Andreas Gampe9186ced2016-12-12 14:28:21 -0800180 std::string command_line(android::base::Join(arg_vector, ' '));
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700181 LOG(INFO) << "GenerateImage: " << command_line;
Brian Carlstrom6449c622014-02-10 23:48:36 -0800182 return Exec(arg_vector, error_msg);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700183}
184
Andreas Gampea463b6a2016-08-12 21:53:32 -0700185static bool FindImageFilenameImpl(const char* image_location,
186 const InstructionSet image_isa,
187 bool* has_system,
188 std::string* system_filename,
189 bool* dalvik_cache_exists,
190 std::string* dalvik_cache,
191 bool* is_global_cache,
192 bool* has_cache,
193 std::string* cache_filename) {
194 DCHECK(dalvik_cache != nullptr);
195
Alex Lighta59dd802014-07-02 16:28:08 -0700196 *has_system = false;
197 *has_cache = false;
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -0700198 // image_location = /system/framework/boot.art
199 // system_image_location = /system/framework/<image_isa>/boot.art
200 std::string system_image_filename(GetSystemImageFilename(image_location, image_isa));
201 if (OS::FileExists(system_image_filename.c_str())) {
Alex Lighta59dd802014-07-02 16:28:08 -0700202 *system_filename = system_image_filename;
203 *has_system = true;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700204 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100205
Alex Lighta59dd802014-07-02 16:28:08 -0700206 bool have_android_data = false;
207 *dalvik_cache_exists = false;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700208 GetDalvikCache(GetInstructionSetString(image_isa),
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100209 /*create_if_absent=*/ true,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700210 dalvik_cache,
211 &have_android_data,
212 dalvik_cache_exists,
213 is_global_cache);
Narayan Kamath52f84882014-05-02 10:10:39 +0100214
Vladimir Marko82e1e272018-08-20 13:38:06 +0000215 if (*dalvik_cache_exists) {
216 DCHECK(have_android_data);
Alex Lighta59dd802014-07-02 16:28:08 -0700217 // Always set output location even if it does not exist,
218 // so that the caller knows where to create the image.
219 //
220 // image_location = /system/framework/boot.art
Vladimir Marko82e1e272018-08-20 13:38:06 +0000221 // *image_filename = /data/dalvik-cache/<image_isa>/system@framework@boot.art
Alex Lighta59dd802014-07-02 16:28:08 -0700222 std::string error_msg;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700223 if (!GetDalvikCacheFilename(image_location,
224 dalvik_cache->c_str(),
225 cache_filename,
226 &error_msg)) {
Alex Lighta59dd802014-07-02 16:28:08 -0700227 LOG(WARNING) << error_msg;
228 return *has_system;
229 }
230 *has_cache = OS::FileExists(cache_filename->c_str());
231 }
232 return *has_system || *has_cache;
233}
234
Andreas Gampea463b6a2016-08-12 21:53:32 -0700235bool ImageSpace::FindImageFilename(const char* image_location,
236 const InstructionSet image_isa,
237 std::string* system_filename,
238 bool* has_system,
239 std::string* cache_filename,
240 bool* dalvik_cache_exists,
241 bool* has_cache,
242 bool* is_global_cache) {
243 std::string dalvik_cache_unused;
244 return FindImageFilenameImpl(image_location,
245 image_isa,
246 has_system,
247 system_filename,
248 dalvik_cache_exists,
249 &dalvik_cache_unused,
250 is_global_cache,
251 has_cache,
252 cache_filename);
253}
254
Vladimir Marko1b13d282019-10-23 15:10:55 +0100255static bool ReadSpecificImageHeader(const char* filename,
256 ImageHeader* image_header,
257 std::string* error_msg) {
Alex Lighta59dd802014-07-02 16:28:08 -0700258 std::unique_ptr<File> image_file(OS::OpenFileForReading(filename));
259 if (image_file.get() == nullptr) {
Vladimir Marko1b13d282019-10-23 15:10:55 +0100260 *error_msg = StringPrintf("Unable to open file \"%s\" for reading image header", filename);
Alex Lighta59dd802014-07-02 16:28:08 -0700261 return false;
262 }
263 const bool success = image_file->ReadFully(image_header, sizeof(ImageHeader));
Vladimir Marko1b13d282019-10-23 15:10:55 +0100264 if (!success) {
265 *error_msg = StringPrintf("Unable to read image header from file \"%s\"", filename);
266 return false;
267 }
268 if (!image_header->IsValid()) {
269 *error_msg = StringPrintf("Image header from file \"%s\" is invalid", filename);
Alex Lighta59dd802014-07-02 16:28:08 -0700270 return false;
271 }
272 return true;
273}
274
Vladimir Marko4df2d802018-09-27 16:42:44 +0000275static std::unique_ptr<ImageHeader> ReadSpecificImageHeader(const char* filename,
276 std::string* error_msg) {
Alex Lighta59dd802014-07-02 16:28:08 -0700277 std::unique_ptr<ImageHeader> hdr(new ImageHeader);
Vladimir Marko1b13d282019-10-23 15:10:55 +0100278 if (!ReadSpecificImageHeader(filename, hdr.get(), error_msg)) {
Alex Lighta59dd802014-07-02 16:28:08 -0700279 return nullptr;
280 }
Vladimir Marko4df2d802018-09-27 16:42:44 +0000281 return hdr;
Narayan Kamath52f84882014-05-02 10:10:39 +0100282}
283
Vladimir Marko4df2d802018-09-27 16:42:44 +0000284std::unique_ptr<ImageHeader> ImageSpace::ReadImageHeader(const char* image_location,
285 const InstructionSet image_isa,
Andreas Gampe86823542019-02-25 09:38:49 -0800286 ImageSpaceLoadingOrder order,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000287 std::string* error_msg) {
Alex Lighta59dd802014-07-02 16:28:08 -0700288 std::string system_filename;
289 bool has_system = false;
290 std::string cache_filename;
291 bool has_cache = false;
292 bool dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -0700293 bool is_global_cache = false;
Vladimir Marko4df2d802018-09-27 16:42:44 +0000294 if (FindImageFilename(image_location,
295 image_isa,
296 &system_filename,
297 &has_system,
298 &cache_filename,
299 &dalvik_cache_exists,
300 &has_cache,
301 &is_global_cache)) {
Andreas Gampe86823542019-02-25 09:38:49 -0800302 if (order == ImageSpaceLoadingOrder::kSystemFirst) {
303 if (has_system) {
304 return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
305 }
306 if (has_cache) {
307 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
308 }
309 } else {
310 if (has_cache) {
311 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
312 }
313 if (has_system) {
314 return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
315 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100316 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100317 }
318
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700319 *error_msg = StringPrintf("Unable to find image file for %s", image_location);
Narayan Kamath52f84882014-05-02 10:10:39 +0100320 return nullptr;
321}
322
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400323static bool CanWriteToDalvikCache(const InstructionSet isa) {
324 const std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(isa));
325 if (access(dalvik_cache.c_str(), O_RDWR) == 0) {
326 return true;
327 } else if (errno != EACCES) {
328 PLOG(WARNING) << "CanWriteToDalvikCache returned error other than EACCES";
329 }
330 return false;
331}
332
333static bool ImageCreationAllowed(bool is_global_cache,
334 const InstructionSet isa,
Vladimir Marko3364d182019-03-13 13:55:01 +0000335 bool is_zygote,
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400336 std::string* error_msg) {
Andreas Gampe3c13a792014-09-18 20:56:04 -0700337 // Anyone can write into a "local" cache.
338 if (!is_global_cache) {
339 return true;
340 }
341
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400342 // Only the zygote running as root is allowed to create the global boot image.
343 // If the zygote is running as non-root (and cannot write to the dalvik-cache),
344 // then image creation is not allowed..
Vladimir Marko3364d182019-03-13 13:55:01 +0000345 if (is_zygote) {
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400346 return CanWriteToDalvikCache(isa);
Andreas Gampe3c13a792014-09-18 20:56:04 -0700347 }
348
349 *error_msg = "Only the zygote can create the global boot image.";
350 return false;
351}
352
Mathieu Chartier31e89252013-08-28 11:29:12 -0700353void ImageSpace::VerifyImageAllocations() {
Ian Rogers13735952014-10-08 12:43:28 -0700354 uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
Mathieu Chartier31e89252013-08-28 11:29:12 -0700355 while (current < End()) {
Mathieu Chartierc7853442015-03-27 14:35:38 -0700356 CHECK_ALIGNED(current, kObjectAlignment);
357 auto* obj = reinterpret_cast<mirror::Object*>(current);
Mathieu Chartier31e89252013-08-28 11:29:12 -0700358 CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
Mathieu Chartier6f382012019-07-30 09:47:35 -0700359 CHECK(live_bitmap_.Test(obj)) << obj->PrettyTypeOf();
Hiroshi Yamauchi12b58b22016-11-01 11:55:29 -0700360 if (kUseBakerReadBarrier) {
361 obj->AssertReadBarrierState();
Hiroshi Yamauchi9d04a202014-01-31 13:35:49 -0800362 }
Mathieu Chartier31e89252013-08-28 11:29:12 -0700363 current += RoundUp(obj->SizeOf(), kObjectAlignment);
364 }
365}
366
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800367// Helper class for relocating from one range of memory to another.
368class RelocationRange {
369 public:
370 RelocationRange() = default;
371 RelocationRange(const RelocationRange&) = default;
372 RelocationRange(uintptr_t source, uintptr_t dest, uintptr_t length)
373 : source_(source),
374 dest_(dest),
375 length_(length) {}
376
Mathieu Chartier91edc622016-02-16 17:16:01 -0800377 bool InSource(uintptr_t address) const {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800378 return address - source_ < length_;
379 }
380
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800381 bool InDest(const void* dest) const {
382 return InDest(reinterpret_cast<uintptr_t>(dest));
383 }
384
Mathieu Chartier91edc622016-02-16 17:16:01 -0800385 bool InDest(uintptr_t address) const {
386 return address - dest_ < length_;
387 }
388
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800389 // Translate a source address to the destination space.
390 uintptr_t ToDest(uintptr_t address) const {
Mathieu Chartier91edc622016-02-16 17:16:01 -0800391 DCHECK(InSource(address));
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800392 return address + Delta();
393 }
394
Vladimir Markoc0b30c92019-07-23 14:58:25 +0100395 template <typename T>
396 T* ToDest(T* src) const {
397 return reinterpret_cast<T*>(ToDest(reinterpret_cast<uintptr_t>(src)));
398 }
399
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800400 // Returns the delta between the dest from the source.
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800401 uintptr_t Delta() const {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800402 return dest_ - source_;
403 }
404
405 uintptr_t Source() const {
406 return source_;
407 }
408
409 uintptr_t Dest() const {
410 return dest_;
411 }
412
413 uintptr_t Length() const {
414 return length_;
415 }
416
417 private:
418 const uintptr_t source_;
419 const uintptr_t dest_;
420 const uintptr_t length_;
421};
422
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800423std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
424 return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
425 << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
426 << reinterpret_cast<const void*>(reloc.Dest()) << "-"
427 << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
428}
429
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800430template <PointerSize kPointerSize, typename HeapVisitor, typename NativeVisitor>
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800431class ImageSpace::PatchObjectVisitor final {
432 public:
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800433 explicit PatchObjectVisitor(HeapVisitor heap_visitor, NativeVisitor native_visitor)
434 : heap_visitor_(heap_visitor), native_visitor_(native_visitor) {}
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800435
Vladimir Markoc0b30c92019-07-23 14:58:25 +0100436 void VisitClass(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Class> class_class)
437 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800438 // A mirror::Class object consists of
439 // - instance fields inherited from j.l.Object,
440 // - instance fields inherited from j.l.Class,
441 // - embedded tables (vtable, interface method table),
442 // - static fields of the class itself.
443 // The reference fields are at the start of each field section (this is how the
444 // ClassLinker orders fields; except when that would create a gap between superclass
445 // fields and the first reference of the subclass due to alignment, it can be filled
446 // with smaller fields - but that's not the case for j.l.Object and j.l.Class).
447
Vladimir Markoc0b30c92019-07-23 14:58:25 +0100448 DCHECK_ALIGNED(klass.Ptr(), kObjectAlignment);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800449 static_assert(IsAligned<kHeapReferenceSize>(kObjectAlignment), "Object alignment check.");
450 // First, patch the `klass->klass_`, known to be a reference to the j.l.Class.class.
451 // This should be the only reference field in j.l.Object and we assert that below.
Vladimir Markoc0b30c92019-07-23 14:58:25 +0100452 DCHECK_EQ(class_class,
453 heap_visitor_(klass->GetClass<kVerifyNone, kWithoutReadBarrier>()));
454 klass->SetFieldObjectWithoutWriteBarrier<
455 /*kTransactionActive=*/ false,
456 /*kCheckTransaction=*/ true,
457 kVerifyNone>(mirror::Object::ClassOffset(), class_class);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800458 // Then patch the reference instance fields described by j.l.Class.class.
459 // Use the sizeof(Object) to determine where these reference fields start;
460 // this is the same as `class_class->GetFirstReferenceInstanceFieldOffset()`
461 // after patching but the j.l.Class may not have been patched yet.
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800462 size_t num_reference_instance_fields = class_class->NumReferenceInstanceFields<kVerifyNone>();
463 DCHECK_NE(num_reference_instance_fields, 0u);
464 static_assert(IsAligned<kHeapReferenceSize>(sizeof(mirror::Object)), "Size alignment check.");
465 MemberOffset instance_field_offset(sizeof(mirror::Object));
466 for (size_t i = 0; i != num_reference_instance_fields; ++i) {
467 PatchReferenceField(klass, instance_field_offset);
468 static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
469 "Heap reference sizes equality check.");
470 instance_field_offset =
471 MemberOffset(instance_field_offset.Uint32Value() + kHeapReferenceSize);
472 }
473 // Now that we have patched the `super_class_`, if this is the j.l.Class.class,
474 // we can get a reference to j.l.Object.class and assert that it has only one
475 // reference instance field (the `klass_` patched above).
476 if (kIsDebugBuild && klass == class_class) {
477 ObjPtr<mirror::Class> object_class =
478 klass->GetSuperClass<kVerifyNone, kWithoutReadBarrier>();
479 CHECK_EQ(object_class->NumReferenceInstanceFields<kVerifyNone>(), 1u);
480 }
481 // Then patch static fields.
482 size_t num_reference_static_fields = klass->NumReferenceStaticFields<kVerifyNone>();
483 if (num_reference_static_fields != 0u) {
484 MemberOffset static_field_offset =
485 klass->GetFirstReferenceStaticFieldOffset<kVerifyNone>(kPointerSize);
486 for (size_t i = 0; i != num_reference_static_fields; ++i) {
487 PatchReferenceField(klass, static_field_offset);
488 static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
489 "Heap reference sizes equality check.");
490 static_field_offset =
491 MemberOffset(static_field_offset.Uint32Value() + kHeapReferenceSize);
492 }
493 }
494 // Then patch native pointers.
Vladimir Markoc0b30c92019-07-23 14:58:25 +0100495 klass->FixupNativePointers<kVerifyNone>(klass.Ptr(), kPointerSize, *this);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800496 }
497
498 template <typename T>
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800499 T* operator()(T* ptr, void** dest_addr ATTRIBUTE_UNUSED) const {
500 return (ptr != nullptr) ? native_visitor_(ptr) : nullptr;
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800501 }
502
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000503 void VisitPointerArray(ObjPtr<mirror::PointerArray> pointer_array)
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800504 REQUIRES_SHARED(Locks::mutator_lock_) {
505 // Fully patch the pointer array, including the `klass_` field.
506 PatchReferenceField</*kMayBeNull=*/ false>(pointer_array, mirror::Object::ClassOffset());
507
508 int32_t length = pointer_array->GetLength<kVerifyNone>();
509 for (int32_t i = 0; i != length; ++i) {
510 ArtMethod** method_entry = reinterpret_cast<ArtMethod**>(
511 pointer_array->ElementAddress<kVerifyNone>(i, kPointerSize));
512 PatchNativePointer</*kMayBeNull=*/ false>(method_entry);
513 }
514 }
515
516 void VisitObject(mirror::Object* object) REQUIRES_SHARED(Locks::mutator_lock_) {
517 // Visit all reference fields.
518 object->VisitReferences</*kVisitNativeRoots=*/ false,
519 kVerifyNone,
520 kWithoutReadBarrier>(*this, *this);
521 // This function should not be called for classes.
522 DCHECK(!object->IsClass<kVerifyNone>());
523 }
524
525 // Visitor for VisitReferences().
Vladimir Marko4617d582019-03-28 13:48:31 +0000526 ALWAYS_INLINE void operator()(ObjPtr<mirror::Object> object,
527 MemberOffset field_offset,
528 bool is_static)
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800529 const REQUIRES_SHARED(Locks::mutator_lock_) {
530 DCHECK(!is_static);
531 PatchReferenceField(object, field_offset);
532 }
533 // Visitor for VisitReferences(), java.lang.ref.Reference case.
Vladimir Marko4617d582019-03-28 13:48:31 +0000534 ALWAYS_INLINE void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800535 REQUIRES_SHARED(Locks::mutator_lock_) {
536 DCHECK(klass->IsTypeOfReferenceClass());
537 this->operator()(ref, mirror::Reference::ReferentOffset(), /*is_static=*/ false);
538 }
539 // Ignore class native roots; not called from VisitReferences() for kVisitNativeRoots == false.
540 void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
541 const {}
542 void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
543
Vladimir Marko423bebb2019-03-26 15:17:21 +0000544 void VisitDexCacheArrays(ObjPtr<mirror::DexCache> dex_cache)
545 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800546 FixupDexCacheArray<mirror::StringDexCacheType>(dex_cache,
547 mirror::DexCache::StringsOffset(),
548 dex_cache->NumStrings<kVerifyNone>());
549 FixupDexCacheArray<mirror::TypeDexCacheType>(dex_cache,
550 mirror::DexCache::ResolvedTypesOffset(),
551 dex_cache->NumResolvedTypes<kVerifyNone>());
552 FixupDexCacheArray<mirror::MethodDexCacheType>(dex_cache,
553 mirror::DexCache::ResolvedMethodsOffset(),
554 dex_cache->NumResolvedMethods<kVerifyNone>());
555 FixupDexCacheArray<mirror::FieldDexCacheType>(dex_cache,
556 mirror::DexCache::ResolvedFieldsOffset(),
557 dex_cache->NumResolvedFields<kVerifyNone>());
558 FixupDexCacheArray<mirror::MethodTypeDexCacheType>(
559 dex_cache,
560 mirror::DexCache::ResolvedMethodTypesOffset(),
561 dex_cache->NumResolvedMethodTypes<kVerifyNone>());
562 FixupDexCacheArray<GcRoot<mirror::CallSite>>(
563 dex_cache,
564 mirror::DexCache::ResolvedCallSitesOffset(),
565 dex_cache->NumResolvedCallSites<kVerifyNone>());
566 FixupDexCacheArray<GcRoot<mirror::String>>(
567 dex_cache,
568 mirror::DexCache::PreResolvedStringsOffset(),
569 dex_cache->NumPreResolvedStrings<kVerifyNone>());
570 }
571
572 template <bool kMayBeNull = true, typename T>
573 ALWAYS_INLINE void PatchGcRoot(/*inout*/GcRoot<T>* root) const
574 REQUIRES_SHARED(Locks::mutator_lock_) {
575 static_assert(sizeof(GcRoot<mirror::Class*>) == sizeof(uint32_t), "GcRoot size check");
576 T* old_value = root->template Read<kWithoutReadBarrier>();
577 DCHECK(kMayBeNull || old_value != nullptr);
578 if (!kMayBeNull || old_value != nullptr) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800579 *root = GcRoot<T>(heap_visitor_(old_value));
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800580 }
581 }
582
583 template <bool kMayBeNull = true, typename T>
584 ALWAYS_INLINE void PatchNativePointer(/*inout*/T** entry) const {
585 if (kPointerSize == PointerSize::k64) {
586 uint64_t* raw_entry = reinterpret_cast<uint64_t*>(entry);
587 T* old_value = reinterpret_cast64<T*>(*raw_entry);
588 DCHECK(kMayBeNull || old_value != nullptr);
589 if (!kMayBeNull || old_value != nullptr) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800590 T* new_value = native_visitor_(old_value);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800591 *raw_entry = reinterpret_cast64<uint64_t>(new_value);
592 }
593 } else {
594 uint32_t* raw_entry = reinterpret_cast<uint32_t*>(entry);
595 T* old_value = reinterpret_cast32<T*>(*raw_entry);
596 DCHECK(kMayBeNull || old_value != nullptr);
597 if (!kMayBeNull || old_value != nullptr) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800598 T* new_value = native_visitor_(old_value);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800599 *raw_entry = reinterpret_cast32<uint32_t>(new_value);
600 }
601 }
602 }
603
604 template <bool kMayBeNull = true>
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000605 ALWAYS_INLINE void PatchReferenceField(ObjPtr<mirror::Object> object, MemberOffset offset) const
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800606 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000607 ObjPtr<mirror::Object> old_value =
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800608 object->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(offset);
609 DCHECK(kMayBeNull || old_value != nullptr);
610 if (!kMayBeNull || old_value != nullptr) {
Vladimir Markoc524e9e2019-03-26 10:54:50 +0000611 ObjPtr<mirror::Object> new_value = heap_visitor_(old_value.Ptr());
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800612 object->SetFieldObjectWithoutWriteBarrier</*kTransactionActive=*/ false,
613 /*kCheckTransaction=*/ true,
614 kVerifyNone>(offset, new_value);
615 }
616 }
617
618 template <typename T>
619 void FixupDexCacheArrayEntry(std::atomic<mirror::DexCachePair<T>>* array, uint32_t index)
620 REQUIRES_SHARED(Locks::mutator_lock_) {
621 static_assert(sizeof(std::atomic<mirror::DexCachePair<T>>) == sizeof(mirror::DexCachePair<T>),
622 "Size check for removing std::atomic<>.");
623 PatchGcRoot(&(reinterpret_cast<mirror::DexCachePair<T>*>(array)[index].object));
624 }
625
626 template <typename T>
627 void FixupDexCacheArrayEntry(std::atomic<mirror::NativeDexCachePair<T>>* array, uint32_t index)
628 REQUIRES_SHARED(Locks::mutator_lock_) {
629 static_assert(sizeof(std::atomic<mirror::NativeDexCachePair<T>>) ==
630 sizeof(mirror::NativeDexCachePair<T>),
631 "Size check for removing std::atomic<>.");
632 mirror::NativeDexCachePair<T> pair =
633 mirror::DexCache::GetNativePairPtrSize(array, index, kPointerSize);
634 if (pair.object != nullptr) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800635 pair.object = native_visitor_(pair.object);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800636 mirror::DexCache::SetNativePairPtrSize(array, index, pair, kPointerSize);
637 }
638 }
639
640 void FixupDexCacheArrayEntry(GcRoot<mirror::CallSite>* array, uint32_t index)
641 REQUIRES_SHARED(Locks::mutator_lock_) {
642 PatchGcRoot(&array[index]);
643 }
644
645 void FixupDexCacheArrayEntry(GcRoot<mirror::String>* array, uint32_t index)
646 REQUIRES_SHARED(Locks::mutator_lock_) {
647 PatchGcRoot(&array[index]);
648 }
649
650 template <typename EntryType>
Vladimir Marko423bebb2019-03-26 15:17:21 +0000651 void FixupDexCacheArray(ObjPtr<mirror::DexCache> dex_cache,
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800652 MemberOffset array_offset,
653 uint32_t size) REQUIRES_SHARED(Locks::mutator_lock_) {
654 EntryType* old_array =
655 reinterpret_cast64<EntryType*>(dex_cache->GetField64<kVerifyNone>(array_offset));
656 DCHECK_EQ(old_array != nullptr, size != 0u);
657 if (old_array != nullptr) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800658 EntryType* new_array = native_visitor_(old_array);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800659 dex_cache->SetField64<kVerifyNone>(array_offset, reinterpret_cast64<uint64_t>(new_array));
660 for (uint32_t i = 0; i != size; ++i) {
661 FixupDexCacheArrayEntry(new_array, i);
662 }
663 }
664 }
665
666 private:
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800667 // Heap objects visitor.
668 HeapVisitor heap_visitor_;
669
670 // Native objects visitor.
671 NativeVisitor native_visitor_;
Mathieu Chartierd3f037b2018-12-06 23:50:56 -0800672};
673
Mathieu Chartier25602dc2018-12-11 11:31:57 -0800674template <typename ReferenceVisitor>
675class ImageSpace::ClassTableVisitor final {
676 public:
677 explicit ClassTableVisitor(const ReferenceVisitor& reference_visitor)
678 : reference_visitor_(reference_visitor) {}
679
680 void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
681 REQUIRES_SHARED(Locks::mutator_lock_) {
682 DCHECK(root->AsMirrorPtr() != nullptr);
683 root->Assign(reference_visitor_(root->AsMirrorPtr()));
684 }
685
686 private:
687 ReferenceVisitor reference_visitor_;
688};
689
Andreas Gampea463b6a2016-08-12 21:53:32 -0700690// Helper class encapsulating loading, so we can access private ImageSpace members (this is a
Vladimir Markoc09cd052018-08-23 16:36:36 +0100691// nested class), but not declare functions in the header.
Vladimir Marko82e1e272018-08-20 13:38:06 +0000692class ImageSpace::Loader {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800693 public:
Vladimir Marko4df2d802018-09-27 16:42:44 +0000694 static std::unique_ptr<ImageSpace> InitAppImage(const char* image_filename,
695 const char* image_location,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000696 const OatFile* oat_file,
697 /*inout*/MemMap* image_reservation,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000698 /*out*/std::string* error_msg)
699 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100700 TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
Mathieu Chartier3ea43222018-12-08 20:44:50 -0800701
Vladimir Marko4df2d802018-09-27 16:42:44 +0000702 std::unique_ptr<ImageSpace> space = Init(image_filename,
703 image_location,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000704 oat_file,
705 &logger,
706 image_reservation,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000707 error_msg);
708 if (space != nullptr) {
Vladimir Marko7391c8c2018-11-21 17:58:44 +0000709 uint32_t expected_reservation_size =
710 RoundUp(space->GetImageHeader().GetImageSize(), kPageSize);
711 if (!CheckImageReservationSize(*space, expected_reservation_size, error_msg) ||
712 !CheckImageComponentCount(*space, /*expected_component_count=*/ 1u, error_msg)) {
713 return nullptr;
714 }
715
Vladimir Marko4df2d802018-09-27 16:42:44 +0000716 TimingLogger::ScopedTiming timing("RelocateImage", &logger);
717 ImageHeader* image_header = reinterpret_cast<ImageHeader*>(space->GetMemMap()->Begin());
Mathieu Chartier25602dc2018-12-11 11:31:57 -0800718 const PointerSize pointer_size = image_header->GetPointerSize();
719 bool result;
720 if (pointer_size == PointerSize::k64) {
721 result = RelocateInPlace<PointerSize::k64>(*image_header,
722 space->GetMemMap()->Begin(),
723 space->GetLiveBitmap(),
724 oat_file,
725 error_msg);
726 } else {
727 result = RelocateInPlace<PointerSize::k32>(*image_header,
728 space->GetMemMap()->Begin(),
729 space->GetLiveBitmap(),
730 oat_file,
731 error_msg);
732 }
733 if (!result) {
Vladimir Marko4df2d802018-09-27 16:42:44 +0000734 return nullptr;
735 }
736 Runtime* runtime = Runtime::Current();
737 CHECK_EQ(runtime->GetResolutionMethod(),
738 image_header->GetImageMethod(ImageHeader::kResolutionMethod));
739 CHECK_EQ(runtime->GetImtConflictMethod(),
740 image_header->GetImageMethod(ImageHeader::kImtConflictMethod));
741 CHECK_EQ(runtime->GetImtUnimplementedMethod(),
742 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod));
743 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves),
744 image_header->GetImageMethod(ImageHeader::kSaveAllCalleeSavesMethod));
745 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly),
746 image_header->GetImageMethod(ImageHeader::kSaveRefsOnlyMethod));
747 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs),
748 image_header->GetImageMethod(ImageHeader::kSaveRefsAndArgsMethod));
749 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything),
750 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethod));
751 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit),
752 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForClinit));
753 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck),
754 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForSuspendCheck));
755
756 VLOG(image) << "ImageSpace::Loader::InitAppImage exiting " << *space.get();
Mathieu Chartier3f1fec62018-10-17 09:14:05 -0700757 }
758 if (VLOG_IS_ON(image)) {
759 logger.Dump(LOG_STREAM(INFO));
Vladimir Marko4df2d802018-09-27 16:42:44 +0000760 }
761 return space;
762 }
763
Andreas Gampea463b6a2016-08-12 21:53:32 -0700764 static std::unique_ptr<ImageSpace> Init(const char* image_filename,
765 const char* image_location,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700766 const OatFile* oat_file,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000767 TimingLogger* logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100768 /*inout*/MemMap* image_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100769 /*out*/std::string* error_msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700770 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700771 CHECK(image_filename != nullptr);
772 CHECK(image_location != nullptr);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800773
Andreas Gampea463b6a2016-08-12 21:53:32 -0700774 VLOG(image) << "ImageSpace::Init entering image_filename=" << image_filename;
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800775
Andreas Gampea463b6a2016-08-12 21:53:32 -0700776 std::unique_ptr<File> file;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700777 {
Vladimir Marko4df2d802018-09-27 16:42:44 +0000778 TimingLogger::ScopedTiming timing("OpenImageFile", logger);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700779 file.reset(OS::OpenFileForReading(image_filename));
780 if (file == nullptr) {
781 *error_msg = StringPrintf("Failed to open '%s'", image_filename);
782 return nullptr;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700783 }
Andreas Gampea463b6a2016-08-12 21:53:32 -0700784 }
785 ImageHeader temp_image_header;
786 ImageHeader* image_header = &temp_image_header;
787 {
Vladimir Marko4df2d802018-09-27 16:42:44 +0000788 TimingLogger::ScopedTiming timing("ReadImageHeader", logger);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700789 bool success = file->ReadFully(image_header, sizeof(*image_header));
790 if (!success || !image_header->IsValid()) {
791 *error_msg = StringPrintf("Invalid image header in '%s'", image_filename);
792 return nullptr;
793 }
794 }
795 // Check that the file is larger or equal to the header size + data size.
796 const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength());
797 if (image_file_size < sizeof(ImageHeader) + image_header->GetDataSize()) {
Mathieu Chartier1a842962018-11-13 15:09:51 -0800798 *error_msg = StringPrintf(
799 "Image file truncated: %" PRIu64 " vs. %" PRIu64 ".",
800 image_file_size,
801 static_cast<uint64_t>(sizeof(ImageHeader) + image_header->GetDataSize()));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700802 return nullptr;
803 }
804
805 if (oat_file != nullptr) {
Vladimir Marko312f10e2018-11-21 12:35:24 +0000806 // If we have an oat file (i.e. for app image), check the oat file checksum.
807 // Otherwise, we open the oat file after the image and check the checksum there.
Andreas Gampea463b6a2016-08-12 21:53:32 -0700808 const uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
809 const uint32_t image_oat_checksum = image_header->GetOatChecksum();
810 if (oat_checksum != image_oat_checksum) {
811 *error_msg = StringPrintf("Oat checksum 0x%x does not match the image one 0x%x in image %s",
812 oat_checksum,
813 image_oat_checksum,
814 image_filename);
815 return nullptr;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700816 }
817 }
818
Andreas Gampea463b6a2016-08-12 21:53:32 -0700819 if (VLOG_IS_ON(startup)) {
820 LOG(INFO) << "Dumping image sections";
821 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
822 const auto section_idx = static_cast<ImageHeader::ImageSections>(i);
823 auto& section = image_header->GetImageSection(section_idx);
824 LOG(INFO) << section_idx << " start="
825 << reinterpret_cast<void*>(image_header->GetImageBegin() + section.Offset()) << " "
826 << section;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700827 }
Andreas Gampea463b6a2016-08-12 21:53:32 -0700828 }
829
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100830 const auto& bitmap_section = image_header->GetImageBitmapSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700831 // The location we want to map from is the first aligned page after the end of the stored
832 // (possibly compressed) data.
833 const size_t image_bitmap_offset = RoundUp(sizeof(ImageHeader) + image_header->GetDataSize(),
834 kPageSize);
835 const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size();
Vladimir Markod68ab242018-10-18 16:07:10 +0100836 if (end_of_bitmap != image_file_size) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700837 *error_msg = StringPrintf(
Vladimir Markod68ab242018-10-18 16:07:10 +0100838 "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.",
Vladimir Marko6121aa62018-07-06 10:04:35 +0100839 image_file_size,
Vladimir Markod68ab242018-10-18 16:07:10 +0100840 end_of_bitmap);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700841 return nullptr;
842 }
843
Andreas Gampea463b6a2016-08-12 21:53:32 -0700844 // GetImageBegin is the preferred address to map the image. If we manage to map the
845 // image at the image begin, the amount of fixup work required is minimized.
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800846 // If it is pic we will retry with error_msg for the2 failure case. Pass a null error_msg to
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800847 // avoid reading proc maps for a mapping failure and slowing everything down.
Vladimir Markoc09cd052018-08-23 16:36:36 +0100848 // For the boot image, we have already reserved the memory and we load the image
849 // into the `image_reservation`.
Vladimir Marko312f10e2018-11-21 12:35:24 +0000850 MemMap map = LoadImageFile(
Vladimir Markoc09cd052018-08-23 16:36:36 +0100851 image_filename,
852 image_location,
853 *image_header,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100854 file->Fd(),
855 logger,
856 image_reservation,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000857 error_msg);
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100858 if (!map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700859 DCHECK(!error_msg->empty());
860 return nullptr;
861 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100862 DCHECK_EQ(0, memcmp(image_header, map.Begin(), sizeof(ImageHeader)));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700863
Vladimir Markoc09cd052018-08-23 16:36:36 +0100864 MemMap image_bitmap_map = MemMap::MapFile(bitmap_section.Size(),
Vladimir Marko4df2d802018-09-27 16:42:44 +0000865 PROT_READ,
866 MAP_PRIVATE,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100867 file->Fd(),
868 image_bitmap_offset,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100869 /*low_4gb=*/ false,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100870 image_filename,
871 error_msg);
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100872 if (!image_bitmap_map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700873 *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
874 return nullptr;
875 }
876 // Loaded the map, use the image header from the file now in case we patch it with
877 // RelocateInPlace.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100878 image_header = reinterpret_cast<ImageHeader*>(map.Begin());
Hans Boehmfb8b4e22018-09-05 16:45:42 -0700879 const uint32_t bitmap_index = ImageSpace::bitmap_index_.fetch_add(1);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700880 std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u",
881 image_filename,
882 bitmap_index));
883 // Bitmap only needs to cover until the end of the mirror objects section.
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100884 const ImageSection& image_objects = image_header->GetObjectsSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700885 // We only want the mirror object, not the ArtFields and ArtMethods.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100886 uint8_t* const image_end = map.Begin() + image_objects.End();
Mathieu Chartier6f382012019-07-30 09:47:35 -0700887 accounting::ContinuousSpaceBitmap bitmap;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700888 {
Vladimir Marko4df2d802018-09-27 16:42:44 +0000889 TimingLogger::ScopedTiming timing("CreateImageBitmap", logger);
Mathieu Chartier6f382012019-07-30 09:47:35 -0700890 bitmap = accounting::ContinuousSpaceBitmap::CreateFromMemMap(
891 bitmap_name,
892 std::move(image_bitmap_map),
893 reinterpret_cast<uint8_t*>(map.Begin()),
894 // Make sure the bitmap is aligned to card size instead of just bitmap word size.
895 RoundUp(image_objects.End(), gc::accounting::CardTable::kCardSize));
896 if (!bitmap.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700897 *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str());
898 return nullptr;
899 }
900 }
Andreas Gampea463b6a2016-08-12 21:53:32 -0700901 // We only want the mirror object, not the ArtFields and ArtMethods.
902 std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename,
903 image_location,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100904 std::move(map),
Vladimir Markoc09cd052018-08-23 16:36:36 +0100905 std::move(bitmap),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700906 image_end));
Vladimir Marko312f10e2018-11-21 12:35:24 +0000907 space->oat_file_non_owned_ = oat_file;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700908 return space;
909 }
910
Vladimir Marko7391c8c2018-11-21 17:58:44 +0000911 static bool CheckImageComponentCount(const ImageSpace& space,
912 uint32_t expected_component_count,
913 /*out*/std::string* error_msg) {
914 const ImageHeader& header = space.GetImageHeader();
915 if (header.GetComponentCount() != expected_component_count) {
916 *error_msg = StringPrintf("Unexpected component count in %s, received %u, expected %u",
917 space.GetImageFilename().c_str(),
918 header.GetComponentCount(),
919 expected_component_count);
920 return false;
921 }
922 return true;
923 }
924
925 static bool CheckImageReservationSize(const ImageSpace& space,
926 uint32_t expected_reservation_size,
927 /*out*/std::string* error_msg) {
928 const ImageHeader& header = space.GetImageHeader();
929 if (header.GetImageReservationSize() != expected_reservation_size) {
930 *error_msg = StringPrintf("Unexpected reservation size in %s, received %u, expected %u",
931 space.GetImageFilename().c_str(),
932 header.GetImageReservationSize(),
933 expected_reservation_size);
934 return false;
935 }
936 return true;
937 }
938
Andreas Gampea463b6a2016-08-12 21:53:32 -0700939 private:
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100940 static MemMap LoadImageFile(const char* image_filename,
941 const char* image_location,
942 const ImageHeader& image_header,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100943 int fd,
Vladimir Marko4df2d802018-09-27 16:42:44 +0000944 TimingLogger* logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100945 /*inout*/MemMap* image_reservation,
Mathieu Chartierf1890fd2019-04-30 17:35:08 -0700946 /*out*/std::string* error_msg)
947 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko4df2d802018-09-27 16:42:44 +0000948 TimingLogger::ScopedTiming timing("MapImageFile", logger);
Mathieu Chartier1a842962018-11-13 15:09:51 -0800949 std::string temp_error_msg;
950 const bool is_compressed = image_header.HasCompressedBlock();
951 if (!is_compressed) {
Vladimir Marko11306592018-10-26 14:22:59 +0100952 uint8_t* address = (image_reservation != nullptr) ? image_reservation->Begin() : nullptr;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700953 return MemMap::MapFileAtAddress(address,
954 image_header.GetImageSize(),
955 PROT_READ | PROT_WRITE,
956 MAP_PRIVATE,
957 fd,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100958 /*start=*/ 0,
959 /*low_4gb=*/ true,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700960 image_filename,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100961 /*reuse=*/ false,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100962 image_reservation,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700963 error_msg);
964 }
965
Andreas Gampea463b6a2016-08-12 21:53:32 -0700966 // Reserve output and decompress into it.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100967 MemMap map = MemMap::MapAnonymous(image_location,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100968 image_header.GetImageSize(),
969 PROT_READ | PROT_WRITE,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100970 /*low_4gb=*/ true,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100971 image_reservation,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100972 error_msg);
973 if (map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700974 const size_t stored_size = image_header.GetDataSize();
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100975 MemMap temp_map = MemMap::MapFile(sizeof(ImageHeader) + stored_size,
976 PROT_READ,
977 MAP_PRIVATE,
978 fd,
Vladimir Markof4efa9e2018-10-17 14:12:45 +0100979 /*start=*/ 0,
980 /*low_4gb=*/ false,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100981 image_filename,
982 error_msg);
983 if (!temp_map.IsValid()) {
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800984 DCHECK(error_msg == nullptr || !error_msg->empty());
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100985 return MemMap::Invalid();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700986 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100987 memcpy(map.Begin(), &image_header, sizeof(ImageHeader));
Mathieu Chartierc6068c72018-11-13 16:00:58 -0800988
Mathieu Chartierada33d72018-12-17 13:17:30 -0800989 Runtime::ScopedThreadPoolUsage stpu;
990 ThreadPool* const pool = stpu.GetThreadPool();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700991 const uint64_t start = NanoTime();
Mathieu Chartierc6068c72018-11-13 16:00:58 -0800992 Thread* const self = Thread::Current();
Mathieu Chartierada33d72018-12-17 13:17:30 -0800993 static constexpr size_t kMinBlocks = 2u;
994 const bool use_parallel = pool != nullptr && image_header.GetBlockCount() >= kMinBlocks;
Mathieu Chartier1a842962018-11-13 15:09:51 -0800995 for (const ImageHeader::Block& block : image_header.GetBlocks(temp_map.Begin())) {
Mathieu Chartierc6068c72018-11-13 16:00:58 -0800996 auto function = [&](Thread*) {
997 const uint64_t start2 = NanoTime();
998 ScopedTrace trace("LZ4 decompress block");
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -0800999 bool result = block.Decompress(/*out_ptr=*/map.Begin(),
1000 /*in_ptr=*/temp_map.Begin(),
1001 error_msg);
1002 if (!result && error_msg != nullptr) {
1003 *error_msg = "Failed to decompress image block " + *error_msg;
Mathieu Chartier1a842962018-11-13 15:09:51 -08001004 }
Mathieu Chartierc6068c72018-11-13 16:00:58 -08001005 VLOG(image) << "Decompress block " << block.GetDataSize() << " -> "
1006 << block.GetImageSize() << " in " << PrettyDuration(NanoTime() - start2);
1007 };
1008 if (use_parallel) {
1009 pool->AddTask(self, new FunctionTask(std::move(function)));
1010 } else {
1011 function(self);
Mathieu Chartier1a842962018-11-13 15:09:51 -08001012 }
1013 }
Mathieu Chartierc6068c72018-11-13 16:00:58 -08001014 if (use_parallel) {
1015 ScopedTrace trace("Waiting for workers");
Mathieu Chartierf1890fd2019-04-30 17:35:08 -07001016 // Go to native since we don't want to suspend while holding the mutator lock.
1017 ScopedThreadSuspension sts(Thread::Current(), kNative);
Mathieu Chartierc6068c72018-11-13 16:00:58 -08001018 pool->Wait(self, true, false);
1019 }
Mathieu Chartier0d4d2912017-02-10 17:22:41 -08001020 const uint64_t time = NanoTime() - start;
1021 // Add one 1 ns to prevent possible divide by 0.
1022 VLOG(image) << "Decompressing image took " << PrettyDuration(time) << " ("
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001023 << PrettySize(static_cast<uint64_t>(map.Size()) * MsToNs(1000) / (time + 1))
Mathieu Chartier0d4d2912017-02-10 17:22:41 -08001024 << "/s)";
Andreas Gampea463b6a2016-08-12 21:53:32 -07001025 }
1026
Vladimir Markoc34bebf2018-08-16 16:12:49 +01001027 return map;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001028 }
1029
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001030 class EmptyRange {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001031 public:
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001032 ALWAYS_INLINE bool InSource(uintptr_t) const { return false; }
1033 ALWAYS_INLINE bool InDest(uintptr_t) const { return false; }
1034 ALWAYS_INLINE uintptr_t ToDest(uintptr_t) const { UNREACHABLE(); }
1035 };
1036
1037 template <typename Range0, typename Range1 = EmptyRange, typename Range2 = EmptyRange>
1038 class ForwardAddress {
1039 public:
Vladimir Marko436c6f52019-07-25 14:50:14 +01001040 explicit ForwardAddress(const Range0& range0 = Range0(),
1041 const Range1& range1 = Range1(),
1042 const Range2& range2 = Range2())
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001043 : range0_(range0), range1_(range1), range2_(range2) {}
Andreas Gampea463b6a2016-08-12 21:53:32 -07001044
1045 // Return the relocated address of a heap object.
Mathieu Chartier9a3da9a2018-12-21 12:56:55 -08001046 // Null checks must be performed in the caller (for performance reasons).
Andreas Gampea463b6a2016-08-12 21:53:32 -07001047 template <typename T>
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001048 ALWAYS_INLINE T* operator()(T* src) const {
Mathieu Chartier9a3da9a2018-12-21 12:56:55 -08001049 DCHECK(src != nullptr);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001050 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001051 if (range2_.InSource(uint_src)) {
1052 return reinterpret_cast<T*>(range2_.ToDest(uint_src));
Andreas Gampea463b6a2016-08-12 21:53:32 -07001053 }
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001054 if (range1_.InSource(uint_src)) {
1055 return reinterpret_cast<T*>(range1_.ToDest(uint_src));
Andreas Gampea463b6a2016-08-12 21:53:32 -07001056 }
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001057 CHECK(range0_.InSource(uint_src))
1058 << reinterpret_cast<const void*>(src) << " not in "
1059 << reinterpret_cast<const void*>(range0_.Source()) << "-"
1060 << reinterpret_cast<const void*>(range0_.Source() + range0_.Length());
1061 return reinterpret_cast<T*>(range0_.ToDest(uint_src));
Andreas Gampea463b6a2016-08-12 21:53:32 -07001062 }
1063
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001064 private:
1065 const Range0 range0_;
1066 const Range1 range1_;
1067 const Range2 range2_;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001068 };
1069
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001070 template <typename Forward>
1071 class FixupRootVisitor {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001072 public:
1073 template<typename... Args>
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001074 explicit FixupRootVisitor(Args... args) : forward_(args...) {}
Andreas Gampea463b6a2016-08-12 21:53:32 -07001075
1076 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001077 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001078 if (!root->IsNull()) {
1079 VisitRoot(root);
1080 }
1081 }
1082
1083 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001084 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001085 mirror::Object* ref = root->AsMirrorPtr();
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001086 mirror::Object* new_ref = forward_(ref);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001087 if (ref != new_ref) {
1088 root->Assign(new_ref);
1089 }
1090 }
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001091
1092 private:
1093 Forward forward_;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001094 };
1095
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001096 template <typename Forward>
1097 class FixupObjectVisitor {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001098 public:
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001099 explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited,
1100 const Forward& forward)
1101 : visited_(visited), forward_(forward) {}
Andreas Gampea463b6a2016-08-12 21:53:32 -07001102
1103 // Fix up separately since we also need to fix up method entrypoints.
1104 ALWAYS_INLINE void VisitRootIfNonNull(
1105 mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
1106
1107 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
1108 const {}
1109
Mathieu Chartier31e88222016-10-14 18:43:19 -07001110 ALWAYS_INLINE void operator()(ObjPtr<mirror::Object> obj,
Andreas Gampea463b6a2016-08-12 21:53:32 -07001111 MemberOffset offset,
1112 bool is_static ATTRIBUTE_UNUSED) const
1113 NO_THREAD_SAFETY_ANALYSIS {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001114 // Space is not yet added to the heap, don't do a read barrier.
1115 mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(
1116 offset);
Mathieu Chartier9a3da9a2018-12-21 12:56:55 -08001117 if (ref != nullptr) {
1118 // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
1119 // image.
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001120 obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(offset, forward_(ref));
Mathieu Chartier9a3da9a2018-12-21 12:56:55 -08001121 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001122 }
1123
1124 // java.lang.ref.Reference visitor.
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001125 ALWAYS_INLINE void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001126 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001127 DCHECK(klass->IsTypeOfReferenceClass());
1128 this->operator()(ref, mirror::Reference::ReferentOffset(), /*is_static=*/ false);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001129 }
1130
Mathieu Chartier8c19d242017-03-06 12:35:10 -08001131 void operator()(mirror::Object* obj) const
1132 NO_THREAD_SAFETY_ANALYSIS {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001133 if (!visited_->Set(obj)) {
1134 // Not already visited.
1135 obj->VisitReferences</*visit native roots*/false, kVerifyNone, kWithoutReadBarrier>(
1136 *this,
1137 *this);
1138 CHECK(!obj->IsClass());
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001139 }
1140 }
Mathieu Chartier91edc622016-02-16 17:16:01 -08001141
Andreas Gampea463b6a2016-08-12 21:53:32 -07001142 private:
Andreas Gampea463b6a2016-08-12 21:53:32 -07001143 gc::accounting::ContinuousSpaceBitmap* const visited_;
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001144 Forward forward_;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001145 };
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001146
Andreas Gampea463b6a2016-08-12 21:53:32 -07001147 // Relocate an image space mapped at target_base which possibly used to be at a different base
Vladimir Marko4df2d802018-09-27 16:42:44 +00001148 // address. In place means modifying a single ImageSpace in place rather than relocating from
1149 // one ImageSpace to another.
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001150 template <PointerSize kPointerSize>
Andreas Gampea463b6a2016-08-12 21:53:32 -07001151 static bool RelocateInPlace(ImageHeader& image_header,
1152 uint8_t* target_base,
1153 accounting::ContinuousSpaceBitmap* bitmap,
1154 const OatFile* app_oat_file,
1155 std::string* error_msg) {
1156 DCHECK(error_msg != nullptr);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001157 // Set up sections.
Andreas Gampea463b6a2016-08-12 21:53:32 -07001158 gc::Heap* const heap = Runtime::Current()->GetHeap();
Vladimir Marko1aff1ef2019-07-02 15:12:50 +01001159 uint32_t boot_image_begin = heap->GetBootImagesStartAddress();
1160 uint32_t boot_image_size = heap->GetBootImagesSize();
1161 if (boot_image_size == 0u) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001162 *error_msg = "Can not relocate app image without boot image space";
1163 return false;
1164 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001165 const uint32_t image_header_boot_image_size = image_header.GetBootImageSize();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001166 if (boot_image_size != image_header_boot_image_size) {
1167 *error_msg = StringPrintf("Boot image size %" PRIu64 " does not match expected size %"
1168 PRIu64,
1169 static_cast<uint64_t>(boot_image_size),
1170 static_cast<uint64_t>(image_header_boot_image_size));
1171 return false;
1172 }
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001173 const ImageSection& objects_section = image_header.GetObjectsSection();
1174 // Where the app image objects are mapped to.
1175 uint8_t* objects_location = target_base + objects_section.Offset();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001176 TimingLogger logger(__FUNCTION__, true, false);
1177 RelocationRange boot_image(image_header.GetBootImageBegin(),
1178 boot_image_begin,
1179 boot_image_size);
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001180 // Metadata is everything after the objects section, use exclusion to be safe.
1181 RelocationRange app_image_metadata(
1182 reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.End(),
1183 reinterpret_cast<uintptr_t>(target_base) + objects_section.End(),
1184 image_header.GetImageSize() - objects_section.End());
1185 // App image heap objects, may be mapped in the heap.
1186 RelocationRange app_image_objects(
1187 reinterpret_cast<uintptr_t>(image_header.GetImageBegin()) + objects_section.Offset(),
1188 reinterpret_cast<uintptr_t>(objects_location),
1189 objects_section.Size());
Andreas Gampea463b6a2016-08-12 21:53:32 -07001190 // Use the oat data section since this is where the OatFile::Begin is.
1191 RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
1192 // Not necessarily in low 4GB.
1193 reinterpret_cast<uintptr_t>(app_oat_file->Begin()),
1194 image_header.GetOatDataEnd() - image_header.GetOatDataBegin());
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001195 VLOG(image) << "App image metadata " << app_image_metadata;
1196 VLOG(image) << "App image objects " << app_image_objects;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001197 VLOG(image) << "App oat " << app_oat;
1198 VLOG(image) << "Boot image " << boot_image;
Vladimir Marko0c78ef72018-11-21 14:09:35 +00001199 // True if we need to fixup any heap pointers.
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001200 const bool fixup_image = boot_image.Delta() != 0 || app_image_metadata.Delta() != 0 ||
1201 app_image_objects.Delta() != 0;
Vladimir Marko0c78ef72018-11-21 14:09:35 +00001202 if (!fixup_image) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001203 // Nothing to fix up.
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001204 return true;
1205 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001206 ScopedDebugDisallowReadBarriers sddrb(Thread::Current());
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001207
1208 using ForwardObject = ForwardAddress<RelocationRange, RelocationRange>;
1209 ForwardObject forward_object(boot_image, app_image_objects);
1210 ForwardObject forward_metadata(boot_image, app_image_metadata);
1211 using ForwardCode = ForwardAddress<RelocationRange, RelocationRange>;
1212 ForwardCode forward_code(boot_image, app_oat);
1213 PatchObjectVisitor<kPointerSize, ForwardObject, ForwardCode> patch_object_visitor(
1214 forward_object,
1215 forward_metadata);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001216 if (fixup_image) {
1217 // Two pass approach, fix up all classes first, then fix up non class-objects.
1218 // The visited bitmap is used to ensure that pointer arrays are not forwarded twice.
Mathieu Chartier6f382012019-07-30 09:47:35 -07001219 gc::accounting::ContinuousSpaceBitmap visited_bitmap(
Andreas Gampea463b6a2016-08-12 21:53:32 -07001220 gc::accounting::ContinuousSpaceBitmap::Create("Relocate bitmap",
1221 target_base,
1222 image_header.GetImageSize()));
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001223 {
1224 TimingLogger::ScopedTiming timing("Fixup classes", &logger);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001225 ObjPtr<mirror::Class> class_class = [&]() NO_THREAD_SAFETY_ANALYSIS {
1226 ObjPtr<mirror::ObjectArray<mirror::Object>> image_roots = app_image_objects.ToDest(
1227 image_header.GetImageRoots<kWithoutReadBarrier>().Ptr());
1228 int32_t class_roots_index = enum_cast<int32_t>(ImageHeader::kClassRoots);
1229 DCHECK_LT(class_roots_index, image_roots->GetLength<kVerifyNone>());
1230 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
1231 ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(boot_image.ToDest(
1232 image_roots->GetWithoutChecks<kVerifyNone>(class_roots_index).Ptr()));
1233 return GetClassRoot<mirror::Class, kWithoutReadBarrier>(class_roots);
1234 }();
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001235 const auto& class_table_section = image_header.GetClassTableSection();
1236 if (class_table_section.Size() > 0u) {
1237 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001238 ClassTableVisitor class_table_visitor(forward_object);
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001239 size_t read_count = 0u;
1240 const uint8_t* data = target_base + class_table_section.Offset();
1241 // We avoid making a copy of the data since we want modifications to be propagated to the
1242 // memory map.
1243 ClassTable::ClassSet temp_set(data, /*make_copy_of_data=*/ false, &read_count);
1244 for (ClassTable::TableSlot& slot : temp_set) {
1245 slot.VisitRoot(class_table_visitor);
Vladimir Marko1fe58392019-04-10 16:14:56 +01001246 ObjPtr<mirror::Class> klass = slot.Read<kWithoutReadBarrier>();
1247 if (!app_image_objects.InDest(klass.Ptr())) {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001248 continue;
1249 }
Mathieu Chartier6f382012019-07-30 09:47:35 -07001250 const bool already_marked = visited_bitmap.Set(klass.Ptr());
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001251 CHECK(!already_marked) << "App image class already visited";
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001252 patch_object_visitor.VisitClass(klass, class_class);
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001253 // Then patch the non-embedded vtable and iftable.
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001254 ObjPtr<mirror::PointerArray> vtable =
1255 klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001256 if (vtable != nullptr &&
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001257 app_image_objects.InDest(vtable.Ptr()) &&
Mathieu Chartier6f382012019-07-30 09:47:35 -07001258 !visited_bitmap.Set(vtable.Ptr())) {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001259 patch_object_visitor.VisitPointerArray(vtable);
1260 }
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001261 ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
1262 if (iftable != nullptr && app_image_objects.InDest(iftable.Ptr())) {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001263 // Avoid processing the fields of iftable since we will process them later anyways
1264 // below.
1265 int32_t ifcount = klass->GetIfTableCount<kVerifyNone>();
1266 for (int32_t i = 0; i != ifcount; ++i) {
Vladimir Marko557fece2019-03-26 14:29:41 +00001267 ObjPtr<mirror::PointerArray> unpatched_ifarray =
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001268 iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
1269 if (unpatched_ifarray != nullptr) {
1270 // The iftable has not been patched, so we need to explicitly adjust the pointer.
Vladimir Marko557fece2019-03-26 14:29:41 +00001271 ObjPtr<mirror::PointerArray> ifarray = forward_object(unpatched_ifarray.Ptr());
1272 if (app_image_objects.InDest(ifarray.Ptr()) &&
Mathieu Chartier6f382012019-07-30 09:47:35 -07001273 !visited_bitmap.Set(ifarray.Ptr())) {
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001274 patch_object_visitor.VisitPointerArray(ifarray);
1275 }
1276 }
1277 }
1278 }
1279 }
1280 }
1281 }
1282
1283 // Fixup objects may read fields in the boot image, use the mutator lock here for sanity.
1284 // Though its probably not required.
Mathieu Chartier2ffc74b2019-01-03 19:25:41 -08001285 TimingLogger::ScopedTiming timing("Fixup objects", &logger);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001286 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001287 // Need to update the image to be at the target base.
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001288 uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset());
1289 uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End());
Mathieu Chartier6f382012019-07-30 09:47:35 -07001290 FixupObjectVisitor<ForwardObject> fixup_object_visitor(&visited_bitmap, forward_object);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001291 bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
1292 // Fixup image roots.
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001293 CHECK(app_image_objects.InSource(reinterpret_cast<uintptr_t>(
Vladimir Markoc13fbd82018-06-04 16:16:28 +01001294 image_header.GetImageRoots<kWithoutReadBarrier>().Ptr())));
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001295 image_header.RelocateImageReferences(app_image_objects.Delta());
1296 image_header.RelocateBootImageReferences(boot_image.Delta());
Andreas Gampea463b6a2016-08-12 21:53:32 -07001297 CHECK_EQ(image_header.GetImageBegin(), target_base);
1298 // Fix up dex cache DexFile pointers.
Vladimir Marko4617d582019-03-28 13:48:31 +00001299 ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
1300 image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)
1301 ->AsObjectArray<mirror::DexCache, kVerifyNone>();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001302 for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
Vladimir Marko423bebb2019-03-26 15:17:21 +00001303 ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i);
Mathieu Chartier25602dc2018-12-11 11:31:57 -08001304 CHECK(dex_cache != nullptr);
1305 patch_object_visitor.VisitDexCacheArrays(dex_cache);
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001306 }
1307 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001308 {
1309 // Only touches objects in the app image, no need for mutator lock.
Andreas Gampea463b6a2016-08-12 21:53:32 -07001310 TimingLogger::ScopedTiming timing("Fixup methods", &logger);
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001311 image_header.VisitPackedArtMethods([&](ArtMethod& method) NO_THREAD_SAFETY_ANALYSIS {
1312 // TODO: Consider a separate visitor for runtime vs normal methods.
1313 if (UNLIKELY(method.IsRuntimeMethod())) {
1314 ImtConflictTable* table = method.GetImtConflictTable(kPointerSize);
1315 if (table != nullptr) {
1316 ImtConflictTable* new_table = forward_metadata(table);
1317 if (table != new_table) {
1318 method.SetImtConflictTable(new_table, kPointerSize);
1319 }
1320 }
1321 const void* old_code = method.GetEntryPointFromQuickCompiledCodePtrSize(kPointerSize);
1322 const void* new_code = forward_code(old_code);
1323 if (old_code != new_code) {
1324 method.SetEntryPointFromQuickCompiledCodePtrSize(new_code, kPointerSize);
1325 }
1326 } else {
Vladimir Marko2180d8e2019-04-11 14:22:53 +01001327 patch_object_visitor.PatchGcRoot(&method.DeclaringClassRoot());
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001328 method.UpdateEntrypoints(forward_code, kPointerSize);
1329 }
1330 }, target_base, kPointerSize);
Mathieu Chartiere42888f2016-04-14 10:49:19 -07001331 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001332 if (fixup_image) {
1333 {
1334 // Only touches objects in the app image, no need for mutator lock.
1335 TimingLogger::ScopedTiming timing("Fixup fields", &logger);
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001336 image_header.VisitPackedArtFields([&](ArtField& field) NO_THREAD_SAFETY_ANALYSIS {
Vladimir Marko2180d8e2019-04-11 14:22:53 +01001337 patch_object_visitor.template PatchGcRoot</*kMayBeNull=*/ false>(
1338 &field.DeclaringClassRoot());
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001339 }, target_base);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001340 }
1341 {
1342 TimingLogger::ScopedTiming timing("Fixup imt", &logger);
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001343 image_header.VisitPackedImTables(forward_metadata, target_base, kPointerSize);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001344 }
1345 {
1346 TimingLogger::ScopedTiming timing("Fixup conflict tables", &logger);
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001347 image_header.VisitPackedImtConflictTables(forward_metadata, target_base, kPointerSize);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001348 }
Mathieu Chartier74ccee62018-10-10 10:30:29 -07001349 // Fix up the intern table.
1350 const auto& intern_table_section = image_header.GetInternedStringsSection();
1351 if (intern_table_section.Size() > 0u) {
1352 TimingLogger::ScopedTiming timing("Fixup intern table", &logger);
1353 ScopedObjectAccess soa(Thread::Current());
1354 // Fixup the pointers in the newly written intern table to contain image addresses.
1355 InternTable temp_intern_table;
1356 // Note that we require that ReadFromMemory does not make an internal copy of the elements
1357 // so that the VisitRoots() will update the memory directly rather than the copies.
Mathieu Chartier74ccee62018-10-10 10:30:29 -07001358 temp_intern_table.AddTableFromMemory(target_base + intern_table_section.Offset(),
1359 [&](InternTable::UnorderedSet& strings)
1360 REQUIRES_SHARED(Locks::mutator_lock_) {
1361 for (GcRoot<mirror::String>& root : strings) {
Mathieu Chartierf0a96eb2019-01-11 11:06:43 -08001362 root = GcRoot<mirror::String>(forward_object(root.Read<kWithoutReadBarrier>()));
Mathieu Chartier74ccee62018-10-10 10:30:29 -07001363 }
Mathieu Chartier8cc418e2018-10-31 10:54:30 -07001364 }, /*is_boot_image=*/ false);
Mathieu Chartier74ccee62018-10-10 10:30:29 -07001365 }
Artem Udovichenkoa62cb9b2016-06-30 09:18:25 +00001366 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001367 if (VLOG_IS_ON(image)) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001368 logger.Dump(LOG_STREAM(INFO));
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001369 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001370 return true;
Andreas Gampe7fa55782016-06-15 17:45:01 -07001371 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001372};
Hiroshi Yamauchibd0fb612014-05-20 13:46:00 -07001373
Vladimir Marko82e1e272018-08-20 13:38:06 +00001374class ImageSpace::BootImageLoader {
1375 public:
Vladimir Marko91f10322018-12-07 18:04:10 +00001376 BootImageLoader(const std::vector<std::string>& boot_class_path,
1377 const std::vector<std::string>& boot_class_path_locations,
1378 const std::string& image_location,
Vladimir Marko3364d182019-03-13 13:55:01 +00001379 InstructionSet image_isa,
1380 bool relocate,
1381 bool executable,
1382 bool is_zygote)
Vladimir Marko91f10322018-12-07 18:04:10 +00001383 : boot_class_path_(boot_class_path),
1384 boot_class_path_locations_(boot_class_path_locations),
1385 image_location_(image_location),
Vladimir Marko82e1e272018-08-20 13:38:06 +00001386 image_isa_(image_isa),
Vladimir Marko3364d182019-03-13 13:55:01 +00001387 relocate_(relocate),
1388 executable_(executable),
1389 is_zygote_(is_zygote),
Vladimir Marko82e1e272018-08-20 13:38:06 +00001390 has_system_(false),
1391 has_cache_(false),
1392 is_global_cache_(true),
Vladimir Markoe3070022018-08-22 09:36:19 +00001393 dalvik_cache_exists_(false),
Vladimir Marko82e1e272018-08-20 13:38:06 +00001394 dalvik_cache_(),
1395 cache_filename_() {
1396 }
1397
1398 bool IsZygote() const { return is_zygote_; }
1399
1400 void FindImageFiles() {
1401 std::string system_filename;
Vladimir Marko82e1e272018-08-20 13:38:06 +00001402 bool found_image = FindImageFilenameImpl(image_location_.c_str(),
1403 image_isa_,
1404 &has_system_,
1405 &system_filename,
Vladimir Markoe3070022018-08-22 09:36:19 +00001406 &dalvik_cache_exists_,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001407 &dalvik_cache_,
1408 &is_global_cache_,
1409 &has_cache_,
1410 &cache_filename_);
Vladimir Markoe3070022018-08-22 09:36:19 +00001411 DCHECK(!dalvik_cache_exists_ || !dalvik_cache_.empty());
Vladimir Marko82e1e272018-08-20 13:38:06 +00001412 DCHECK_EQ(found_image, has_system_ || has_cache_);
1413 }
1414
1415 bool HasSystem() const { return has_system_; }
1416 bool HasCache() const { return has_cache_; }
1417
Vladimir Markoe3070022018-08-22 09:36:19 +00001418 bool DalvikCacheExists() const { return dalvik_cache_exists_; }
Vladimir Marko82e1e272018-08-20 13:38:06 +00001419 bool IsGlobalCache() const { return is_global_cache_; }
1420
1421 const std::string& GetDalvikCache() const {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001422 return dalvik_cache_;
1423 }
1424
1425 const std::string& GetCacheFilename() const {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001426 return cache_filename_;
1427 }
1428
Andreas Gampe86823542019-02-25 09:38:49 -08001429 bool LoadFromSystem(bool validate_oat_file,
1430 size_t extra_reservation_size,
Vladimir Markod44d7032018-08-30 13:02:31 +01001431 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1432 /*out*/MemMap* extra_reservation,
1433 /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001434 TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
Vladimir Marko82e1e272018-08-20 13:38:06 +00001435 std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001436
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001437 if (!LoadFromFile(filename,
Andreas Gampe86823542019-02-25 09:38:49 -08001438 validate_oat_file,
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001439 extra_reservation_size,
1440 &logger,
1441 boot_image_spaces,
1442 extra_reservation,
1443 error_msg)) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001444 return false;
1445 }
1446
Vladimir Marko4df2d802018-09-27 16:42:44 +00001447 if (VLOG_IS_ON(image)) {
Vladimir Marko312f10e2018-11-21 12:35:24 +00001448 LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromSystem exiting "
1449 << boot_image_spaces->front();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001450 logger.Dump(LOG_STREAM(INFO));
1451 }
Vladimir Marko82e1e272018-08-20 13:38:06 +00001452 return true;
1453 }
1454
1455 bool LoadFromDalvikCache(
Vladimir Marko82e1e272018-08-20 13:38:06 +00001456 bool validate_oat_file,
Vladimir Markod44d7032018-08-30 13:02:31 +01001457 size_t extra_reservation_size,
1458 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1459 /*out*/MemMap* extra_reservation,
1460 /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001461 TimingLogger logger(__PRETTY_FUNCTION__, /*precise=*/ true, VLOG_IS_ON(image));
Vladimir Marko82e1e272018-08-20 13:38:06 +00001462 DCHECK(DalvikCacheExists());
Vladimir Markoc09cd052018-08-23 16:36:36 +01001463
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001464 if (!LoadFromFile(cache_filename_,
1465 validate_oat_file,
1466 extra_reservation_size,
1467 &logger,
1468 boot_image_spaces,
1469 extra_reservation,
1470 error_msg)) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001471 return false;
1472 }
1473
Vladimir Marko4df2d802018-09-27 16:42:44 +00001474 if (VLOG_IS_ON(image)) {
Vladimir Marko312f10e2018-11-21 12:35:24 +00001475 LOG(INFO) << "ImageSpace::BootImageLoader::LoadFromDalvikCache exiting "
1476 << boot_image_spaces->front();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001477 logger.Dump(LOG_STREAM(INFO));
1478 }
Vladimir Marko82e1e272018-08-20 13:38:06 +00001479 return true;
1480 }
1481
1482 private:
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001483 bool LoadFromFile(
1484 const std::string& filename,
1485 bool validate_oat_file,
1486 size_t extra_reservation_size,
1487 TimingLogger* logger,
1488 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1489 /*out*/MemMap* extra_reservation,
1490 /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
1491 ImageHeader system_hdr;
Vladimir Marko1b13d282019-10-23 15:10:55 +01001492 if (!ReadSpecificImageHeader(filename.c_str(), &system_hdr, error_msg)) {
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001493 return false;
1494 }
Vladimir Marko0ace5632018-12-14 11:11:47 +00001495 if (system_hdr.GetComponentCount() == 0u ||
1496 system_hdr.GetComponentCount() > boot_class_path_.size()) {
1497 *error_msg = StringPrintf("Unexpected component count in %s, received %u, "
1498 "expected non-zero and <= %zu",
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001499 filename.c_str(),
1500 system_hdr.GetComponentCount(),
1501 boot_class_path_.size());
1502 return false;
1503 }
1504 MemMap image_reservation;
1505 MemMap local_extra_reservation;
1506 if (!ReserveBootImageMemory(system_hdr.GetImageReservationSize(),
1507 reinterpret_cast32<uint32_t>(system_hdr.GetImageBegin()),
1508 extra_reservation_size,
1509 &image_reservation,
1510 &local_extra_reservation,
1511 error_msg)) {
1512 return false;
1513 }
1514
Vladimir Marko0ace5632018-12-14 11:11:47 +00001515 ArrayRef<const std::string> provided_locations(boot_class_path_locations_.data(),
1516 system_hdr.GetComponentCount());
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001517 std::vector<std::string> locations =
Vladimir Marko0ace5632018-12-14 11:11:47 +00001518 ExpandMultiImageLocations(provided_locations, image_location_);
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001519 std::vector<std::string> filenames =
Vladimir Marko0ace5632018-12-14 11:11:47 +00001520 ExpandMultiImageLocations(provided_locations, filename);
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001521 DCHECK_EQ(locations.size(), filenames.size());
1522 std::vector<std::unique_ptr<ImageSpace>> spaces;
1523 spaces.reserve(locations.size());
1524 for (std::size_t i = 0u, size = locations.size(); i != size; ++i) {
1525 spaces.push_back(Load(locations[i], filenames[i], logger, &image_reservation, error_msg));
1526 const ImageSpace* space = spaces.back().get();
1527 if (space == nullptr) {
1528 return false;
1529 }
1530 uint32_t expected_component_count = (i == 0u) ? system_hdr.GetComponentCount() : 0u;
1531 uint32_t expected_reservation_size = (i == 0u) ? system_hdr.GetImageReservationSize() : 0u;
1532 if (!Loader::CheckImageReservationSize(*space, expected_reservation_size, error_msg) ||
1533 !Loader::CheckImageComponentCount(*space, expected_component_count, error_msg)) {
1534 return false;
1535 }
1536 }
1537 for (size_t i = 0u, size = spaces.size(); i != size; ++i) {
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001538 if (!OpenOatFile(spaces[i].get(),
1539 boot_class_path_[i],
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001540 validate_oat_file,
Vladimir Marko436c6f52019-07-25 14:50:14 +01001541 /*available_dependencies=*/ ArrayRef<const std::unique_ptr<ImageSpace>>(),
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001542 logger,
1543 &image_reservation,
1544 error_msg)) {
1545 return false;
1546 }
1547 }
1548 if (!CheckReservationExhausted(image_reservation, error_msg)) {
1549 return false;
1550 }
1551
1552 MaybeRelocateSpaces(spaces, logger);
Vladimir Marko7391c8c2018-11-21 17:58:44 +00001553 boot_image_spaces->swap(spaces);
1554 *extra_reservation = std::move(local_extra_reservation);
1555 return true;
1556 }
1557
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001558 private:
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001559 class SimpleRelocateVisitor {
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001560 public:
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001561 SimpleRelocateVisitor(uint32_t diff, uint32_t begin, uint32_t size)
1562 : diff_(diff), begin_(begin), size_(size) {}
1563
1564 // Adapter taking the same arguments as SplitRangeRelocateVisitor
1565 // to simplify constructing the various visitors in DoRelocateSpaces().
1566 SimpleRelocateVisitor(uint32_t base_diff,
1567 uint32_t current_diff,
1568 uint32_t bound,
1569 uint32_t begin,
1570 uint32_t size)
1571 : SimpleRelocateVisitor(base_diff, begin, size) {
1572 // Check arguments unused by this class.
1573 DCHECK_EQ(base_diff, current_diff);
1574 DCHECK_EQ(bound, begin);
1575 }
Vladimir Marko4df2d802018-09-27 16:42:44 +00001576
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001577 template <typename T>
1578 ALWAYS_INLINE T* operator()(T* src) const {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001579 DCHECK(InSource(src));
1580 uint32_t raw_src = reinterpret_cast32<uint32_t>(src);
1581 return reinterpret_cast32<T*>(raw_src + diff_);
1582 }
1583
1584 template <typename T>
1585 ALWAYS_INLINE bool InSource(T* ptr) const {
1586 uint32_t raw_ptr = reinterpret_cast32<uint32_t>(ptr);
1587 return raw_ptr - begin_ < size_;
Vladimir Marko4df2d802018-09-27 16:42:44 +00001588 }
Vladimir Marko4df2d802018-09-27 16:42:44 +00001589
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001590 private:
1591 const uint32_t diff_;
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001592 const uint32_t begin_;
1593 const uint32_t size_;
1594 };
1595
1596 class SplitRangeRelocateVisitor {
1597 public:
1598 SplitRangeRelocateVisitor(uint32_t base_diff,
1599 uint32_t current_diff,
1600 uint32_t bound,
1601 uint32_t begin,
1602 uint32_t size)
1603 : base_diff_(base_diff),
1604 current_diff_(current_diff),
1605 bound_(bound),
1606 begin_(begin),
1607 size_(size) {
1608 DCHECK_NE(begin_, bound_);
1609 // The bound separates the boot image range and the extension range.
1610 DCHECK_LT(bound_ - begin_, size_);
1611 }
1612
1613 template <typename T>
1614 ALWAYS_INLINE T* operator()(T* src) const {
1615 DCHECK(InSource(src));
1616 uint32_t raw_src = reinterpret_cast32<uint32_t>(src);
1617 uint32_t diff = (raw_src < bound_) ? base_diff_ : current_diff_;
1618 return reinterpret_cast32<T*>(raw_src + diff);
1619 }
1620
1621 template <typename T>
1622 ALWAYS_INLINE bool InSource(T* ptr) const {
1623 uint32_t raw_ptr = reinterpret_cast32<uint32_t>(ptr);
1624 return raw_ptr - begin_ < size_;
1625 }
1626
1627 private:
1628 const uint32_t base_diff_;
1629 const uint32_t current_diff_;
1630 const uint32_t bound_;
1631 const uint32_t begin_;
1632 const uint32_t size_;
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001633 };
Vladimir Marko4df2d802018-09-27 16:42:44 +00001634
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001635 static void** PointerAddress(ArtMethod* method, MemberOffset offset) {
1636 return reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(method) + offset.Uint32Value());
1637 }
1638
Vladimir Marko4df2d802018-09-27 16:42:44 +00001639 template <PointerSize kPointerSize>
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001640 static void DoRelocateSpaces(ArrayRef<const std::unique_ptr<ImageSpace>>& spaces,
1641 int64_t base_diff64) REQUIRES_SHARED(Locks::mutator_lock_) {
1642 DCHECK(!spaces.empty());
Mathieu Chartier6f382012019-07-30 09:47:35 -07001643 gc::accounting::ContinuousSpaceBitmap patched_objects(
Mathieu Chartier2ffc74b2019-01-03 19:25:41 -08001644 gc::accounting::ContinuousSpaceBitmap::Create(
1645 "Marked objects",
1646 spaces.front()->Begin(),
1647 spaces.back()->End() - spaces.front()->Begin()));
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001648 const ImageHeader& base_header = spaces[0]->GetImageHeader();
1649 size_t base_component_count = base_header.GetComponentCount();
1650 DCHECK_LE(base_component_count, spaces.size());
1651 DoRelocateSpaces<kPointerSize, /*kExtension=*/ false>(
1652 spaces.SubArray(/*pos=*/ 0u, base_component_count),
1653 base_diff64,
Mathieu Chartier6f382012019-07-30 09:47:35 -07001654 &patched_objects);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001655
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001656 for (size_t i = base_component_count, size = spaces.size(); i != size; ) {
1657 const ImageHeader& ext_header = spaces[i]->GetImageHeader();
1658 size_t ext_component_count = ext_header.GetComponentCount();
1659 DCHECK_LE(ext_component_count, size - i);
1660 DoRelocateSpaces<kPointerSize, /*kExtension=*/ true>(
1661 spaces.SubArray(/*pos=*/ i, ext_component_count),
1662 base_diff64,
Mathieu Chartier6f382012019-07-30 09:47:35 -07001663 &patched_objects);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001664 i += ext_component_count;
1665 }
1666 }
1667
1668 template <PointerSize kPointerSize, bool kExtension>
1669 static void DoRelocateSpaces(ArrayRef<const std::unique_ptr<ImageSpace>> spaces,
1670 int64_t base_diff64,
1671 gc::accounting::ContinuousSpaceBitmap* patched_objects)
1672 REQUIRES_SHARED(Locks::mutator_lock_) {
1673 DCHECK(!spaces.empty());
1674 const ImageHeader& first_header = spaces.front()->GetImageHeader();
1675 uint32_t image_begin = reinterpret_cast32<uint32_t>(first_header.GetImageBegin());
1676 uint32_t image_size = first_header.GetImageReservationSize();
1677 DCHECK_NE(image_size, 0u);
1678 uint32_t source_begin = kExtension ? first_header.GetBootImageBegin() : image_begin;
1679 uint32_t source_size = kExtension ? first_header.GetBootImageSize() + image_size : image_size;
1680 if (kExtension) {
1681 DCHECK_EQ(first_header.GetBootImageBegin() + first_header.GetBootImageSize(), image_begin);
1682 }
1683 int64_t current_diff64 = kExtension
1684 ? static_cast<int64_t>(reinterpret_cast32<uint32_t>(spaces.front()->Begin())) -
1685 static_cast<int64_t>(image_begin)
1686 : base_diff64;
1687 uint32_t base_diff = static_cast<uint32_t>(base_diff64);
1688 uint32_t current_diff = static_cast<uint32_t>(current_diff64);
1689
1690 // For boot image the main visitor is a SimpleRelocateVisitor. For the boot image extension we
1691 // mostly use a SplitRelocationVisitor but some work can still use the SimpleRelocationVisitor.
1692 using MainRelocateVisitor = typename std::conditional<
1693 kExtension, SplitRangeRelocateVisitor, SimpleRelocateVisitor>::type;
1694 SimpleRelocateVisitor simple_relocate_visitor(current_diff, image_begin, image_size);
1695 MainRelocateVisitor main_relocate_visitor(
1696 base_diff, current_diff, /*bound=*/ image_begin, source_begin, source_size);
1697
1698 using MainPatchRelocateVisitor =
1699 PatchObjectVisitor<kPointerSize, MainRelocateVisitor, MainRelocateVisitor>;
1700 using SimplePatchRelocateVisitor =
1701 PatchObjectVisitor<kPointerSize, SimpleRelocateVisitor, SimpleRelocateVisitor>;
1702 MainPatchRelocateVisitor main_patch_object_visitor(main_relocate_visitor,
1703 main_relocate_visitor);
1704 SimplePatchRelocateVisitor simple_patch_object_visitor(simple_relocate_visitor,
1705 simple_relocate_visitor);
1706
1707 // Retrieve the Class.class, Method.class and Constructor.class needed in the loops below.
1708 ObjPtr<mirror::Class> class_class;
1709 ObjPtr<mirror::Class> method_class;
1710 ObjPtr<mirror::Class> constructor_class;
1711 {
1712 ObjPtr<mirror::ObjectArray<mirror::Object>> image_roots =
1713 simple_relocate_visitor(first_header.GetImageRoots<kWithoutReadBarrier>().Ptr());
1714 DCHECK(!patched_objects->Test(image_roots.Ptr()));
1715
1716 SimpleRelocateVisitor base_relocate_visitor(
1717 base_diff,
1718 source_begin,
1719 kExtension ? source_size - image_size : image_size);
1720 int32_t class_roots_index = enum_cast<int32_t>(ImageHeader::kClassRoots);
1721 DCHECK_LT(class_roots_index, image_roots->GetLength<kVerifyNone>());
1722 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
1723 ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(base_relocate_visitor(
1724 image_roots->GetWithoutChecks<kVerifyNone>(class_roots_index).Ptr()));
1725 if (kExtension) {
1726 DCHECK(patched_objects->Test(class_roots.Ptr()));
1727 class_class = GetClassRoot<mirror::Class, kWithoutReadBarrier>(class_roots);
1728 method_class = GetClassRoot<mirror::Method, kWithoutReadBarrier>(class_roots);
1729 constructor_class = GetClassRoot<mirror::Constructor, kWithoutReadBarrier>(class_roots);
1730 } else {
1731 DCHECK(!patched_objects->Test(class_roots.Ptr()));
1732 class_class = simple_relocate_visitor(
1733 GetClassRoot<mirror::Class, kWithoutReadBarrier>(class_roots).Ptr());
1734 method_class = simple_relocate_visitor(
1735 GetClassRoot<mirror::Method, kWithoutReadBarrier>(class_roots).Ptr());
1736 constructor_class = simple_relocate_visitor(
1737 GetClassRoot<mirror::Constructor, kWithoutReadBarrier>(class_roots).Ptr());
1738 }
1739 }
1740
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001741 for (const std::unique_ptr<ImageSpace>& space : spaces) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001742 // First patch the image header.
1743 reinterpret_cast<ImageHeader*>(space->Begin())->RelocateImageReferences(current_diff64);
1744 reinterpret_cast<ImageHeader*>(space->Begin())->RelocateBootImageReferences(base_diff64);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001745
1746 // Patch fields and methods.
1747 const ImageHeader& image_header = space->GetImageHeader();
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001748 image_header.VisitPackedArtFields([&](ArtField& field) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001749 // Fields always reference class in the current image.
1750 simple_patch_object_visitor.template PatchGcRoot</*kMayBeNull=*/ false>(
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001751 &field.DeclaringClassRoot());
1752 }, space->Begin());
1753 image_header.VisitPackedArtMethods([&](ArtMethod& method)
1754 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001755 main_patch_object_visitor.PatchGcRoot(&method.DeclaringClassRoot());
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001756 void** data_address = PointerAddress(&method, ArtMethod::DataOffset(kPointerSize));
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001757 main_patch_object_visitor.PatchNativePointer(data_address);
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001758 void** entrypoint_address =
1759 PointerAddress(&method, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kPointerSize));
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001760 main_patch_object_visitor.PatchNativePointer(entrypoint_address);
Mathieu Chartier9d5956a2019-03-22 11:29:08 -07001761 }, space->Begin(), kPointerSize);
Mathieu Chartierd3f037b2018-12-06 23:50:56 -08001762 auto method_table_visitor = [&](ArtMethod* method) {
Vladimir Marko4df2d802018-09-27 16:42:44 +00001763 DCHECK(method != nullptr);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001764 return main_relocate_visitor(method);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001765 };
1766 image_header.VisitPackedImTables(method_table_visitor, space->Begin(), kPointerSize);
1767 image_header.VisitPackedImtConflictTables(method_table_visitor, space->Begin(), kPointerSize);
1768
1769 // Patch the intern table.
1770 if (image_header.GetInternedStringsSection().Size() != 0u) {
1771 const uint8_t* data = space->Begin() + image_header.GetInternedStringsSection().Offset();
1772 size_t read_count;
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001773 InternTable::UnorderedSet temp_set(data, /*make_copy_of_data=*/ false, &read_count);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001774 for (GcRoot<mirror::String>& slot : temp_set) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001775 // The intern table contains only strings in the current image.
1776 simple_patch_object_visitor.template PatchGcRoot</*kMayBeNull=*/ false>(&slot);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001777 }
1778 }
1779
1780 // Patch the class table and classes, so that we can traverse class hierarchy to
1781 // determine the types of other objects when we visit them later.
1782 if (image_header.GetClassTableSection().Size() != 0u) {
1783 uint8_t* data = space->Begin() + image_header.GetClassTableSection().Offset();
1784 size_t read_count;
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001785 ClassTable::ClassSet temp_set(data, /*make_copy_of_data=*/ false, &read_count);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001786 DCHECK(!temp_set.empty());
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001787 // The class table contains only classes in the current image.
1788 ClassTableVisitor class_table_visitor(simple_relocate_visitor);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001789 for (ClassTable::TableSlot& slot : temp_set) {
1790 slot.VisitRoot(class_table_visitor);
Vladimir Marko1fe58392019-04-10 16:14:56 +01001791 ObjPtr<mirror::Class> klass = slot.Read<kWithoutReadBarrier>();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001792 DCHECK(klass != nullptr);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001793 DCHECK(!patched_objects->Test(klass.Ptr()));
Vladimir Marko1fe58392019-04-10 16:14:56 +01001794 patched_objects->Set(klass.Ptr());
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001795 main_patch_object_visitor.VisitClass(klass, class_class);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001796 // Then patch the non-embedded vtable and iftable.
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001797 ObjPtr<mirror::PointerArray> vtable =
1798 klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001799 if ((kExtension ? simple_relocate_visitor.InSource(vtable.Ptr()) : vtable != nullptr) &&
1800 !patched_objects->Set(vtable.Ptr())) {
1801 main_patch_object_visitor.VisitPointerArray(vtable);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001802 }
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001803 ObjPtr<mirror::IfTable> iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001804 if (iftable != nullptr) {
Vladimir Markodbcb48f2018-11-12 11:47:04 +00001805 int32_t ifcount = klass->GetIfTableCount<kVerifyNone>();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001806 for (int32_t i = 0; i != ifcount; ++i) {
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001807 ObjPtr<mirror::PointerArray> unpatched_ifarray =
Vladimir Marko4df2d802018-09-27 16:42:44 +00001808 iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001809 if (kExtension ? simple_relocate_visitor.InSource(unpatched_ifarray.Ptr())
1810 : unpatched_ifarray != nullptr) {
Vladimir Marko4df2d802018-09-27 16:42:44 +00001811 // The iftable has not been patched, so we need to explicitly adjust the pointer.
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001812 ObjPtr<mirror::PointerArray> ifarray =
1813 simple_relocate_visitor(unpatched_ifarray.Ptr());
Vladimir Markoc524e9e2019-03-26 10:54:50 +00001814 if (!patched_objects->Set(ifarray.Ptr())) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001815 main_patch_object_visitor.VisitPointerArray(ifarray);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001816 }
1817 }
1818 }
1819 }
1820 }
1821 }
1822 }
1823
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001824 for (const std::unique_ptr<ImageSpace>& space : spaces) {
Vladimir Marko4df2d802018-09-27 16:42:44 +00001825 const ImageHeader& image_header = space->GetImageHeader();
1826
1827 static_assert(IsAligned<kObjectAlignment>(sizeof(ImageHeader)), "Header alignment check");
1828 uint32_t objects_end = image_header.GetObjectsSection().Size();
1829 DCHECK_ALIGNED(objects_end, kObjectAlignment);
1830 for (uint32_t pos = sizeof(ImageHeader); pos != objects_end; ) {
1831 mirror::Object* object = reinterpret_cast<mirror::Object*>(space->Begin() + pos);
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001832 // Note: use Test() rather than Set() as this is the last time we're checking this object.
Mathieu Chartier2ffc74b2019-01-03 19:25:41 -08001833 if (!patched_objects->Test(object)) {
1834 // This is the last pass over objects, so we do not need to Set().
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001835 main_patch_object_visitor.VisitObject(object);
Vladimir Marko4617d582019-03-28 13:48:31 +00001836 ObjPtr<mirror::Class> klass = object->GetClass<kVerifyNone, kWithoutReadBarrier>();
Vladimir Marko4df2d802018-09-27 16:42:44 +00001837 if (klass->IsDexCacheClass<kVerifyNone>()) {
1838 // Patch dex cache array pointers and elements.
Vladimir Marko4617d582019-03-28 13:48:31 +00001839 ObjPtr<mirror::DexCache> dex_cache =
1840 object->AsDexCache<kVerifyNone, kWithoutReadBarrier>();
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001841 main_patch_object_visitor.VisitDexCacheArrays(dex_cache);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001842 } else if (klass == method_class || klass == constructor_class) {
1843 // Patch the ArtMethod* in the mirror::Executable subobject.
1844 ObjPtr<mirror::Executable> as_executable =
Vladimir Markod7e9bbf2019-03-28 13:18:57 +00001845 ObjPtr<mirror::Executable>::DownCast(object);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001846 ArtMethod* unpatched_method = as_executable->GetArtMethod<kVerifyNone>();
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001847 ArtMethod* patched_method = main_relocate_visitor(unpatched_method);
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001848 as_executable->SetArtMethod</*kTransactionActive=*/ false,
1849 /*kCheckTransaction=*/ true,
Vladimir Marko4df2d802018-09-27 16:42:44 +00001850 kVerifyNone>(patched_method);
1851 }
1852 }
1853 pos += RoundUp(object->SizeOf<kVerifyNone>(), kObjectAlignment);
1854 }
1855 }
1856 }
1857
Vladimir Marko3364d182019-03-13 13:55:01 +00001858 void MaybeRelocateSpaces(const std::vector<std::unique_ptr<ImageSpace>>& spaces,
1859 TimingLogger* logger)
Vladimir Marko4df2d802018-09-27 16:42:44 +00001860 REQUIRES_SHARED(Locks::mutator_lock_) {
1861 TimingLogger::ScopedTiming timing("MaybeRelocateSpaces", logger);
1862 ImageSpace* first_space = spaces.front().get();
1863 const ImageHeader& first_space_header = first_space->GetImageHeader();
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001864 int64_t base_diff64 =
1865 static_cast<int64_t>(reinterpret_cast32<uint32_t>(first_space->Begin())) -
1866 static_cast<int64_t>(reinterpret_cast32<uint32_t>(first_space_header.GetImageBegin()));
Vladimir Marko3364d182019-03-13 13:55:01 +00001867 if (!relocate_) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001868 DCHECK_EQ(base_diff64, 0);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001869 return;
1870 }
1871
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001872 ArrayRef<const std::unique_ptr<ImageSpace>> spaces_ref(spaces);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001873 PointerSize pointer_size = first_space_header.GetPointerSize();
1874 if (pointer_size == PointerSize::k64) {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001875 DoRelocateSpaces<PointerSize::k64>(spaces_ref, base_diff64);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001876 } else {
Vladimir Markoc0b30c92019-07-23 14:58:25 +01001877 DoRelocateSpaces<PointerSize::k32>(spaces_ref, base_diff64);
Vladimir Marko4df2d802018-09-27 16:42:44 +00001878 }
1879 }
1880
Vladimir Markoc09cd052018-08-23 16:36:36 +01001881 std::unique_ptr<ImageSpace> Load(const std::string& image_location,
1882 const std::string& image_filename,
Vladimir Marko4df2d802018-09-27 16:42:44 +00001883 TimingLogger* logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001884 /*inout*/MemMap* image_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001885 /*out*/std::string* error_msg)
1886 REQUIRES_SHARED(Locks::mutator_lock_) {
1887 // Should this be a RDWR lock? This is only a defensive measure, as at
1888 // this point the image should exist.
1889 // However, only the zygote can write into the global dalvik-cache, so
1890 // restrict to zygote processes, or any process that isn't using
1891 // /data/dalvik-cache (which we assume to be allowed to write there).
1892 const bool rw_lock = is_zygote_ || !is_global_cache_;
1893
1894 // Note that we must not use the file descriptor associated with
1895 // ScopedFlock::GetFile to Init the image file. We want the file
1896 // descriptor (and the associated exclusive lock) to be released when
1897 // we leave Create.
1898 ScopedFlock image = LockedFile::Open(image_filename.c_str(),
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001899 /*flags=*/ rw_lock ? (O_CREAT | O_RDWR) : O_RDONLY,
1900 /*block=*/ true,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001901 error_msg);
1902
1903 VLOG(startup) << "Using image file " << image_filename.c_str() << " for image location "
1904 << image_location;
1905 // If we are in /system we can assume the image is good. We can also
1906 // assume this if we are using a relocated image (i.e. image checksum
1907 // matches) since this is only different by the offset. We need this to
1908 // make sure that host tests continue to work.
1909 // Since we are the boot image, pass null since we load the oat file from the boot image oat
1910 // file name.
1911 return Loader::Init(image_filename.c_str(),
1912 image_location.c_str(),
Vladimir Markof4efa9e2018-10-17 14:12:45 +01001913 /*oat_file=*/ nullptr,
Vladimir Marko4df2d802018-09-27 16:42:44 +00001914 logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001915 image_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001916 error_msg);
1917 }
1918
Vladimir Marko312f10e2018-11-21 12:35:24 +00001919 bool OpenOatFile(ImageSpace* space,
Vladimir Marko91f10322018-12-07 18:04:10 +00001920 const std::string& dex_filename,
Vladimir Marko312f10e2018-11-21 12:35:24 +00001921 bool validate_oat_file,
Vladimir Marko436c6f52019-07-25 14:50:14 +01001922 ArrayRef<const std::unique_ptr<ImageSpace>> available_dependencies,
Vladimir Marko312f10e2018-11-21 12:35:24 +00001923 TimingLogger* logger,
1924 /*inout*/MemMap* image_reservation,
1925 /*out*/std::string* error_msg) {
1926 // VerifyImageAllocations() will be called later in Runtime::Init()
1927 // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_
1928 // and ArtField::java_lang_reflect_ArtField_, which are used from
1929 // Object::SizeOf() which VerifyImageAllocations() calls, are not
1930 // set yet at this point.
1931 DCHECK(image_reservation != nullptr);
1932 std::unique_ptr<OatFile> oat_file;
1933 {
1934 TimingLogger::ScopedTiming timing("OpenOatFile", logger);
1935 std::string oat_filename =
1936 ImageHeader::GetOatLocationFromImageLocation(space->GetImageFilename());
Vladimir Marko91f10322018-12-07 18:04:10 +00001937 std::string oat_location =
1938 ImageHeader::GetOatLocationFromImageLocation(space->GetImageLocation());
Vladimir Marko312f10e2018-11-21 12:35:24 +00001939
1940 oat_file.reset(OatFile::Open(/*zip_fd=*/ -1,
1941 oat_filename,
Vladimir Marko91f10322018-12-07 18:04:10 +00001942 oat_location,
Vladimir Marko3364d182019-03-13 13:55:01 +00001943 executable_,
Vladimir Marko312f10e2018-11-21 12:35:24 +00001944 /*low_4gb=*/ false,
Vladimir Marko91f10322018-12-07 18:04:10 +00001945 /*abs_dex_location=*/ dex_filename.c_str(),
Vladimir Marko312f10e2018-11-21 12:35:24 +00001946 image_reservation,
1947 error_msg));
1948 if (oat_file == nullptr) {
1949 *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s",
1950 oat_filename.c_str(),
1951 space->GetName(),
1952 error_msg->c_str());
1953 return false;
1954 }
1955 const ImageHeader& image_header = space->GetImageHeader();
1956 uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
1957 uint32_t image_oat_checksum = image_header.GetOatChecksum();
1958 if (oat_checksum != image_oat_checksum) {
1959 *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum"
1960 " 0x%x in image %s",
1961 oat_checksum,
1962 image_oat_checksum,
1963 space->GetName());
1964 return false;
1965 }
Vladimir Marko91f10322018-12-07 18:04:10 +00001966 const char* oat_boot_class_path =
1967 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathKey);
1968 oat_boot_class_path = (oat_boot_class_path != nullptr) ? oat_boot_class_path : "";
Vladimir Marko436c6f52019-07-25 14:50:14 +01001969 const char* oat_boot_class_path_checksums =
1970 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1971 oat_boot_class_path_checksums =
1972 (oat_boot_class_path_checksums != nullptr) ? oat_boot_class_path_checksums : "";
1973 size_t component_count = image_header.GetComponentCount();
1974 if (component_count == 0u) {
1975 if (oat_boot_class_path[0] != 0 || oat_boot_class_path_checksums[0] != 0) {
1976 *error_msg = StringPrintf("Unexpected non-empty boot class path %s and/or checksums %s"
1977 " in image %s",
1978 oat_boot_class_path,
1979 oat_boot_class_path_checksums,
1980 space->GetName());
1981 return false;
1982 }
1983 } else if (available_dependencies.empty()) {
1984 std::string expected_boot_class_path = android::base::Join(ArrayRef<const std::string>(
1985 boot_class_path_locations_).SubArray(0u, component_count), ':');
1986 if (expected_boot_class_path != oat_boot_class_path) {
1987 *error_msg = StringPrintf("Failed to match oat boot class path %s to expected "
1988 "boot class path %s in image %s",
1989 oat_boot_class_path,
1990 expected_boot_class_path.c_str(),
1991 space->GetName());
1992 return false;
1993 }
1994 } else {
1995 std::string local_error_msg;
1996 if (!VerifyBootClassPathChecksums(
1997 oat_boot_class_path_checksums,
1998 oat_boot_class_path,
1999 available_dependencies,
2000 ArrayRef<const std::string>(boot_class_path_locations_),
2001 ArrayRef<const std::string>(boot_class_path_),
2002 &local_error_msg)) {
2003 *error_msg = StringPrintf("Failed to verify BCP %s with checksums %s in image %s: %s",
2004 oat_boot_class_path,
2005 oat_boot_class_path_checksums,
2006 space->GetName(),
2007 local_error_msg.c_str());
2008 return false;
2009 }
Vladimir Marko91f10322018-12-07 18:04:10 +00002010 }
Vladimir Marko312f10e2018-11-21 12:35:24 +00002011 ptrdiff_t relocation_diff = space->Begin() - image_header.GetImageBegin();
2012 CHECK(image_header.GetOatDataBegin() != nullptr);
2013 uint8_t* oat_data_begin = image_header.GetOatDataBegin() + relocation_diff;
2014 if (oat_file->Begin() != oat_data_begin) {
2015 *error_msg = StringPrintf("Oat file '%s' referenced from image %s has unexpected begin"
2016 " %p v. %p",
2017 oat_filename.c_str(),
2018 space->GetName(),
2019 oat_file->Begin(),
2020 oat_data_begin);
2021 return false;
2022 }
2023 }
2024 if (validate_oat_file) {
2025 TimingLogger::ScopedTiming timing("ValidateOatFile", logger);
2026 if (!ImageSpace::ValidateOatFile(*oat_file, error_msg)) {
2027 DCHECK(!error_msg->empty());
2028 return false;
2029 }
2030 }
2031 space->oat_file_ = std::move(oat_file);
2032 space->oat_file_non_owned_ = space->oat_file_.get();
2033 return true;
2034 }
2035
Vladimir Marko312f10e2018-11-21 12:35:24 +00002036 bool ReserveBootImageMemory(uint32_t reservation_size,
2037 uint32_t image_start,
Vladimir Markod44d7032018-08-30 13:02:31 +01002038 size_t extra_reservation_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01002039 /*out*/MemMap* image_reservation,
Vladimir Markod44d7032018-08-30 13:02:31 +01002040 /*out*/MemMap* extra_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01002041 /*out*/std::string* error_msg) {
Vladimir Marko7391c8c2018-11-21 17:58:44 +00002042 DCHECK_ALIGNED(reservation_size, kPageSize);
2043 DCHECK_ALIGNED(image_start, kPageSize);
Vladimir Markoc09cd052018-08-23 16:36:36 +01002044 DCHECK(!image_reservation->IsValid());
Vladimir Marko312f10e2018-11-21 12:35:24 +00002045 DCHECK_LT(extra_reservation_size, std::numeric_limits<uint32_t>::max() - reservation_size);
2046 size_t total_size = reservation_size + extra_reservation_size;
Vladimir Markoae581ed2018-10-08 09:29:05 +01002047 // If relocating, choose a random address for ALSR.
Vladimir Marko3364d182019-03-13 13:55:01 +00002048 uint32_t addr = relocate_ ? ART_BASE_ADDRESS + ChooseRelocationOffsetDelta() : image_start;
Vladimir Markoc09cd052018-08-23 16:36:36 +01002049 *image_reservation =
2050 MemMap::MapAnonymous("Boot image reservation",
Vladimir Markoae581ed2018-10-08 09:29:05 +01002051 reinterpret_cast32<uint8_t*>(addr),
2052 total_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01002053 PROT_NONE,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01002054 /*low_4gb=*/ true,
2055 /*reuse=*/ false,
2056 /*reservation=*/ nullptr,
Vladimir Markoc09cd052018-08-23 16:36:36 +01002057 error_msg);
2058 if (!image_reservation->IsValid()) {
2059 return false;
2060 }
Vladimir Markod44d7032018-08-30 13:02:31 +01002061 DCHECK(!extra_reservation->IsValid());
2062 if (extra_reservation_size != 0u) {
2063 DCHECK_ALIGNED(extra_reservation_size, kPageSize);
2064 DCHECK_LT(extra_reservation_size, image_reservation->Size());
2065 uint8_t* split = image_reservation->End() - extra_reservation_size;
2066 *extra_reservation = image_reservation->RemapAtEnd(split,
2067 "Boot image extra reservation",
2068 PROT_NONE,
2069 error_msg);
2070 if (!extra_reservation->IsValid()) {
2071 return false;
2072 }
2073 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01002074
2075 return true;
2076 }
2077
Vladimir Marko312f10e2018-11-21 12:35:24 +00002078 bool CheckReservationExhausted(const MemMap& image_reservation, /*out*/std::string* error_msg) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01002079 if (image_reservation.IsValid()) {
2080 *error_msg = StringPrintf("Excessive image reservation after loading boot image: %p-%p",
2081 image_reservation.Begin(),
2082 image_reservation.End());
2083 return false;
2084 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01002085 return true;
2086 }
2087
Vladimir Marko91f10322018-12-07 18:04:10 +00002088 const std::vector<std::string>& boot_class_path_;
2089 const std::vector<std::string>& boot_class_path_locations_;
Vladimir Marko82e1e272018-08-20 13:38:06 +00002090 const std::string& image_location_;
2091 InstructionSet image_isa_;
Vladimir Marko3364d182019-03-13 13:55:01 +00002092 bool relocate_;
2093 bool executable_;
Vladimir Marko82e1e272018-08-20 13:38:06 +00002094 bool is_zygote_;
2095 bool has_system_;
2096 bool has_cache_;
2097 bool is_global_cache_;
Vladimir Markoe3070022018-08-22 09:36:19 +00002098 bool dalvik_cache_exists_;
Vladimir Marko82e1e272018-08-20 13:38:06 +00002099 std::string dalvik_cache_;
2100 std::string cache_filename_;
2101};
2102
Andreas Gampea463b6a2016-08-12 21:53:32 -07002103static constexpr uint64_t kLowSpaceValue = 50 * MB;
2104static constexpr uint64_t kTmpFsSentinelValue = 384 * MB;
2105
2106// Read the free space of the cache partition and make a decision whether to keep the generated
2107// image. This is to try to mitigate situations where the system might run out of space later.
2108static bool CheckSpace(const std::string& cache_filename, std::string* error_msg) {
2109 // Using statvfs vs statvfs64 because of b/18207376, and it is enough for all practical purposes.
2110 struct statvfs buf;
2111
2112 int res = TEMP_FAILURE_RETRY(statvfs(cache_filename.c_str(), &buf));
2113 if (res != 0) {
2114 // Could not stat. Conservatively tell the system to delete the image.
2115 *error_msg = "Could not stat the filesystem, assuming low-memory situation.";
2116 return false;
Nicolas Geoffray1bc977c2016-01-23 14:15:49 +00002117 }
Nicolas Geoffray1bc977c2016-01-23 14:15:49 +00002118
Andreas Gampea463b6a2016-08-12 21:53:32 -07002119 uint64_t fs_overall_size = buf.f_bsize * static_cast<uint64_t>(buf.f_blocks);
2120 // Zygote is privileged, but other things are not. Use bavail.
2121 uint64_t fs_free_size = buf.f_bsize * static_cast<uint64_t>(buf.f_bavail);
Brian Carlstrom56d947f2013-07-15 13:14:23 -07002122
Andreas Gampea463b6a2016-08-12 21:53:32 -07002123 // Take the overall size as an indicator for a tmpfs, which is being used for the decryption
2124 // environment. We do not want to fail quickening the boot image there, as it is beneficial
2125 // for time-to-UI.
2126 if (fs_overall_size > kTmpFsSentinelValue) {
2127 if (fs_free_size < kLowSpaceValue) {
2128 *error_msg = StringPrintf("Low-memory situation: only %4.2f megabytes available, need at "
2129 "least %" PRIu64 ".",
2130 static_cast<double>(fs_free_size) / MB,
2131 kLowSpaceValue / MB);
Brian Carlstrom56d947f2013-07-15 13:14:23 -07002132 return false;
2133 }
2134 }
2135 return true;
2136}
2137
Vladimir Marko82e1e272018-08-20 13:38:06 +00002138bool ImageSpace::LoadBootImage(
Vladimir Marko91f10322018-12-07 18:04:10 +00002139 const std::vector<std::string>& boot_class_path,
2140 const std::vector<std::string>& boot_class_path_locations,
Vladimir Marko82e1e272018-08-20 13:38:06 +00002141 const std::string& image_location,
2142 const InstructionSet image_isa,
Andreas Gampe86823542019-02-25 09:38:49 -08002143 ImageSpaceLoadingOrder order,
Vladimir Marko3364d182019-03-13 13:55:01 +00002144 bool relocate,
2145 bool executable,
2146 bool is_zygote,
Vladimir Markod44d7032018-08-30 13:02:31 +01002147 size_t extra_reservation_size,
2148 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
2149 /*out*/MemMap* extra_reservation) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002150 ScopedTrace trace(__FUNCTION__);
2151
Vladimir Marko82e1e272018-08-20 13:38:06 +00002152 DCHECK(boot_image_spaces != nullptr);
2153 DCHECK(boot_image_spaces->empty());
Vladimir Markod44d7032018-08-30 13:02:31 +01002154 DCHECK_ALIGNED(extra_reservation_size, kPageSize);
2155 DCHECK(extra_reservation != nullptr);
Vladimir Marko82e1e272018-08-20 13:38:06 +00002156 DCHECK_NE(image_isa, InstructionSet::kNone);
2157
2158 if (image_location.empty()) {
2159 return false;
2160 }
2161
Vladimir Marko3364d182019-03-13 13:55:01 +00002162 BootImageLoader loader(boot_class_path,
2163 boot_class_path_locations,
2164 image_location,
2165 image_isa,
2166 relocate,
2167 executable,
2168 is_zygote);
Vladimir Marko82e1e272018-08-20 13:38:06 +00002169
Andreas Gampea463b6a2016-08-12 21:53:32 -07002170 // Step 0: Extra zygote work.
2171
2172 // Step 0.a: If we're the zygote, mark boot.
Vladimir Marko82e1e272018-08-20 13:38:06 +00002173 if (loader.IsZygote() && CanWriteToDalvikCache(image_isa)) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002174 MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots());
2175 }
2176
Vladimir Marko82e1e272018-08-20 13:38:06 +00002177 loader.FindImageFiles();
2178
Andreas Gampea463b6a2016-08-12 21:53:32 -07002179 // Step 0.b: If we're the zygote, check for free space, and prune the cache preemptively,
2180 // if necessary. While the runtime may be fine (it is pretty tolerant to
2181 // out-of-disk-space situations), other parts of the platform are not.
2182 //
2183 // The advantage of doing this proactively is that the later steps are simplified,
2184 // i.e., we do not need to code retries.
Vladimir Marko3364d182019-03-13 13:55:01 +00002185 bool low_space = false;
Vladimir Marko82e1e272018-08-20 13:38:06 +00002186 if (loader.IsZygote() && loader.DalvikCacheExists()) {
Andreas Gampe6e74abb2018-03-01 17:33:19 -08002187 // Extra checks for the zygote. These only apply when loading the first image, explained below.
Vladimir Marko82e1e272018-08-20 13:38:06 +00002188 const std::string& dalvik_cache = loader.GetDalvikCache();
Andreas Gampea463b6a2016-08-12 21:53:32 -07002189 DCHECK(!dalvik_cache.empty());
2190 std::string local_error_msg;
Andreas Gampe6e74abb2018-03-01 17:33:19 -08002191 bool check_space = CheckSpace(dalvik_cache, &local_error_msg);
Vladimir Marko4df2d802018-09-27 16:42:44 +00002192 if (!check_space) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002193 LOG(WARNING) << local_error_msg << " Preemptively pruning the dalvik cache.";
2194 PruneDalvikCache(image_isa);
2195
2196 // Re-evaluate the image.
Vladimir Marko82e1e272018-08-20 13:38:06 +00002197 loader.FindImageFiles();
Vladimir Marko3364d182019-03-13 13:55:01 +00002198
Andreas Gampe6e74abb2018-03-01 17:33:19 -08002199 // Disable compilation/patching - we do not want to fill up the space again.
Vladimir Marko3364d182019-03-13 13:55:01 +00002200 low_space = true;
Andreas Gampe6e74abb2018-03-01 17:33:19 -08002201 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07002202 }
2203
2204 // Collect all the errors.
2205 std::vector<std::string> error_msgs;
2206
Andreas Gampe86823542019-02-25 09:38:49 -08002207 auto try_load_from = [&](auto has_fn, auto load_fn, bool validate_oat_file) {
2208 if ((loader.*has_fn)()) {
2209 std::string local_error_msg;
2210 if ((loader.*load_fn)(validate_oat_file,
2211 extra_reservation_size,
2212 boot_image_spaces,
2213 extra_reservation,
2214 &local_error_msg)) {
2215 return true;
2216 }
2217 error_msgs.push_back(local_error_msg);
2218 }
2219 return false;
2220 };
Andreas Gampea463b6a2016-08-12 21:53:32 -07002221
Andreas Gampe86823542019-02-25 09:38:49 -08002222 auto try_load_from_system = [&]() {
Andreas Gampe96b3baa2019-03-12 12:45:58 -07002223 // Validate the oat files if the loading order checks data first. Otherwise assume system
2224 // integrity.
2225 return try_load_from(&BootImageLoader::HasSystem,
2226 &BootImageLoader::LoadFromSystem,
2227 /*validate_oat_file=*/ order != ImageSpaceLoadingOrder::kSystemFirst);
Andreas Gampe86823542019-02-25 09:38:49 -08002228 };
2229 auto try_load_from_cache = [&]() {
Andreas Gampe96b3baa2019-03-12 12:45:58 -07002230 // Always validate oat files from the dalvik cache.
2231 return try_load_from(&BootImageLoader::HasCache,
2232 &BootImageLoader::LoadFromDalvikCache,
2233 /*validate_oat_file=*/ true);
Andreas Gampe86823542019-02-25 09:38:49 -08002234 };
2235
2236 auto invoke_sequentially = [](auto first, auto second) {
2237 return first() || second();
2238 };
2239
2240 // Step 1+2: Check system and cache images in the asked-for order.
2241 if (order == ImageSpaceLoadingOrder::kSystemFirst) {
2242 if (invoke_sequentially(try_load_from_system, try_load_from_cache)) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00002243 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07002244 }
Andreas Gampe86823542019-02-25 09:38:49 -08002245 } else {
2246 if (invoke_sequentially(try_load_from_cache, try_load_from_system)) {
Vladimir Marko4df2d802018-09-27 16:42:44 +00002247 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07002248 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07002249 }
2250
Vladimir Marko82e1e272018-08-20 13:38:06 +00002251 // Step 3: We do not have an existing image in /system,
2252 // so generate an image into the dalvik cache.
Vladimir Markoe3070022018-08-22 09:36:19 +00002253 if (!loader.HasSystem() && loader.DalvikCacheExists()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002254 std::string local_error_msg;
Vladimir Marko3364d182019-03-13 13:55:01 +00002255 if (low_space || !Runtime::Current()->IsImageDex2OatEnabled()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002256 local_error_msg = "Image compilation disabled.";
Vladimir Marko3364d182019-03-13 13:55:01 +00002257 } else if (ImageCreationAllowed(loader.IsGlobalCache(),
2258 image_isa,
2259 is_zygote,
2260 &local_error_msg)) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00002261 bool compilation_success =
2262 GenerateImage(loader.GetCacheFilename(), image_isa, &local_error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -07002263 if (compilation_success) {
Vladimir Markof4efa9e2018-10-17 14:12:45 +01002264 if (loader.LoadFromDalvikCache(/*validate_oat_file=*/ false,
Vladimir Markod44d7032018-08-30 13:02:31 +01002265 extra_reservation_size,
Vladimir Marko82e1e272018-08-20 13:38:06 +00002266 boot_image_spaces,
Vladimir Markod44d7032018-08-30 13:02:31 +01002267 extra_reservation,
Vladimir Marko82e1e272018-08-20 13:38:06 +00002268 &local_error_msg)) {
2269 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07002270 }
2271 }
2272 }
2273 error_msgs.push_back(StringPrintf("Cannot compile image to %s: %s",
Vladimir Marko82e1e272018-08-20 13:38:06 +00002274 loader.GetCacheFilename().c_str(),
Andreas Gampea463b6a2016-08-12 21:53:32 -07002275 local_error_msg.c_str()));
2276 }
2277
Vladimir Marko82e1e272018-08-20 13:38:06 +00002278 // We failed. Prune the cache the free up space, create a compound error message
2279 // and return false.
Vladimir Marko3364d182019-03-13 13:55:01 +00002280 if (loader.DalvikCacheExists()) {
2281 PruneDalvikCache(image_isa);
2282 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07002283
2284 std::ostringstream oss;
2285 bool first = true;
Andreas Gampe4c481a42016-11-03 08:21:59 -07002286 for (const auto& msg : error_msgs) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07002287 if (!first) {
2288 oss << "\n ";
2289 }
2290 oss << msg;
2291 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07002292
Vladimir Marko82e1e272018-08-20 13:38:06 +00002293 LOG(ERROR) << "Could not create image space with image file '" << image_location << "'. "
2294 << "Attempting to fall back to imageless running. Error was: " << oss.str();
Andreas Gampea463b6a2016-08-12 21:53:32 -07002295
Vladimir Marko82e1e272018-08-20 13:38:06 +00002296 return false;
Andreas Gampe2bd84282016-12-05 12:37:36 -08002297}
2298
Igor Murashkin8275fba2017-05-02 15:58:02 -07002299ImageSpace::~ImageSpace() {
Vladimir Marko3364d182019-03-13 13:55:01 +00002300 // Everything done by member destructors. Classes forward-declared in header are now defined.
Igor Murashkin8275fba2017-05-02 15:58:02 -07002301}
2302
Andreas Gampea463b6a2016-08-12 21:53:32 -07002303std::unique_ptr<ImageSpace> ImageSpace::CreateFromAppImage(const char* image,
2304 const OatFile* oat_file,
2305 std::string* error_msg) {
Vladimir Marko312f10e2018-11-21 12:35:24 +00002306 // Note: The oat file has already been validated.
Vladimir Marko4df2d802018-09-27 16:42:44 +00002307 return Loader::InitAppImage(image,
2308 image,
Vladimir Marko4df2d802018-09-27 16:42:44 +00002309 oat_file,
Vladimir Markof4efa9e2018-10-17 14:12:45 +01002310 /*image_reservation=*/ nullptr,
Vladimir Marko4df2d802018-09-27 16:42:44 +00002311 error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -07002312}
2313
Andreas Gampe22f8e5c2014-07-09 11:38:21 -07002314const OatFile* ImageSpace::GetOatFile() const {
Andreas Gampe88da3b02015-06-12 20:38:49 -07002315 return oat_file_non_owned_;
Andreas Gampe22f8e5c2014-07-09 11:38:21 -07002316}
2317
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07002318std::unique_ptr<const OatFile> ImageSpace::ReleaseOatFile() {
2319 CHECK(oat_file_ != nullptr);
2320 return std::move(oat_file_);
Ian Rogers1d54e732013-05-02 21:10:01 -07002321}
2322
Ian Rogers1d54e732013-05-02 21:10:01 -07002323void ImageSpace::Dump(std::ostream& os) const {
2324 os << GetType()
Mathieu Chartier590fee92013-09-13 13:46:47 -07002325 << " begin=" << reinterpret_cast<void*>(Begin())
Ian Rogers1d54e732013-05-02 21:10:01 -07002326 << ",end=" << reinterpret_cast<void*>(End())
2327 << ",size=" << PrettySize(Size())
2328 << ",name=\"" << GetName() << "\"]";
2329}
2330
Richard Uhler84f50ae2017-02-06 15:12:45 +00002331bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) {
David Sehr013fd802018-01-11 22:55:24 -08002332 const ArtDexFileLoader dex_file_loader;
Andreas Gampeb40d3612018-06-26 15:49:42 -07002333 for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002334 const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
2335
2336 // Skip multidex locations - These will be checked when we visit their
2337 // corresponding primary non-multidex location.
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002338 if (DexFileLoader::IsMultiDexLocation(dex_file_location.c_str())) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002339 continue;
2340 }
2341
2342 std::vector<uint32_t> checksums;
David Sehr013fd802018-01-11 22:55:24 -08002343 if (!dex_file_loader.GetMultiDexChecksums(dex_file_location.c_str(), &checksums, error_msg)) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002344 *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' "
2345 "referenced by oat file %s: %s",
2346 dex_file_location.c_str(),
2347 oat_file.GetLocation().c_str(),
2348 error_msg->c_str());
2349 return false;
2350 }
2351 CHECK(!checksums.empty());
2352 if (checksums[0] != oat_dex_file->GetDexFileLocationChecksum()) {
2353 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
2354 "'%s' and dex file '%s' (0x%x != 0x%x)",
2355 oat_file.GetLocation().c_str(),
2356 dex_file_location.c_str(),
2357 oat_dex_file->GetDexFileLocationChecksum(),
2358 checksums[0]);
2359 return false;
2360 }
2361
2362 // Verify checksums for any related multidex entries.
2363 for (size_t i = 1; i < checksums.size(); i++) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002364 std::string multi_dex_location = DexFileLoader::GetMultiDexLocation(
2365 i,
2366 dex_file_location.c_str());
Andreas Gampeb40d3612018-06-26 15:49:42 -07002367 const OatDexFile* multi_dex = oat_file.GetOatDexFile(multi_dex_location.c_str(),
2368 nullptr,
2369 error_msg);
Richard Uhler84f50ae2017-02-06 15:12:45 +00002370 if (multi_dex == nullptr) {
2371 *error_msg = StringPrintf("ValidateOatFile oat file '%s' is missing entry '%s'",
2372 oat_file.GetLocation().c_str(),
2373 multi_dex_location.c_str());
2374 return false;
2375 }
2376
2377 if (checksums[i] != multi_dex->GetDexFileLocationChecksum()) {
2378 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
2379 "'%s' and dex file '%s' (0x%x != 0x%x)",
2380 oat_file.GetLocation().c_str(),
2381 multi_dex_location.c_str(),
2382 multi_dex->GetDexFileLocationChecksum(),
2383 checksums[i]);
2384 return false;
2385 }
2386 }
2387 }
2388 return true;
2389}
2390
Vladimir Marko436c6f52019-07-25 14:50:14 +01002391static void AppendImageChecksum(const ImageHeader& header, /*inout*/std::string* checksums) {
2392 static_assert(ImageSpace::kImageChecksumPrefix == 'i', "Format prefix check.");
2393 StringAppendF(checksums, "i;%u/%08x", header.GetComponentCount(), header.GetImageChecksum());
2394}
2395
2396std::string ImageSpace::GetBootClassPathChecksums(
2397 ArrayRef<ImageSpace* const> image_spaces,
2398 ArrayRef<const DexFile* const> boot_class_path) {
2399 DCHECK(!boot_class_path.empty());
2400 size_t bcp_pos = 0u;
2401 std::string boot_image_checksum;
2402
2403 for (size_t image_pos = 0u, size = image_spaces.size(); image_pos != size; ) {
2404 const ImageSpace* main_space = image_spaces[image_pos];
2405 // Caller must make sure that the image spaces correspond to the head of the BCP.
2406 DCHECK_NE(main_space->oat_file_non_owned_->GetOatDexFiles().size(), 0u);
2407 DCHECK_EQ(main_space->oat_file_non_owned_->GetOatDexFiles()[0]->GetDexFileLocation(),
2408 boot_class_path[bcp_pos]->GetLocation());
2409 const ImageHeader& current_header = main_space->GetImageHeader();
2410 uint32_t component_count = current_header.GetComponentCount();
2411 DCHECK_NE(component_count, 0u);
2412 DCHECK_LE(component_count, image_spaces.size() - image_pos);
2413 if (image_pos != 0u) {
2414 boot_image_checksum += ':';
2415 }
2416 AppendImageChecksum(current_header, &boot_image_checksum);
2417 for (size_t component_index = 0; component_index != component_count; ++component_index) {
2418 const ImageSpace* space = image_spaces[image_pos + component_index];
2419 const OatFile* oat_file = space->oat_file_non_owned_;
2420 size_t num_dex_files = oat_file->GetOatDexFiles().size();
2421 if (kIsDebugBuild) {
2422 CHECK_NE(num_dex_files, 0u);
2423 CHECK_LE(oat_file->GetOatDexFiles().size(), boot_class_path.size() - bcp_pos);
2424 for (size_t i = 0; i != num_dex_files; ++i) {
2425 CHECK_EQ(oat_file->GetOatDexFiles()[i]->GetDexFileLocation(),
2426 boot_class_path[bcp_pos + i]->GetLocation());
2427 }
2428 }
2429 bcp_pos += num_dex_files;
2430 }
2431 image_pos += component_count;
2432 }
2433
2434 ArrayRef<const DexFile* const> boot_class_path_tail =
2435 ArrayRef<const DexFile* const>(boot_class_path).SubArray(bcp_pos);
2436 DCHECK(boot_class_path_tail.empty() ||
2437 !DexFileLoader::IsMultiDexLocation(boot_class_path_tail.front()->GetLocation().c_str()));
2438 for (const DexFile* dex_file : boot_class_path_tail) {
2439 if (!boot_image_checksum.empty()) {
2440 boot_image_checksum += ':';
2441 }
2442 if (!DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str())) {
2443 boot_image_checksum += kDexFileChecksumPrefix;
2444 }
2445 StringAppendF(&boot_image_checksum, "/%08x", dex_file->GetLocationChecksum());
2446 }
2447 return boot_image_checksum;
2448}
2449
2450static size_t CheckAndCountBCPComponents(std::string_view oat_boot_class_path,
2451 ArrayRef<const std::string> boot_class_path,
2452 /*out*/std::string* error_msg) {
2453 // Check that the oat BCP is a prefix of current BCP locations and count components.
2454 size_t component_count = 0u;
2455 std::string_view remaining_bcp(oat_boot_class_path);
2456 bool bcp_ok = false;
2457 for (const std::string& location : boot_class_path) {
2458 if (!StartsWith(remaining_bcp, location)) {
2459 break;
2460 }
2461 remaining_bcp.remove_prefix(location.size());
2462 ++component_count;
2463 if (remaining_bcp.empty()) {
2464 bcp_ok = true;
2465 break;
2466 }
2467 if (!StartsWith(remaining_bcp, ":")) {
2468 break;
2469 }
2470 remaining_bcp.remove_prefix(1u);
2471 }
2472 if (!bcp_ok) {
2473 *error_msg = StringPrintf("Oat boot class path (%s) is not a prefix of"
2474 " runtime boot class path (%s)",
2475 std::string(oat_boot_class_path).c_str(),
2476 android::base::Join(boot_class_path, ':').c_str());
2477 return static_cast<size_t>(-1);
2478 }
2479 return component_count;
2480}
2481
2482static bool CheckAndRemoveImageChecksum(const ImageHeader& header,
2483 /*inout*/std::string_view* oat_checksums,
2484 /*out*/std::string* error_msg) {
2485 std::string image_checksum;
2486 AppendImageChecksum(header, &image_checksum);
2487 if (!StartsWith(*oat_checksums, image_checksum)) {
2488 *error_msg = StringPrintf("Image checksum mismatch, expected %s to start with %s",
2489 std::string(*oat_checksums).c_str(),
2490 image_checksum.c_str());
2491 return false;
2492 }
2493 oat_checksums->remove_prefix(image_checksum.size());
2494 return true;
2495}
2496
2497bool ImageSpace::VerifyBootClassPathChecksums(std::string_view oat_checksums,
2498 std::string_view oat_boot_class_path,
2499 const std::string& image_location,
2500 ArrayRef<const std::string> boot_class_path_locations,
2501 ArrayRef<const std::string> boot_class_path,
2502 InstructionSet image_isa,
2503 ImageSpaceLoadingOrder order,
2504 /*out*/std::string* error_msg) {
2505 if (oat_checksums.empty() || oat_boot_class_path.empty()) {
2506 *error_msg = oat_checksums.empty() ? "Empty checksums." : "Empty boot class path.";
2507 return false;
2508 }
2509
2510 DCHECK_EQ(boot_class_path_locations.size(), boot_class_path.size());
2511 size_t bcp_size =
2512 CheckAndCountBCPComponents(oat_boot_class_path, boot_class_path_locations, error_msg);
2513 if (bcp_size == static_cast<size_t>(-1)) {
2514 DCHECK(!error_msg->empty());
2515 return false;
2516 }
2517
2518 bool load_extensions = false; // TODO: Boot image extensions.
2519 const std::string& actual_image_location = image_location; // TODO: Boot image extensions.
Vladimir Marko0ace5632018-12-14 11:11:47 +00002520 std::string system_filename;
2521 bool has_system = false;
2522 std::string cache_filename;
2523 bool has_cache = false;
2524 bool dalvik_cache_exists = false;
2525 bool is_global_cache = false;
Vladimir Marko436c6f52019-07-25 14:50:14 +01002526 if (!FindImageFilename(actual_image_location.c_str(),
Vladimir Marko0ace5632018-12-14 11:11:47 +00002527 image_isa,
2528 &system_filename,
2529 &has_system,
2530 &cache_filename,
2531 &dalvik_cache_exists,
2532 &has_cache,
2533 &is_global_cache)) {
2534 *error_msg = StringPrintf("Unable to find image file for %s and %s",
2535 image_location.c_str(),
2536 GetInstructionSetString(image_isa));
Vladimir Marko436c6f52019-07-25 14:50:14 +01002537 return false;
Vladimir Marko0ace5632018-12-14 11:11:47 +00002538 }
2539
2540 DCHECK(has_system || has_cache);
Andreas Gampe86823542019-02-25 09:38:49 -08002541 const std::string& filename = (order == ImageSpaceLoadingOrder::kSystemFirst)
2542 ? (has_system ? system_filename : cache_filename)
2543 : (has_cache ? cache_filename : system_filename);
Vladimir Marko436c6f52019-07-25 14:50:14 +01002544
2545 size_t bcp_pos = 0u;
2546 while (StartsWith(oat_checksums, "i")) {
2547 const std::string& current_filename = filename;
2548 if (bcp_pos != 0u) {
2549 if (!load_extensions) {
2550 *error_msg = "Checksum specifies boot image extension but extensions are not used.";
2551 return false;
2552 }
2553 UNREACHABLE(); // TODO: Boot image extensions.
2554 }
2555 ImageHeader header;
2556 if (!ReadSpecificImageHeader(current_filename.c_str(), &header, error_msg)) {
2557 return false;
2558 }
2559 size_t component_count = header.GetComponentCount();
2560 if (component_count == 0u || component_count > bcp_size - bcp_pos) {
2561 *error_msg = StringPrintf("Unexpected component count in %s, received %u, "
2562 "expected non-zero and <= %zu",
2563 current_filename.c_str(),
2564 header.GetComponentCount(),
2565 bcp_size - bcp_pos);
2566 return false;
2567 }
2568 if (!CheckAndRemoveImageChecksum(header, &oat_checksums, error_msg)) {
2569 DCHECK(!error_msg->empty());
2570 return false;
2571 }
2572 bcp_pos += component_count;
2573 if (oat_checksums.empty()) {
2574 if (bcp_pos != bcp_size) {
2575 *error_msg = StringPrintf("Checksum too short, missing %zu components.",
2576 bcp_size - bcp_pos);
2577 return false;
2578 }
2579 return true;
2580 }
2581 if (!StartsWith(oat_checksums, ":")) {
2582 *error_msg = StringPrintf("Missing ':' separator at start of %s",
2583 std::string(oat_checksums).c_str());
2584 return false;
2585 }
2586 oat_checksums.remove_prefix(1u);
Vladimir Marko0ace5632018-12-14 11:11:47 +00002587 }
2588
Vladimir Marko436c6f52019-07-25 14:50:14 +01002589 for ( ; bcp_pos != bcp_size; ++bcp_pos) {
2590 static_assert(ImageSpace::kDexFileChecksumPrefix == 'd', "Format prefix check.");
2591 if (!StartsWith(oat_checksums, "d")) {
2592 *error_msg = StringPrintf("Missing dex checksums, expected %s to start with 'd'",
2593 std::string(oat_checksums).c_str());
2594 return false;
2595 }
2596 oat_checksums.remove_prefix(1u);
2597
2598 const std::string& bcp_filename = boot_class_path[bcp_pos];
Vladimir Marko0ace5632018-12-14 11:11:47 +00002599 std::vector<std::unique_ptr<const DexFile>> dex_files;
2600 const ArtDexFileLoader dex_file_loader;
2601 if (!dex_file_loader.Open(bcp_filename.c_str(),
2602 bcp_filename, // The location does not matter here.
2603 /*verify=*/ false,
2604 /*verify_checksum=*/ false,
2605 error_msg,
2606 &dex_files)) {
Vladimir Marko436c6f52019-07-25 14:50:14 +01002607 return false;
Vladimir Marko0ace5632018-12-14 11:11:47 +00002608 }
2609 DCHECK(!dex_files.empty());
Vladimir Marko0ace5632018-12-14 11:11:47 +00002610 for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
Vladimir Marko436c6f52019-07-25 14:50:14 +01002611 std::string dex_file_checksum = StringPrintf("/%08x", dex_file->GetLocationChecksum());
2612 if (!StartsWith(oat_checksums, dex_file_checksum)) {
2613 *error_msg = StringPrintf("Dex checksum mismatch, expected %s to start with %s",
2614 std::string(oat_checksums).c_str(),
2615 dex_file_checksum.c_str());
2616 return false;
2617 }
2618 oat_checksums.remove_prefix(dex_file_checksum.size());
2619 }
2620 if (bcp_pos + 1u != bcp_size) {
2621 if (!StartsWith(oat_checksums, ":")) {
2622 *error_msg = StringPrintf("Missing ':' separator at start of %s",
2623 std::string(oat_checksums).c_str());
2624 return false;
2625 }
Vladimir Marko0ace5632018-12-14 11:11:47 +00002626 }
2627 }
Vladimir Marko436c6f52019-07-25 14:50:14 +01002628 if (!oat_checksums.empty()) {
2629 *error_msg = StringPrintf("Checksum too long, unexpected tail %s",
2630 std::string(oat_checksums).c_str());
2631 return false;
2632 }
2633 return true;
Vladimir Marko0ace5632018-12-14 11:11:47 +00002634}
2635
Vladimir Marko436c6f52019-07-25 14:50:14 +01002636bool ImageSpace::VerifyBootClassPathChecksums(
2637 std::string_view oat_checksums,
2638 std::string_view oat_boot_class_path,
2639 ArrayRef<const std::unique_ptr<ImageSpace>> image_spaces,
2640 ArrayRef<const std::string> boot_class_path_locations,
2641 ArrayRef<const std::string> boot_class_path,
2642 /*out*/std::string* error_msg) {
2643 DCHECK_EQ(boot_class_path.size(), boot_class_path_locations.size());
2644 DCHECK_GE(boot_class_path_locations.size(), image_spaces.size());
2645 if (oat_checksums.empty() || oat_boot_class_path.empty()) {
2646 *error_msg = oat_checksums.empty() ? "Empty checksums." : "Empty boot class path.";
2647 return false;
2648 }
David Brazdil2c5bcb82019-04-03 11:14:34 +01002649
Vladimir Marko436c6f52019-07-25 14:50:14 +01002650 size_t oat_bcp_size =
2651 CheckAndCountBCPComponents(oat_boot_class_path, boot_class_path_locations, error_msg);
2652 if (oat_bcp_size == static_cast<size_t>(-1)) {
2653 DCHECK(!error_msg->empty());
2654 return false;
2655 }
2656
2657 // Verify image checksums.
2658 size_t image_pos = 0u;
2659 while (image_pos != image_spaces.size() && StartsWith(oat_checksums, "i")) {
2660 // Verify the current image checksum.
2661 const ImageHeader& current_header = image_spaces[image_pos]->GetImageHeader();
2662 uint32_t component_count = current_header.GetComponentCount();
2663 DCHECK_NE(component_count, 0u);
2664 DCHECK_LE(component_count, image_spaces.size() - image_pos);
2665 if (!CheckAndRemoveImageChecksum(current_header, &oat_checksums, error_msg)) {
2666 DCHECK(!error_msg->empty());
2667 return false;
2668 }
2669
2670 if (kIsDebugBuild) {
2671 for (size_t component_index = 0; component_index != component_count; ++component_index) {
2672 const OatFile* oat_file = image_spaces[image_pos + component_index]->oat_file_non_owned_;
2673 size_t num_dex_files = oat_file->GetOatDexFiles().size();
David Brazdil2c5bcb82019-04-03 11:14:34 +01002674 CHECK_NE(num_dex_files, 0u);
Vladimir Marko436c6f52019-07-25 14:50:14 +01002675 const std::string main_location = oat_file->GetOatDexFiles()[0]->GetDexFileLocation();
2676 CHECK_EQ(main_location, boot_class_path[image_pos + component_index]);
2677 CHECK(!DexFileLoader::IsMultiDexLocation(main_location.c_str()));
2678 for (size_t i = 1u; i != num_dex_files; ++i) {
2679 CHECK(DexFileLoader::IsMultiDexLocation(
2680 oat_file->GetOatDexFiles()[i]->GetDexFileLocation().c_str()));
David Brazdil2c5bcb82019-04-03 11:14:34 +01002681 }
Vladimir Marko0ace5632018-12-14 11:11:47 +00002682 }
2683 }
Vladimir Marko436c6f52019-07-25 14:50:14 +01002684
2685 image_pos += component_count;
2686
2687 if (!StartsWith(oat_checksums, ":")) {
2688 // Check that we've reached the end of checksums and BCP.
2689 if (!oat_checksums.empty()) {
2690 *error_msg = StringPrintf("Expected ':' separator or end of checksums, remaining %s.",
2691 std::string(oat_checksums).c_str());
2692 return false;
2693 }
2694 if (image_pos != oat_bcp_size) {
2695 *error_msg = StringPrintf("Component count mismatch between checksums (%zu) and BCP (%zu)",
2696 image_pos,
2697 oat_bcp_size);
2698 return false;
2699 }
2700 return true;
2701 }
2702 oat_checksums.remove_prefix(1u);
Vladimir Marko0ace5632018-12-14 11:11:47 +00002703 }
David Brazdil2c5bcb82019-04-03 11:14:34 +01002704
Vladimir Marko436c6f52019-07-25 14:50:14 +01002705 // We do not allow dependencies of extensions on dex files. That would require
2706 // interleaving the loading of the images with opening the other BCP dex files.
2707 return false;
Vladimir Marko0ace5632018-12-14 11:11:47 +00002708}
2709
Vladimir Marko91f10322018-12-07 18:04:10 +00002710std::vector<std::string> ImageSpace::ExpandMultiImageLocations(
2711 const std::vector<std::string>& dex_locations,
Vladimir Marko436c6f52019-07-25 14:50:14 +01002712 const std::string& image_location,
2713 bool boot_image_extension) {
2714 return ExpandMultiImageLocations(
2715 ArrayRef<const std::string>(dex_locations), image_location, boot_image_extension);
Vladimir Marko0ace5632018-12-14 11:11:47 +00002716}
2717
2718std::vector<std::string> ImageSpace::ExpandMultiImageLocations(
2719 ArrayRef<const std::string> dex_locations,
Vladimir Marko436c6f52019-07-25 14:50:14 +01002720 const std::string& image_location,
2721 bool boot_image_extension) {
Vladimir Marko91f10322018-12-07 18:04:10 +00002722 DCHECK(!dex_locations.empty());
Andreas Gampe8994a042015-12-30 19:03:17 +00002723
Vladimir Marko91f10322018-12-07 18:04:10 +00002724 // Find the path.
2725 size_t last_slash = image_location.rfind('/');
2726 CHECK_NE(last_slash, std::string::npos);
Andreas Gampe8994a042015-12-30 19:03:17 +00002727
Vladimir Marko91f10322018-12-07 18:04:10 +00002728 // We also need to honor path components that were encoded through '@'. Otherwise the loading
2729 // code won't be able to find the images.
2730 if (image_location.find('@', last_slash) != std::string::npos) {
2731 last_slash = image_location.rfind('@');
Andreas Gampe8994a042015-12-30 19:03:17 +00002732 }
Andreas Gampe8994a042015-12-30 19:03:17 +00002733
Vladimir Marko91f10322018-12-07 18:04:10 +00002734 // Find the dot separating the primary image name from the extension.
2735 size_t last_dot = image_location.rfind('.');
2736 // Extract the extension and base (the path and primary image name).
2737 std::string extension;
2738 std::string base = image_location;
2739 if (last_dot != std::string::npos && last_dot > last_slash) {
2740 extension = image_location.substr(last_dot); // Including the dot.
2741 base.resize(last_dot);
Andreas Gampe8994a042015-12-30 19:03:17 +00002742 }
Vladimir Marko91f10322018-12-07 18:04:10 +00002743 // For non-empty primary image name, add '-' to the `base`.
2744 if (last_slash + 1u != base.size()) {
2745 base += '-';
2746 }
2747
2748 std::vector<std::string> locations;
2749 locations.reserve(dex_locations.size());
Vladimir Marko436c6f52019-07-25 14:50:14 +01002750 size_t start_index = 0u;
2751 if (!boot_image_extension) {
2752 start_index = 1u;
2753 locations.push_back(image_location);
2754 }
Vladimir Marko91f10322018-12-07 18:04:10 +00002755
Vladimir Marko436c6f52019-07-25 14:50:14 +01002756 // Now create the other names. Use a counted loop to skip the first one if needed.
2757 for (size_t i = start_index; i < dex_locations.size(); ++i) {
Vladimir Marko91f10322018-12-07 18:04:10 +00002758 // Replace path with `base` (i.e. image path and prefix) and replace the original
2759 // extension (if any) with `extension`.
2760 std::string name = dex_locations[i];
2761 size_t last_dex_slash = name.rfind('/');
2762 if (last_dex_slash != std::string::npos) {
2763 name = name.substr(last_dex_slash + 1);
2764 }
2765 size_t last_dex_dot = name.rfind('.');
2766 if (last_dex_dot != std::string::npos) {
2767 name.resize(last_dex_dot);
2768 }
2769 locations.push_back(base + name + extension);
2770 }
2771 return locations;
Andreas Gampe8994a042015-12-30 19:03:17 +00002772}
2773
Mathieu Chartierd5f3f322016-03-21 14:05:56 -07002774void ImageSpace::DumpSections(std::ostream& os) const {
2775 const uint8_t* base = Begin();
2776 const ImageHeader& header = GetImageHeader();
2777 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
2778 auto section_type = static_cast<ImageHeader::ImageSections>(i);
2779 const ImageSection& section = header.GetImageSection(section_type);
2780 os << section_type << " " << reinterpret_cast<const void*>(base + section.Offset())
2781 << "-" << reinterpret_cast<const void*>(base + section.End()) << "\n";
2782 }
2783}
2784
Mathieu Chartier6e7a72c2019-03-07 21:40:10 -08002785void ImageSpace::DisablePreResolvedStrings() {
2786 // Clear dex cache pointers.
2787 ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
2788 GetImageHeader().GetImageRoot(ImageHeader::kDexCaches)->AsObjectArray<mirror::DexCache>();
2789 for (size_t len = dex_caches->GetLength(), i = 0; i < len; ++i) {
2790 ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
2791 dex_cache->ClearPreResolvedStrings();
2792 }
2793}
2794
2795void ImageSpace::ReleaseMetadata() {
2796 const ImageSection& metadata = GetImageHeader().GetMetadataSection();
2797 VLOG(image) << "Releasing " << metadata.Size() << " image metadata bytes";
2798 // In the case where new app images may have been added around the checkpoint, ensure that we
2799 // don't madvise the cache for these.
2800 ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
2801 GetImageHeader().GetImageRoot(ImageHeader::kDexCaches)->AsObjectArray<mirror::DexCache>();
2802 bool have_startup_cache = false;
2803 for (size_t len = dex_caches->GetLength(), i = 0; i < len; ++i) {
2804 ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
2805 if (dex_cache->NumPreResolvedStrings() != 0u) {
2806 have_startup_cache = true;
2807 }
2808 }
2809 // Only safe to do for images that have their preresolved strings caches disabled. This is because
2810 // uncompressed images madvise to the original unrelocated image contents.
2811 if (!have_startup_cache) {
2812 // Avoid using ZeroAndReleasePages since the zero fill might not be word atomic.
2813 uint8_t* const page_begin = AlignUp(Begin() + metadata.Offset(), kPageSize);
2814 uint8_t* const page_end = AlignDown(Begin() + metadata.End(), kPageSize);
2815 if (page_begin < page_end) {
2816 CHECK_NE(madvise(page_begin, page_end - page_begin, MADV_DONTNEED), -1) << "madvise failed";
2817 }
2818 }
2819}
2820
Ian Rogers1d54e732013-05-02 21:10:01 -07002821} // namespace space
2822} // namespace gc
2823} // namespace art