11d54e73444e017d3a65234e0f193846f3e27472bIan Rogers/*
21d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Copyright (C) 2011 The Android Open Source Project
31d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
41d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Licensed under the Apache License, Version 2.0 (the "License");
51d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * you may not use this file except in compliance with the License.
61d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * You may obtain a copy of the License at
71d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
81d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *      http://www.apache.org/licenses/LICENSE-2.0
91d54e73444e017d3a65234e0f193846f3e27472bIan Rogers *
101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * Unless required by applicable law or agreed to in writing, software
111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * distributed under the License is distributed on an "AS IS" BASIS,
121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * See the License for the specific language governing permissions and
141d54e73444e017d3a65234e0f193846f3e27472bIan Rogers * limitations under the License.
151d54e73444e017d3a65234e0f193846f3e27472bIan Rogers */
161d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
171d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "image_space.h"
181d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
1956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom#include <sys/types.h>
2056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom#include <sys/wait.h>
2156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
2256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom#include "base/stl_util.h"
231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "base/unix_file/fd_file.h"
241d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/space_bitmap-inl.h"
25ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method.h"
261d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "mirror/class-inl.h"
271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "mirror/object-inl.h"
2856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom#include "oat_file.h"
291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "os.h"
301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "runtime.h"
311d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "space-inl.h"
321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "utils.h"
331d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
341d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace art {
351d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace gc {
361d54e73444e017d3a65234e0f193846f3e27472bIan Rogersnamespace space {
371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
3831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu ChartierAtomicInteger ImageSpace::bitmap_index_(0);
3931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
4031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu ChartierImageSpace::ImageSpace(const std::string& name, MemMap* mem_map,
4131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                       accounting::SpaceBitmap* live_bitmap)
4231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    : MemMapSpace(name, mem_map, mem_map->Size(), kGcRetentionPolicyNeverCollect) {
4331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  DCHECK(live_bitmap != NULL);
4431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  live_bitmap_.reset(live_bitmap);
451d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}
461d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
4756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstromstatic bool GenerateImage(const std::string& image_file_name) {
4856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString());
4956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::vector<std::string> boot_class_path;
5056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  Split(boot_class_path_string, ':', boot_class_path);
5156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (boot_class_path.empty()) {
5256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(FATAL) << "Failed to generate image because no boot class path specified";
5356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
5456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
558bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  std::vector<std::string> arg_vector;
5656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
57e5426c9995d28bcb19391d8dbf0ad70606cf1770Mathieu Chartier  std::string dex2oat(GetAndroidRoot());
5808d7d44bc33a7251ff34287422c7751c5a65683dMathieu Chartier  dex2oat += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
5908d7d44bc33a7251ff34287422c7751c5a65683dMathieu Chartier  arg_vector.push_back(dex2oat);
6056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
6156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::string image_option_string("--image=");
6256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  image_option_string += image_file_name;
638bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back(image_option_string);
6456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
658bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back("--runtime-arg");
668bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back("-Xms64m");
6756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
688bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back("--runtime-arg");
698bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back("-Xmx64m");
7056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
7156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  for (size_t i = 0; i < boot_class_path.size(); i++) {
728bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
7356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
7456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
7556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::string oat_file_option_string("--oat-file=");
7656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  oat_file_option_string += image_file_name;
7756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  oat_file_option_string.erase(oat_file_option_string.size() - 3);
7856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  oat_file_option_string += "oat";
798bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back(oat_file_option_string);
8056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
818bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS));
8256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
8356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (kIsTargetBuild) {
848bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    arg_vector.push_back("--image-classes-zip=/system/framework/framework.jar");
858bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    arg_vector.push_back("--image-classes=preloaded-classes");
8656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  } else {
878bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    arg_vector.push_back("--host");
8856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
8956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
9056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::string command_line(Join(arg_vector, ' '));
9156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  LOG(INFO) << "GenerateImage: " << command_line;
9256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
938bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  // Convert the args to char pointers.
948bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  std::vector<char*> char_args;
958bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  for (std::vector<std::string>::iterator it = arg_vector.begin(); it != arg_vector.end();
968bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier      ++it) {
978bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    char_args.push_back(const_cast<char*>(it->c_str()));
988bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  }
998bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier  char_args.push_back(NULL);
10056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
10156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // fork and exec dex2oat
10256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  pid_t pid = fork();
10356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (pid == 0) {
10456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    // no allocation allowed between fork and exec
10556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
10656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    // change process groups, so we don't get reaped by ProcessManager
10756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    setpgid(0, 0);
10856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
10908d7d44bc33a7251ff34287422c7751c5a65683dMathieu Chartier    execv(dex2oat.c_str(), &char_args[0]);
11056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
11156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    PLOG(FATAL) << "execv(" << dex2oat << ") failed";
11256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return false;
11356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  } else {
1148bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    if (pid == -1) {
1158bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier      PLOG(ERROR) << "fork failed";
1168bbc8c0ac51dbb61535016872e8389620c49982aMathieu Chartier    }
11756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
11856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    // wait for dex2oat to finish
11956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    int status;
12056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
12156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    if (got_pid != pid) {
12256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      PLOG(ERROR) << "waitpid failed: wanted " << pid << ", got " << got_pid;
12356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      return false;
12456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    }
12556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
12656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      LOG(ERROR) << dex2oat << " failed: " << command_line;
12756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      return false;
12856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    }
12956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
13056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return true;
13156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom}
13256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
13356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian CarlstromImageSpace* ImageSpace::Create(const std::string& original_image_file_name) {
13456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (OS::FileExists(original_image_file_name.c_str())) {
13556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    // If the /system file exists, it should be up-to-date, don't try to generate
13656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return space::ImageSpace::Init(original_image_file_name, false);
13756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
13856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // If the /system file didn't exist, we need to use one from the dalvik-cache.
13956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // If the cache file exists, try to open, but if it fails, regenerate.
14056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // If it does not exist, generate.
14156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name));
14256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (OS::FileExists(image_file_name.c_str())) {
14356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    space::ImageSpace* image_space = space::ImageSpace::Init(image_file_name, true);
14456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    if (image_space != NULL) {
14556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      return image_space;
14656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    }
14756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
14856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  CHECK(GenerateImage(image_file_name)) << "Failed to generate image: " << image_file_name;
14956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return space::ImageSpace::Init(image_file_name, true);
15056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom}
15156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
15231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartiervoid ImageSpace::VerifyImageAllocations() {
15331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  byte* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
15431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  while (current < End()) {
15531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    DCHECK_ALIGNED(current, kObjectAlignment);
15631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    const mirror::Object* obj = reinterpret_cast<const mirror::Object*>(current);
15731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    CHECK(live_bitmap_->Test(obj));
15831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class";
15931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    current += RoundUp(obj->SizeOf(), kObjectAlignment);
16031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  }
16131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier}
16231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
16356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian CarlstromImageSpace* ImageSpace::Init(const std::string& image_file_name, bool validate_oat_file) {
1641d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK(!image_file_name.empty());
1651d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
1661d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  uint64_t start_time = 0;
1671d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
1681d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    start_time = NanoTime();
16956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
1701d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
1711d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
1727571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom  UniquePtr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
1731d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (file.get() == NULL) {
1741d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    LOG(ERROR) << "Failed to open " << image_file_name;
1751d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return NULL;
1761d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
1771d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  ImageHeader image_header;
1781d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  bool success = file->ReadFully(&image_header, sizeof(image_header));
1791d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (!success || !image_header.IsValid()) {
1801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    LOG(ERROR) << "Invalid image header " << image_file_name;
1811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return NULL;
1821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
18331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
18431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  // Note: The image header is part of the image due to mmap page alignment required of offset.
1851d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  UniquePtr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(),
18631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                 image_header.GetImageSize(),
1871d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                 PROT_READ | PROT_WRITE,
1881d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                 MAP_PRIVATE | MAP_FIXED,
1891d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                 file->Fd(),
1901d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                 0,
1911d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                 false));
1921d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (map.get() == NULL) {
1931d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    LOG(ERROR) << "Failed to map " << image_file_name;
1941d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    return NULL;
1951d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
1961d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  CHECK_EQ(image_header.GetImageBegin(), map->Begin());
1971d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));
1981d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
19931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  UniquePtr<MemMap> image_map(MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(),
20031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                       PROT_READ, MAP_PRIVATE,
20131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                       file->Fd(), image_header.GetBitmapOffset(),
20231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                       false));
20331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  CHECK(image_map.get() != nullptr) << "failed to map image bitmap";
20431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  size_t bitmap_index = bitmap_index_.fetch_add(1);
20531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_file_name.c_str(),
20631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                       bitmap_index));
20731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  UniquePtr<accounting::SpaceBitmap> bitmap(
20831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier      accounting::SpaceBitmap::CreateFromMemMap(bitmap_name, image_map.release(),
20931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                reinterpret_cast<byte*>(map->Begin()),
21031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                                                map->Size()));
21131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  CHECK(bitmap.get() != nullptr) << "could not create " << bitmap_name;
21231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
2131d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  Runtime* runtime = Runtime::Current();
2141d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
215ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  runtime->SetResolutionMethod(down_cast<mirror::ArtMethod*>(resolution_method));
2161d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
2171d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
218ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kSaveAll);
2191d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
220ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsOnly);
2211d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
222ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsAndArgs);
2231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
22431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  UniquePtr<ImageSpace> space(new ImageSpace(image_file_name, map.release(), bitmap.release()));
22531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  if (kIsDebugBuild) {
22631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    space->VerifyImageAllocations();
22731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  }
22856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
22956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  space->oat_file_.reset(space->OpenOatFile());
23056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (space->oat_file_.get() == NULL) {
23156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(ERROR) << "Failed to open oat file for image: " << image_file_name;
23256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return NULL;
23356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
23456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
23556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (validate_oat_file && !space->ValidateOatFile()) {
23656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(WARNING) << "Failed to validate oat file for image: " << image_file_name;
23756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return NULL;
23856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
23956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
2401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
24156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time)
24256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom             << ") " << *space.get();
2431d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
24456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return space.release();
24556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom}
24656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
24756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian CarlstromOatFile* ImageSpace::OpenOatFile() const {
24856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  const Runtime* runtime = Runtime::Current();
24956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  const ImageHeader& image_header = GetImageHeader();
25056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // Grab location but don't use Object::AsString as we haven't yet initialized the roots to
25156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  // check the down cast
25256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  mirror::String* oat_location =
25356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      down_cast<mirror::String*>(image_header.GetImageRoot(ImageHeader::kOatLocation));
25456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  std::string oat_filename;
25556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  oat_filename += runtime->GetHostPrefix();
25656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  oat_filename += oat_location->ToModifiedUtf8();
25756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatDataBegin(),
25856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom                                    !Runtime::Current()->IsCompiler());
25956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (oat_file == NULL) {
26056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
26156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return NULL;
26256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
26356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum();
26456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  uint32_t image_oat_checksum = image_header.GetOatChecksum();
26556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  if (oat_checksum != image_oat_checksum) {
26656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    LOG(ERROR) << "Failed to match oat file checksum " << std::hex << oat_checksum
26756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom               << " to expected oat checksum " << std::hex << image_oat_checksum
26856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom               << " in image";
26956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    return NULL;
27056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
27156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return oat_file;
27256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom}
27356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
27456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrombool ImageSpace::ValidateOatFile() const {
27556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  CHECK(oat_file_.get() != NULL);
27631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  for (const OatFile::OatDexFile* oat_dex_file : oat_file_->GetOatDexFiles()) {
27756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    const std::string& dex_file_location = oat_dex_file->GetDexFileLocation();
27856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    uint32_t dex_file_location_checksum;
2797c3d13aebdd8611cae58a1048bffb13cbdc465cbBrian Carlstrom    if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum)) {
28056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      LOG(WARNING) << "ValidateOatFile could not find checksum for " << dex_file_location;
28156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      return false;
28256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    }
28356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) {
28456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      LOG(WARNING) << "ValidateOatFile found checksum mismatch between oat file "
28556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom                   << oat_file_->GetLocation() << " and dex file " << dex_file_location
28656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom                   << " (" << oat_dex_file->GetDexFileLocationChecksum() << " != "
28756d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom                   << dex_file_location_checksum << ")";
28856d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom      return false;
28956d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom    }
29056d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  }
29156d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return true;
29256d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom}
29356d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom
29456d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian CarlstromOatFile& ImageSpace::ReleaseOatFile() {
29556d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  CHECK(oat_file_.get() != NULL);
29656d947fbc9bc2992e2f93112fafb73e50d2aaa7aBrian Carlstrom  return *oat_file_.release();
2971d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}
2981d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
2991d54e73444e017d3a65234e0f193846f3e27472bIan Rogersvoid ImageSpace::Dump(std::ostream& os) const {
3001d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  os << GetType()
3011d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      << "begin=" << reinterpret_cast<void*>(Begin())
3021d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      << ",end=" << reinterpret_cast<void*>(End())
3031d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      << ",size=" << PrettySize(Size())
3041d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      << ",name=\"" << GetName() << "\"]";
3051d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}
3061d54e73444e017d3a65234e0f193846f3e27472bIan Rogers
3071d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace space
3081d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace gc
3091d54e73444e017d3a65234e0f193846f3e27472bIan Rogers}  // namespace art
310