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