blob: b6877f59aec3727a21617c8fe10a882dccd2f468 [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
Mathieu Chartierceb07b32015-12-10 09:33:21 -080019#include <lz4.h>
Andreas Gampe70be1fb2014-10-31 16:45:19 -070020#include <sys/statvfs.h>
Alex Light25396132014-08-27 15:37:23 -070021#include <sys/types.h>
Narayan Kamath5a2be3f2015-02-16 13:51:51 +000022#include <unistd.h>
Alex Light25396132014-08-27 15:37:23 -070023
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070024#include <random>
25
Andreas Gampe46ee31b2016-12-14 10:11:49 -080026#include "android-base/stringprintf.h"
Andreas Gampe9186ced2016-12-12 14:28:21 -080027#include "android-base/strings.h"
28
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"
Andreas Gampe8228cdf2017-05-30 15:03:54 -070031#include "base/callee_save_type.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070032#include "base/enums.h"
David Sehr891a50e2017-10-27 17:01:07 -070033#include "base/file_utils.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070034#include "base/macros.h"
David Sehrc431b9d2018-03-02 12:01:51 -080035#include "base/os.h"
Narayan Kamathd1c606f2014-06-09 16:50:19 +010036#include "base/scoped_flock.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070037#include "base/stl_util.h"
Mathieu Chartier32ce2ad2016-03-04 14:58:03 -080038#include "base/systrace.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010039#include "base/time_utils.h"
David Sehrc431b9d2018-03-02 12:01:51 -080040#include "base/utils.h"
David Sehr013fd802018-01-11 22:55:24 -080041#include "dex/art_dex_file_loader.h"
David Sehr9e734c72018-01-04 17:56:19 -080042#include "dex/dex_file_loader.h"
David Sehr97c381e2017-02-01 15:09:58 -080043#include "exec_utils.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070044#include "gc/accounting/space_bitmap-inl.h"
Mathieu Chartier4a26f172016-01-26 14:26:18 -080045#include "image-inl.h"
Andreas Gampebec63582015-11-20 19:26:51 -080046#include "image_space_fs.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070047#include "mirror/class-inl.h"
48#include "mirror/object-inl.h"
Andreas Gampec6ea7d02017-02-01 16:46:28 -080049#include "mirror/object-refvisitor-inl.h"
Brian Carlstrom56d947f2013-07-15 13:14:23 -070050#include "oat_file.h"
Andreas Gamped482e732017-04-24 17:59:09 -070051#include "runtime.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070052#include "space-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070053
54namespace art {
55namespace gc {
56namespace space {
57
Andreas Gampe46ee31b2016-12-14 10:11:49 -080058using android::base::StringAppendF;
59using android::base::StringPrintf;
60
Ian Rogersef7d42f2014-01-06 12:55:46 -080061Atomic<uint32_t> ImageSpace::bitmap_index_(0);
Ian Rogers1d54e732013-05-02 21:10:01 -070062
Jeff Haodcdc85b2015-12-04 14:06:18 -080063ImageSpace::ImageSpace(const std::string& image_filename,
64 const char* image_location,
Vladimir Markoc34bebf2018-08-16 16:12:49 +010065 MemMap&& mem_map,
Vladimir Markoc09cd052018-08-23 16:36:36 +010066 std::unique_ptr<accounting::ContinuousSpaceBitmap> live_bitmap,
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080067 uint8_t* end)
68 : MemMapSpace(image_filename,
Vladimir Markoc34bebf2018-08-16 16:12:49 +010069 std::move(mem_map),
70 mem_map.Begin(),
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080071 end,
72 end,
Narayan Kamath52f84882014-05-02 10:10:39 +010073 kGcRetentionPolicyNeverCollect),
Vladimir Markoc09cd052018-08-23 16:36:36 +010074 live_bitmap_(std::move(live_bitmap)),
Jeff Haodcdc85b2015-12-04 14:06:18 -080075 oat_file_non_owned_(nullptr),
Mathieu Chartier2d124ec2016-01-05 18:03:15 -080076 image_location_(image_location) {
Vladimir Markoc09cd052018-08-23 16:36:36 +010077 DCHECK(live_bitmap_ != nullptr);
Ian Rogers1d54e732013-05-02 21:10:01 -070078}
79
Alex Lightcf4bf382014-07-24 11:29:14 -070080static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
81 CHECK_ALIGNED(min_delta, kPageSize);
82 CHECK_ALIGNED(max_delta, kPageSize);
83 CHECK_LT(min_delta, max_delta);
84
Alex Light15324762015-11-19 11:03:10 -080085 int32_t r = GetRandomNumber<int32_t>(min_delta, max_delta);
Alex Lightcf4bf382014-07-24 11:29:14 -070086 if (r % 2 == 0) {
87 r = RoundUp(r, kPageSize);
88 } else {
89 r = RoundDown(r, kPageSize);
90 }
91 CHECK_LE(min_delta, r);
92 CHECK_GE(max_delta, r);
93 CHECK_ALIGNED(r, kPageSize);
94 return r;
95}
96
Andreas Gampea463b6a2016-08-12 21:53:32 -070097static int32_t ChooseRelocationOffsetDelta() {
98 return ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, ART_BASE_ADDRESS_MAX_DELTA);
99}
100
101static bool GenerateImage(const std::string& image_filename,
102 InstructionSet image_isa,
Alex Light25396132014-08-27 15:37:23 -0700103 std::string* error_msg) {
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700104 const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
105 std::vector<std::string> boot_class_path;
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700106 Split(boot_class_path_string, ':', &boot_class_path);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700107 if (boot_class_path.empty()) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700108 *error_msg = "Failed to generate image because no boot class path specified";
109 return false;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700110 }
Alex Light25396132014-08-27 15:37:23 -0700111 // We should clean up so we are more likely to have room for the image.
112 if (Runtime::Current()->IsZygote()) {
Andreas Gampe3c13a792014-09-18 20:56:04 -0700113 LOG(INFO) << "Pruning dalvik-cache since we are generating an image and will need to recompile";
Narayan Kamath28bc9872014-11-07 17:46:28 +0000114 PruneDalvikCache(image_isa);
Alex Light25396132014-08-27 15:37:23 -0700115 }
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700116
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700117 std::vector<std::string> arg_vector;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700118
Tsu Chiang Chuang12e6d742014-05-22 10:22:25 -0700119 std::string dex2oat(Runtime::Current()->GetCompilerExecutable());
Mathieu Chartier08d7d442013-07-31 18:08:51 -0700120 arg_vector.push_back(dex2oat);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700121
122 std::string image_option_string("--image=");
Narayan Kamath52f84882014-05-02 10:10:39 +0100123 image_option_string += image_filename;
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700124 arg_vector.push_back(image_option_string);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700125
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700126 for (size_t i = 0; i < boot_class_path.size(); i++) {
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700127 arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700128 }
129
130 std::string oat_file_option_string("--oat-file=");
Brian Carlstrom2f1e15c2014-10-27 16:27:06 -0700131 oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename);
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700132 arg_vector.push_back(oat_file_option_string);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700133
Sebastien Hertz0de11332015-05-13 12:14:05 +0200134 // Note: we do not generate a fully debuggable boot image so we do not pass the
135 // compiler flag --debuggable here.
136
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700137 Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector);
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700138 CHECK_EQ(image_isa, kRuntimeISA)
139 << "We should always be generating an image for the current isa.";
Ian Rogers8afeb852014-04-02 14:55:49 -0700140
Andreas Gampea463b6a2016-08-12 21:53:32 -0700141 int32_t base_offset = ChooseRelocationOffsetDelta();
Alex Lightcf4bf382014-07-24 11:29:14 -0700142 LOG(INFO) << "Using an offset of 0x" << std::hex << base_offset << " from default "
143 << "art base address of 0x" << std::hex << ART_BASE_ADDRESS;
144 arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700145
Brian Carlstrom57309db2014-07-30 15:13:25 -0700146 if (!kIsTargetBuild) {
Mathieu Chartier8bbc8c02013-07-31 16:27:01 -0700147 arg_vector.push_back("--host");
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700148 }
149
Brian Carlstrom6449c622014-02-10 23:48:36 -0800150 const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions();
Brian Carlstrom2ec65202014-03-03 15:16:37 -0800151 for (size_t i = 0; i < compiler_options.size(); ++i) {
Brian Carlstrom6449c622014-02-10 23:48:36 -0800152 arg_vector.push_back(compiler_options[i].c_str());
153 }
154
Andreas Gampe9186ced2016-12-12 14:28:21 -0800155 std::string command_line(android::base::Join(arg_vector, ' '));
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700156 LOG(INFO) << "GenerateImage: " << command_line;
Brian Carlstrom6449c622014-02-10 23:48:36 -0800157 return Exec(arg_vector, error_msg);
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700158}
159
Andreas Gampea463b6a2016-08-12 21:53:32 -0700160static bool FindImageFilenameImpl(const char* image_location,
161 const InstructionSet image_isa,
162 bool* has_system,
163 std::string* system_filename,
164 bool* dalvik_cache_exists,
165 std::string* dalvik_cache,
166 bool* is_global_cache,
167 bool* has_cache,
168 std::string* cache_filename) {
169 DCHECK(dalvik_cache != nullptr);
170
Alex Lighta59dd802014-07-02 16:28:08 -0700171 *has_system = false;
172 *has_cache = false;
Brian Carlstrom0e12bdc2014-05-14 17:44:28 -0700173 // image_location = /system/framework/boot.art
174 // system_image_location = /system/framework/<image_isa>/boot.art
175 std::string system_image_filename(GetSystemImageFilename(image_location, image_isa));
176 if (OS::FileExists(system_image_filename.c_str())) {
Alex Lighta59dd802014-07-02 16:28:08 -0700177 *system_filename = system_image_filename;
178 *has_system = true;
Brian Carlstrom56d947f2013-07-15 13:14:23 -0700179 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100180
Alex Lighta59dd802014-07-02 16:28:08 -0700181 bool have_android_data = false;
182 *dalvik_cache_exists = false;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700183 GetDalvikCache(GetInstructionSetString(image_isa),
Vladimir Marko82e1e272018-08-20 13:38:06 +0000184 /* create_if_absent */ true,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700185 dalvik_cache,
186 &have_android_data,
187 dalvik_cache_exists,
188 is_global_cache);
Narayan Kamath52f84882014-05-02 10:10:39 +0100189
Vladimir Marko82e1e272018-08-20 13:38:06 +0000190 if (*dalvik_cache_exists) {
191 DCHECK(have_android_data);
Alex Lighta59dd802014-07-02 16:28:08 -0700192 // Always set output location even if it does not exist,
193 // so that the caller knows where to create the image.
194 //
195 // image_location = /system/framework/boot.art
Vladimir Marko82e1e272018-08-20 13:38:06 +0000196 // *image_filename = /data/dalvik-cache/<image_isa>/system@framework@boot.art
Alex Lighta59dd802014-07-02 16:28:08 -0700197 std::string error_msg;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700198 if (!GetDalvikCacheFilename(image_location,
199 dalvik_cache->c_str(),
200 cache_filename,
201 &error_msg)) {
Alex Lighta59dd802014-07-02 16:28:08 -0700202 LOG(WARNING) << error_msg;
203 return *has_system;
204 }
205 *has_cache = OS::FileExists(cache_filename->c_str());
206 }
207 return *has_system || *has_cache;
208}
209
Andreas Gampea463b6a2016-08-12 21:53:32 -0700210bool ImageSpace::FindImageFilename(const char* image_location,
211 const InstructionSet image_isa,
212 std::string* system_filename,
213 bool* has_system,
214 std::string* cache_filename,
215 bool* dalvik_cache_exists,
216 bool* has_cache,
217 bool* is_global_cache) {
218 std::string dalvik_cache_unused;
219 return FindImageFilenameImpl(image_location,
220 image_isa,
221 has_system,
222 system_filename,
223 dalvik_cache_exists,
224 &dalvik_cache_unused,
225 is_global_cache,
226 has_cache,
227 cache_filename);
228}
229
Alex Lighta59dd802014-07-02 16:28:08 -0700230static bool ReadSpecificImageHeader(const char* filename, ImageHeader* image_header) {
231 std::unique_ptr<File> image_file(OS::OpenFileForReading(filename));
232 if (image_file.get() == nullptr) {
233 return false;
234 }
235 const bool success = image_file->ReadFully(image_header, sizeof(ImageHeader));
236 if (!success || !image_header->IsValid()) {
237 return false;
238 }
239 return true;
240}
241
Alex Light6e183f22014-07-18 14:57:04 -0700242// Relocate the image at image_location to dest_filename and relocate it by a random amount.
Andreas Gampea463b6a2016-08-12 21:53:32 -0700243static bool RelocateImage(const char* image_location,
Chris Morin88c6d262018-02-13 15:26:21 -0800244 const char* dest_directory,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700245 InstructionSet isa,
246 std::string* error_msg) {
Alex Light25396132014-08-27 15:37:23 -0700247 // We should clean up so we are more likely to have room for the image.
248 if (Runtime::Current()->IsZygote()) {
249 LOG(INFO) << "Pruning dalvik-cache since we are relocating an image and will need to recompile";
Narayan Kamath28bc9872014-11-07 17:46:28 +0000250 PruneDalvikCache(isa);
Alex Light25396132014-08-27 15:37:23 -0700251 }
252
Alex Lighta59dd802014-07-02 16:28:08 -0700253 std::string patchoat(Runtime::Current()->GetPatchoatExecutable());
254
255 std::string input_image_location_arg("--input-image-location=");
256 input_image_location_arg += image_location;
257
Chris Morin88c6d262018-02-13 15:26:21 -0800258 std::string output_image_directory_arg("--output-image-directory=");
259 output_image_directory_arg += dest_directory;
Alex Lighta59dd802014-07-02 16:28:08 -0700260
Alex Lighta59dd802014-07-02 16:28:08 -0700261 std::string instruction_set_arg("--instruction-set=");
262 instruction_set_arg += GetInstructionSetString(isa);
263
264 std::string base_offset_arg("--base-offset-delta=");
Andreas Gampea463b6a2016-08-12 21:53:32 -0700265 StringAppendF(&base_offset_arg, "%d", ChooseRelocationOffsetDelta());
Alex Lighta59dd802014-07-02 16:28:08 -0700266
267 std::vector<std::string> argv;
268 argv.push_back(patchoat);
269
270 argv.push_back(input_image_location_arg);
Chris Morin88c6d262018-02-13 15:26:21 -0800271 argv.push_back(output_image_directory_arg);
Alex Lighta59dd802014-07-02 16:28:08 -0700272
Alex Lighta59dd802014-07-02 16:28:08 -0700273 argv.push_back(instruction_set_arg);
274 argv.push_back(base_offset_arg);
275
Andreas Gampe9186ced2016-12-12 14:28:21 -0800276 std::string command_line(android::base::Join(argv, ' '));
Alex Lighta59dd802014-07-02 16:28:08 -0700277 LOG(INFO) << "RelocateImage: " << command_line;
278 return Exec(argv, error_msg);
279}
280
Chris Morine5fac732018-02-05 14:27:40 -0800281static bool VerifyImage(const char* image_location,
Chris Morin88c6d262018-02-13 15:26:21 -0800282 const char* dest_directory,
Chris Morine5fac732018-02-05 14:27:40 -0800283 InstructionSet isa,
284 std::string* error_msg) {
285 std::string patchoat(Runtime::Current()->GetPatchoatExecutable());
286
287 std::string input_image_location_arg("--input-image-location=");
288 input_image_location_arg += image_location;
289
Chris Morin88c6d262018-02-13 15:26:21 -0800290 std::string output_image_directory_arg("--output-image-directory=");
291 output_image_directory_arg += dest_directory;
Chris Morine5fac732018-02-05 14:27:40 -0800292
293 std::string instruction_set_arg("--instruction-set=");
294 instruction_set_arg += GetInstructionSetString(isa);
295
296 std::vector<std::string> argv;
297 argv.push_back(patchoat);
298
299 argv.push_back(input_image_location_arg);
Chris Morin88c6d262018-02-13 15:26:21 -0800300 argv.push_back(output_image_directory_arg);
Chris Morine5fac732018-02-05 14:27:40 -0800301
302 argv.push_back(instruction_set_arg);
303
304 argv.push_back("--verify");
305
306 std::string command_line(android::base::Join(argv, ' '));
307 LOG(INFO) << "VerifyImage: " << command_line;
308 return Exec(argv, error_msg);
309}
310
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700311static ImageHeader* ReadSpecificImageHeader(const char* filename, std::string* error_msg) {
Alex Lighta59dd802014-07-02 16:28:08 -0700312 std::unique_ptr<ImageHeader> hdr(new ImageHeader);
313 if (!ReadSpecificImageHeader(filename, hdr.get())) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700314 *error_msg = StringPrintf("Unable to read image header for %s", filename);
Alex Lighta59dd802014-07-02 16:28:08 -0700315 return nullptr;
316 }
317 return hdr.release();
Narayan Kamath52f84882014-05-02 10:10:39 +0100318}
319
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700320ImageHeader* ImageSpace::ReadImageHeader(const char* image_location,
321 const InstructionSet image_isa,
322 std::string* error_msg) {
Alex Lighta59dd802014-07-02 16:28:08 -0700323 std::string system_filename;
324 bool has_system = false;
325 std::string cache_filename;
326 bool has_cache = false;
327 bool dalvik_cache_exists = false;
Andreas Gampe3c13a792014-09-18 20:56:04 -0700328 bool is_global_cache = false;
Alex Lighta59dd802014-07-02 16:28:08 -0700329 if (FindImageFilename(image_location, image_isa, &system_filename, &has_system,
Andreas Gampe3c13a792014-09-18 20:56:04 -0700330 &cache_filename, &dalvik_cache_exists, &has_cache, &is_global_cache)) {
Alex Lighta59dd802014-07-02 16:28:08 -0700331 if (Runtime::Current()->ShouldRelocate()) {
332 if (has_system && has_cache) {
333 std::unique_ptr<ImageHeader> sys_hdr(new ImageHeader);
334 std::unique_ptr<ImageHeader> cache_hdr(new ImageHeader);
335 if (!ReadSpecificImageHeader(system_filename.c_str(), sys_hdr.get())) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700336 *error_msg = StringPrintf("Unable to read image header for %s at %s",
337 image_location, system_filename.c_str());
Alex Lighta59dd802014-07-02 16:28:08 -0700338 return nullptr;
339 }
340 if (!ReadSpecificImageHeader(cache_filename.c_str(), cache_hdr.get())) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700341 *error_msg = StringPrintf("Unable to read image header for %s at %s",
342 image_location, cache_filename.c_str());
Alex Lighta59dd802014-07-02 16:28:08 -0700343 return nullptr;
344 }
345 if (sys_hdr->GetOatChecksum() != cache_hdr->GetOatChecksum()) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700346 *error_msg = StringPrintf("Unable to find a relocated version of image file %s",
347 image_location);
Alex Lighta59dd802014-07-02 16:28:08 -0700348 return nullptr;
349 }
350 return cache_hdr.release();
351 } else if (!has_cache) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700352 *error_msg = StringPrintf("Unable to find a relocated version of image file %s",
353 image_location);
Alex Lighta59dd802014-07-02 16:28:08 -0700354 return nullptr;
355 } else if (!has_system && has_cache) {
356 // This can probably just use the cache one.
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700357 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
Alex Lighta59dd802014-07-02 16:28:08 -0700358 }
359 } else {
360 // We don't want to relocate, Just pick the appropriate one if we have it and return.
361 if (has_system && has_cache) {
362 // We want the cache if the checksum matches, otherwise the system.
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700363 std::unique_ptr<ImageHeader> system(ReadSpecificImageHeader(system_filename.c_str(),
364 error_msg));
365 std::unique_ptr<ImageHeader> cache(ReadSpecificImageHeader(cache_filename.c_str(),
366 error_msg));
Alex Lighta59dd802014-07-02 16:28:08 -0700367 if (system.get() == nullptr ||
368 (cache.get() != nullptr && cache->GetOatChecksum() == system->GetOatChecksum())) {
369 return cache.release();
370 } else {
371 return system.release();
372 }
373 } else if (has_system) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700374 return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
Alex Lighta59dd802014-07-02 16:28:08 -0700375 } else if (has_cache) {
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700376 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
Alex Lighta59dd802014-07-02 16:28:08 -0700377 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100378 }
Narayan Kamath52f84882014-05-02 10:10:39 +0100379 }
380
Brian Carlstrom31d8f522014-09-29 11:22:54 -0700381 *error_msg = StringPrintf("Unable to find image file for %s", image_location);
Narayan Kamath52f84882014-05-02 10:10:39 +0100382 return nullptr;
383}
384
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400385static bool CanWriteToDalvikCache(const InstructionSet isa) {
386 const std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(isa));
387 if (access(dalvik_cache.c_str(), O_RDWR) == 0) {
388 return true;
389 } else if (errno != EACCES) {
390 PLOG(WARNING) << "CanWriteToDalvikCache returned error other than EACCES";
391 }
392 return false;
393}
394
395static bool ImageCreationAllowed(bool is_global_cache,
396 const InstructionSet isa,
397 std::string* error_msg) {
Andreas Gampe3c13a792014-09-18 20:56:04 -0700398 // Anyone can write into a "local" cache.
399 if (!is_global_cache) {
400 return true;
401 }
402
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400403 // Only the zygote running as root is allowed to create the global boot image.
404 // If the zygote is running as non-root (and cannot write to the dalvik-cache),
405 // then image creation is not allowed..
Andreas Gampe3c13a792014-09-18 20:56:04 -0700406 if (Runtime::Current()->IsZygote()) {
Robert Sesekbfa1f8d2016-08-15 15:21:09 -0400407 return CanWriteToDalvikCache(isa);
Andreas Gampe3c13a792014-09-18 20:56:04 -0700408 }
409
410 *error_msg = "Only the zygote can create the global boot image.";
411 return false;
412}
413
Mathieu Chartier31e89252013-08-28 11:29:12 -0700414void ImageSpace::VerifyImageAllocations() {
Ian Rogers13735952014-10-08 12:43:28 -0700415 uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
Mathieu Chartier31e89252013-08-28 11:29:12 -0700416 while (current < End()) {
Mathieu Chartierc7853442015-03-27 14:35:38 -0700417 CHECK_ALIGNED(current, kObjectAlignment);
418 auto* obj = reinterpret_cast<mirror::Object*>(current);
Mathieu Chartier31e89252013-08-28 11:29:12 -0700419 CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
David Sehr709b0702016-10-13 09:12:37 -0700420 CHECK(live_bitmap_->Test(obj)) << obj->PrettyTypeOf();
Hiroshi Yamauchi12b58b22016-11-01 11:55:29 -0700421 if (kUseBakerReadBarrier) {
422 obj->AssertReadBarrierState();
Hiroshi Yamauchi9d04a202014-01-31 13:35:49 -0800423 }
Mathieu Chartier31e89252013-08-28 11:29:12 -0700424 current += RoundUp(obj->SizeOf(), kObjectAlignment);
425 }
426}
427
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800428// Helper class for relocating from one range of memory to another.
429class RelocationRange {
430 public:
431 RelocationRange() = default;
432 RelocationRange(const RelocationRange&) = default;
433 RelocationRange(uintptr_t source, uintptr_t dest, uintptr_t length)
434 : source_(source),
435 dest_(dest),
436 length_(length) {}
437
Mathieu Chartier91edc622016-02-16 17:16:01 -0800438 bool InSource(uintptr_t address) const {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800439 return address - source_ < length_;
440 }
441
Mathieu Chartier91edc622016-02-16 17:16:01 -0800442 bool InDest(uintptr_t address) const {
443 return address - dest_ < length_;
444 }
445
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800446 // Translate a source address to the destination space.
447 uintptr_t ToDest(uintptr_t address) const {
Mathieu Chartier91edc622016-02-16 17:16:01 -0800448 DCHECK(InSource(address));
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800449 return address + Delta();
450 }
451
452 // Returns the delta between the dest from the source.
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800453 uintptr_t Delta() const {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800454 return dest_ - source_;
455 }
456
457 uintptr_t Source() const {
458 return source_;
459 }
460
461 uintptr_t Dest() const {
462 return dest_;
463 }
464
465 uintptr_t Length() const {
466 return length_;
467 }
468
469 private:
470 const uintptr_t source_;
471 const uintptr_t dest_;
472 const uintptr_t length_;
473};
474
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800475std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) {
476 return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-"
477 << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->("
478 << reinterpret_cast<const void*>(reloc.Dest()) << "-"
479 << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")";
480}
481
Andreas Gampea463b6a2016-08-12 21:53:32 -0700482// Helper class encapsulating loading, so we can access private ImageSpace members (this is a
Vladimir Markoc09cd052018-08-23 16:36:36 +0100483// nested class), but not declare functions in the header.
Vladimir Marko82e1e272018-08-20 13:38:06 +0000484class ImageSpace::Loader {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800485 public:
Andreas Gampea463b6a2016-08-12 21:53:32 -0700486 static std::unique_ptr<ImageSpace> Init(const char* image_filename,
487 const char* image_location,
488 bool validate_oat_file,
489 const OatFile* oat_file,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100490 /*inout*/MemMap* image_reservation,
491 /*inout*/MemMap* oat_reservation,
492 /*out*/std::string* error_msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700493 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700494 CHECK(image_filename != nullptr);
495 CHECK(image_location != nullptr);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800496
Andreas Gampea463b6a2016-08-12 21:53:32 -0700497 TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image));
498 VLOG(image) << "ImageSpace::Init entering image_filename=" << image_filename;
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800499
Andreas Gampea463b6a2016-08-12 21:53:32 -0700500 std::unique_ptr<File> file;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700501 {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700502 TimingLogger::ScopedTiming timing("OpenImageFile", &logger);
503 file.reset(OS::OpenFileForReading(image_filename));
504 if (file == nullptr) {
505 *error_msg = StringPrintf("Failed to open '%s'", image_filename);
506 return nullptr;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700507 }
Andreas Gampea463b6a2016-08-12 21:53:32 -0700508 }
509 ImageHeader temp_image_header;
510 ImageHeader* image_header = &temp_image_header;
511 {
512 TimingLogger::ScopedTiming timing("ReadImageHeader", &logger);
513 bool success = file->ReadFully(image_header, sizeof(*image_header));
514 if (!success || !image_header->IsValid()) {
515 *error_msg = StringPrintf("Invalid image header in '%s'", image_filename);
516 return nullptr;
517 }
518 }
519 // Check that the file is larger or equal to the header size + data size.
520 const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength());
521 if (image_file_size < sizeof(ImageHeader) + image_header->GetDataSize()) {
522 *error_msg = StringPrintf("Image file truncated: %" PRIu64 " vs. %" PRIu64 ".",
523 image_file_size,
524 sizeof(ImageHeader) + image_header->GetDataSize());
525 return nullptr;
526 }
527
528 if (oat_file != nullptr) {
529 // If we have an oat file, check the oat file checksum. The oat file is only non-null for the
530 // app image case. Otherwise, we open the oat file after the image and check the checksum there.
531 const uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
532 const uint32_t image_oat_checksum = image_header->GetOatChecksum();
533 if (oat_checksum != image_oat_checksum) {
534 *error_msg = StringPrintf("Oat checksum 0x%x does not match the image one 0x%x in image %s",
535 oat_checksum,
536 image_oat_checksum,
537 image_filename);
538 return nullptr;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700539 }
540 }
541
Andreas Gampea463b6a2016-08-12 21:53:32 -0700542 if (VLOG_IS_ON(startup)) {
543 LOG(INFO) << "Dumping image sections";
544 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
545 const auto section_idx = static_cast<ImageHeader::ImageSections>(i);
546 auto& section = image_header->GetImageSection(section_idx);
547 LOG(INFO) << section_idx << " start="
548 << reinterpret_cast<void*>(image_header->GetImageBegin() + section.Offset()) << " "
549 << section;
Mathieu Chartier92ec5942016-04-11 12:03:48 -0700550 }
Andreas Gampea463b6a2016-08-12 21:53:32 -0700551 }
552
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100553 const auto& bitmap_section = image_header->GetImageBitmapSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700554 // The location we want to map from is the first aligned page after the end of the stored
555 // (possibly compressed) data.
556 const size_t image_bitmap_offset = RoundUp(sizeof(ImageHeader) + image_header->GetDataSize(),
557 kPageSize);
558 const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size();
Vladimir Marko6121aa62018-07-06 10:04:35 +0100559 const ImageSection& relocations_section = image_header->GetImageRelocationsSection();
560 if (relocations_section.Offset() != bitmap_section.Offset() + bitmap_section.Size()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700561 *error_msg = StringPrintf(
Vladimir Marko6121aa62018-07-06 10:04:35 +0100562 "Relocations do not start immediately after bitmap: %u vs. %u + %u.",
563 relocations_section.Offset(),
564 bitmap_section.Offset(),
565 bitmap_section.Size());
566 return nullptr;
567 }
568 const size_t end_of_relocations = end_of_bitmap + relocations_section.Size();
569 if (end_of_relocations != image_file_size) {
570 *error_msg = StringPrintf(
571 "Image file size does not equal end of relocations: size=%" PRIu64 " vs. %zu.",
572 image_file_size,
573 end_of_relocations);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700574 return nullptr;
575 }
576
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100577 MemMap map;
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800578
Andreas Gampea463b6a2016-08-12 21:53:32 -0700579 // GetImageBegin is the preferred address to map the image. If we manage to map the
580 // image at the image begin, the amount of fixup work required is minimized.
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800581 // If it is pic we will retry with error_msg for the failure case. Pass a null error_msg to
582 // avoid reading proc maps for a mapping failure and slowing everything down.
Vladimir Markoc09cd052018-08-23 16:36:36 +0100583 // For the boot image, we have already reserved the memory and we load the image
584 // into the `image_reservation`.
585 map = LoadImageFile(
586 image_filename,
587 image_location,
588 *image_header,
589 image_header->GetImageBegin(),
590 file->Fd(),
591 logger,
592 image_reservation,
593 (image_reservation == nullptr && image_header->IsPic()) ? nullptr : error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700594 // If the header specifies PIC mode, we can also map at a random low_4gb address since we can
595 // relocate in-place.
Vladimir Markoc09cd052018-08-23 16:36:36 +0100596 if (!map.IsValid() && image_reservation == nullptr && image_header->IsPic()) {
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100597 map = LoadImageFile(image_filename,
598 image_location,
599 *image_header,
600 /* address */ nullptr,
601 file->Fd(),
602 logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100603 /* image_reservation */ nullptr,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100604 error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700605 }
606 // Were we able to load something and continue?
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100607 if (!map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700608 DCHECK(!error_msg->empty());
609 return nullptr;
610 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100611 DCHECK_EQ(0, memcmp(image_header, map.Begin(), sizeof(ImageHeader)));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700612
Vladimir Markoc09cd052018-08-23 16:36:36 +0100613 MemMap image_bitmap_map = MemMap::MapFile(bitmap_section.Size(),
614 PROT_READ, MAP_PRIVATE,
615 file->Fd(),
616 image_bitmap_offset,
617 /* low_4gb */ false,
618 image_filename,
619 error_msg);
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100620 if (!image_bitmap_map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700621 *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
622 return nullptr;
623 }
624 // Loaded the map, use the image header from the file now in case we patch it with
625 // RelocateInPlace.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100626 image_header = reinterpret_cast<ImageHeader*>(map.Begin());
Hans Boehmfb8b4e22018-09-05 16:45:42 -0700627 const uint32_t bitmap_index = ImageSpace::bitmap_index_.fetch_add(1);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700628 std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u",
629 image_filename,
630 bitmap_index));
631 // Bitmap only needs to cover until the end of the mirror objects section.
Vladimir Markocd87c3e2017-09-05 13:11:57 +0100632 const ImageSection& image_objects = image_header->GetObjectsSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700633 // We only want the mirror object, not the ArtFields and ArtMethods.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100634 uint8_t* const image_end = map.Begin() + image_objects.End();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700635 std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap;
636 {
637 TimingLogger::ScopedTiming timing("CreateImageBitmap", &logger);
638 bitmap.reset(
639 accounting::ContinuousSpaceBitmap::CreateFromMemMap(
640 bitmap_name,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100641 std::move(image_bitmap_map),
642 reinterpret_cast<uint8_t*>(map.Begin()),
Mathieu Chartier612ff542017-05-01 09:59:24 -0700643 // Make sure the bitmap is aligned to card size instead of just bitmap word size.
644 RoundUp(image_objects.End(), gc::accounting::CardTable::kCardSize)));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700645 if (bitmap == nullptr) {
646 *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str());
647 return nullptr;
648 }
649 }
650 {
651 TimingLogger::ScopedTiming timing("RelocateImage", &logger);
652 if (!RelocateInPlace(*image_header,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100653 map.Begin(),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700654 bitmap.get(),
655 oat_file,
656 error_msg)) {
657 return nullptr;
658 }
659 }
660 // We only want the mirror object, not the ArtFields and ArtMethods.
661 std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename,
662 image_location,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100663 std::move(map),
Vladimir Markoc09cd052018-08-23 16:36:36 +0100664 std::move(bitmap),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700665 image_end));
666
667 // VerifyImageAllocations() will be called later in Runtime::Init()
668 // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_
669 // and ArtField::java_lang_reflect_ArtField_, which are used from
670 // Object::SizeOf() which VerifyImageAllocations() calls, are not
671 // set yet at this point.
672 if (oat_file == nullptr) {
673 TimingLogger::ScopedTiming timing("OpenOatFile", &logger);
Vladimir Markoc09cd052018-08-23 16:36:36 +0100674 space->oat_file_ = OpenOatFile(*space, image_filename, oat_reservation, error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700675 if (space->oat_file_ == nullptr) {
676 DCHECK(!error_msg->empty());
677 return nullptr;
678 }
679 space->oat_file_non_owned_ = space->oat_file_.get();
680 } else {
681 space->oat_file_non_owned_ = oat_file;
682 }
683
684 if (validate_oat_file) {
685 TimingLogger::ScopedTiming timing("ValidateOatFile", &logger);
686 CHECK(space->oat_file_ != nullptr);
Richard Uhler84f50ae2017-02-06 15:12:45 +0000687 if (!ImageSpace::ValidateOatFile(*space->oat_file_, error_msg)) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700688 DCHECK(!error_msg->empty());
689 return nullptr;
690 }
691 }
692
693 Runtime* runtime = Runtime::Current();
694
695 // If oat_file is null, then it is the boot image space. Use oat_file_non_owned_ from the space
696 // to set the runtime methods.
697 CHECK_EQ(oat_file != nullptr, image_header->IsAppImage());
698 if (image_header->IsAppImage()) {
699 CHECK_EQ(runtime->GetResolutionMethod(),
700 image_header->GetImageMethod(ImageHeader::kResolutionMethod));
701 CHECK_EQ(runtime->GetImtConflictMethod(),
702 image_header->GetImageMethod(ImageHeader::kImtConflictMethod));
703 CHECK_EQ(runtime->GetImtUnimplementedMethod(),
704 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod));
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700705 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700706 image_header->GetImageMethod(ImageHeader::kSaveAllCalleeSavesMethod));
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700707 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700708 image_header->GetImageMethod(ImageHeader::kSaveRefsOnlyMethod));
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700709 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700710 image_header->GetImageMethod(ImageHeader::kSaveRefsAndArgsMethod));
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700711 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything),
Andreas Gampea463b6a2016-08-12 21:53:32 -0700712 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethod));
Mingyao Yang0a87a652017-04-12 13:43:15 -0700713 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit),
714 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForClinit));
715 CHECK_EQ(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck),
716 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForSuspendCheck));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700717 } else if (!runtime->HasResolutionMethod()) {
718 runtime->SetInstructionSet(space->oat_file_non_owned_->GetOatHeader().GetInstructionSet());
719 runtime->SetResolutionMethod(image_header->GetImageMethod(ImageHeader::kResolutionMethod));
720 runtime->SetImtConflictMethod(image_header->GetImageMethod(ImageHeader::kImtConflictMethod));
721 runtime->SetImtUnimplementedMethod(
722 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod));
723 runtime->SetCalleeSaveMethod(
724 image_header->GetImageMethod(ImageHeader::kSaveAllCalleeSavesMethod),
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700725 CalleeSaveType::kSaveAllCalleeSaves);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700726 runtime->SetCalleeSaveMethod(
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700727 image_header->GetImageMethod(ImageHeader::kSaveRefsOnlyMethod),
728 CalleeSaveType::kSaveRefsOnly);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700729 runtime->SetCalleeSaveMethod(
730 image_header->GetImageMethod(ImageHeader::kSaveRefsAndArgsMethod),
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700731 CalleeSaveType::kSaveRefsAndArgs);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700732 runtime->SetCalleeSaveMethod(
Andreas Gampe8228cdf2017-05-30 15:03:54 -0700733 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethod),
734 CalleeSaveType::kSaveEverything);
Mingyao Yang0a87a652017-04-12 13:43:15 -0700735 runtime->SetCalleeSaveMethod(
736 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForClinit),
737 CalleeSaveType::kSaveEverythingForClinit);
738 runtime->SetCalleeSaveMethod(
739 image_header->GetImageMethod(ImageHeader::kSaveEverythingMethodForSuspendCheck),
740 CalleeSaveType::kSaveEverythingForSuspendCheck);
Andreas Gampea463b6a2016-08-12 21:53:32 -0700741 }
742
743 VLOG(image) << "ImageSpace::Init exiting " << *space.get();
744 if (VLOG_IS_ON(image)) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700745 logger.Dump(LOG_STREAM(INFO));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700746 }
747 return space;
748 }
749
750 private:
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100751 static MemMap LoadImageFile(const char* image_filename,
752 const char* image_location,
753 const ImageHeader& image_header,
754 uint8_t* address,
755 int fd,
756 TimingLogger& logger,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100757 /*inout*/MemMap* image_reservation,
758 /*out*/std::string* error_msg) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700759 TimingLogger::ScopedTiming timing("MapImageFile", &logger);
760 const ImageHeader::StorageMode storage_mode = image_header.GetStorageMode();
761 if (storage_mode == ImageHeader::kStorageModeUncompressed) {
762 return MemMap::MapFileAtAddress(address,
763 image_header.GetImageSize(),
764 PROT_READ | PROT_WRITE,
765 MAP_PRIVATE,
766 fd,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100767 /* start */ 0,
768 /* low_4gb */ true,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700769 image_filename,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100770 /* reuse */ false,
771 image_reservation,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700772 error_msg);
773 }
774
775 if (storage_mode != ImageHeader::kStorageModeLZ4 &&
776 storage_mode != ImageHeader::kStorageModeLZ4HC) {
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800777 if (error_msg != nullptr) {
778 *error_msg = StringPrintf("Invalid storage mode in image header %d",
779 static_cast<int>(storage_mode));
780 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100781 return MemMap::Invalid();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700782 }
783
784 // Reserve output and decompress into it.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100785 MemMap map = MemMap::MapAnonymous(image_location,
786 address,
787 image_header.GetImageSize(),
788 PROT_READ | PROT_WRITE,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100789 /* low_4gb */ true,
790 /* reuse */ false,
791 image_reservation,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100792 error_msg);
793 if (map.IsValid()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700794 const size_t stored_size = image_header.GetDataSize();
795 const size_t decompress_offset = sizeof(ImageHeader); // Skip the header.
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100796 MemMap temp_map = MemMap::MapFile(sizeof(ImageHeader) + stored_size,
797 PROT_READ,
798 MAP_PRIVATE,
799 fd,
Vladimir Markoc09cd052018-08-23 16:36:36 +0100800 /* offset */ 0,
801 /* low_4gb */ false,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100802 image_filename,
803 error_msg);
804 if (!temp_map.IsValid()) {
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800805 DCHECK(error_msg == nullptr || !error_msg->empty());
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100806 return MemMap::Invalid();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700807 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100808 memcpy(map.Begin(), &image_header, sizeof(ImageHeader));
Andreas Gampea463b6a2016-08-12 21:53:32 -0700809 const uint64_t start = NanoTime();
810 // LZ4HC and LZ4 have same internal format, both use LZ4_decompress.
811 TimingLogger::ScopedTiming timing2("LZ4 decompress image", &logger);
812 const size_t decompressed_size = LZ4_decompress_safe(
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100813 reinterpret_cast<char*>(temp_map.Begin()) + sizeof(ImageHeader),
814 reinterpret_cast<char*>(map.Begin()) + decompress_offset,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700815 stored_size,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100816 map.Size() - decompress_offset);
Mathieu Chartier0d4d2912017-02-10 17:22:41 -0800817 const uint64_t time = NanoTime() - start;
818 // Add one 1 ns to prevent possible divide by 0.
819 VLOG(image) << "Decompressing image took " << PrettyDuration(time) << " ("
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100820 << PrettySize(static_cast<uint64_t>(map.Size()) * MsToNs(1000) / (time + 1))
Mathieu Chartier0d4d2912017-02-10 17:22:41 -0800821 << "/s)";
Andreas Gampea463b6a2016-08-12 21:53:32 -0700822 if (decompressed_size + sizeof(ImageHeader) != image_header.GetImageSize()) {
Mathieu Chartier66b1d572017-02-10 18:41:39 -0800823 if (error_msg != nullptr) {
824 *error_msg = StringPrintf(
825 "Decompressed size does not match expected image size %zu vs %zu",
826 decompressed_size + sizeof(ImageHeader),
827 image_header.GetImageSize());
828 }
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100829 return MemMap::Invalid();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700830 }
831 }
832
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100833 return map;
Andreas Gampea463b6a2016-08-12 21:53:32 -0700834 }
835
836 class FixupVisitor : public ValueObject {
837 public:
838 FixupVisitor(const RelocationRange& boot_image,
839 const RelocationRange& boot_oat,
840 const RelocationRange& app_image,
841 const RelocationRange& app_oat)
842 : boot_image_(boot_image),
843 boot_oat_(boot_oat),
844 app_image_(app_image),
845 app_oat_(app_oat) {}
846
847 // Return the relocated address of a heap object.
848 template <typename T>
849 ALWAYS_INLINE T* ForwardObject(T* src) const {
850 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
851 if (boot_image_.InSource(uint_src)) {
852 return reinterpret_cast<T*>(boot_image_.ToDest(uint_src));
853 }
854 if (app_image_.InSource(uint_src)) {
855 return reinterpret_cast<T*>(app_image_.ToDest(uint_src));
856 }
857 // Since we are fixing up the app image, there should only be pointers to the app image and
858 // boot image.
859 DCHECK(src == nullptr) << reinterpret_cast<const void*>(src);
860 return src;
861 }
862
863 // Return the relocated address of a code pointer (contained by an oat file).
864 ALWAYS_INLINE const void* ForwardCode(const void* src) const {
865 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src);
866 if (boot_oat_.InSource(uint_src)) {
867 return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src));
868 }
869 if (app_oat_.InSource(uint_src)) {
870 return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src));
871 }
872 DCHECK(src == nullptr) << src;
873 return src;
874 }
875
876 // Must be called on pointers that already have been relocated to the destination relocation.
877 ALWAYS_INLINE bool IsInAppImage(mirror::Object* object) const {
878 return app_image_.InDest(reinterpret_cast<uintptr_t>(object));
879 }
880
881 protected:
882 // Source section.
883 const RelocationRange boot_image_;
884 const RelocationRange boot_oat_;
885 const RelocationRange app_image_;
886 const RelocationRange app_oat_;
887 };
888
889 // Adapt for mirror::Class::FixupNativePointers.
890 class FixupObjectAdapter : public FixupVisitor {
891 public:
892 template<typename... Args>
893 explicit FixupObjectAdapter(Args... args) : FixupVisitor(args...) {}
894
895 template <typename T>
Mathieu Chartier8c19d242017-03-06 12:35:10 -0800896 T* operator()(T* obj, void** dest_addr ATTRIBUTE_UNUSED = nullptr) const {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700897 return ForwardObject(obj);
898 }
899 };
900
901 class FixupRootVisitor : public FixupVisitor {
902 public:
903 template<typename... Args>
904 explicit FixupRootVisitor(Args... args) : FixupVisitor(args...) {}
905
906 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700907 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700908 if (!root->IsNull()) {
909 VisitRoot(root);
910 }
911 }
912
913 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700914 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700915 mirror::Object* ref = root->AsMirrorPtr();
916 mirror::Object* new_ref = ForwardObject(ref);
917 if (ref != new_ref) {
918 root->Assign(new_ref);
919 }
920 }
921 };
922
923 class FixupObjectVisitor : public FixupVisitor {
924 public:
925 template<typename... Args>
926 explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited,
927 const PointerSize pointer_size,
928 Args... args)
929 : FixupVisitor(args...),
930 pointer_size_(pointer_size),
931 visited_(visited) {}
932
933 // Fix up separately since we also need to fix up method entrypoints.
934 ALWAYS_INLINE void VisitRootIfNonNull(
935 mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {}
936
937 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED)
938 const {}
939
Mathieu Chartier31e88222016-10-14 18:43:19 -0700940 ALWAYS_INLINE void operator()(ObjPtr<mirror::Object> obj,
Andreas Gampea463b6a2016-08-12 21:53:32 -0700941 MemberOffset offset,
942 bool is_static ATTRIBUTE_UNUSED) const
943 NO_THREAD_SAFETY_ANALYSIS {
944 // There could be overlap between ranges, we must avoid visiting the same reference twice.
945 // Avoid the class field since we already fixed it up in FixupClassVisitor.
946 if (offset.Uint32Value() != mirror::Object::ClassOffset().Uint32Value()) {
947 // Space is not yet added to the heap, don't do a read barrier.
948 mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>(
949 offset);
950 // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
951 // image.
952 obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(offset, ForwardObject(ref));
953 }
954 }
955
956 // Visit a pointer array and forward corresponding native data. Ignores pointer arrays in the
957 // boot image. Uses the bitmap to ensure the same array is not visited multiple times.
958 template <typename Visitor>
959 void UpdatePointerArrayContents(mirror::PointerArray* array, const Visitor& visitor) const
960 NO_THREAD_SAFETY_ANALYSIS {
961 DCHECK(array != nullptr);
962 DCHECK(visitor.IsInAppImage(array));
963 // The bit for the array contents is different than the bit for the array. Since we may have
964 // already visited the array as a long / int array from walking the bitmap without knowing it
965 // was a pointer array.
966 static_assert(kObjectAlignment == 8u, "array bit may be in another object");
967 mirror::Object* const contents_bit = reinterpret_cast<mirror::Object*>(
968 reinterpret_cast<uintptr_t>(array) + kObjectAlignment);
969 // If the bit is not set then the contents have not yet been updated.
970 if (!visited_->Test(contents_bit)) {
971 array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, pointer_size_, visitor);
972 visited_->Set(contents_bit);
973 }
974 }
975
976 // java.lang.ref.Reference visitor.
Mathieu Chartier31e88222016-10-14 18:43:19 -0700977 void operator()(ObjPtr<mirror::Class> klass ATTRIBUTE_UNUSED,
978 ObjPtr<mirror::Reference> ref) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700979 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700980 mirror::Object* obj = ref->GetReferent<kWithoutReadBarrier>();
981 ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
982 mirror::Reference::ReferentOffset(),
983 ForwardObject(obj));
984 }
985
Mathieu Chartier8c19d242017-03-06 12:35:10 -0800986 void operator()(mirror::Object* obj) const
987 NO_THREAD_SAFETY_ANALYSIS {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700988 if (visited_->Test(obj)) {
989 // Already visited.
990 return;
991 }
992 visited_->Set(obj);
993
994 // Handle class specially first since we need it to be updated to properly visit the rest of
995 // the instance fields.
996 {
997 mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
998 DCHECK(klass != nullptr) << "Null class in image";
999 // No AsClass since our fields aren't quite fixed up yet.
1000 mirror::Class* new_klass = down_cast<mirror::Class*>(ForwardObject(klass));
1001 if (klass != new_klass) {
1002 obj->SetClass<kVerifyNone>(new_klass);
1003 }
1004 if (new_klass != klass && IsInAppImage(new_klass)) {
1005 // Make sure the klass contents are fixed up since we depend on it to walk the fields.
1006 operator()(new_klass);
1007 }
1008 }
1009
Chang Xing4be3e9b2017-07-10 15:03:22 -07001010 if (obj->IsClass()) {
Mathieu Chartierd7a7f2f2018-09-07 11:57:18 -07001011 mirror::Class* klass = obj->AsClass<kVerifyNone>();
Chang Xing4be3e9b2017-07-10 15:03:22 -07001012 // Fixup super class before visiting instance fields which require
1013 // information from their super class to calculate offsets.
Chang Xing6f54cf22017-07-14 09:59:01 -07001014 mirror::Class* super_class = klass->GetSuperClass<kVerifyNone, kWithoutReadBarrier>();
Chang Xing4be3e9b2017-07-10 15:03:22 -07001015 if (super_class != nullptr) {
1016 mirror::Class* new_super_class = down_cast<mirror::Class*>(ForwardObject(super_class));
1017 if (new_super_class != super_class && IsInAppImage(new_super_class)) {
1018 // Recursively fix all dependencies.
1019 operator()(new_super_class);
1020 }
1021 }
1022 }
1023
Andreas Gampea463b6a2016-08-12 21:53:32 -07001024 obj->VisitReferences</*visit native roots*/false, kVerifyNone, kWithoutReadBarrier>(
1025 *this,
1026 *this);
1027 // Note that this code relies on no circular dependencies.
1028 // We want to use our own class loader and not the one in the image.
Mathieu Chartierd7a7f2f2018-09-07 11:57:18 -07001029 if (obj->IsClass<kVerifyNone>()) {
1030 mirror::Class* as_klass = obj->AsClass<kVerifyNone>();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001031 FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_);
1032 as_klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(as_klass,
1033 pointer_size_,
1034 visitor);
1035 // Deal with the pointer arrays. Use the helper function since multiple classes can reference
1036 // the same arrays.
1037 mirror::PointerArray* const vtable = as_klass->GetVTable<kVerifyNone, kWithoutReadBarrier>();
1038 if (vtable != nullptr && IsInAppImage(vtable)) {
1039 operator()(vtable);
1040 UpdatePointerArrayContents(vtable, visitor);
1041 }
1042 mirror::IfTable* iftable = as_klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>();
1043 // Ensure iftable arrays are fixed up since we need GetMethodArray to return the valid
1044 // contents.
Mathieu Chartier6beced42016-11-15 15:51:31 -08001045 if (IsInAppImage(iftable)) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001046 operator()(iftable);
1047 for (int32_t i = 0, count = iftable->Count(); i < count; ++i) {
1048 if (iftable->GetMethodArrayCount<kVerifyNone, kWithoutReadBarrier>(i) > 0) {
1049 mirror::PointerArray* methods =
1050 iftable->GetMethodArray<kVerifyNone, kWithoutReadBarrier>(i);
1051 if (visitor.IsInAppImage(methods)) {
1052 operator()(methods);
1053 DCHECK(methods != nullptr);
1054 UpdatePointerArrayContents(methods, visitor);
1055 }
Mathieu Chartier92ec5942016-04-11 12:03:48 -07001056 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001057 }
1058 }
1059 }
1060 }
Mathieu Chartier91edc622016-02-16 17:16:01 -08001061
Andreas Gampea463b6a2016-08-12 21:53:32 -07001062 private:
1063 const PointerSize pointer_size_;
1064 gc::accounting::ContinuousSpaceBitmap* const visited_;
1065 };
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001066
Andreas Gampea463b6a2016-08-12 21:53:32 -07001067 class ForwardObjectAdapter {
1068 public:
1069 ALWAYS_INLINE explicit ForwardObjectAdapter(const FixupVisitor* visitor) : visitor_(visitor) {}
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001070
Andreas Gampea463b6a2016-08-12 21:53:32 -07001071 template <typename T>
1072 ALWAYS_INLINE T* operator()(T* src) const {
1073 return visitor_->ForwardObject(src);
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001074 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001075
Andreas Gampea463b6a2016-08-12 21:53:32 -07001076 private:
1077 const FixupVisitor* const visitor_;
1078 };
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001079
Andreas Gampea463b6a2016-08-12 21:53:32 -07001080 class ForwardCodeAdapter {
1081 public:
1082 ALWAYS_INLINE explicit ForwardCodeAdapter(const FixupVisitor* visitor)
1083 : visitor_(visitor) {}
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001084
Andreas Gampea463b6a2016-08-12 21:53:32 -07001085 template <typename T>
1086 ALWAYS_INLINE T* operator()(T* src) const {
1087 return visitor_->ForwardCode(src);
1088 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001089
Andreas Gampea463b6a2016-08-12 21:53:32 -07001090 private:
1091 const FixupVisitor* const visitor_;
1092 };
1093
1094 class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor {
1095 public:
1096 template<typename... Args>
1097 explicit FixupArtMethodVisitor(bool fixup_heap_objects, PointerSize pointer_size, Args... args)
1098 : FixupVisitor(args...),
1099 fixup_heap_objects_(fixup_heap_objects),
1100 pointer_size_(pointer_size) {}
1101
Andreas Gampefa6a1b02018-09-07 08:11:55 -07001102 void Visit(ArtMethod* method) override NO_THREAD_SAFETY_ANALYSIS {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001103 // TODO: Separate visitor for runtime vs normal methods.
1104 if (UNLIKELY(method->IsRuntimeMethod())) {
1105 ImtConflictTable* table = method->GetImtConflictTable(pointer_size_);
1106 if (table != nullptr) {
1107 ImtConflictTable* new_table = ForwardObject(table);
1108 if (table != new_table) {
1109 method->SetImtConflictTable(new_table, pointer_size_);
1110 }
1111 }
1112 const void* old_code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size_);
1113 const void* new_code = ForwardCode(old_code);
1114 if (old_code != new_code) {
1115 method->SetEntryPointFromQuickCompiledCodePtrSize(new_code, pointer_size_);
1116 }
1117 } else {
1118 if (fixup_heap_objects_) {
Vladimir Marko5122e6b2017-08-17 16:10:09 +01001119 method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this));
Andreas Gampea463b6a2016-08-12 21:53:32 -07001120 }
Vladimir Markoc945e0d2018-07-18 17:26:45 +01001121 method->UpdateEntrypoints(ForwardCodeAdapter(this), pointer_size_);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001122 }
1123 }
1124
1125 private:
1126 const bool fixup_heap_objects_;
1127 const PointerSize pointer_size_;
1128 };
1129
1130 class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor {
1131 public:
1132 template<typename... Args>
1133 explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {}
1134
Andreas Gampefa6a1b02018-09-07 08:11:55 -07001135 void Visit(ArtField* field) override NO_THREAD_SAFETY_ANALYSIS {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001136 field->UpdateObjects(ForwardObjectAdapter(this));
1137 }
1138 };
1139
1140 // Relocate an image space mapped at target_base which possibly used to be at a different base
1141 // address. Only needs a single image space, not one for both source and destination.
1142 // In place means modifying a single ImageSpace in place rather than relocating from one ImageSpace
1143 // to another.
1144 static bool RelocateInPlace(ImageHeader& image_header,
1145 uint8_t* target_base,
1146 accounting::ContinuousSpaceBitmap* bitmap,
1147 const OatFile* app_oat_file,
1148 std::string* error_msg) {
1149 DCHECK(error_msg != nullptr);
1150 if (!image_header.IsPic()) {
1151 if (image_header.GetImageBegin() == target_base) {
1152 return true;
1153 }
1154 *error_msg = StringPrintf("Cannot relocate non-pic image for oat file %s",
1155 (app_oat_file != nullptr) ? app_oat_file->GetLocation().c_str() : "");
1156 return false;
1157 }
1158 // Set up sections.
1159 uint32_t boot_image_begin = 0;
1160 uint32_t boot_image_end = 0;
1161 uint32_t boot_oat_begin = 0;
1162 uint32_t boot_oat_end = 0;
1163 const PointerSize pointer_size = image_header.GetPointerSize();
1164 gc::Heap* const heap = Runtime::Current()->GetHeap();
1165 heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end);
1166 if (boot_image_begin == boot_image_end) {
1167 *error_msg = "Can not relocate app image without boot image space";
1168 return false;
1169 }
1170 if (boot_oat_begin == boot_oat_end) {
1171 *error_msg = "Can not relocate app image without boot oat file";
1172 return false;
1173 }
1174 const uint32_t boot_image_size = boot_image_end - boot_image_begin;
1175 const uint32_t boot_oat_size = boot_oat_end - boot_oat_begin;
1176 const uint32_t image_header_boot_image_size = image_header.GetBootImageSize();
1177 const uint32_t image_header_boot_oat_size = image_header.GetBootOatSize();
1178 if (boot_image_size != image_header_boot_image_size) {
1179 *error_msg = StringPrintf("Boot image size %" PRIu64 " does not match expected size %"
1180 PRIu64,
1181 static_cast<uint64_t>(boot_image_size),
1182 static_cast<uint64_t>(image_header_boot_image_size));
1183 return false;
1184 }
1185 if (boot_oat_size != image_header_boot_oat_size) {
1186 *error_msg = StringPrintf("Boot oat size %" PRIu64 " does not match expected size %"
1187 PRIu64,
1188 static_cast<uint64_t>(boot_oat_size),
1189 static_cast<uint64_t>(image_header_boot_oat_size));
1190 return false;
1191 }
1192 TimingLogger logger(__FUNCTION__, true, false);
1193 RelocationRange boot_image(image_header.GetBootImageBegin(),
1194 boot_image_begin,
1195 boot_image_size);
1196 RelocationRange boot_oat(image_header.GetBootOatBegin(),
1197 boot_oat_begin,
1198 boot_oat_size);
1199 RelocationRange app_image(reinterpret_cast<uintptr_t>(image_header.GetImageBegin()),
1200 reinterpret_cast<uintptr_t>(target_base),
1201 image_header.GetImageSize());
1202 // Use the oat data section since this is where the OatFile::Begin is.
1203 RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
1204 // Not necessarily in low 4GB.
1205 reinterpret_cast<uintptr_t>(app_oat_file->Begin()),
1206 image_header.GetOatDataEnd() - image_header.GetOatDataBegin());
1207 VLOG(image) << "App image " << app_image;
1208 VLOG(image) << "App oat " << app_oat;
1209 VLOG(image) << "Boot image " << boot_image;
1210 VLOG(image) << "Boot oat " << boot_oat;
1211 // True if we need to fixup any heap pointers, otherwise only code pointers.
1212 const bool fixup_image = boot_image.Delta() != 0 || app_image.Delta() != 0;
1213 const bool fixup_code = boot_oat.Delta() != 0 || app_oat.Delta() != 0;
1214 if (!fixup_image && !fixup_code) {
1215 // Nothing to fix up.
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001216 return true;
1217 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001218 ScopedDebugDisallowReadBarriers sddrb(Thread::Current());
1219 // Need to update the image to be at the target base.
Vladimir Markocd87c3e2017-09-05 13:11:57 +01001220 const ImageSection& objects_section = image_header.GetObjectsSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001221 uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset());
1222 uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End());
1223 FixupObjectAdapter fixup_adapter(boot_image, boot_oat, app_image, app_oat);
1224 if (fixup_image) {
1225 // Two pass approach, fix up all classes first, then fix up non class-objects.
1226 // The visited bitmap is used to ensure that pointer arrays are not forwarded twice.
1227 std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> visited_bitmap(
1228 gc::accounting::ContinuousSpaceBitmap::Create("Relocate bitmap",
1229 target_base,
1230 image_header.GetImageSize()));
1231 FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(),
1232 pointer_size,
1233 boot_image,
1234 boot_oat,
1235 app_image,
1236 app_oat);
1237 TimingLogger::ScopedTiming timing("Fixup classes", &logger);
1238 // Fixup objects may read fields in the boot image, use the mutator lock here for sanity. Though
1239 // its probably not required.
1240 ScopedObjectAccess soa(Thread::Current());
1241 timing.NewTiming("Fixup objects");
1242 bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor);
1243 // Fixup image roots.
1244 CHECK(app_image.InSource(reinterpret_cast<uintptr_t>(
Vladimir Markoc13fbd82018-06-04 16:16:28 +01001245 image_header.GetImageRoots<kWithoutReadBarrier>().Ptr())));
Andreas Gampea463b6a2016-08-12 21:53:32 -07001246 image_header.RelocateImageObjects(app_image.Delta());
1247 CHECK_EQ(image_header.GetImageBegin(), target_base);
1248 // Fix up dex cache DexFile pointers.
1249 auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)->
1250 AsObjectArray<mirror::DexCache, kVerifyNone, kWithoutReadBarrier>();
1251 for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
1252 mirror::DexCache* dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i);
1253 // Fix up dex cache pointers.
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -07001254 mirror::StringDexCacheType* strings = dex_cache->GetStrings();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001255 if (strings != nullptr) {
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -07001256 mirror::StringDexCacheType* new_strings = fixup_adapter.ForwardObject(strings);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001257 if (strings != new_strings) {
1258 dex_cache->SetStrings(new_strings);
1259 }
1260 dex_cache->FixupStrings<kWithoutReadBarrier>(new_strings, fixup_adapter);
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001261 }
Vladimir Marko8d6768d2017-03-14 10:13:21 +00001262 mirror::TypeDexCacheType* types = dex_cache->GetResolvedTypes();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001263 if (types != nullptr) {
Vladimir Marko8d6768d2017-03-14 10:13:21 +00001264 mirror::TypeDexCacheType* new_types = fixup_adapter.ForwardObject(types);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001265 if (types != new_types) {
1266 dex_cache->SetResolvedTypes(new_types);
1267 }
1268 dex_cache->FixupResolvedTypes<kWithoutReadBarrier>(new_types, fixup_adapter);
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001269 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +01001270 mirror::MethodDexCacheType* methods = dex_cache->GetResolvedMethods();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001271 if (methods != nullptr) {
Vladimir Marko07bfbac2017-07-06 14:55:02 +01001272 mirror::MethodDexCacheType* new_methods = fixup_adapter.ForwardObject(methods);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001273 if (methods != new_methods) {
1274 dex_cache->SetResolvedMethods(new_methods);
1275 }
1276 for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) {
Vladimir Marko07bfbac2017-07-06 14:55:02 +01001277 auto pair = mirror::DexCache::GetNativePairPtrSize(new_methods, j, pointer_size);
1278 ArtMethod* orig = pair.object;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001279 ArtMethod* copy = fixup_adapter.ForwardObject(orig);
1280 if (orig != copy) {
Vladimir Marko07bfbac2017-07-06 14:55:02 +01001281 pair.object = copy;
1282 mirror::DexCache::SetNativePairPtrSize(new_methods, j, pair, pointer_size);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001283 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001284 }
1285 }
Vladimir Markof44d36c2017-03-14 14:18:46 +00001286 mirror::FieldDexCacheType* fields = dex_cache->GetResolvedFields();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001287 if (fields != nullptr) {
Vladimir Markof44d36c2017-03-14 14:18:46 +00001288 mirror::FieldDexCacheType* new_fields = fixup_adapter.ForwardObject(fields);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001289 if (fields != new_fields) {
1290 dex_cache->SetResolvedFields(new_fields);
1291 }
1292 for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) {
Vladimir Markof44d36c2017-03-14 14:18:46 +00001293 mirror::FieldDexCachePair orig =
1294 mirror::DexCache::GetNativePairPtrSize(new_fields, j, pointer_size);
1295 mirror::FieldDexCachePair copy(fixup_adapter.ForwardObject(orig.object), orig.index);
1296 if (orig.object != copy.object) {
1297 mirror::DexCache::SetNativePairPtrSize(new_fields, j, copy, pointer_size);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001298 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001299 }
1300 }
Narayan Kamath7fe56582016-10-14 18:49:12 +01001301
1302 mirror::MethodTypeDexCacheType* method_types = dex_cache->GetResolvedMethodTypes();
1303 if (method_types != nullptr) {
1304 mirror::MethodTypeDexCacheType* new_method_types =
1305 fixup_adapter.ForwardObject(method_types);
1306 if (method_types != new_method_types) {
1307 dex_cache->SetResolvedMethodTypes(new_method_types);
1308 }
1309 dex_cache->FixupResolvedMethodTypes<kWithoutReadBarrier>(new_method_types, fixup_adapter);
1310 }
Orion Hodsonc069a302017-01-18 09:23:12 +00001311 GcRoot<mirror::CallSite>* call_sites = dex_cache->GetResolvedCallSites();
1312 if (call_sites != nullptr) {
1313 GcRoot<mirror::CallSite>* new_call_sites = fixup_adapter.ForwardObject(call_sites);
1314 if (call_sites != new_call_sites) {
1315 dex_cache->SetResolvedCallSites(new_call_sites);
1316 }
1317 dex_cache->FixupResolvedCallSites<kWithoutReadBarrier>(new_call_sites, fixup_adapter);
1318 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001319 }
1320 }
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001321 {
1322 // Only touches objects in the app image, no need for mutator lock.
Andreas Gampea463b6a2016-08-12 21:53:32 -07001323 TimingLogger::ScopedTiming timing("Fixup methods", &logger);
1324 FixupArtMethodVisitor method_visitor(fixup_image,
1325 pointer_size,
1326 boot_image,
1327 boot_oat,
1328 app_image,
1329 app_oat);
1330 image_header.VisitPackedArtMethods(&method_visitor, target_base, pointer_size);
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);
1336 FixupArtFieldVisitor field_visitor(boot_image, boot_oat, app_image, app_oat);
1337 image_header.VisitPackedArtFields(&field_visitor, target_base);
1338 }
1339 {
1340 TimingLogger::ScopedTiming timing("Fixup imt", &logger);
1341 image_header.VisitPackedImTables(fixup_adapter, target_base, pointer_size);
1342 }
1343 {
1344 TimingLogger::ScopedTiming timing("Fixup conflict tables", &logger);
1345 image_header.VisitPackedImtConflictTables(fixup_adapter, target_base, pointer_size);
1346 }
1347 // In the app image case, the image methods are actually in the boot image.
1348 image_header.RelocateImageMethods(boot_image.Delta());
Vladimir Markocd87c3e2017-09-05 13:11:57 +01001349 const auto& class_table_section = image_header.GetClassTableSection();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001350 if (class_table_section.Size() > 0u) {
1351 // Note that we require that ReadFromMemory does not make an internal copy of the elements.
1352 // This also relies on visit roots not doing any verification which could fail after we update
1353 // the roots to be the image addresses.
1354 ScopedObjectAccess soa(Thread::Current());
1355 WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
1356 ClassTable temp_table;
1357 temp_table.ReadFromMemory(target_base + class_table_section.Offset());
1358 FixupRootVisitor root_visitor(boot_image, boot_oat, app_image, app_oat);
1359 temp_table.VisitRoots(root_visitor);
1360 }
Artem Udovichenkoa62cb9b2016-06-30 09:18:25 +00001361 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001362 if (VLOG_IS_ON(image)) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001363 logger.Dump(LOG_STREAM(INFO));
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001364 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001365 return true;
Andreas Gampe7fa55782016-06-15 17:45:01 -07001366 }
1367
Andreas Gampea463b6a2016-08-12 21:53:32 -07001368 static std::unique_ptr<OatFile> OpenOatFile(const ImageSpace& image,
1369 const char* image_path,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001370 /*inout*/MemMap* oat_reservation,
Andreas Gampea463b6a2016-08-12 21:53:32 -07001371 std::string* error_msg) {
1372 const ImageHeader& image_header = image.GetImageHeader();
1373 std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_path);
Andreas Gampe7fa55782016-06-15 17:45:01 -07001374
Andreas Gampea463b6a2016-08-12 21:53:32 -07001375 CHECK(image_header.GetOatDataBegin() != nullptr);
1376
Nicolas Geoffray30025092018-04-19 14:43:29 +01001377 std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
1378 oat_filename,
Andreas Gampea463b6a2016-08-12 21:53:32 -07001379 oat_filename,
1380 image_header.GetOatDataBegin(),
Andreas Gampea463b6a2016-08-12 21:53:32 -07001381 !Runtime::Current()->IsAotCompiler(),
Vladimir Markoc09cd052018-08-23 16:36:36 +01001382 /* low_4gb */ false,
1383 /* abs_dex_location */ nullptr,
1384 oat_reservation,
Andreas Gampea463b6a2016-08-12 21:53:32 -07001385 error_msg));
1386 if (oat_file == nullptr) {
1387 *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s",
1388 oat_filename.c_str(),
1389 image.GetName(),
1390 error_msg->c_str());
Andreas Gampe7fa55782016-06-15 17:45:01 -07001391 return nullptr;
1392 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001393 uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
1394 uint32_t image_oat_checksum = image_header.GetOatChecksum();
Mathieu Chartier9ff84602016-01-29 12:22:17 -08001395 if (oat_checksum != image_oat_checksum) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001396 *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum 0x%x"
1397 " in image %s",
Mathieu Chartier9ff84602016-01-29 12:22:17 -08001398 oat_checksum,
1399 image_oat_checksum,
Andreas Gampea463b6a2016-08-12 21:53:32 -07001400 image.GetName());
Mathieu Chartier9ff84602016-01-29 12:22:17 -08001401 return nullptr;
1402 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001403
1404 return oat_file;
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001405 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001406};
Hiroshi Yamauchibd0fb612014-05-20 13:46:00 -07001407
Vladimir Marko82e1e272018-08-20 13:38:06 +00001408class ImageSpace::BootImageLoader {
1409 public:
1410 BootImageLoader(const std::string& image_location, InstructionSet image_isa)
1411 : image_location_(image_location),
1412 image_isa_(image_isa),
1413 is_zygote_(Runtime::Current()->IsZygote()),
1414 has_system_(false),
1415 has_cache_(false),
1416 is_global_cache_(true),
Vladimir Markoe3070022018-08-22 09:36:19 +00001417 dalvik_cache_exists_(false),
Vladimir Marko82e1e272018-08-20 13:38:06 +00001418 dalvik_cache_(),
1419 cache_filename_() {
1420 }
1421
1422 bool IsZygote() const { return is_zygote_; }
1423
1424 void FindImageFiles() {
1425 std::string system_filename;
Vladimir Marko82e1e272018-08-20 13:38:06 +00001426 bool found_image = FindImageFilenameImpl(image_location_.c_str(),
1427 image_isa_,
1428 &has_system_,
1429 &system_filename,
Vladimir Markoe3070022018-08-22 09:36:19 +00001430 &dalvik_cache_exists_,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001431 &dalvik_cache_,
1432 &is_global_cache_,
1433 &has_cache_,
1434 &cache_filename_);
Vladimir Markoe3070022018-08-22 09:36:19 +00001435 DCHECK(!dalvik_cache_exists_ || !dalvik_cache_.empty());
Vladimir Marko82e1e272018-08-20 13:38:06 +00001436 DCHECK_EQ(found_image, has_system_ || has_cache_);
1437 }
1438
1439 bool HasSystem() const { return has_system_; }
1440 bool HasCache() const { return has_cache_; }
1441
Vladimir Markoe3070022018-08-22 09:36:19 +00001442 bool DalvikCacheExists() const { return dalvik_cache_exists_; }
Vladimir Marko82e1e272018-08-20 13:38:06 +00001443 bool IsGlobalCache() const { return is_global_cache_; }
1444
1445 const std::string& GetDalvikCache() const {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001446 return dalvik_cache_;
1447 }
1448
1449 const std::string& GetCacheFilename() const {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001450 return cache_filename_;
1451 }
1452
Vladimir Markod44d7032018-08-30 13:02:31 +01001453 bool LoadFromSystem(size_t extra_reservation_size,
1454 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1455 /*out*/MemMap* extra_reservation,
1456 /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001457 std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_);
1458 std::vector<std::string> locations;
1459 if (!GetBootClassPathImageLocations(image_location_, filename, &locations, error_msg)) {
1460 return false;
1461 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001462 uint32_t image_start;
1463 uint32_t image_end;
1464 uint32_t oat_end;
1465 if (!GetBootImageAddressRange(filename, &image_start, &image_end, &oat_end, error_msg)) {
1466 return false;
1467 }
1468 if (locations.size() > 1u) {
1469 std::string last_filename = GetSystemImageFilename(locations.back().c_str(), image_isa_);
1470 uint32_t dummy;
1471 if (!GetBootImageAddressRange(last_filename, &dummy, &image_end, &oat_end, error_msg)) {
1472 return false;
1473 }
1474 }
1475 MemMap image_reservation;
1476 MemMap oat_reservation;
Vladimir Markod44d7032018-08-30 13:02:31 +01001477 MemMap local_extra_reservation;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001478 if (!ReserveBootImageMemory(image_start,
1479 image_end,
1480 oat_end,
Vladimir Markod44d7032018-08-30 13:02:31 +01001481 extra_reservation_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001482 &image_reservation,
1483 &oat_reservation,
Vladimir Markod44d7032018-08-30 13:02:31 +01001484 &local_extra_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001485 error_msg)) {
1486 return false;
1487 }
1488
Vladimir Marko82e1e272018-08-20 13:38:06 +00001489 std::vector<std::unique_ptr<ImageSpace>> spaces;
1490 spaces.reserve(locations.size());
1491 for (const std::string& location : locations) {
1492 filename = GetSystemImageFilename(location.c_str(), image_isa_);
Vladimir Markoc09cd052018-08-23 16:36:36 +01001493 spaces.push_back(Load(location,
1494 filename,
1495 /* validate_oat_file */ false,
1496 &image_reservation,
1497 &oat_reservation,
1498 error_msg));
Vladimir Marko82e1e272018-08-20 13:38:06 +00001499 if (spaces.back() == nullptr) {
1500 return false;
1501 }
1502 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001503 if (!CheckReservationsExhausted(image_reservation, oat_reservation, error_msg)) {
1504 return false;
1505 }
1506
Vladimir Markod44d7032018-08-30 13:02:31 +01001507 *extra_reservation = std::move(local_extra_reservation);
Vladimir Marko82e1e272018-08-20 13:38:06 +00001508 boot_image_spaces->swap(spaces);
1509 return true;
1510 }
1511
1512 bool LoadFromDalvikCache(
1513 bool validate_system_checksums,
1514 bool validate_oat_file,
Vladimir Markod44d7032018-08-30 13:02:31 +01001515 size_t extra_reservation_size,
1516 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1517 /*out*/MemMap* extra_reservation,
1518 /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001519 DCHECK(DalvikCacheExists());
1520 std::vector<std::string> locations;
1521 if (!GetBootClassPathImageLocations(image_location_, cache_filename_, &locations, error_msg)) {
1522 return false;
1523 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001524 uint32_t image_start;
1525 uint32_t image_end;
1526 uint32_t oat_end;
1527 if (!GetBootImageAddressRange(cache_filename_, &image_start, &image_end, &oat_end, error_msg)) {
1528 return false;
1529 }
1530 if (locations.size() > 1u) {
1531 std::string last_filename;
1532 if (!GetDalvikCacheFilename(locations.back().c_str(),
1533 dalvik_cache_.c_str(),
1534 &last_filename,
1535 error_msg)) {
1536 return false;
1537 }
1538 uint32_t dummy;
1539 if (!GetBootImageAddressRange(last_filename, &dummy, &image_end, &oat_end, error_msg)) {
1540 return false;
1541 }
1542 }
1543 MemMap image_reservation;
1544 MemMap oat_reservation;
Vladimir Markod44d7032018-08-30 13:02:31 +01001545 MemMap local_extra_reservation;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001546 if (!ReserveBootImageMemory(image_start,
1547 image_end,
1548 oat_end,
Vladimir Markod44d7032018-08-30 13:02:31 +01001549 extra_reservation_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001550 &image_reservation,
1551 &oat_reservation,
Vladimir Markod44d7032018-08-30 13:02:31 +01001552 &local_extra_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001553 error_msg)) {
1554 return false;
1555 }
1556
Vladimir Marko82e1e272018-08-20 13:38:06 +00001557 std::vector<std::unique_ptr<ImageSpace>> spaces;
1558 spaces.reserve(locations.size());
1559 for (const std::string& location : locations) {
1560 std::string filename;
1561 if (!GetDalvikCacheFilename(location.c_str(), dalvik_cache_.c_str(), &filename, error_msg)) {
1562 return false;
1563 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001564 spaces.push_back(Load(location,
1565 filename,
1566 validate_oat_file,
1567 &image_reservation,
1568 &oat_reservation,
1569 error_msg));
Vladimir Marko82e1e272018-08-20 13:38:06 +00001570 if (spaces.back() == nullptr) {
1571 return false;
1572 }
1573 if (validate_system_checksums) {
1574 ImageHeader system_hdr;
1575 std::string system_filename = GetSystemImageFilename(location.c_str(), image_isa_);
1576 if (!ReadSpecificImageHeader(system_filename.c_str(), &system_hdr)) {
1577 *error_msg = StringPrintf("Cannot read header of %s", system_filename.c_str());
1578 return false;
1579 }
1580 if (spaces.back()->GetImageHeader().GetOatChecksum() != system_hdr.GetOatChecksum()) {
1581 *error_msg = StringPrintf("Checksum mismatch: %u(%s) vs %u(%s)",
1582 spaces.back()->GetImageHeader().GetOatChecksum(),
1583 filename.c_str(),
1584 system_hdr.GetOatChecksum(),
1585 system_filename.c_str());
1586 return false;
1587 }
1588 }
1589 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001590 if (!CheckReservationsExhausted(image_reservation, oat_reservation, error_msg)) {
1591 return false;
1592 }
1593
Vladimir Markod44d7032018-08-30 13:02:31 +01001594 *extra_reservation = std::move(local_extra_reservation);
Vladimir Marko82e1e272018-08-20 13:38:06 +00001595 boot_image_spaces->swap(spaces);
1596 return true;
1597 }
1598
1599 private:
Vladimir Markoc09cd052018-08-23 16:36:36 +01001600 std::unique_ptr<ImageSpace> Load(const std::string& image_location,
1601 const std::string& image_filename,
1602 bool validate_oat_file,
1603 /*inout*/MemMap* image_reservation,
1604 /*inout*/MemMap* oat_reservation,
1605 /*out*/std::string* error_msg)
1606 REQUIRES_SHARED(Locks::mutator_lock_) {
1607 // Should this be a RDWR lock? This is only a defensive measure, as at
1608 // this point the image should exist.
1609 // However, only the zygote can write into the global dalvik-cache, so
1610 // restrict to zygote processes, or any process that isn't using
1611 // /data/dalvik-cache (which we assume to be allowed to write there).
1612 const bool rw_lock = is_zygote_ || !is_global_cache_;
1613
1614 // Note that we must not use the file descriptor associated with
1615 // ScopedFlock::GetFile to Init the image file. We want the file
1616 // descriptor (and the associated exclusive lock) to be released when
1617 // we leave Create.
1618 ScopedFlock image = LockedFile::Open(image_filename.c_str(),
1619 rw_lock ? (O_CREAT | O_RDWR) : O_RDONLY /* flags */,
1620 true /* block */,
1621 error_msg);
1622
1623 VLOG(startup) << "Using image file " << image_filename.c_str() << " for image location "
1624 << image_location;
1625 // If we are in /system we can assume the image is good. We can also
1626 // assume this if we are using a relocated image (i.e. image checksum
1627 // matches) since this is only different by the offset. We need this to
1628 // make sure that host tests continue to work.
1629 // Since we are the boot image, pass null since we load the oat file from the boot image oat
1630 // file name.
1631 return Loader::Init(image_filename.c_str(),
1632 image_location.c_str(),
1633 validate_oat_file,
1634 /* oat_file */ nullptr,
1635 image_reservation,
1636 oat_reservation,
1637 error_msg);
1638 }
1639
Vladimir Marko82e1e272018-08-20 13:38:06 +00001640 // Extract boot class path from oat file associated with `image_filename`
1641 // and list all associated image locations.
1642 static bool GetBootClassPathImageLocations(const std::string& image_location,
1643 const std::string& image_filename,
1644 /*out*/ std::vector<std::string>* all_locations,
1645 /*out*/ std::string* error_msg) {
1646 std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_filename);
1647 std::unique_ptr<OatFile> oat_file(OatFile::Open(/* zip_fd */ -1,
1648 oat_filename,
1649 oat_filename,
1650 /* requested_base */ nullptr,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001651 /* executable */ false,
1652 /* low_4gb */ false,
1653 /* abs_dex_location */ nullptr,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001654 /* reservation */ nullptr,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001655 error_msg));
1656 if (oat_file == nullptr) {
1657 *error_msg = StringPrintf("Failed to open oat file '%s' for image file %s: %s",
1658 oat_filename.c_str(),
1659 image_filename.c_str(),
1660 error_msg->c_str());
1661 return false;
1662 }
1663 const OatHeader& oat_header = oat_file->GetOatHeader();
1664 const char* boot_classpath = oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey);
1665 all_locations->push_back(image_location);
1666 if (boot_classpath != nullptr && boot_classpath[0] != 0) {
1667 ExtractMultiImageLocations(image_location, boot_classpath, all_locations);
1668 }
1669 return true;
1670 }
1671
Vladimir Markoc09cd052018-08-23 16:36:36 +01001672 bool GetBootImageAddressRange(const std::string& filename,
1673 /*out*/uint32_t* start,
1674 /*out*/uint32_t* end,
1675 /*out*/uint32_t* oat_end,
1676 /*out*/std::string* error_msg) {
1677 ImageHeader system_hdr;
1678 if (!ReadSpecificImageHeader(filename.c_str(), &system_hdr)) {
1679 *error_msg = StringPrintf("Cannot read header of %s", filename.c_str());
1680 return false;
1681 }
1682 *start = reinterpret_cast32<uint32_t>(system_hdr.GetImageBegin());
1683 CHECK_ALIGNED(*start, kPageSize);
1684 *end = RoundUp(*start + system_hdr.GetImageSize(), kPageSize);
1685 *oat_end = RoundUp(reinterpret_cast32<uint32_t>(system_hdr.GetOatFileEnd()), kPageSize);
1686 return true;
1687 }
1688
1689 bool ReserveBootImageMemory(uint32_t image_start,
1690 uint32_t image_end,
1691 uint32_t oat_end,
Vladimir Markod44d7032018-08-30 13:02:31 +01001692 size_t extra_reservation_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001693 /*out*/MemMap* image_reservation,
1694 /*out*/MemMap* oat_reservation,
Vladimir Markod44d7032018-08-30 13:02:31 +01001695 /*out*/MemMap* extra_reservation,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001696 /*out*/std::string* error_msg) {
1697 DCHECK(!image_reservation->IsValid());
Vladimir Markod44d7032018-08-30 13:02:31 +01001698 size_t total_size =
1699 dchecked_integral_cast<size_t>(oat_end - image_start) + extra_reservation_size;
Vladimir Markoc09cd052018-08-23 16:36:36 +01001700 *image_reservation =
1701 MemMap::MapAnonymous("Boot image reservation",
1702 reinterpret_cast32<uint8_t*>(image_start),
Vladimir Markod44d7032018-08-30 13:02:31 +01001703 total_size,
Vladimir Markoc09cd052018-08-23 16:36:36 +01001704 PROT_NONE,
1705 /* low_4gb */ true,
1706 /* reuse */ false,
1707 /* reservation */ nullptr,
1708 error_msg);
1709 if (!image_reservation->IsValid()) {
1710 return false;
1711 }
Vladimir Markod44d7032018-08-30 13:02:31 +01001712 DCHECK(!extra_reservation->IsValid());
1713 if (extra_reservation_size != 0u) {
1714 DCHECK_ALIGNED(extra_reservation_size, kPageSize);
1715 DCHECK_LT(extra_reservation_size, image_reservation->Size());
1716 uint8_t* split = image_reservation->End() - extra_reservation_size;
1717 *extra_reservation = image_reservation->RemapAtEnd(split,
1718 "Boot image extra reservation",
1719 PROT_NONE,
1720 error_msg);
1721 if (!extra_reservation->IsValid()) {
1722 return false;
1723 }
1724 }
Vladimir Markoc09cd052018-08-23 16:36:36 +01001725 DCHECK(!oat_reservation->IsValid());
1726 *oat_reservation = image_reservation->RemapAtEnd(reinterpret_cast32<uint8_t*>(image_end),
1727 "Boot image oat reservation",
1728 PROT_NONE,
1729 error_msg);
1730 if (!oat_reservation->IsValid()) {
1731 return false;
1732 }
1733
1734 return true;
1735 }
1736
1737 bool CheckReservationsExhausted(const MemMap& image_reservation,
1738 const MemMap& oat_reservation,
1739 /*out*/std::string* error_msg) {
1740 if (image_reservation.IsValid()) {
1741 *error_msg = StringPrintf("Excessive image reservation after loading boot image: %p-%p",
1742 image_reservation.Begin(),
1743 image_reservation.End());
1744 return false;
1745 }
1746 if (oat_reservation.IsValid()) {
1747 *error_msg = StringPrintf("Excessive oat reservation after loading boot image: %p-%p",
1748 image_reservation.Begin(),
1749 image_reservation.End());
1750 return false;
1751 }
1752 return true;
1753 }
1754
Vladimir Marko82e1e272018-08-20 13:38:06 +00001755 const std::string& image_location_;
1756 InstructionSet image_isa_;
1757 bool is_zygote_;
1758 bool has_system_;
1759 bool has_cache_;
1760 bool is_global_cache_;
Vladimir Markoe3070022018-08-22 09:36:19 +00001761 bool dalvik_cache_exists_;
Vladimir Marko82e1e272018-08-20 13:38:06 +00001762 std::string dalvik_cache_;
1763 std::string cache_filename_;
1764};
1765
Andreas Gampea463b6a2016-08-12 21:53:32 -07001766static constexpr uint64_t kLowSpaceValue = 50 * MB;
1767static constexpr uint64_t kTmpFsSentinelValue = 384 * MB;
1768
1769// Read the free space of the cache partition and make a decision whether to keep the generated
1770// image. This is to try to mitigate situations where the system might run out of space later.
1771static bool CheckSpace(const std::string& cache_filename, std::string* error_msg) {
1772 // Using statvfs vs statvfs64 because of b/18207376, and it is enough for all practical purposes.
1773 struct statvfs buf;
1774
1775 int res = TEMP_FAILURE_RETRY(statvfs(cache_filename.c_str(), &buf));
1776 if (res != 0) {
1777 // Could not stat. Conservatively tell the system to delete the image.
1778 *error_msg = "Could not stat the filesystem, assuming low-memory situation.";
1779 return false;
Nicolas Geoffray1bc977c2016-01-23 14:15:49 +00001780 }
Nicolas Geoffray1bc977c2016-01-23 14:15:49 +00001781
Andreas Gampea463b6a2016-08-12 21:53:32 -07001782 uint64_t fs_overall_size = buf.f_bsize * static_cast<uint64_t>(buf.f_blocks);
1783 // Zygote is privileged, but other things are not. Use bavail.
1784 uint64_t fs_free_size = buf.f_bsize * static_cast<uint64_t>(buf.f_bavail);
Brian Carlstrom56d947f2013-07-15 13:14:23 -07001785
Andreas Gampea463b6a2016-08-12 21:53:32 -07001786 // Take the overall size as an indicator for a tmpfs, which is being used for the decryption
1787 // environment. We do not want to fail quickening the boot image there, as it is beneficial
1788 // for time-to-UI.
1789 if (fs_overall_size > kTmpFsSentinelValue) {
1790 if (fs_free_size < kLowSpaceValue) {
1791 *error_msg = StringPrintf("Low-memory situation: only %4.2f megabytes available, need at "
1792 "least %" PRIu64 ".",
1793 static_cast<double>(fs_free_size) / MB,
1794 kLowSpaceValue / MB);
Brian Carlstrom56d947f2013-07-15 13:14:23 -07001795 return false;
1796 }
1797 }
1798 return true;
1799}
1800
Vladimir Marko82e1e272018-08-20 13:38:06 +00001801bool ImageSpace::LoadBootImage(
1802 const std::string& image_location,
1803 const InstructionSet image_isa,
Vladimir Markod44d7032018-08-30 13:02:31 +01001804 size_t extra_reservation_size,
1805 /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
1806 /*out*/MemMap* extra_reservation) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001807 ScopedTrace trace(__FUNCTION__);
1808
Vladimir Marko82e1e272018-08-20 13:38:06 +00001809 DCHECK(boot_image_spaces != nullptr);
1810 DCHECK(boot_image_spaces->empty());
Vladimir Markod44d7032018-08-30 13:02:31 +01001811 DCHECK_ALIGNED(extra_reservation_size, kPageSize);
1812 DCHECK(extra_reservation != nullptr);
Vladimir Marko82e1e272018-08-20 13:38:06 +00001813 DCHECK_NE(image_isa, InstructionSet::kNone);
1814
1815 if (image_location.empty()) {
1816 return false;
1817 }
1818
1819 BootImageLoader loader(image_location, image_isa);
1820
Andreas Gampea463b6a2016-08-12 21:53:32 -07001821 // Step 0: Extra zygote work.
1822
1823 // Step 0.a: If we're the zygote, mark boot.
Vladimir Marko82e1e272018-08-20 13:38:06 +00001824 if (loader.IsZygote() && CanWriteToDalvikCache(image_isa)) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001825 MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots());
1826 }
1827
Vladimir Marko82e1e272018-08-20 13:38:06 +00001828 loader.FindImageFiles();
1829
Andreas Gampea463b6a2016-08-12 21:53:32 -07001830 // Step 0.b: If we're the zygote, check for free space, and prune the cache preemptively,
1831 // if necessary. While the runtime may be fine (it is pretty tolerant to
1832 // out-of-disk-space situations), other parts of the platform are not.
1833 //
1834 // The advantage of doing this proactively is that the later steps are simplified,
1835 // i.e., we do not need to code retries.
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001836 bool dex2oat_enabled = Runtime::Current()->IsImageDex2OatEnabled();
1837
Vladimir Marko82e1e272018-08-20 13:38:06 +00001838 if (loader.IsZygote() && loader.DalvikCacheExists()) {
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001839 // Extra checks for the zygote. These only apply when loading the first image, explained below.
Vladimir Marko82e1e272018-08-20 13:38:06 +00001840 const std::string& dalvik_cache = loader.GetDalvikCache();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001841 DCHECK(!dalvik_cache.empty());
1842 std::string local_error_msg;
Chris Morine5fac732018-02-05 14:27:40 -08001843 // All secondary images are verified when the primary image is verified.
Vladimir Marko82e1e272018-08-20 13:38:06 +00001844 bool verified =
1845 VerifyImage(image_location.c_str(), dalvik_cache.c_str(), image_isa, &local_error_msg);
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001846 bool check_space = CheckSpace(dalvik_cache, &local_error_msg);
1847 if (!verified || !check_space) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001848 LOG(WARNING) << local_error_msg << " Preemptively pruning the dalvik cache.";
1849 PruneDalvikCache(image_isa);
1850
1851 // Re-evaluate the image.
Vladimir Marko82e1e272018-08-20 13:38:06 +00001852 loader.FindImageFiles();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001853 }
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001854 if (!check_space) {
1855 // Disable compilation/patching - we do not want to fill up the space again.
1856 dex2oat_enabled = false;
1857 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001858 }
1859
1860 // Collect all the errors.
1861 std::vector<std::string> error_msgs;
1862
Vladimir Marko82e1e272018-08-20 13:38:06 +00001863 // Step 1: Check if we have an existing image in the dalvik cache.
1864 if (loader.HasCache()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001865 std::string local_error_msg;
Vladimir Marko82e1e272018-08-20 13:38:06 +00001866 // If we have system image, validate system image checksums, otherwise validate the oat file.
1867 if (loader.LoadFromDalvikCache(/* validate_system_checksums */ loader.HasSystem(),
1868 /* validate_oat_file */ !loader.HasSystem(),
Vladimir Markod44d7032018-08-30 13:02:31 +01001869 extra_reservation_size,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001870 boot_image_spaces,
Vladimir Markod44d7032018-08-30 13:02:31 +01001871 extra_reservation,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001872 &local_error_msg)) {
1873 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001874 }
1875 error_msgs.push_back(local_error_msg);
1876 }
1877
1878 // Step 2: We have an existing image in /system.
1879
1880 // Step 2.a: We are not required to relocate it. Then we can use it directly.
1881 bool relocate = Runtime::Current()->ShouldRelocate();
1882
Vladimir Marko82e1e272018-08-20 13:38:06 +00001883 if (loader.HasSystem() && !relocate) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001884 std::string local_error_msg;
Vladimir Markod44d7032018-08-30 13:02:31 +01001885 if (loader.LoadFromSystem(extra_reservation_size,
1886 boot_image_spaces,
1887 extra_reservation,
1888 &local_error_msg)) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001889 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001890 }
1891 error_msgs.push_back(local_error_msg);
1892 }
1893
Vladimir Marko82e1e272018-08-20 13:38:06 +00001894 // Step 2.b: We require a relocated image. Then we must patch it.
1895 if (loader.HasSystem() && relocate) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001896 std::string local_error_msg;
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001897 if (!dex2oat_enabled) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001898 local_error_msg = "Patching disabled.";
Vladimir Marko82e1e272018-08-20 13:38:06 +00001899 } else if (ImageCreationAllowed(loader.IsGlobalCache(), image_isa, &local_error_msg)) {
1900 bool patch_success = RelocateImage(
1901 image_location.c_str(), loader.GetDalvikCache().c_str(), image_isa, &local_error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001902 if (patch_success) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001903 if (loader.LoadFromDalvikCache(/* validate_system_checksums */ false,
1904 /* validate_oat_file */ false,
Vladimir Markod44d7032018-08-30 13:02:31 +01001905 extra_reservation_size,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001906 boot_image_spaces,
Vladimir Markod44d7032018-08-30 13:02:31 +01001907 extra_reservation,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001908 &local_error_msg)) {
1909 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001910 }
1911 }
1912 }
1913 error_msgs.push_back(StringPrintf("Cannot relocate image %s to %s: %s",
Vladimir Marko82e1e272018-08-20 13:38:06 +00001914 image_location.c_str(),
1915 loader.GetCacheFilename().c_str(),
Andreas Gampea463b6a2016-08-12 21:53:32 -07001916 local_error_msg.c_str()));
1917 }
1918
Vladimir Marko82e1e272018-08-20 13:38:06 +00001919 // Step 3: We do not have an existing image in /system,
1920 // so generate an image into the dalvik cache.
Vladimir Markoe3070022018-08-22 09:36:19 +00001921 if (!loader.HasSystem() && loader.DalvikCacheExists()) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001922 std::string local_error_msg;
Andreas Gampe6e74abb2018-03-01 17:33:19 -08001923 if (!dex2oat_enabled) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001924 local_error_msg = "Image compilation disabled.";
Vladimir Marko82e1e272018-08-20 13:38:06 +00001925 } else if (ImageCreationAllowed(loader.IsGlobalCache(), image_isa, &local_error_msg)) {
1926 bool compilation_success =
1927 GenerateImage(loader.GetCacheFilename(), image_isa, &local_error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001928 if (compilation_success) {
Vladimir Marko82e1e272018-08-20 13:38:06 +00001929 if (loader.LoadFromDalvikCache(/* validate_system_checksums */ false,
1930 /* validate_oat_file */ false,
Vladimir Markod44d7032018-08-30 13:02:31 +01001931 extra_reservation_size,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001932 boot_image_spaces,
Vladimir Markod44d7032018-08-30 13:02:31 +01001933 extra_reservation,
Vladimir Marko82e1e272018-08-20 13:38:06 +00001934 &local_error_msg)) {
1935 return true;
Andreas Gampea463b6a2016-08-12 21:53:32 -07001936 }
1937 }
1938 }
1939 error_msgs.push_back(StringPrintf("Cannot compile image to %s: %s",
Vladimir Marko82e1e272018-08-20 13:38:06 +00001940 loader.GetCacheFilename().c_str(),
Andreas Gampea463b6a2016-08-12 21:53:32 -07001941 local_error_msg.c_str()));
1942 }
1943
Vladimir Marko82e1e272018-08-20 13:38:06 +00001944 // We failed. Prune the cache the free up space, create a compound error message
1945 // and return false.
Andreas Gampea463b6a2016-08-12 21:53:32 -07001946 PruneDalvikCache(image_isa);
1947
1948 std::ostringstream oss;
1949 bool first = true;
Andreas Gampe4c481a42016-11-03 08:21:59 -07001950 for (const auto& msg : error_msgs) {
Andreas Gampea463b6a2016-08-12 21:53:32 -07001951 if (!first) {
1952 oss << "\n ";
1953 }
1954 oss << msg;
1955 }
Andreas Gampea463b6a2016-08-12 21:53:32 -07001956
Vladimir Marko82e1e272018-08-20 13:38:06 +00001957 LOG(ERROR) << "Could not create image space with image file '" << image_location << "'. "
1958 << "Attempting to fall back to imageless running. Error was: " << oss.str();
Andreas Gampea463b6a2016-08-12 21:53:32 -07001959
Vladimir Marko82e1e272018-08-20 13:38:06 +00001960 return false;
Andreas Gampe2bd84282016-12-05 12:37:36 -08001961}
1962
Igor Murashkin8275fba2017-05-02 15:58:02 -07001963ImageSpace::~ImageSpace() {
1964 Runtime* runtime = Runtime::Current();
1965 if (runtime == nullptr) {
1966 return;
1967 }
1968
1969 if (GetImageHeader().IsAppImage()) {
1970 // This image space did not modify resolution method then in Init.
1971 return;
1972 }
1973
1974 if (!runtime->HasResolutionMethod()) {
1975 // Another image space has already unloaded the below methods.
1976 return;
1977 }
1978
1979 runtime->ClearInstructionSet();
1980 runtime->ClearResolutionMethod();
1981 runtime->ClearImtConflictMethod();
1982 runtime->ClearImtUnimplementedMethod();
1983 runtime->ClearCalleeSaveMethods();
1984}
1985
Andreas Gampea463b6a2016-08-12 21:53:32 -07001986std::unique_ptr<ImageSpace> ImageSpace::CreateFromAppImage(const char* image,
1987 const OatFile* oat_file,
1988 std::string* error_msg) {
Vladimir Markoc09cd052018-08-23 16:36:36 +01001989 return Loader::Init(image,
1990 image,
1991 /* validate_oat_file */ false,
1992 oat_file,
1993 /* image_reservation */ nullptr,
1994 /* oat_reservation */ nullptr,
1995 error_msg);
Andreas Gampea463b6a2016-08-12 21:53:32 -07001996}
1997
Andreas Gampe22f8e5c2014-07-09 11:38:21 -07001998const OatFile* ImageSpace::GetOatFile() const {
Andreas Gampe88da3b02015-06-12 20:38:49 -07001999 return oat_file_non_owned_;
Andreas Gampe22f8e5c2014-07-09 11:38:21 -07002000}
2001
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07002002std::unique_ptr<const OatFile> ImageSpace::ReleaseOatFile() {
2003 CHECK(oat_file_ != nullptr);
2004 return std::move(oat_file_);
Ian Rogers1d54e732013-05-02 21:10:01 -07002005}
2006
Ian Rogers1d54e732013-05-02 21:10:01 -07002007void ImageSpace::Dump(std::ostream& os) const {
2008 os << GetType()
Mathieu Chartier590fee92013-09-13 13:46:47 -07002009 << " begin=" << reinterpret_cast<void*>(Begin())
Ian Rogers1d54e732013-05-02 21:10:01 -07002010 << ",end=" << reinterpret_cast<void*>(End())
2011 << ",size=" << PrettySize(Size())
2012 << ",name=\"" << GetName() << "\"]";
2013}
2014
Mathieu Chartier866d8742016-09-21 15:24:18 -07002015std::string ImageSpace::GetMultiImageBootClassPath(
2016 const std::vector<const char*>& dex_locations,
2017 const std::vector<const char*>& oat_filenames,
2018 const std::vector<const char*>& image_filenames) {
2019 DCHECK_GT(oat_filenames.size(), 1u);
2020 // If the image filename was adapted (e.g., for our tests), we need to change this here,
2021 // too, but need to strip all path components (they will be re-established when loading).
2022 std::ostringstream bootcp_oss;
2023 bool first_bootcp = true;
2024 for (size_t i = 0; i < dex_locations.size(); ++i) {
2025 if (!first_bootcp) {
2026 bootcp_oss << ":";
2027 }
2028
2029 std::string dex_loc = dex_locations[i];
2030 std::string image_filename = image_filenames[i];
2031
2032 // Use the dex_loc path, but the image_filename name (without path elements).
2033 size_t dex_last_slash = dex_loc.rfind('/');
2034
2035 // npos is max(size_t). That makes this a bit ugly.
2036 size_t image_last_slash = image_filename.rfind('/');
2037 size_t image_last_at = image_filename.rfind('@');
2038 size_t image_last_sep = (image_last_slash == std::string::npos)
2039 ? image_last_at
2040 : (image_last_at == std::string::npos)
2041 ? std::string::npos
2042 : std::max(image_last_slash, image_last_at);
2043 // Note: whenever image_last_sep == npos, +1 overflow means using the full string.
2044
2045 if (dex_last_slash == std::string::npos) {
2046 dex_loc = image_filename.substr(image_last_sep + 1);
2047 } else {
2048 dex_loc = dex_loc.substr(0, dex_last_slash + 1) +
2049 image_filename.substr(image_last_sep + 1);
2050 }
2051
2052 // Image filenames already end with .art, no need to replace.
2053
2054 bootcp_oss << dex_loc;
2055 first_bootcp = false;
2056 }
2057 return bootcp_oss.str();
2058}
2059
Richard Uhler84f50ae2017-02-06 15:12:45 +00002060bool ImageSpace::ValidateOatFile(const OatFile& oat_file, std::string* error_msg) {
David Sehr013fd802018-01-11 22:55:24 -08002061 const ArtDexFileLoader dex_file_loader;
Andreas Gampeb40d3612018-06-26 15:49:42 -07002062 for (const OatDexFile* oat_dex_file : oat_file.GetOatDexFiles()) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002063 const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
2064
2065 // Skip multidex locations - These will be checked when we visit their
2066 // corresponding primary non-multidex location.
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002067 if (DexFileLoader::IsMultiDexLocation(dex_file_location.c_str())) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002068 continue;
2069 }
2070
2071 std::vector<uint32_t> checksums;
David Sehr013fd802018-01-11 22:55:24 -08002072 if (!dex_file_loader.GetMultiDexChecksums(dex_file_location.c_str(), &checksums, error_msg)) {
Richard Uhler84f50ae2017-02-06 15:12:45 +00002073 *error_msg = StringPrintf("ValidateOatFile failed to get checksums of dex file '%s' "
2074 "referenced by oat file %s: %s",
2075 dex_file_location.c_str(),
2076 oat_file.GetLocation().c_str(),
2077 error_msg->c_str());
2078 return false;
2079 }
2080 CHECK(!checksums.empty());
2081 if (checksums[0] != oat_dex_file->GetDexFileLocationChecksum()) {
2082 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
2083 "'%s' and dex file '%s' (0x%x != 0x%x)",
2084 oat_file.GetLocation().c_str(),
2085 dex_file_location.c_str(),
2086 oat_dex_file->GetDexFileLocationChecksum(),
2087 checksums[0]);
2088 return false;
2089 }
2090
2091 // Verify checksums for any related multidex entries.
2092 for (size_t i = 1; i < checksums.size(); i++) {
Mathieu Chartier79c87da2017-10-10 11:54:29 -07002093 std::string multi_dex_location = DexFileLoader::GetMultiDexLocation(
2094 i,
2095 dex_file_location.c_str());
Andreas Gampeb40d3612018-06-26 15:49:42 -07002096 const OatDexFile* multi_dex = oat_file.GetOatDexFile(multi_dex_location.c_str(),
2097 nullptr,
2098 error_msg);
Richard Uhler84f50ae2017-02-06 15:12:45 +00002099 if (multi_dex == nullptr) {
2100 *error_msg = StringPrintf("ValidateOatFile oat file '%s' is missing entry '%s'",
2101 oat_file.GetLocation().c_str(),
2102 multi_dex_location.c_str());
2103 return false;
2104 }
2105
2106 if (checksums[i] != multi_dex->GetDexFileLocationChecksum()) {
2107 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file "
2108 "'%s' and dex file '%s' (0x%x != 0x%x)",
2109 oat_file.GetLocation().c_str(),
2110 multi_dex_location.c_str(),
2111 multi_dex->GetDexFileLocationChecksum(),
2112 checksums[i]);
2113 return false;
2114 }
2115 }
2116 }
2117 return true;
2118}
2119
Mathieu Chartier866d8742016-09-21 15:24:18 -07002120void ImageSpace::ExtractMultiImageLocations(const std::string& input_image_file_name,
2121 const std::string& boot_classpath,
2122 std::vector<std::string>* image_file_names) {
Andreas Gampe8994a042015-12-30 19:03:17 +00002123 DCHECK(image_file_names != nullptr);
2124
2125 std::vector<std::string> images;
2126 Split(boot_classpath, ':', &images);
2127
2128 // Add the rest into the list. We have to adjust locations, possibly:
2129 //
2130 // For example, image_file_name is /a/b/c/d/e.art
2131 // images[0] is f/c/d/e.art
2132 // ----------------------------------------------
2133 // images[1] is g/h/i/j.art -> /a/b/h/i/j.art
Mathieu Chartier8b8f6d62016-03-08 16:50:20 -08002134 const std::string& first_image = images[0];
2135 // Length of common suffix.
2136 size_t common = 0;
2137 while (common < input_image_file_name.size() &&
2138 common < first_image.size() &&
2139 *(input_image_file_name.end() - common - 1) == *(first_image.end() - common - 1)) {
2140 ++common;
Andreas Gampe8994a042015-12-30 19:03:17 +00002141 }
Mathieu Chartier8b8f6d62016-03-08 16:50:20 -08002142 // We want to replace the prefix of the input image with the prefix of the boot class path.
2143 // This handles the case where the image file contains @ separators.
2144 // Example image_file_name is oats/system@framework@boot.art
2145 // images[0] is .../arm/boot.art
2146 // means that the image name prefix will be oats/system@framework@
2147 // so that the other images are openable.
2148 const size_t old_prefix_length = first_image.size() - common;
2149 const std::string new_prefix = input_image_file_name.substr(
2150 0,
2151 input_image_file_name.size() - common);
Andreas Gampe8994a042015-12-30 19:03:17 +00002152
2153 // Apply pattern to images[1] .. images[n].
2154 for (size_t i = 1; i < images.size(); ++i) {
Mathieu Chartier8b8f6d62016-03-08 16:50:20 -08002155 const std::string& image = images[i];
2156 CHECK_GT(image.length(), old_prefix_length);
2157 std::string suffix = image.substr(old_prefix_length);
2158 image_file_names->push_back(new_prefix + suffix);
Andreas Gampe8994a042015-12-30 19:03:17 +00002159 }
2160}
2161
Mathieu Chartierd5f3f322016-03-21 14:05:56 -07002162void ImageSpace::DumpSections(std::ostream& os) const {
2163 const uint8_t* base = Begin();
2164 const ImageHeader& header = GetImageHeader();
2165 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
2166 auto section_type = static_cast<ImageHeader::ImageSections>(i);
2167 const ImageSection& section = header.GetImageSection(section_type);
2168 os << section_type << " " << reinterpret_cast<const void*>(base + section.Offset())
2169 << "-" << reinterpret_cast<const void*>(base + section.End()) << "\n";
2170 }
2171}
2172
Ian Rogers1d54e732013-05-02 21:10:01 -07002173} // namespace space
2174} // namespace gc
2175} // namespace art