• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SetUp()44   virtual void SetUp() {
45     ReserveImageSpace();
46     CommonCompilerTest::SetUp();
47   }
48   void TestWriteRead(ImageHeader::StorageMode storage_mode);
49 };
50 
TestWriteRead(ImageHeader::StorageMode storage_mode)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 
TEST_F(ImageTest,WriteReadUncompressed)290 TEST_F(ImageTest, WriteReadUncompressed) {
291   TestWriteRead(ImageHeader::kStorageModeUncompressed);
292 }
293 
TEST_F(ImageTest,WriteReadLZ4)294 TEST_F(ImageTest, WriteReadLZ4) {
295   TestWriteRead(ImageHeader::kStorageModeLZ4);
296 }
297 
TEST_F(ImageTest,WriteReadLZ4HC)298 TEST_F(ImageTest, WriteReadLZ4HC) {
299   TestWriteRead(ImageHeader::kStorageModeLZ4HC);
300 }
301 
302 
TEST_F(ImageTest,ImageHeaderIsValid)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