Home | History | Annotate | Download | only in compiler
      1 /*
      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.h"
     18 
     19 #include <memory>
     20 #include <string>
     21 #include <vector>
     22 
     23 #include "base/unix_file/fd_file.h"
     24 #include "class_linker-inl.h"
     25 #include "common_compiler_test.h"
     26 #include "debug/method_debug_info.h"
     27 #include "driver/compiler_options.h"
     28 #include "elf_writer.h"
     29 #include "elf_writer_quick.h"
     30 #include "gc/space/image_space.h"
     31 #include "image_writer.h"
     32 #include "linker/multi_oat_relative_patcher.h"
     33 #include "lock_word.h"
     34 #include "mirror/object-inl.h"
     35 #include "oat_writer.h"
     36 #include "scoped_thread_state_change.h"
     37 #include "signal_catcher.h"
     38 #include "utils.h"
     39 
     40 namespace art {
     41 
     42 class ImageTest : public CommonCompilerTest {
     43  protected:
     44   virtual void SetUp() {
     45     ReserveImageSpace();
     46     CommonCompilerTest::SetUp();
     47   }
     48   void TestWriteRead(ImageHeader::StorageMode storage_mode);
     49 };
     50 
     51 void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) {
     52   CreateCompilerDriver(Compiler::kOptimizing, kRuntimeISA, kIsTargetBuild ? 2U : 16U);
     53 
     54   // Set inline filter values.
     55   compiler_options_->SetInlineDepthLimit(CompilerOptions::kDefaultInlineDepthLimit);
     56   compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
     57 
     58   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     59   // Enable write for dex2dex.
     60   for (const DexFile* dex_file : class_linker->GetBootClassPath()) {
     61     dex_file->EnableWrite();
     62   }
     63   // Create a generic location tmp file, to be the base of the .art and .oat temporary files.
     64   ScratchFile location;
     65   ScratchFile image_location(location, ".art");
     66 
     67   std::string image_filename(GetSystemImageFilename(image_location.GetFilename().c_str(),
     68                                                     kRuntimeISA));
     69   size_t pos = image_filename.rfind('/');
     70   CHECK_NE(pos, std::string::npos) << image_filename;
     71   std::string image_dir(image_filename, 0, pos);
     72   int mkdir_result = mkdir(image_dir.c_str(), 0700);
     73   CHECK_EQ(0, mkdir_result) << image_dir;
     74   ScratchFile image_file(OS::CreateEmptyFile(image_filename.c_str()));
     75 
     76   std::string oat_filename(image_filename, 0, image_filename.size() - 3);
     77   oat_filename += "oat";
     78   ScratchFile oat_file(OS::CreateEmptyFile(oat_filename.c_str()));
     79 
     80   const uintptr_t requested_image_base = ART_BASE_ADDRESS;
     81   std::unordered_map<const DexFile*, size_t> dex_file_to_oat_index_map;
     82   std::vector<const char*> oat_filename_vector(1, oat_filename.c_str());
     83   for (const DexFile* dex_file : class_linker->GetBootClassPath()) {
     84     dex_file_to_oat_index_map.emplace(dex_file, 0);
     85   }
     86   std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_driver_,
     87                                                       requested_image_base,
     88                                                       /*compile_pic*/false,
     89                                                       /*compile_app_image*/false,
     90                                                       storage_mode,
     91                                                       oat_filename_vector,
     92                                                       dex_file_to_oat_index_map));
     93   // TODO: compile_pic should be a test argument.
     94   {
     95     {
     96       jobject class_loader = nullptr;
     97       TimingLogger timings("ImageTest::WriteRead", false, false);
     98       TimingLogger::ScopedTiming t("CompileAll", &timings);
     99       compiler_driver_->SetDexFilesForOatFile(class_linker->GetBootClassPath());
    100       compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
    101 
    102       t.NewTiming("WriteElf");
    103       SafeMap<std::string, std::string> key_value_store;
    104       const std::vector<const DexFile*>& dex_files = class_linker->GetBootClassPath();
    105       std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
    106           compiler_driver_->GetInstructionSet(),
    107           compiler_driver_->GetInstructionSetFeatures(),
    108           &compiler_driver_->GetCompilerOptions(),
    109           oat_file.GetFile());
    110       elf_writer->Start();
    111       OatWriter oat_writer(/*compiling_boot_image*/true, &timings);
    112       OutputStream* rodata = elf_writer->StartRoData();
    113       for (const DexFile* dex_file : dex_files) {
    114         ArrayRef<const uint8_t> raw_dex_file(
    115             reinterpret_cast<const uint8_t*>(&dex_file->GetHeader()),
    116             dex_file->GetHeader().file_size_);
    117         oat_writer.AddRawDexFileSource(raw_dex_file,
    118                                        dex_file->GetLocation().c_str(),
    119                                        dex_file->GetLocationChecksum());
    120       }
    121       std::unique_ptr<MemMap> opened_dex_files_map;
    122       std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
    123       bool dex_files_ok = oat_writer.WriteAndOpenDexFiles(
    124           rodata,
    125           oat_file.GetFile(),
    126           compiler_driver_->GetInstructionSet(),
    127           compiler_driver_->GetInstructionSetFeatures(),
    128           &key_value_store,
    129           /* verify */ false,           // Dex files may be dex-to-dex-ed, don't verify.
    130           &opened_dex_files_map,
    131           &opened_dex_files);
    132       ASSERT_TRUE(dex_files_ok);
    133 
    134       bool image_space_ok = writer->PrepareImageAddressSpace();
    135       ASSERT_TRUE(image_space_ok);
    136 
    137       linker::MultiOatRelativePatcher patcher(compiler_driver_->GetInstructionSet(),
    138                                               instruction_set_features_.get());
    139       oat_writer.PrepareLayout(compiler_driver_.get(), writer.get(), dex_files, &patcher);
    140       size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset();
    141       size_t text_size = oat_writer.GetSize() - rodata_size;
    142       elf_writer->SetLoadedSectionSizes(rodata_size, text_size, oat_writer.GetBssSize());
    143 
    144       writer->UpdateOatFileLayout(/* oat_index */ 0u,
    145                                   elf_writer->GetLoadedSize(),
    146                                   oat_writer.GetOatDataOffset(),
    147                                   oat_writer.GetSize());
    148 
    149       bool rodata_ok = oat_writer.WriteRodata(rodata);
    150       ASSERT_TRUE(rodata_ok);
    151       elf_writer->EndRoData(rodata);
    152 
    153       OutputStream* text = elf_writer->StartText();
    154       bool text_ok = oat_writer.WriteCode(text);
    155       ASSERT_TRUE(text_ok);
    156       elf_writer->EndText(text);
    157 
    158       bool header_ok = oat_writer.WriteHeader(elf_writer->GetStream(), 0u, 0u, 0u);
    159       ASSERT_TRUE(header_ok);
    160 
    161       writer->UpdateOatFileHeader(/* oat_index */ 0u, oat_writer.GetOatHeader());
    162 
    163       elf_writer->WriteDynamicSection();
    164       elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo());
    165       elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations());
    166 
    167       bool success = elf_writer->End();
    168       ASSERT_TRUE(success);
    169     }
    170   }
    171   // Workound bug that mcld::Linker::emit closes oat_file by reopening as dup_oat.
    172   std::unique_ptr<File> dup_oat(OS::OpenFileReadWrite(oat_file.GetFilename().c_str()));
    173   ASSERT_TRUE(dup_oat.get() != nullptr);
    174 
    175   {
    176     std::vector<const char*> dup_oat_filename(1, dup_oat->GetPath().c_str());
    177     std::vector<const char*> dup_image_filename(1, image_file.GetFilename().c_str());
    178     bool success_image = writer->Write(kInvalidFd,
    179                                        dup_image_filename,
    180                                        dup_oat_filename);
    181     ASSERT_TRUE(success_image);
    182     bool success_fixup = ElfWriter::Fixup(dup_oat.get(),
    183                                           writer->GetOatDataBegin(0));
    184     ASSERT_TRUE(success_fixup);
    185 
    186     ASSERT_EQ(dup_oat->FlushCloseOrErase(), 0) << "Could not flush and close oat file "
    187                                                << oat_file.GetFilename();
    188   }
    189 
    190   uint64_t image_file_size;
    191   {
    192     std::unique_ptr<File> file(OS::OpenFileForReading(image_file.GetFilename().c_str()));
    193     ASSERT_TRUE(file.get() != nullptr);
    194     ImageHeader image_header;
    195     ASSERT_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
    196     ASSERT_TRUE(image_header.IsValid());
    197     const auto& bitmap_section = image_header.GetImageSection(ImageHeader::kSectionImageBitmap);
    198     ASSERT_GE(bitmap_section.Offset(), sizeof(image_header));
    199     ASSERT_NE(0U, bitmap_section.Size());
    200 
    201     gc::Heap* heap = Runtime::Current()->GetHeap();
    202     ASSERT_TRUE(heap->HaveContinuousSpaces());
    203     gc::space::ContinuousSpace* space = heap->GetNonMovingSpace();
    204     ASSERT_FALSE(space->IsImageSpace());
    205     ASSERT_TRUE(space != nullptr);
    206     ASSERT_TRUE(space->IsMallocSpace());
    207 
    208     image_file_size = file->GetLength();
    209   }
    210 
    211   ASSERT_TRUE(compiler_driver_->GetImageClasses() != nullptr);
    212   std::unordered_set<std::string> image_classes(*compiler_driver_->GetImageClasses());
    213 
    214   // Need to delete the compiler since it has worker threads which are attached to runtime.
    215   compiler_driver_.reset();
    216 
    217   // Tear down old runtime before making a new one, clearing out misc state.
    218 
    219   // Remove the reservation of the memory for use to load the image.
    220   // Need to do this before we reset the runtime.
    221   UnreserveImageSpace();
    222   writer.reset(nullptr);
    223 
    224   runtime_.reset();
    225   java_lang_dex_file_ = nullptr;
    226 
    227   MemMap::Init();
    228   std::unique_ptr<const DexFile> dex(LoadExpectSingleDexFile(GetLibCoreDexFileNames()[0].c_str()));
    229 
    230   RuntimeOptions options;
    231   std::string image("-Ximage:");
    232   image.append(image_location.GetFilename());
    233   options.push_back(std::make_pair(image.c_str(), static_cast<void*>(nullptr)));
    234   // By default the compiler this creates will not include patch information.
    235   options.push_back(std::make_pair("-Xnorelocate", nullptr));
    236 
    237   if (!Runtime::Create(options, false)) {
    238     LOG(FATAL) << "Failed to create runtime";
    239     return;
    240   }
    241   runtime_.reset(Runtime::Current());
    242   // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
    243   // give it away now and then switch to a more managable ScopedObjectAccess.
    244   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
    245   ScopedObjectAccess soa(Thread::Current());
    246   ASSERT_TRUE(runtime_.get() != nullptr);
    247   class_linker_ = runtime_->GetClassLinker();
    248 
    249   gc::Heap* heap = Runtime::Current()->GetHeap();
    250   ASSERT_TRUE(heap->HasBootImageSpace());
    251   ASSERT_TRUE(heap->GetNonMovingSpace()->IsMallocSpace());
    252 
    253   // We loaded the runtime with an explicit image, so it must exist.
    254   gc::space::ImageSpace* image_space = heap->GetBootImageSpaces()[0];
    255   ASSERT_TRUE(image_space != nullptr);
    256   if (storage_mode == ImageHeader::kStorageModeUncompressed) {
    257     // Uncompressed, image should be smaller than file.
    258     ASSERT_LE(image_space->Size(), image_file_size);
    259   } else {
    260     // Compressed, file should be smaller than image.
    261     ASSERT_LE(image_file_size, image_space->Size());
    262   }
    263 
    264   image_space->VerifyImageAllocations();
    265   uint8_t* image_begin = image_space->Begin();
    266   uint8_t* image_end = image_space->End();
    267   CHECK_EQ(requested_image_base, reinterpret_cast<uintptr_t>(image_begin));
    268   for (size_t i = 0; i < dex->NumClassDefs(); ++i) {
    269     const DexFile::ClassDef& class_def = dex->GetClassDef(i);
    270     const char* descriptor = dex->GetClassDescriptor(class_def);
    271     mirror::Class* klass = class_linker_->FindSystemClass(soa.Self(), descriptor);
    272     EXPECT_TRUE(klass != nullptr) << descriptor;
    273     if (image_classes.find(descriptor) != image_classes.end()) {
    274       // Image classes should be located inside the image.
    275       EXPECT_LT(image_begin, reinterpret_cast<uint8_t*>(klass)) << descriptor;
    276       EXPECT_LT(reinterpret_cast<uint8_t*>(klass), image_end) << descriptor;
    277     } else {
    278       EXPECT_TRUE(reinterpret_cast<uint8_t*>(klass) >= image_end ||
    279                   reinterpret_cast<uint8_t*>(klass) < image_begin) << descriptor;
    280     }
    281     EXPECT_TRUE(Monitor::IsValidLockWord(klass->GetLockWord(false)));
    282   }
    283 
    284   image_file.Unlink();
    285   oat_file.Unlink();
    286   int rmdir_result = rmdir(image_dir.c_str());
    287   CHECK_EQ(0, rmdir_result);
    288 }
    289 
    290 TEST_F(ImageTest, WriteReadUncompressed) {
    291   TestWriteRead(ImageHeader::kStorageModeUncompressed);
    292 }
    293 
    294 TEST_F(ImageTest, WriteReadLZ4) {
    295   TestWriteRead(ImageHeader::kStorageModeLZ4);
    296 }
    297 
    298 TEST_F(ImageTest, WriteReadLZ4HC) {
    299   TestWriteRead(ImageHeader::kStorageModeLZ4HC);
    300 }
    301 
    302 
    303 TEST_F(ImageTest, ImageHeaderIsValid) {
    304     uint32_t image_begin = ART_BASE_ADDRESS;
    305     uint32_t image_size_ = 16 * KB;
    306     uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
    307     uint32_t oat_checksum = 0;
    308     uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB);  // page aligned
    309     uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB);  // page aligned
    310     uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB);
    311     uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
    312     ImageSection sections[ImageHeader::kSectionCount];
    313     ImageHeader image_header(image_begin,
    314                              image_size_,
    315                              sections,
    316                              image_roots,
    317                              oat_checksum,
    318                              oat_file_begin,
    319                              oat_data_begin,
    320                              oat_data_end,
    321                              oat_file_end,
    322                              /*boot_image_begin*/0U,
    323                              /*boot_image_size*/0U,
    324                              /*boot_oat_begin*/0U,
    325                              /*boot_oat_size_*/0U,
    326                              sizeof(void*),
    327                              /*compile_pic*/false,
    328                              /*is_pic*/false,
    329                              ImageHeader::kDefaultStorageMode,
    330                              /*data_size*/0u);
    331     ASSERT_TRUE(image_header.IsValid());
    332     ASSERT_TRUE(!image_header.IsAppImage());
    333 
    334     char* magic = const_cast<char*>(image_header.GetMagic());
    335     strcpy(magic, "");  // bad magic
    336     ASSERT_FALSE(image_header.IsValid());
    337     strcpy(magic, "art\n000");  // bad version
    338     ASSERT_FALSE(image_header.IsValid());
    339 }
    340 
    341 }  // namespace art
    342