1 /*
2  * Copyright (C) 2016 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 <sys/wait.h>
18 #include <unistd.h>
19 
20 #include <algorithm>
21 #include <iterator>
22 #include <optional>
23 #include <regex>
24 #include <sstream>
25 #include <string>
26 #include <vector>
27 
28 #include "android-base/logging.h"
29 #include "android-base/macros.h"
30 #include "android-base/stringprintf.h"
31 #include "arch/instruction_set_features.h"
32 #include "base/macros.h"
33 #include "base/mutex-inl.h"
34 #include "base/utils.h"
35 #include "base/zip_archive.h"
36 #include "common_runtime_test.h"
37 #include "dex/art_dex_file_loader.h"
38 #include "dex/base64_test_util.h"
39 #include "dex/bytecode_utils.h"
40 #include "dex/class_accessor-inl.h"
41 #include "dex/code_item_accessors-inl.h"
42 #include "dex/dex_file-inl.h"
43 #include "dex/dex_file_loader.h"
44 #include "dex2oat_environment_test.h"
45 #include "gc_root-inl.h"
46 #include "intern_table-inl.h"
47 #include "oat/elf_file.h"
48 #include "oat/elf_file_impl.h"
49 #include "oat/oat.h"
50 #include "oat/oat_file.h"
51 #include "profile/profile_compilation_info.h"
52 #include "vdex_file.h"
53 #include "ziparchive/zip_writer.h"
54 
55 namespace art {
56 
57 using android::base::StringPrintf;
58 
59 class Dex2oatTest : public Dex2oatEnvironmentTest {
60  public:
TearDown()61   void TearDown() override {
62     Dex2oatEnvironmentTest::TearDown();
63 
64     output_ = "";
65     error_msg_ = "";
66   }
67 
68  protected:
GenerateOdexForTestWithStatus(const std::vector<std::string> & dex_locations,const std::string & odex_location,CompilerFilter::Filter filter,std::string * error_msg,const std::vector<std::string> & extra_args={},bool use_fd=false)69   int GenerateOdexForTestWithStatus(const std::vector<std::string>& dex_locations,
70                                     const std::string& odex_location,
71                                     CompilerFilter::Filter filter,
72                                     std::string* error_msg,
73                                     const std::vector<std::string>& extra_args = {},
74                                     bool use_fd = false) {
75     std::unique_ptr<File> oat_file;
76     std::vector<std::string> args;
77     args.reserve(dex_locations.size() + extra_args.size() + 6);
78     // Add dex file args.
79     for (const std::string& dex_location : dex_locations) {
80       args.push_back("--dex-file=" + dex_location);
81     }
82     if (use_fd) {
83       oat_file.reset(OS::CreateEmptyFile(odex_location.c_str()));
84       CHECK(oat_file != nullptr) << odex_location;
85       args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
86       args.push_back("--oat-location=" + odex_location);
87     } else {
88       args.push_back("--oat-file=" + odex_location);
89     }
90     args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
91     args.push_back("--runtime-arg");
92     args.push_back("-Xnorelocate");
93 
94     // Unless otherwise stated, use a small amount of threads, so that potential aborts are
95     // shorter. This can be overridden with extra_args.
96     args.push_back("-j4");
97 
98     args.insert(args.end(), extra_args.begin(), extra_args.end());
99 
100     int status = Dex2Oat(args, &output_, error_msg);
101     if (oat_file != nullptr) {
102       CHECK_EQ(oat_file->FlushClose(), 0) << "Could not flush and close oat file";
103     }
104     return status;
105   }
106 
GenerateOdexForTest(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter filter,const std::vector<std::string> & extra_args={},bool expect_success=true,bool use_fd=false,bool use_zip_fd=false)107   ::testing::AssertionResult GenerateOdexForTest(const std::string& dex_location,
108                                                  const std::string& odex_location,
109                                                  CompilerFilter::Filter filter,
110                                                  const std::vector<std::string>& extra_args = {},
111                                                  bool expect_success = true,
112                                                  bool use_fd = false,
113                                                  bool use_zip_fd = false) WARN_UNUSED {
114     return GenerateOdexForTest(dex_location,
115                                odex_location,
116                                filter,
117                                extra_args,
118                                expect_success,
119                                use_fd,
120                                use_zip_fd,
__anon390640650102(const OatFile&) 121                                [](const OatFile&) {});
122   }
123 
124   bool test_accepts_odex_file_on_failure = false;
125 
126   template <typename T>
GenerateOdexForTest(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter filter,const std::vector<std::string> & extra_args,bool expect_success,bool use_fd,bool use_zip_fd,T check_oat)127   ::testing::AssertionResult GenerateOdexForTest(const std::string& dex_location,
128                                                  const std::string& odex_location,
129                                                  CompilerFilter::Filter filter,
130                                                  const std::vector<std::string>& extra_args,
131                                                  bool expect_success,
132                                                  bool use_fd,
133                                                  bool use_zip_fd,
134                                                  T check_oat) WARN_UNUSED {
135     std::vector<std::string> dex_locations;
136     if (use_zip_fd) {
137       std::string loc_arg = "--zip-location=" + dex_location;
138       CHECK(std::any_of(extra_args.begin(), extra_args.end(), [&](const std::string& s) {
139         return s == loc_arg;
140       }));
141       CHECK(std::any_of(extra_args.begin(), extra_args.end(), [](const std::string& s) {
142         return s.starts_with("--zip-fd=");
143       }));
144     } else {
145       dex_locations.push_back(dex_location);
146     }
147     std::string error_msg;
148     int status = GenerateOdexForTestWithStatus(
149         dex_locations, odex_location, filter, &error_msg, extra_args, use_fd);
150     bool success = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
151     if (expect_success) {
152       if (!success) {
153         return ::testing::AssertionFailure() << "Failed to compile odex: " << error_msg << std::endl
154                                              << output_;
155       }
156 
157       // Verify the odex file was generated as expected.
158       std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
159                                                        odex_location,
160                                                        odex_location,
161                                                        /*executable=*/false,
162                                                        /*low_4gb=*/false,
163                                                        dex_location,
164                                                        &error_msg));
165       if (odex_file == nullptr) {
166         return ::testing::AssertionFailure() << "Could not open odex file: " << error_msg;
167       }
168 
169       CheckFilter(filter, odex_file->GetCompilerFilter());
170       check_oat(*(odex_file.get()));
171     } else {
172       if (success) {
173         return ::testing::AssertionFailure() << "Succeeded to compile odex: " << output_;
174       }
175 
176       error_msg_ = error_msg;
177 
178       if (!test_accepts_odex_file_on_failure) {
179         // Verify there's no loadable odex file.
180         std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
181                                                          odex_location,
182                                                          odex_location,
183                                                          /*executable=*/false,
184                                                          /*low_4gb=*/false,
185                                                          dex_location,
186                                                          &error_msg));
187         if (odex_file != nullptr) {
188           return ::testing::AssertionFailure() << "Could open odex file: " << error_msg;
189         }
190       }
191     }
192     return ::testing::AssertionSuccess();
193   }
194 
195   // Check the input compiler filter against the generated oat file's filter. May be overridden
196   // in subclasses when equality is not expected.
CheckFilter(CompilerFilter::Filter expected,CompilerFilter::Filter actual)197   virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
198     EXPECT_EQ(expected, actual);
199   }
200 
201   std::string output_ = "";
202   std::string error_msg_ = "";
203 };
204 
205 // This test class provides an easy way to validate an expected filter which is different
206 // then the one pass to generate the odex file (compared to adding yet another argument
207 // to what's already huge test methods).
208 class Dex2oatWithExpectedFilterTest : public Dex2oatTest {
209  protected:
CheckFilter(CompilerFilter::Filter expected,CompilerFilter::Filter actual)210   void CheckFilter([[maybe_unused]] CompilerFilter::Filter expected,
211                    CompilerFilter::Filter actual) override {
212     EXPECT_EQ(expected_filter_, actual);
213   }
214 
215   CompilerFilter::Filter expected_filter_;
216 };
217 
218 class Dex2oatSwapTest : public Dex2oatTest {
219  protected:
RunTest(bool use_fd,bool expect_use,const std::vector<std::string> & extra_args={})220   void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
221     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
222     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
223 
224     Copy(GetTestDexFileName(), dex_location);
225 
226     std::vector<std::string> copy(extra_args);
227 
228     std::unique_ptr<ScratchFile> sf;
229     if (use_fd) {
230       sf.reset(new ScratchFile());
231       copy.push_back(android::base::StringPrintf("--swap-fd=%d", sf->GetFd()));
232     } else {
233       std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
234       copy.push_back("--swap-file=" + swap_location);
235     }
236     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy));
237 
238     CheckValidity();
239     CheckResult(expect_use);
240   }
241 
GetTestDexFileName()242   virtual std::string GetTestDexFileName() {
243     return Dex2oatEnvironmentTest::GetTestDexFileName("VerifierDeps");
244   }
245 
CheckResult(bool expect_use)246   virtual void CheckResult(bool expect_use) {
247     if (kIsTargetBuild) {
248       CheckTargetResult(expect_use);
249     } else {
250       CheckHostResult(expect_use);
251     }
252   }
253 
CheckTargetResult(bool expect_use)254   virtual void CheckTargetResult([[maybe_unused]] bool expect_use) {
255     // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
256     //       something for variants with file descriptor where we can control the lifetime of
257     //       the swap file and thus take a look at it.
258   }
259 
CheckHostResult(bool expect_use)260   virtual void CheckHostResult(bool expect_use) {
261     if (!kIsTargetBuild) {
262       if (expect_use) {
263         EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
264             << output_;
265       } else {
266         EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
267             << output_;
268       }
269     }
270   }
271 
272   // Check whether the dex2oat run was really successful.
CheckValidity()273   virtual void CheckValidity() {
274     if (kIsTargetBuild) {
275       CheckTargetValidity();
276     } else {
277       CheckHostValidity();
278     }
279   }
280 
CheckTargetValidity()281   virtual void CheckTargetValidity() {
282     // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
283     //       something for variants with file descriptor where we can control the lifetime of
284     //       the swap file and thus take a look at it.
285   }
286 
287   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()288   virtual void CheckHostValidity() {
289     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
290   }
291 };
292 
TEST_F(Dex2oatSwapTest,DoNotUseSwapDefaultSingleSmall)293 TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
294   RunTest(/*use_fd=*/false, /*expect_use=*/false);
295   RunTest(/*use_fd=*/true, /*expect_use=*/false);
296 }
297 
TEST_F(Dex2oatSwapTest,DoNotUseSwapSingle)298 TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
299   RunTest(/*use_fd=*/false, /*expect_use=*/false, {"--swap-dex-size-threshold=0"});
300   RunTest(/*use_fd=*/true, /*expect_use=*/false, {"--swap-dex-size-threshold=0"});
301 }
302 
TEST_F(Dex2oatSwapTest,DoNotUseSwapSmall)303 TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
304   RunTest(/*use_fd=*/false, /*expect_use=*/false, {"--swap-dex-count-threshold=0"});
305   RunTest(/*use_fd=*/true, /*expect_use=*/false, {"--swap-dex-count-threshold=0"});
306 }
307 
TEST_F(Dex2oatSwapTest,DoUseSwapSingleSmall)308 TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
309   RunTest(/*use_fd=*/false,
310           /*expect_use=*/true,
311           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
312   RunTest(/*use_fd=*/true,
313           /*expect_use=*/true,
314           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
315 }
316 
317 class Dex2oatSwapUseTest : public Dex2oatSwapTest {
318  protected:
CheckHostResult(bool expect_use)319   void CheckHostResult(bool expect_use) override {
320     if (!kIsTargetBuild) {
321       if (expect_use) {
322         EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
323             << output_;
324       } else {
325         EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
326             << output_;
327       }
328     }
329   }
330 
GetTestDexFileName()331   std::string GetTestDexFileName() override {
332     // Use Statics as it has a handful of functions.
333     return CommonRuntimeTest::GetTestDexFileName("Statics");
334   }
335 
GrabResult1()336   void GrabResult1() {
337     if (!kIsTargetBuild) {
338       native_alloc_1_ = ParseNativeAlloc();
339       swap_1_ = ParseSwap(/*expected=*/false);
340     } else {
341       native_alloc_1_ = std::numeric_limits<size_t>::max();
342       swap_1_ = 0;
343     }
344   }
345 
GrabResult2()346   void GrabResult2() {
347     if (!kIsTargetBuild) {
348       native_alloc_2_ = ParseNativeAlloc();
349       swap_2_ = ParseSwap(/*expected=*/true);
350     } else {
351       native_alloc_2_ = 0;
352       swap_2_ = std::numeric_limits<size_t>::max();
353     }
354   }
355 
356  private:
ParseNativeAlloc()357   size_t ParseNativeAlloc() {
358     std::regex native_alloc_regex("dex2oat took.*native alloc=[^ ]+ \\(([0-9]+)B\\)");
359     std::smatch native_alloc_match;
360     bool found = std::regex_search(output_, native_alloc_match, native_alloc_regex);
361     if (!found) {
362       EXPECT_TRUE(found);
363       return 0;
364     }
365     if (native_alloc_match.size() != 2U) {
366       EXPECT_EQ(native_alloc_match.size(), 2U);
367       return 0;
368     }
369 
370     std::istringstream stream(native_alloc_match[1].str());
371     size_t value;
372     stream >> value;
373 
374     return value;
375   }
376 
ParseSwap(bool expected)377   size_t ParseSwap(bool expected) {
378     std::regex swap_regex("dex2oat took[^\\n]+swap=[^ ]+ \\(([0-9]+)B\\)");
379     std::smatch swap_match;
380     bool found = std::regex_search(output_, swap_match, swap_regex);
381     if (found != expected) {
382       EXPECT_EQ(expected, found);
383       return 0;
384     }
385 
386     if (!found) {
387       return 0;
388     }
389 
390     if (swap_match.size() != 2U) {
391       EXPECT_EQ(swap_match.size(), 2U);
392       return 0;
393     }
394 
395     std::istringstream stream(swap_match[1].str());
396     size_t value;
397     stream >> value;
398 
399     return value;
400   }
401 
402  protected:
403   size_t native_alloc_1_;
404   size_t native_alloc_2_;
405 
406   size_t swap_1_;
407   size_t swap_2_;
408 };
409 
TEST_F(Dex2oatSwapUseTest,CheckSwapUsage)410 TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) {
411   // Native memory usage isn't correctly tracked when running under ASan.
412   TEST_DISABLED_FOR_MEMORY_TOOL();
413 
414   // The `native_alloc_2_ >= native_alloc_1_` assertion below may not
415   // hold true on some x86 or x86_64 systems; disable this test while we
416   // investigate (b/29259363).
417   TEST_DISABLED_FOR_X86();
418   TEST_DISABLED_FOR_X86_64();
419 
420   RunTest(/*use_fd=*/false,
421           /*expect_use=*/false);
422   GrabResult1();
423   std::string output_1 = output_;
424 
425   output_ = "";
426 
427   RunTest(/*use_fd=*/false,
428           /*expect_use=*/true,
429           {"--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0"});
430   GrabResult2();
431   std::string output_2 = output_;
432 
433   if (native_alloc_2_ >= native_alloc_1_ || swap_1_ >= swap_2_) {
434     EXPECT_LT(native_alloc_2_, native_alloc_1_);
435     EXPECT_LT(swap_1_, swap_2_);
436 
437     LOG(ERROR) << output_1;
438     LOG(ERROR) << output_2;
439   }
440 }
441 
442 class Dex2oatVeryLargeTest : public Dex2oatTest {
443  protected:
CheckFilter(CompilerFilter::Filter input,CompilerFilter::Filter result)444   void CheckFilter([[maybe_unused]] CompilerFilter::Filter input,
445                    [[maybe_unused]] CompilerFilter::Filter result) override {
446     // Ignore, we'll do our own checks.
447   }
448 
RunTest(CompilerFilter::Filter filter,bool expect_large,bool expect_downgrade,const std::vector<std::string> & extra_args={})449   void RunTest(CompilerFilter::Filter filter,
450                bool expect_large,
451                bool expect_downgrade,
452                const std::vector<std::string>& extra_args = {}) {
453     RunTest(filter, filter, expect_large, expect_downgrade, extra_args);
454   }
455 
RunTest(CompilerFilter::Filter filter,CompilerFilter::Filter expected_filter,bool expect_large,bool expect_downgrade,const std::vector<std::string> & extra_args={})456   void RunTest(CompilerFilter::Filter filter,
457                CompilerFilter::Filter expected_filter,
458                bool expect_large,
459                bool expect_downgrade,
460                const std::vector<std::string>& extra_args = {}) {
461     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
462     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
463     std::string app_image_file = GetScratchDir() + "/Test.art";
464 
465     Copy(GetDexSrc1(), dex_location);
466 
467     std::vector<std::string> new_args(extra_args);
468     new_args.push_back("--app-image-file=" + app_image_file);
469     ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, filter, new_args));
470 
471     CheckValidity();
472     CheckResult(dex_location,
473                 odex_location,
474                 app_image_file,
475                 expected_filter,
476                 expect_large,
477                 expect_downgrade);
478   }
479 
CheckResult(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file,CompilerFilter::Filter expected_filter,bool expect_large,bool expect_downgrade)480   void CheckResult(const std::string& dex_location,
481                    const std::string& odex_location,
482                    const std::string& app_image_file,
483                    CompilerFilter::Filter expected_filter,
484                    bool expect_large,
485                    bool expect_downgrade) {
486     if (expect_downgrade) {
487       EXPECT_TRUE(expect_large);
488     }
489     // Host/target independent checks.
490     std::string error_msg;
491     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
492                                                      odex_location,
493                                                      odex_location,
494                                                      /*executable=*/false,
495                                                      /*low_4gb=*/false,
496                                                      dex_location,
497                                                      &error_msg));
498     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
499     EXPECT_GT(app_image_file.length(), 0u);
500     std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file.c_str()));
501     if (expect_large) {
502       // Note: we cannot check the following
503       // EXPECT_FALSE(CompilerFilter::IsAotCompilationEnabled(odex_file->GetCompilerFilter()));
504       // The reason is that the filter override currently happens when the dex files are
505       // loaded in dex2oat, which is after the oat file has been started. Thus, the header
506       // store cannot be changed, and the original filter is set in stone.
507 
508       for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
509         std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
510         ASSERT_TRUE(dex_file != nullptr);
511         uint32_t class_def_count = dex_file->NumClassDefs();
512         ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
513         for (uint16_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
514           OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
515           EXPECT_EQ(oat_class.GetType(), OatClassType::kNoneCompiled);
516         }
517       }
518 
519       // If the input filter was "below," it should have been used.
520       EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
521 
522       // If expect large, make sure the app image isn't generated or is empty.
523       if (file != nullptr) {
524         EXPECT_EQ(file->GetLength(), 0u);
525       }
526     } else {
527       EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
528       ASSERT_TRUE(file != nullptr) << app_image_file;
529       EXPECT_GT(file->GetLength(), 0u);
530     }
531 
532     // Host/target dependent checks.
533     if (kIsTargetBuild) {
534       CheckTargetResult(expect_downgrade);
535     } else {
536       CheckHostResult(expect_downgrade);
537     }
538   }
539 
CheckTargetResult(bool expect_downgrade)540   void CheckTargetResult([[maybe_unused]] bool expect_downgrade) {
541     // TODO: Ignore for now. May do something for fd things.
542   }
543 
CheckHostResult(bool expect_downgrade)544   void CheckHostResult(bool expect_downgrade) {
545     if (!kIsTargetBuild) {
546       if (expect_downgrade) {
547         EXPECT_NE(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
548       } else {
549         EXPECT_EQ(output_.find("Very large app, downgrading to"), std::string::npos) << output_;
550       }
551     }
552   }
553 
554   // Check whether the dex2oat run was really successful.
CheckValidity()555   void CheckValidity() {
556     if (kIsTargetBuild) {
557       CheckTargetValidity();
558     } else {
559       CheckHostValidity();
560     }
561   }
562 
CheckTargetValidity()563   void CheckTargetValidity() {
564     // TODO: Ignore for now.
565   }
566 
567   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()568   void CheckHostValidity() {
569     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
570   }
571 };
572 
TEST_F(Dex2oatVeryLargeTest,DontUseVeryLarge)573 TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) {
574   RunTest(CompilerFilter::kAssumeVerified, false, false);
575   RunTest(CompilerFilter::kSpeed, false, false);
576 
577   RunTest(CompilerFilter::kAssumeVerified, false, false, {"--very-large-app-threshold=10000000"});
578   RunTest(CompilerFilter::kSpeed, false, false, {"--very-large-app-threshold=10000000"});
579 }
580 
TEST_F(Dex2oatVeryLargeTest,UseVeryLarge)581 TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) {
582   RunTest(CompilerFilter::kAssumeVerified, true, false, {"--very-large-app-threshold=100"});
583   RunTest(CompilerFilter::kSpeed, true, true, {"--very-large-app-threshold=100"});
584 }
585 
586 // Regressin test for b/35665292.
TEST_F(Dex2oatVeryLargeTest,SpeedProfileNoProfile)587 TEST_F(Dex2oatVeryLargeTest, SpeedProfileNoProfile) {
588   // Test that dex2oat doesn't crash with speed-profile but no input profile.
589   RunTest(CompilerFilter::kSpeedProfile, CompilerFilter::kVerify, false, false);
590 }
591 
592 class Dex2oatLayoutTest : public Dex2oatTest {
593  protected:
CheckFilter(CompilerFilter::Filter input,CompilerFilter::Filter result)594   void CheckFilter([[maybe_unused]] CompilerFilter::Filter input,
595                    [[maybe_unused]] CompilerFilter::Filter result) override {
596     // Ignore, we'll do our own checks.
597   }
598 
599   // Emits a profile with a single dex file with the given location and classes ranging
600   // from `class_offset` to `class_offset + num_classes`.
GenerateProfile(const std::string & test_profile,const std::string & dex_location,size_t num_classes,size_t class_offset=0)601   void GenerateProfile(const std::string& test_profile,
602                        const std::string& dex_location,
603                        size_t num_classes,
604                        size_t class_offset = 0) {
605     const char* location = dex_location.c_str();
606     std::string error_msg;
607     std::vector<std::unique_ptr<const DexFile>> dex_files;
608     ArtDexFileLoader dex_file_loader(location);
609     ASSERT_TRUE(dex_file_loader.Open(
610         /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files));
611     EXPECT_EQ(dex_files.size(), 1U);
612     std::unique_ptr<const DexFile>& dex_file = dex_files[0];
613 
614     int profile_test_fd =
615         open(test_profile.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
616     CHECK_GE(profile_test_fd, 0);
617 
618     ProfileCompilationInfo info;
619     std::vector<dex::TypeIndex> classes;
620     for (size_t i = 0; i < num_classes; ++i) {
621       classes.push_back(dex::TypeIndex(class_offset + 1 + i));
622     }
623     info.AddClassesForDex(dex_file.get(), classes.begin(), classes.end());
624     bool result = info.Save(profile_test_fd);
625     close(profile_test_fd);
626     ASSERT_TRUE(result);
627   }
628 
629   // Compiles a dex file with profiles.
CompileProfileOdex(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name,bool use_fd,const std::vector<std::string> & profile_locations,const std::vector<std::string> & extra_args={},bool expect_success=true)630   void CompileProfileOdex(const std::string& dex_location,
631                           const std::string& odex_location,
632                           const std::string& app_image_file_name,
633                           bool use_fd,
634                           const std::vector<std::string>& profile_locations,
635                           const std::vector<std::string>& extra_args = {},
636                           bool expect_success = true) {
637     std::vector<std::string> copy(extra_args);
638     for (const std::string& profile_location : profile_locations) {
639       copy.push_back("--profile-file=" + profile_location);
640     }
641     std::unique_ptr<File> app_image_file;
642     if (!app_image_file_name.empty()) {
643       if (use_fd) {
644         app_image_file.reset(OS::CreateEmptyFile(app_image_file_name.c_str()));
645         copy.push_back("--app-image-fd=" + std::to_string(app_image_file->Fd()));
646       } else {
647         copy.push_back("--app-image-file=" + app_image_file_name);
648       }
649     }
650     ASSERT_TRUE(GenerateOdexForTest(
651         dex_location, odex_location, CompilerFilter::kSpeedProfile, copy, expect_success, use_fd));
652     if (app_image_file != nullptr) {
653       ASSERT_EQ(app_image_file->FlushCloseOrErase(), 0) << "Could not flush and close art file";
654     }
655   }
656 
657   // Same as above, but generates the profile internally with classes ranging from 0 to
658   // `num_profile_classes`.
CompileProfileOdex(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name,bool use_fd,size_t num_profile_classes,const std::vector<std::string> & extra_args={},bool expect_success=true)659   void CompileProfileOdex(const std::string& dex_location,
660                           const std::string& odex_location,
661                           const std::string& app_image_file_name,
662                           bool use_fd,
663                           size_t num_profile_classes,
664                           const std::vector<std::string>& extra_args = {},
665                           bool expect_success = true) {
666     const std::string profile_location = GetScratchDir() + "/primary.prof";
667     GenerateProfile(profile_location, dex_location, num_profile_classes);
668     CompileProfileOdex(dex_location,
669                        odex_location,
670                        app_image_file_name,
671                        use_fd,
672                        {profile_location},
673                        extra_args,
674                        expect_success);
675   }
676 
GetImageObjectSectionSize(const std::string & image_file_name)677   uint32_t GetImageObjectSectionSize(const std::string& image_file_name) {
678     EXPECT_FALSE(image_file_name.empty());
679     std::unique_ptr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
680     CHECK(file != nullptr);
681     ImageHeader image_header;
682     const bool success = file->ReadFully(&image_header, sizeof(image_header));
683     CHECK(success);
684     CHECK(image_header.IsValid());
685     ReaderMutexLock mu(Thread::Current(), *Locks::mutator_lock_);
686     return image_header.GetObjectsSection().Size();
687   }
688 
RunTest(bool app_image)689   void RunTest(bool app_image) {
690     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
691     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
692     std::string app_image_file = app_image ? (GetOdexDir() + "/DexOdexNoOat.art") : "";
693     Copy(GetDexSrc2(), dex_location);
694 
695     uint32_t image_file_empty_profile = 0;
696     if (app_image) {
697       CompileProfileOdex(dex_location,
698                          odex_location,
699                          app_image_file,
700                          /*use_fd=*/false,
701                          /*num_profile_classes=*/0);
702       CheckValidity();
703       // Don't check the result since CheckResult relies on the class being in the profile.
704       image_file_empty_profile = GetImageObjectSectionSize(app_image_file);
705       EXPECT_GT(image_file_empty_profile, 0u);
706       CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kVerify);
707     }
708 
709     // Small profile.
710     CompileProfileOdex(dex_location,
711                        odex_location,
712                        app_image_file,
713                        /*use_fd=*/false,
714                        /*num_profile_classes=*/1);
715     CheckValidity();
716     CheckResult(dex_location, odex_location, app_image_file);
717     CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kSpeedProfile);
718 
719     if (app_image) {
720       // Test that the profile made a difference by adding more classes.
721       const uint32_t image_file_small_profile = GetImageObjectSectionSize(app_image_file);
722       ASSERT_LT(image_file_empty_profile, image_file_small_profile);
723     }
724   }
725 
CheckCompilerFilter(const std::string & dex_location,const std::string & odex_location,CompilerFilter::Filter expected_filter)726   void CheckCompilerFilter(const std::string& dex_location,
727                            const std::string& odex_location,
728                            CompilerFilter::Filter expected_filter) {
729     std::string error_msg;
730     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
731                                                      odex_location,
732                                                      odex_location,
733                                                      /*executable=*/false,
734                                                      /*low_4gb=*/false,
735                                                      dex_location,
736                                                      &error_msg));
737     EXPECT_EQ(odex_file->GetCompilerFilter(), expected_filter);
738   }
739 
RunTestVDex()740   void RunTestVDex() {
741     std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
742     std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
743     std::string vdex_location = GetOdexDir() + "/DexOdexNoOat.vdex";
744     std::string app_image_file_name = GetOdexDir() + "/DexOdexNoOat.art";
745     Copy(GetDexSrc2(), dex_location);
746 
747     std::unique_ptr<File> vdex_file1(OS::CreateEmptyFile(vdex_location.c_str()));
748     CHECK(vdex_file1 != nullptr) << vdex_location;
749     ScratchFile vdex_file2;
750     {
751       std::string input_vdex = "--input-vdex-fd=-1";
752       std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file1->Fd());
753       CompileProfileOdex(dex_location,
754                          odex_location,
755                          app_image_file_name,
756                          /*use_fd=*/true,
757                          /*num_profile_classes=*/1,
758                          {input_vdex, output_vdex});
759       EXPECT_GT(vdex_file1->GetLength(), 0u);
760     }
761     {
762       // Test that vdex and dexlayout fail gracefully.
763       std::string input_vdex = StringPrintf("--input-vdex-fd=%d", vdex_file1->Fd());
764       std::string output_vdex = StringPrintf("--output-vdex-fd=%d", vdex_file2.GetFd());
765       CompileProfileOdex(dex_location,
766                          odex_location,
767                          app_image_file_name,
768                          /*use_fd=*/true,
769                          /*num_profile_classes=*/1,
770                          {input_vdex, output_vdex},
771                          /*expect_success=*/true);
772       EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u);
773     }
774     ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file";
775     CheckValidity();
776   }
777 
CheckResult(const std::string & dex_location,const std::string & odex_location,const std::string & app_image_file_name)778   void CheckResult(const std::string& dex_location,
779                    const std::string& odex_location,
780                    const std::string& app_image_file_name) {
781     // Host/target independent checks.
782     std::string error_msg;
783     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
784                                                      odex_location,
785                                                      odex_location,
786                                                      /*executable=*/false,
787                                                      /*low_4gb=*/false,
788                                                      dex_location,
789                                                      &error_msg));
790     ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
791 
792     const char* location = dex_location.c_str();
793     std::vector<std::unique_ptr<const DexFile>> dex_files;
794     ArtDexFileLoader dex_file_loader(location);
795     ASSERT_TRUE(dex_file_loader.Open(
796         /*verify=*/true, /*verify_checksum=*/true, &error_msg, &dex_files));
797     EXPECT_EQ(dex_files.size(), 1U);
798     std::unique_ptr<const DexFile>& old_dex_file = dex_files[0];
799 
800     for (const OatDexFile* oat_dex_file : odex_file->GetOatDexFiles()) {
801       std::unique_ptr<const DexFile> new_dex_file = oat_dex_file->OpenDexFile(&error_msg);
802       ASSERT_TRUE(new_dex_file != nullptr);
803       uint32_t class_def_count = new_dex_file->NumClassDefs();
804       ASSERT_LT(class_def_count, std::numeric_limits<uint16_t>::max());
805       ASSERT_GE(class_def_count, 2U);
806 
807       // Make sure the indexes stay the same.
808       std::string old_class0 = old_dex_file->PrettyType(old_dex_file->GetClassDef(0).class_idx_);
809       std::string old_class1 = old_dex_file->PrettyType(old_dex_file->GetClassDef(1).class_idx_);
810       std::string new_class0 = new_dex_file->PrettyType(new_dex_file->GetClassDef(0).class_idx_);
811       std::string new_class1 = new_dex_file->PrettyType(new_dex_file->GetClassDef(1).class_idx_);
812       EXPECT_EQ(old_class0, new_class0);
813       EXPECT_EQ(old_class1, new_class1);
814     }
815 
816     EXPECT_EQ(odex_file->GetCompilerFilter(), CompilerFilter::kSpeedProfile);
817 
818     if (!app_image_file_name.empty()) {
819       // Go peek at the image header to make sure it was large enough to contain the class.
820       std::unique_ptr<File> file(OS::OpenFileForReading(app_image_file_name.c_str()));
821       ImageHeader image_header;
822       bool success = file->ReadFully(&image_header, sizeof(image_header));
823       ASSERT_TRUE(success);
824       ASSERT_TRUE(image_header.IsValid());
825       EXPECT_GT(image_header.GetObjectsSection().Size(), 0u);
826     }
827   }
828 
829   // Check whether the dex2oat run was really successful.
CheckValidity()830   void CheckValidity() {
831     if (kIsTargetBuild) {
832       CheckTargetValidity();
833     } else {
834       CheckHostValidity();
835     }
836   }
837 
CheckTargetValidity()838   void CheckTargetValidity() {
839     // TODO: Ignore for now.
840   }
841 
842   // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
CheckHostValidity()843   void CheckHostValidity() {
844     EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
845   }
846 };
847 
TEST_F(Dex2oatLayoutTest,TestLayout)848 TEST_F(Dex2oatLayoutTest, TestLayout) { RunTest(/*app_image=*/false); }
849 
TEST_F(Dex2oatLayoutTest,TestLayoutAppImage)850 TEST_F(Dex2oatLayoutTest, TestLayoutAppImage) { RunTest(/*app_image=*/true); }
851 
TEST_F(Dex2oatLayoutTest,TestLayoutAppImageMissingBootImage)852 TEST_F(Dex2oatLayoutTest, TestLayoutAppImageMissingBootImage) {
853   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
854   std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
855   std::string app_image_file = GetOdexDir() + "/DexOdexNoOat.art";
856   Copy(GetDexSrc2(), dex_location);
857 
858   CompileProfileOdex(dex_location,
859                      odex_location,
860                      app_image_file,
861                      /*use_fd=*/false,
862                      /*num_profile_classes=*/1,
863                      /*extra_args=*/{"--boot-image=/nonx/boot.art"},
864                      /*expect_success=*/true);
865 
866   // Verify the odex file does not require an image.
867   std::string error_msg;
868   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
869                                                    odex_location,
870                                                    odex_location,
871                                                    /*executable=*/false,
872                                                    /*low_4gb=*/false,
873                                                    dex_location,
874                                                    &error_msg));
875   ASSERT_TRUE(odex_file != nullptr) << "Could not open odex file: " << error_msg;
876 
877   CheckFilter(CompilerFilter::kSpeedProfile, odex_file->GetCompilerFilter());
878   ASSERT_FALSE(odex_file->GetOatHeader().RequiresImage());
879 }
880 
TEST_F(Dex2oatLayoutTest,TestLayoutMultipleProfiles)881 TEST_F(Dex2oatLayoutTest, TestLayoutMultipleProfiles) {
882   std::string dex_location = GetScratchDir() + "/Dex.jar";
883   std::string odex_location = GetOdexDir() + "/Dex.odex";
884   std::string app_image_file = GetOdexDir() + "/Dex.art";
885   Copy(GetDexSrc2(), dex_location);
886 
887   const std::string profile1_location = GetScratchDir() + "/primary.prof";
888   GenerateProfile(profile1_location, dex_location, /*num_classes=*/1, /*class_offset=*/0);
889   CompileProfileOdex(dex_location,
890                      odex_location,
891                      app_image_file,
892                      /*use_fd=*/false,
893                      {profile1_location});
894   uint32_t image_file_size_profile1 = GetImageObjectSectionSize(app_image_file);
895 
896   const std::string profile2_location = GetScratchDir() + "/secondary.prof";
897   GenerateProfile(profile2_location, dex_location, /*num_classes=*/1, /*class_offset=*/1);
898   CompileProfileOdex(dex_location,
899                      odex_location,
900                      app_image_file,
901                      /*use_fd=*/false,
902                      {profile2_location});
903   uint32_t image_file_size_profile2 = GetImageObjectSectionSize(app_image_file);
904 
905   CompileProfileOdex(dex_location,
906                      odex_location,
907                      app_image_file,
908                      /*use_fd=*/false,
909                      {profile1_location, profile2_location});
910   uint32_t image_file_size_multiple_profiles = GetImageObjectSectionSize(app_image_file);
911 
912   CheckCompilerFilter(dex_location, odex_location, CompilerFilter::Filter::kSpeedProfile);
913 
914   // The image file generated with multiple profiles should be larger than any image file generated
915   // with each profile.
916   ASSERT_GT(image_file_size_multiple_profiles, image_file_size_profile1);
917   ASSERT_GT(image_file_size_multiple_profiles, image_file_size_profile2);
918 }
919 
TEST_F(Dex2oatLayoutTest,TestLayoutMultipleProfilesChecksumMismatch)920 TEST_F(Dex2oatLayoutTest, TestLayoutMultipleProfilesChecksumMismatch) {
921   std::string dex_location = GetScratchDir() + "/Dex.jar";
922 
923   // Create two profiles whose dex locations are the same but checksums are different.
924   Copy(GetDexSrc1(), dex_location);
925   const std::string profile_old = GetScratchDir() + "/profile_old.prof";
926   GenerateProfile(profile_old, dex_location, /*num_classes=*/1, /*class_offset=*/0);
927 
928   Copy(GetDexSrc2(), dex_location);
929   const std::string profile_new = GetScratchDir() + "/profile_new.prof";
930   GenerateProfile(profile_new, dex_location, /*num_classes=*/1, /*class_offset=*/0);
931 
932   // Create an empty profile for reference.
933   const std::string profile_empty = GetScratchDir() + "/profile_empty.prof";
934   GenerateProfile(profile_empty, dex_location, /*num_classes=*/0, /*class_offset=*/0);
935 
936   std::string odex_location = GetOdexDir() + "/Dex.odex";
937   std::string app_image_file = GetOdexDir() + "/Dex.art";
938 
939   // This should produce a normal image because only `profile_new` is used and it has the right
940   // checksum.
941   CompileProfileOdex(dex_location,
942                      odex_location,
943                      app_image_file,
944                      /*use_fd=*/false,
945                      {profile_new, profile_old});
946   uint32_t image_size_right_checksum = GetImageObjectSectionSize(app_image_file);
947 
948   // This should produce an empty image because only `profile_old` is used and it has the wrong
949   // checksum. Note that dex2oat does not abort compilation when the profile verification fails
950   // (b/62602192, b/65260586).
951   CompileProfileOdex(dex_location,
952                      odex_location,
953                      app_image_file,
954                      /*use_fd=*/false,
955                      {profile_old, profile_new});
956   uint32_t image_size_wrong_checksum = GetImageObjectSectionSize(app_image_file);
957 
958   // Create an empty image using an empty profile for reference.
959   CompileProfileOdex(dex_location,
960                      odex_location,
961                      app_image_file,
962                      /*use_fd=*/false,
963                      {profile_empty});
964   uint32_t image_size_empty = GetImageObjectSectionSize(app_image_file);
965 
966   EXPECT_GT(image_size_right_checksum, image_size_empty);
967   EXPECT_EQ(image_size_wrong_checksum, image_size_empty);
968 }
969 
TEST_F(Dex2oatLayoutTest,TestVdexLayout)970 TEST_F(Dex2oatLayoutTest, TestVdexLayout) { RunTestVDex(); }
971 
972 class Dex2oatWatchdogTest : public Dex2oatTest {
973  protected:
RunTest(bool expect_success,const std::vector<std::string> & extra_args={})974   void RunTest(bool expect_success, const std::vector<std::string>& extra_args = {}) {
975     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
976     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
977 
978     Copy(GetTestDexFileName(), dex_location);
979 
980     std::vector<std::string> copy(extra_args);
981 
982     std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
983     copy.push_back("--swap-file=" + swap_location);
984     copy.push_back("-j512");  // Excessive idle threads just slow down dex2oat.
985     ASSERT_TRUE(GenerateOdexForTest(
986         dex_location, odex_location, CompilerFilter::kSpeed, copy, expect_success));
987   }
988 
GetTestDexFileName()989   std::string GetTestDexFileName() { return GetDexSrc1(); }
990 };
991 
TEST_F(Dex2oatWatchdogTest,TestWatchdogOK)992 TEST_F(Dex2oatWatchdogTest, TestWatchdogOK) {
993   // Check with default.
994   RunTest(true);
995 
996   // Check with ten minutes.
997   RunTest(true, {"--watchdog-timeout=600000"});
998 }
999 
TEST_F(Dex2oatWatchdogTest,TestWatchdogTrigger)1000 TEST_F(Dex2oatWatchdogTest, TestWatchdogTrigger) {
1001   // This test is frequently interrupted by signal_dumper on host (x86);
1002   // disable it while we investigate (b/121352534).
1003   TEST_DISABLED_FOR_X86();
1004 
1005   // The watchdog is independent of dex2oat and will not delete intermediates. It is possible
1006   // that the compilation succeeds and the file is completely written by the time the watchdog
1007   // kills dex2oat (but the dex2oat threads must have been scheduled pretty badly).
1008   test_accepts_odex_file_on_failure = true;
1009 
1010   // Check with ten milliseconds.
1011   RunTest(false, {"--watchdog-timeout=10"});
1012 }
1013 
1014 class Dex2oatReturnCodeTest : public Dex2oatTest {
1015  protected:
RunTest(const std::vector<std::string> & extra_args={})1016   int RunTest(const std::vector<std::string>& extra_args = {}) {
1017     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1018     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1019 
1020     Copy(GetTestDexFileName(), dex_location);
1021 
1022     std::string error_msg;
1023     return GenerateOdexForTestWithStatus(
1024         {dex_location}, odex_location, CompilerFilter::kSpeed, &error_msg, extra_args);
1025   }
1026 
GetTestDexFileName()1027   std::string GetTestDexFileName() { return GetDexSrc1(); }
1028 };
1029 
1030 class Dex2oatClassLoaderContextTest : public Dex2oatTest {
1031  protected:
RunTest(const char * class_loader_context,const char * expected_classpath_key,bool expected_success,bool use_second_source=false,bool generate_image=false)1032   void RunTest(const char* class_loader_context,
1033                const char* expected_classpath_key,
1034                bool expected_success,
1035                bool use_second_source = false,
1036                bool generate_image = false) {
1037     std::string dex_location = GetUsedDexLocation();
1038     std::string odex_location = GetUsedOatLocation();
1039 
1040     Copy(use_second_source ? GetDexSrc2() : GetDexSrc1(), dex_location);
1041 
1042     std::string error_msg;
1043     std::vector<std::string> extra_args;
1044     if (class_loader_context != nullptr) {
1045       extra_args.push_back(std::string("--class-loader-context=") + class_loader_context);
1046     }
1047     if (generate_image) {
1048       extra_args.push_back(std::string("--app-image-file=") + GetUsedImageLocation());
1049     }
1050     auto check_oat = [expected_classpath_key](const OatFile& oat_file) {
1051       ASSERT_TRUE(expected_classpath_key != nullptr);
1052       const char* classpath = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
1053       ASSERT_TRUE(classpath != nullptr);
1054       ASSERT_STREQ(expected_classpath_key, classpath);
1055     };
1056 
1057     ASSERT_TRUE(GenerateOdexForTest(dex_location,
1058                                     odex_location,
1059                                     CompilerFilter::kVerify,
1060                                     extra_args,
1061                                     expected_success,
1062                                     /*use_fd=*/false,
1063                                     /*use_zip_fd=*/false,
1064                                     check_oat));
1065   }
1066 
GetUsedDexLocation()1067   std::string GetUsedDexLocation() { return GetScratchDir() + "/Context.jar"; }
1068 
GetUsedOatLocation()1069   std::string GetUsedOatLocation() { return GetOdexDir() + "/Context.odex"; }
1070 
GetUsedImageLocation()1071   std::string GetUsedImageLocation() { return GetOdexDir() + "/Context.art"; }
1072 
1073   const char* kEmptyClassPathKey = "PCL[]";
1074 };
1075 
TEST_F(Dex2oatClassLoaderContextTest,InvalidContext)1076 TEST_F(Dex2oatClassLoaderContextTest, InvalidContext) {
1077   RunTest("Invalid[]", /*expected_classpath_key*/ nullptr, /*expected_success*/ false);
1078 }
1079 
TEST_F(Dex2oatClassLoaderContextTest,EmptyContext)1080 TEST_F(Dex2oatClassLoaderContextTest, EmptyContext) {
1081   RunTest("PCL[]", kEmptyClassPathKey, /*expected_success*/ true);
1082 }
1083 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithTheSourceDexFiles)1084 TEST_F(Dex2oatClassLoaderContextTest, ContextWithTheSourceDexFiles) {
1085   std::string context = "PCL[" + GetUsedDexLocation() + "]";
1086   RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1087 }
1088 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithOtherDexFiles)1089 TEST_F(Dex2oatClassLoaderContextTest, ContextWithOtherDexFiles) {
1090   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Nested");
1091 
1092   uint32_t expected_checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
1093 
1094   std::string context = "PCL[" + dex_files[0]->GetLocation() + "]";
1095   std::string expected_classpath_key =
1096       "PCL[" + dex_files[0]->GetLocation() + "*" + std::to_string(expected_checksum) + "]";
1097   RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1098 }
1099 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithResourceOnlyDexFiles)1100 TEST_F(Dex2oatClassLoaderContextTest, ContextWithResourceOnlyDexFiles) {
1101   std::string resource_only_classpath = GetScratchDir() + "/resource_only_classpath.jar";
1102   Copy(GetResourceOnlySrc1(), resource_only_classpath);
1103 
1104   std::string context = "PCL[" + resource_only_classpath + "]";
1105   // Expect an empty context because resource only dex files cannot be open.
1106   RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1107 }
1108 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithNotExistentDexFiles)1109 TEST_F(Dex2oatClassLoaderContextTest, ContextWithNotExistentDexFiles) {
1110   std::string context = "PCL[does_not_exists.dex]";
1111   // Expect an empty context because stripped dex files cannot be open.
1112   RunTest(context.c_str(), kEmptyClassPathKey, /*expected_success*/ true);
1113 }
1114 
TEST_F(Dex2oatClassLoaderContextTest,ChainContext)1115 TEST_F(Dex2oatClassLoaderContextTest, ChainContext) {
1116   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1117   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1118 
1119   std::string context =
1120       "PCL[" + GetTestDexFileName("Nested") + "];" + "DLC[" + GetTestDexFileName("MultiDex") + "]";
1121   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "];" +
1122                                        "DLC[" + CreateClassPathWithChecksums(dex_files2) + "]";
1123 
1124   RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1125 }
1126 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibrary)1127 TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibrary) {
1128   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1129   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1130 
1131   std::string context =
1132       "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" + GetTestDexFileName("MultiDex") + "]}";
1133   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1134                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1135   RunTest(context.c_str(), expected_classpath_key.c_str(), true);
1136 }
1137 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibraryAndImage)1138 TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibraryAndImage) {
1139   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1140   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1141 
1142   std::string context =
1143       "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" + GetTestDexFileName("MultiDex") + "]}";
1144   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1145                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1146   RunTest(context.c_str(),
1147           expected_classpath_key.c_str(),
1148           /*expected_success=*/true,
1149           /*use_second_source=*/false,
1150           /*generate_image=*/true);
1151 }
1152 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSameSharedLibrariesAndImage)1153 TEST_F(Dex2oatClassLoaderContextTest, ContextWithSameSharedLibrariesAndImage) {
1154   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1155   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1156 
1157   std::string context = "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" +
1158                         GetTestDexFileName("MultiDex") + "]" + "#PCL[" +
1159                         GetTestDexFileName("MultiDex") + "]}";
1160   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1161                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]" +
1162                                        "#PCL[" + CreateClassPathWithChecksums(dex_files2) + "]}";
1163   RunTest(context.c_str(),
1164           expected_classpath_key.c_str(),
1165           /*expected_success=*/true,
1166           /*use_second_source=*/false,
1167           /*generate_image=*/true);
1168 }
1169 
TEST_F(Dex2oatClassLoaderContextTest,ContextWithSharedLibrariesDependenciesAndImage)1170 TEST_F(Dex2oatClassLoaderContextTest, ContextWithSharedLibrariesDependenciesAndImage) {
1171   std::vector<std::unique_ptr<const DexFile>> dex_files1 = OpenTestDexFiles("Nested");
1172   std::vector<std::unique_ptr<const DexFile>> dex_files2 = OpenTestDexFiles("MultiDex");
1173 
1174   std::string context = "PCL[" + GetTestDexFileName("Nested") + "]" + "{PCL[" +
1175                         GetTestDexFileName("MultiDex") + "]" + "{PCL[" +
1176                         GetTestDexFileName("Nested") + "]}}";
1177   std::string expected_classpath_key = "PCL[" + CreateClassPathWithChecksums(dex_files1) + "]" +
1178                                        "{PCL[" + CreateClassPathWithChecksums(dex_files2) + "]" +
1179                                        "{PCL[" + CreateClassPathWithChecksums(dex_files1) + "]}}";
1180   RunTest(context.c_str(),
1181           expected_classpath_key.c_str(),
1182           /*expected_success=*/true,
1183           /*use_second_source=*/false,
1184           /*generate_image=*/true);
1185 }
1186 
1187 class Dex2oatDeterminism : public Dex2oatTest {};
1188 
TEST_F(Dex2oatDeterminism,UnloadCompile)1189 TEST_F(Dex2oatDeterminism, UnloadCompile) {
1190   Runtime* const runtime = Runtime::Current();
1191   std::string out_dir = GetScratchDir();
1192   const std::string base_oat_name = out_dir + "/base.oat";
1193   const std::string base_vdex_name = out_dir + "/base.vdex";
1194   const std::string unload_oat_name = out_dir + "/unload.oat";
1195   const std::string unload_vdex_name = out_dir + "/unload.vdex";
1196   const std::string no_unload_oat_name = out_dir + "/nounload.oat";
1197   const std::string no_unload_vdex_name = out_dir + "/nounload.vdex";
1198   std::string error_msg;
1199   const std::vector<gc::space::ImageSpace*>& spaces = runtime->GetHeap()->GetBootImageSpaces();
1200   ASSERT_GT(spaces.size(), 0u);
1201   const std::string image_location = spaces[0]->GetImageLocation();
1202   // Without passing in an app image, it will unload in between compilations.
1203   const int res =
1204       GenerateOdexForTestWithStatus(GetLibCoreDexFileNames(),
1205                                     base_oat_name,
1206                                     CompilerFilter::Filter::kVerify,
1207                                     &error_msg,
1208                                     {"--force-determinism", "--avoid-storing-invocation"});
1209   ASSERT_EQ(res, 0);
1210   Copy(base_oat_name, unload_oat_name);
1211   Copy(base_vdex_name, unload_vdex_name);
1212   std::unique_ptr<File> unload_oat(OS::OpenFileForReading(unload_oat_name.c_str()));
1213   std::unique_ptr<File> unload_vdex(OS::OpenFileForReading(unload_vdex_name.c_str()));
1214   ASSERT_TRUE(unload_oat != nullptr);
1215   ASSERT_TRUE(unload_vdex != nullptr);
1216   EXPECT_GT(unload_oat->GetLength(), 0u);
1217   EXPECT_GT(unload_vdex->GetLength(), 0u);
1218   // Regenerate with an app image to disable the dex2oat unloading and verify that the output is
1219   // the same.
1220   const int res2 = GenerateOdexForTestWithStatus(
1221       GetLibCoreDexFileNames(),
1222       base_oat_name,
1223       CompilerFilter::Filter::kVerify,
1224       &error_msg,
1225       {"--force-determinism", "--avoid-storing-invocation", "--compile-individually"});
1226   ASSERT_EQ(res2, 0);
1227   Copy(base_oat_name, no_unload_oat_name);
1228   Copy(base_vdex_name, no_unload_vdex_name);
1229   std::unique_ptr<File> no_unload_oat(OS::OpenFileForReading(no_unload_oat_name.c_str()));
1230   std::unique_ptr<File> no_unload_vdex(OS::OpenFileForReading(no_unload_vdex_name.c_str()));
1231   ASSERT_TRUE(no_unload_oat != nullptr);
1232   ASSERT_TRUE(no_unload_vdex != nullptr);
1233   EXPECT_GT(no_unload_oat->GetLength(), 0u);
1234   EXPECT_GT(no_unload_vdex->GetLength(), 0u);
1235   // Verify that both of the files are the same (odex and vdex).
1236   EXPECT_EQ(unload_oat->GetLength(), no_unload_oat->GetLength());
1237   EXPECT_EQ(unload_vdex->GetLength(), no_unload_vdex->GetLength());
1238   EXPECT_EQ(unload_oat->Compare(no_unload_oat.get()), 0)
1239       << unload_oat_name << " " << no_unload_oat_name;
1240   EXPECT_EQ(unload_vdex->Compare(no_unload_vdex.get()), 0)
1241       << unload_vdex_name << " " << no_unload_vdex_name;
1242 }
1243 
1244 class Dex2oatVerifierAbort : public Dex2oatTest {};
1245 
TEST_F(Dex2oatVerifierAbort,HardFail)1246 TEST_F(Dex2oatVerifierAbort, HardFail) {
1247   // Use VerifierDeps as it has hard-failing classes.
1248   std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDeps"));
1249   std::string out_dir = GetScratchDir();
1250   const std::string base_oat_name = out_dir + "/base.oat";
1251   std::string error_msg;
1252   const int res_fail = GenerateOdexForTestWithStatus({dex->GetLocation()},
1253                                                      base_oat_name,
1254                                                      CompilerFilter::Filter::kVerify,
1255                                                      &error_msg,
1256                                                      {"--abort-on-hard-verifier-error"});
1257   EXPECT_NE(0, res_fail);
1258 
1259   const int res_no_fail = GenerateOdexForTestWithStatus({dex->GetLocation()},
1260                                                         base_oat_name,
1261                                                         CompilerFilter::Filter::kVerify,
1262                                                         &error_msg,
1263                                                         {"--no-abort-on-hard-verifier-error"});
1264   EXPECT_EQ(0, res_no_fail);
1265 }
1266 
1267 class Dex2oatDedupeCode : public Dex2oatTest {};
1268 
TEST_F(Dex2oatDedupeCode,DedupeTest)1269 TEST_F(Dex2oatDedupeCode, DedupeTest) {
1270   // Use MyClassNatives. It has lots of native methods that will produce deduplicate-able code.
1271   std::unique_ptr<const DexFile> dex(OpenTestDexFile("MyClassNatives"));
1272   std::string out_dir = GetScratchDir();
1273   const std::string base_oat_name = out_dir + "/base.oat";
1274   size_t no_dedupe_size = 0;
1275   ASSERT_TRUE(
1276       GenerateOdexForTest(dex->GetLocation(),
1277                           base_oat_name,
1278                           CompilerFilter::Filter::kSpeed,
1279                           {"--deduplicate-code=false"},
1280                           /*expect_success=*/true,
1281                           /*use_fd=*/false,
1282                           /*use_zip_fd=*/false,
1283                           [&no_dedupe_size](const OatFile& o) { no_dedupe_size = o.Size(); }));
1284 
1285   size_t dedupe_size = 0;
1286   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
1287                                   base_oat_name,
1288                                   CompilerFilter::Filter::kSpeed,
1289                                   {"--deduplicate-code=true"},
1290                                   /*expect_success=*/true,
1291                                   /*use_fd=*/false,
1292                                   /*use_zip_fd=*/false,
1293                                   [&dedupe_size](const OatFile& o) { dedupe_size = o.Size(); }));
1294 
1295   EXPECT_LT(dedupe_size, no_dedupe_size);
1296 }
1297 
TEST_F(Dex2oatTest,UncompressedTest)1298 TEST_F(Dex2oatTest, UncompressedTest) {
1299   std::unique_ptr<const DexFile> dex(OpenTestDexFile("MainUncompressedAligned"));
1300   std::string out_dir = GetScratchDir();
1301   const std::string base_oat_name = out_dir + "/base.oat";
1302   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
1303                                   base_oat_name,
1304                                   CompilerFilter::Filter::kVerify,
1305                                   {},
1306                                   /*expect_success=*/true,
1307                                   /*use_fd=*/false,
1308                                   /*use_zip_fd=*/false,
1309                                   [](const OatFile& o) { CHECK(!o.ContainsDexCode()); }));
1310 }
1311 
TEST_F(Dex2oatTest,MissingBootImageTest)1312 TEST_F(Dex2oatTest, MissingBootImageTest) {
1313   std::string out_dir = GetScratchDir();
1314   const std::string base_oat_name = out_dir + "/base.oat";
1315   // The compilation should succeed even without the boot image.
1316   ASSERT_TRUE(GenerateOdexForTest(
1317       {GetTestDexFileName("MainUncompressedAligned")},
1318       base_oat_name,
1319       CompilerFilter::Filter::kVerify,
1320       // Note: Extra options go last and the second `--boot-image` option overrides the first.
1321       {"--boot-image=/nonx/boot.art"}));
1322 }
1323 
TEST_F(Dex2oatTest,EmptyUncompressedDexTest)1324 TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
1325   std::string out_dir = GetScratchDir();
1326   const std::string base_oat_name = out_dir + "/base.oat";
1327   std::string error_msg;
1328   int status = GenerateOdexForTestWithStatus({GetTestDexFileName("MainEmptyUncompressed")},
1329                                              base_oat_name,
1330                                              CompilerFilter::Filter::kVerify,
1331                                              &error_msg,
1332                                              {},
1333                                              /*use_fd*/ false);
1334   // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1335   ASSERT_TRUE(WIFEXITED(status));
1336   ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1337 }
1338 
TEST_F(Dex2oatTest,EmptyUncompressedAlignedDexTest)1339 TEST_F(Dex2oatTest, EmptyUncompressedAlignedDexTest) {
1340   std::string out_dir = GetScratchDir();
1341   const std::string base_oat_name = out_dir + "/base.oat";
1342   std::string error_msg;
1343   int status = GenerateOdexForTestWithStatus({GetTestDexFileName("MainEmptyUncompressedAligned")},
1344                                              base_oat_name,
1345                                              CompilerFilter::Filter::kVerify,
1346                                              &error_msg,
1347                                              {},
1348                                              /*use_fd*/ false);
1349   // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
1350   ASSERT_TRUE(WIFEXITED(status));
1351   ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
1352 }
1353 
TEST_F(Dex2oatTest,StderrLoggerOutput)1354 TEST_F(Dex2oatTest, StderrLoggerOutput) {
1355   std::string dex_location = GetScratchDir() + "/Dex2OatStderrLoggerTest.jar";
1356   std::string odex_location = GetOdexDir() + "/Dex2OatStderrLoggerTest.odex";
1357 
1358   // Test file doesn't matter.
1359   Copy(GetDexSrc1(), dex_location);
1360 
1361   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1362                                   odex_location,
1363                                   CompilerFilter::kVerify,
1364                                   {"--runtime-arg", "-Xuse-stderr-logger"},
1365                                   true));
1366   // Look for some random part of dex2oat logging. With the stderr logger this should be captured,
1367   // even on device.
1368   EXPECT_NE(std::string::npos, output_.find("dex2oat took"));
1369 }
1370 
TEST_F(Dex2oatTest,VerifyCompilationReason)1371 TEST_F(Dex2oatTest, VerifyCompilationReason) {
1372   std::string dex_location = GetScratchDir() + "/Dex2OatCompilationReason.jar";
1373   std::string odex_location = GetOdexDir() + "/Dex2OatCompilationReason.odex";
1374 
1375   // Test file doesn't matter.
1376   Copy(GetDexSrc1(), dex_location);
1377 
1378   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1379                                   odex_location,
1380                                   CompilerFilter::kVerify,
1381                                   {"--compilation-reason=install"},
1382                                   true));
1383   std::string error_msg;
1384   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1385                                                    odex_location,
1386                                                    odex_location,
1387                                                    /*executable=*/false,
1388                                                    /*low_4gb=*/false,
1389                                                    dex_location,
1390                                                    &error_msg));
1391   ASSERT_TRUE(odex_file != nullptr);
1392   ASSERT_STREQ("install", odex_file->GetCompilationReason());
1393 }
1394 
TEST_F(Dex2oatTest,VerifyNoCompilationReason)1395 TEST_F(Dex2oatTest, VerifyNoCompilationReason) {
1396   std::string dex_location = GetScratchDir() + "/Dex2OatNoCompilationReason.jar";
1397   std::string odex_location = GetOdexDir() + "/Dex2OatNoCompilationReason.odex";
1398 
1399   // Test file doesn't matter.
1400   Copy(GetDexSrc1(), dex_location);
1401 
1402   ASSERT_TRUE(GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerify, {}, true));
1403   std::string error_msg;
1404   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1405                                                    odex_location,
1406                                                    odex_location,
1407                                                    /*executable=*/false,
1408                                                    /*low_4gb=*/false,
1409                                                    dex_location,
1410                                                    &error_msg));
1411   ASSERT_TRUE(odex_file != nullptr);
1412   ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
1413 }
1414 
TEST_F(Dex2oatTest,DontExtract)1415 TEST_F(Dex2oatTest, DontExtract) {
1416   std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
1417   std::string error_msg;
1418   const std::string out_dir = GetScratchDir();
1419   const std::string dex_location = dex->GetLocation();
1420   const std::string odex_location = out_dir + "/base.oat";
1421   const std::string vdex_location = out_dir + "/base.vdex";
1422   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1423                                   odex_location,
1424                                   CompilerFilter::Filter::kVerify,
1425                                   {"--copy-dex-files=false"},
1426                                   /*expect_success=*/true,
1427                                   /*use_fd=*/false,
1428                                   /*use_zip_fd=*/false,
1429                                   [](const OatFile&) {}));
1430   {
1431     // Check the vdex doesn't have dex.
1432     std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location,
1433                                                   /*writable=*/false,
1434                                                   /*low_4gb=*/false,
1435                                                   &error_msg));
1436     ASSERT_TRUE(vdex != nullptr);
1437     EXPECT_FALSE(vdex->HasDexSection()) << output_;
1438   }
1439   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1440                                                    odex_location,
1441                                                    odex_location,
1442                                                    /*executable=*/false,
1443                                                    /*low_4gb=*/false,
1444                                                    dex_location,
1445                                                    &error_msg));
1446   ASSERT_TRUE(odex_file != nullptr) << dex_location;
1447   std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
1448   ASSERT_EQ(oat_dex_files.size(), 1u);
1449   // Verify that the oat file can still open the dex files.
1450   for (const OatDexFile* oat_dex : oat_dex_files) {
1451     std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
1452     ASSERT_TRUE(dex_file != nullptr) << error_msg;
1453   }
1454   // Create a dm file and use it to verify.
1455   // Add produced artifacts to a zip file that doesn't contain the classes.dex.
1456   ScratchFile dm_file;
1457   {
1458     std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
1459     ASSERT_TRUE(vdex_file != nullptr);
1460     ASSERT_GT(vdex_file->GetLength(), 0u);
1461     FILE* file = fdopen(DupCloexec(dm_file.GetFd()), "w+b");
1462     ZipWriter writer(file);
1463     auto write_all_bytes = [&](File* file) {
1464       std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
1465       ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
1466       ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
1467     };
1468     // Add vdex to zip.
1469     writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
1470     write_all_bytes(vdex_file.get());
1471     writer.FinishEntry();
1472     writer.Finish();
1473     ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
1474   }
1475 
1476   auto generate_and_check = [&](CompilerFilter::Filter filter) {
1477     output_.clear();
1478     ASSERT_TRUE(GenerateOdexForTest(dex_location,
1479                                     odex_location,
1480                                     filter,
1481                                     {"--dump-timings",
1482                                      "--dm-file=" + dm_file.GetFilename(),
1483                                      // Pass -Xuse-stderr-logger have dex2oat output in output_ on
1484                                      // target.
1485                                      "--runtime-arg",
1486                                      "-Xuse-stderr-logger"},
1487                                     /*expect_success=*/true,
1488                                     /*use_fd=*/false,
1489                                     /*use_zip_fd=*/false,
1490                                     [](const OatFile& o) { CHECK(o.ContainsDexCode()); }));
1491     // Check the output for "Fast verify", this is printed from --dump-timings.
1492     std::istringstream iss(output_);
1493     std::string line;
1494     bool found_fast_verify = false;
1495     const std::string kFastVerifyString = "Fast Verify";
1496     while (std::getline(iss, line) && !found_fast_verify) {
1497       found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
1498     }
1499     EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
1500   };
1501 
1502   // Use verify compiler filter to check that FastVerify works for that filter too.
1503   generate_and_check(CompilerFilter::Filter::kVerify);
1504 }
1505 
1506 // Test that compact dex generation with invalid dex files doesn't crash dex2oat. b/75970654
TEST_F(Dex2oatTest,CompactDexInvalidSource)1507 TEST_F(Dex2oatTest, CompactDexInvalidSource) {
1508   ScratchFile invalid_dex;
1509   {
1510     FILE* file = fdopen(DupCloexec(invalid_dex.GetFd()), "w+b");
1511     ZipWriter writer(file);
1512     writer.StartEntry("classes.dex", ZipWriter::kAlign32);
1513     DexFile::Header header = {};
1514     StandardDexFile::WriteMagic(header.magic_.data());
1515     StandardDexFile::WriteCurrentVersion(header.magic_.data());
1516     header.file_size_ = 4 * KB;
1517     header.data_size_ = 4 * KB;
1518     header.data_off_ = 10 * MB;
1519     header.map_off_ = 10 * MB;
1520     header.class_defs_off_ = 10 * MB;
1521     header.class_defs_size_ = 10000;
1522     ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1523     writer.FinishEntry();
1524     writer.Finish();
1525     ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1526   }
1527   const std::string& dex_location = invalid_dex.GetFilename();
1528   const std::string odex_location = GetOdexDir() + "/output.odex";
1529   std::string error_msg;
1530   int status = GenerateOdexForTestWithStatus(
1531       {dex_location}, odex_location, CompilerFilter::kVerify, &error_msg, {});
1532   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1533 }
1534 
1535 // Retain the header magic for the now removed compact dex files.
1536 class LegacyCompactDexFile : public DexFile {
1537  public:
1538   static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
1539   static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
1540 
WriteMagic(uint8_t * magic)1541   static void WriteMagic(uint8_t* magic) {
1542     std::copy_n(kDexMagic, kDexMagicSize, magic);
1543   }
1544 
WriteCurrentVersion(uint8_t * magic)1545   static void WriteCurrentVersion(uint8_t* magic) {
1546     std::copy_n(kDexMagicVersion, kDexVersionLen, magic + kDexMagicSize);
1547   }
1548 };
1549 
1550 // Test that dex2oat with a legacy CompactDex file in the APK fails.
TEST_F(Dex2oatTest,CompactDexInZip)1551 TEST_F(Dex2oatTest, CompactDexInZip) {
1552   LegacyCompactDexFile::Header header = {};
1553   LegacyCompactDexFile::WriteMagic(header.magic_.data());
1554   LegacyCompactDexFile::WriteCurrentVersion(header.magic_.data());
1555   header.file_size_ = sizeof(LegacyCompactDexFile::Header);
1556   header.map_off_ = 10 * MB;
1557   header.class_defs_off_ = 10 * MB;
1558   header.class_defs_size_ = 10000;
1559   // Create a zip containing the invalid dex.
1560   ScratchFile invalid_dex_zip;
1561   {
1562     FILE* file = fdopen(DupCloexec(invalid_dex_zip.GetFd()), "w+b");
1563     ZipWriter writer(file);
1564     writer.StartEntry("classes.dex", ZipWriter::kCompress);
1565     ASSERT_GE(writer.WriteBytes(&header, sizeof(header)), 0);
1566     writer.FinishEntry();
1567     writer.Finish();
1568     ASSERT_EQ(invalid_dex_zip.GetFile()->Flush(), 0);
1569   }
1570   // Create the dex file directly.
1571   ScratchFile invalid_dex;
1572   {
1573     ASSERT_GE(invalid_dex.GetFile()->WriteFully(&header, sizeof(header)), 0);
1574     ASSERT_EQ(invalid_dex.GetFile()->Flush(), 0);
1575   }
1576   std::string error_msg;
1577   int status = 0u;
1578 
1579   status = GenerateOdexForTestWithStatus({invalid_dex_zip.GetFilename()},
1580                                          GetOdexDir() + "/output_apk.odex",
1581                                          CompilerFilter::kVerify,
1582                                          &error_msg,
1583                                          {});
1584   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1585 
1586   status = GenerateOdexForTestWithStatus({invalid_dex.GetFilename()},
1587                                          GetOdexDir() + "/output.odex",
1588                                          CompilerFilter::kVerify,
1589                                          &error_msg,
1590                                          {});
1591   ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
1592 }
1593 
TEST_F(Dex2oatWithExpectedFilterTest,AppImageNoProfile)1594 TEST_F(Dex2oatWithExpectedFilterTest, AppImageNoProfile) {
1595   // Set the expected filter.
1596   expected_filter_ = CompilerFilter::Filter::kVerify;
1597 
1598   ScratchFile app_image_file;
1599   const std::string out_dir = GetScratchDir();
1600   const std::string odex_location = out_dir + "/base.odex";
1601   ASSERT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
1602                                   odex_location,
1603                                   CompilerFilter::Filter::kSpeedProfile,
1604                                   {"--app-image-fd=" + std::to_string(app_image_file.GetFd())},
1605                                   /*expect_success=*/true,
1606                                   /*use_fd=*/false,
1607                                   /*use_zip_fd=*/false,
1608                                   [](const OatFile&) {}));
1609   // Open our generated oat file.
1610   std::string error_msg;
1611   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1612                                                    odex_location,
1613                                                    odex_location,
1614                                                    /*executable=*/false,
1615                                                    /*low_4gb=*/false,
1616                                                    &error_msg));
1617   ASSERT_TRUE(odex_file != nullptr);
1618   ImageHeader header = {};
1619   ASSERT_TRUE(app_image_file.GetFile()->PreadFully(reinterpret_cast<void*>(&header),
1620                                                    sizeof(header),
1621                                                    /*offset*/ 0u))
1622       << app_image_file.GetFile()->GetLength();
1623   EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
1624   EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
1625   EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
1626 }
1627 
TEST_F(Dex2oatTest,ZipFd)1628 TEST_F(Dex2oatTest, ZipFd) {
1629   std::string zip_location = GetTestDexFileName("MainUncompressedAligned");
1630   std::unique_ptr<File> dex_file(OS::OpenFileForReading(zip_location.c_str()));
1631   std::vector<std::string> extra_args{
1632       StringPrintf("--zip-fd=%d", dex_file->Fd()),
1633       "--zip-location=" + zip_location,
1634   };
1635   std::string out_dir = GetScratchDir();
1636   const std::string base_oat_name = out_dir + "/base.oat";
1637   ASSERT_TRUE(GenerateOdexForTest(zip_location,
1638                                   base_oat_name,
1639                                   CompilerFilter::Filter::kVerify,
1640                                   extra_args,
1641                                   /*expect_success=*/true,
1642                                   /*use_fd=*/false,
1643                                   /*use_zip_fd=*/true));
1644 }
1645 
TEST_F(Dex2oatWithExpectedFilterTest,AppImageEmptyDex)1646 TEST_F(Dex2oatWithExpectedFilterTest, AppImageEmptyDex) {
1647   // Set the expected filter.
1648   expected_filter_ = CompilerFilter::Filter::kVerify;
1649 
1650   // Create a profile with the startup method marked.
1651   ScratchFile profile_file;
1652   ScratchFile temp_dex;
1653   const std::string& dex_location = temp_dex.GetFilename();
1654   std::vector<uint16_t> methods;
1655   std::vector<dex::TypeIndex> classes;
1656   {
1657     MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("StringLiterals"), [&](DexFile* dex) {
1658       // Modify the header to make the dex file valid but empty.
1659       DexFile::Header* header = const_cast<DexFile::Header*>(&dex->GetHeader());
1660       header->string_ids_size_ = 0;
1661       header->string_ids_off_ = 0;
1662       header->type_ids_size_ = 0;
1663       header->type_ids_off_ = 0;
1664       header->proto_ids_size_ = 0;
1665       header->proto_ids_off_ = 0;
1666       header->field_ids_size_ = 0;
1667       header->field_ids_off_ = 0;
1668       header->method_ids_size_ = 0;
1669       header->method_ids_off_ = 0;
1670       header->class_defs_size_ = 0;
1671       header->class_defs_off_ = 0;
1672       ASSERT_GT(header->file_size_,
1673                 sizeof(*header) + sizeof(dex::MapList) + sizeof(dex::MapItem) * 2);
1674       // Move map list to be right after the header.
1675       header->map_off_ = header->header_size_;
1676       dex::MapList* map_list = const_cast<dex::MapList*>(dex->GetMapList());
1677       map_list->list_[0].type_ = DexFile::kDexTypeHeaderItem;
1678       map_list->list_[0].size_ = 1u;
1679       map_list->list_[0].offset_ = 0u;
1680       map_list->list_[1].type_ = DexFile::kDexTypeMapList;
1681       map_list->list_[1].size_ = 1u;
1682       map_list->list_[1].offset_ = header->map_off_;
1683       map_list->size_ = 2;
1684       header->data_off_ = header->map_off_;
1685       header->data_size_ = map_list->Size();
1686       header->SetDexContainer(0, header->file_size_);
1687     });
1688   }
1689   std::unique_ptr<const DexFile> dex_file(OpenDexFile(temp_dex.GetFilename().c_str()));
1690   const std::string out_dir = GetScratchDir();
1691   const std::string odex_location = out_dir + "/base.odex";
1692   const std::string app_image_location = out_dir + "/base.art";
1693   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1694                                   odex_location,
1695                                   CompilerFilter::Filter::kSpeedProfile,
1696                                   {"--app-image-file=" + app_image_location,
1697                                    "--resolve-startup-const-strings=true",
1698                                    "--profile-file=" + profile_file.GetFilename()},
1699                                   /*expect_success=*/true,
1700                                   /*use_fd=*/false,
1701                                   /*use_zip_fd=*/false,
1702                                   [](const OatFile&) {}));
1703   // Open our generated oat file.
1704   std::string error_msg;
1705   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1706                                                    odex_location,
1707                                                    odex_location,
1708                                                    /*executable=*/false,
1709                                                    /*low_4gb=*/false,
1710                                                    &error_msg));
1711   ASSERT_TRUE(odex_file != nullptr);
1712 }
1713 
TEST_F(Dex2oatTest,DexFileFd)1714 TEST_F(Dex2oatTest, DexFileFd) {
1715   std::string error_msg;
1716   std::string zip_location = GetTestDexFileName("Main");
1717   std::unique_ptr<File> zip_file(OS::OpenFileForReading(zip_location.c_str()));
1718   ASSERT_NE(-1, zip_file->Fd());
1719 
1720   std::unique_ptr<ZipArchive> zip_archive(
1721       ZipArchive::OpenFromFd(zip_file->Release(), zip_location.c_str(), &error_msg));
1722   ASSERT_TRUE(zip_archive != nullptr);
1723 
1724   std::string entry_name = DexFileLoader::GetMultiDexClassesDexName(0);
1725   std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg));
1726   ASSERT_TRUE(entry != nullptr);
1727 
1728   ScratchFile dex_file;
1729   const std::string& dex_location = dex_file.GetFilename();
1730   const std::string base_oat_name = GetScratchDir() + "/base.oat";
1731 
1732   bool success = entry->ExtractToFile(*(dex_file.GetFile()), &error_msg);
1733   ASSERT_TRUE(success);
1734   ASSERT_EQ(0, lseek(dex_file.GetFd(), 0, SEEK_SET));
1735 
1736   std::vector<std::string> extra_args{
1737       StringPrintf("--zip-fd=%d", dex_file.GetFd()),
1738       "--zip-location=" + dex_location,
1739   };
1740   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1741                                   base_oat_name,
1742                                   CompilerFilter::Filter::kVerify,
1743                                   extra_args,
1744                                   /*expect_success=*/true,
1745                                   /*use_fd=*/false,
1746                                   /*use_zip_fd=*/true));
1747 }
1748 
TEST_F(Dex2oatTest,DontCopyPlainDex)1749 TEST_F(Dex2oatTest, DontCopyPlainDex) {
1750   std::unique_ptr<const DexFile> dex(OpenTestDexFile("VerifierDepsMulti"));
1751   std::string error_msg;
1752   const std::string out_dir = GetScratchDir();
1753   const std::string dex_location = dex->GetLocation();
1754   const std::string odex_location = out_dir + "/base.oat";
1755   const std::string vdex_location = out_dir + "/base.vdex";
1756   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1757                                   odex_location,
1758                                   CompilerFilter::Filter::kVerify,
1759                                   {},
1760                                   /*expect_success=*/true,
1761                                   /*use_fd=*/false,
1762                                   /*use_zip_fd=*/false,
1763                                   [](const OatFile&) {}));
1764 
1765   // Check that the vdex doesn't have dex code.
1766   std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location,
1767                                                 /*writable=*/false,
1768                                                 /*low_4gb=*/false,
1769                                                 &error_msg));
1770   ASSERT_TRUE(vdex != nullptr);
1771   EXPECT_FALSE(vdex->HasDexSection()) << output_;
1772 }
1773 
TEST_F(Dex2oatTest,AppImageResolveStrings)1774 TEST_F(Dex2oatTest, AppImageResolveStrings) {
1775   using Hotness = ProfileCompilationInfo::MethodHotness;
1776   // Create a profile with the startup method marked.
1777   ScratchFile profile_file;
1778   ScratchFile temp_dex;
1779   const std::string& dex_location = temp_dex.GetFilename();
1780   std::vector<uint16_t> methods;
1781   std::vector<dex::TypeIndex> classes;
1782   {
1783     MutateDexFile(
1784         temp_dex.GetFile(), GetTestDexFileName("StringLiterals"), [&](DexFile* dex) {
1785           bool mutated_successfully = false;
1786           // Change the dex instructions to make an opcode that spans past the end of the code item.
1787           for (ClassAccessor accessor : dex->GetClasses()) {
1788             if (accessor.GetDescriptor() == std::string("LStringLiterals$StartupClass;")) {
1789               classes.push_back(accessor.GetClassIdx());
1790             }
1791             for (const ClassAccessor::Method& method : accessor.GetMethods()) {
1792               std::string method_name(dex->GetMethodName(dex->GetMethodId(method.GetIndex())));
1793               CodeItemInstructionAccessor instructions = method.GetInstructions();
1794               if (method_name == "startUpMethod2") {
1795                 // Make an instruction that runs past the end of the code item and verify that it
1796                 // doesn't cause dex2oat to crash.
1797                 ASSERT_TRUE(instructions.begin() != instructions.end());
1798                 DexInstructionIterator last_instruction = instructions.begin();
1799                 for (auto dex_it = instructions.begin(); dex_it != instructions.end(); ++dex_it) {
1800                   last_instruction = dex_it;
1801                 }
1802                 ASSERT_EQ(last_instruction->SizeInCodeUnits(), 1u);
1803                 // Set the opcode to something that will go past the end of the code item.
1804                 const_cast<Instruction&>(last_instruction.Inst())
1805                     .SetOpcode(Instruction::CONST_STRING_JUMBO);
1806                 mutated_successfully = true;
1807                 // Test that the safe iterator doesn't go past the end.
1808                 SafeDexInstructionIterator it2(instructions.begin(), instructions.end());
1809                 while (!it2.IsErrorState()) {
1810                   ++it2;
1811                 }
1812                 EXPECT_TRUE(it2 == last_instruction);
1813                 EXPECT_TRUE(it2 < instructions.end());
1814                 methods.push_back(method.GetIndex());
1815                 mutated_successfully = true;
1816               } else if (method_name == "startUpMethod") {
1817                 methods.push_back(method.GetIndex());
1818               }
1819             }
1820           }
1821           CHECK(mutated_successfully)
1822               << "Failed to find candidate code item with only one code unit in last instruction.";
1823         });
1824   }
1825   std::unique_ptr<const DexFile> dex_file(OpenDexFile(temp_dex.GetFilename().c_str()));
1826   {
1827     ASSERT_GT(classes.size(), 0u);
1828     ASSERT_GT(methods.size(), 0u);
1829     // Here, we build the profile from the method lists.
1830     ProfileCompilationInfo info;
1831     info.AddClassesForDex(dex_file.get(), classes.begin(), classes.end());
1832     info.AddMethodsForDex(Hotness::kFlagStartup, dex_file.get(), methods.begin(), methods.end());
1833     // Save the profile since we want to use it with dex2oat to produce an oat file.
1834     ASSERT_TRUE(info.Save(profile_file.GetFd()));
1835   }
1836   const std::string out_dir = GetScratchDir();
1837   const std::string odex_location = out_dir + "/base.odex";
1838   const std::string app_image_location = out_dir + "/base.art";
1839   ASSERT_TRUE(GenerateOdexForTest(dex_location,
1840                                   odex_location,
1841                                   CompilerFilter::Filter::kSpeedProfile,
1842                                   {"--app-image-file=" + app_image_location,
1843                                    "--resolve-startup-const-strings=true",
1844                                    "--profile-file=" + profile_file.GetFilename()},
1845                                   /*expect_success=*/true,
1846                                   /*use_fd=*/false,
1847                                   /*use_zip_fd=*/false,
1848                                   [](const OatFile&) {}));
1849   // Open our generated oat file.
1850   std::string error_msg;
1851   std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
1852                                                    odex_location,
1853                                                    odex_location,
1854                                                    /*executable=*/false,
1855                                                    /*low_4gb=*/false,
1856                                                    &error_msg));
1857   ASSERT_TRUE(odex_file != nullptr);
1858   // Check the strings in the app image intern table only contain the "startup" strigs.
1859   {
1860     ScopedObjectAccess soa(Thread::Current());
1861     std::unique_ptr<gc::space::ImageSpace> space = gc::space::ImageSpace::CreateFromAppImage(
1862         app_image_location.c_str(), odex_file.get(), &error_msg);
1863     ASSERT_TRUE(space != nullptr) << error_msg;
1864     std::set<std::string> seen;
1865     InternTable intern_table;
1866     intern_table.AddImageStringsToTable(
1867         space.get(), [&](InternTable::UnorderedSet& interns) REQUIRES_SHARED(Locks::mutator_lock_) {
1868           for (const GcRoot<mirror::String>& str : interns) {
1869             seen.insert(str.Read()->ToModifiedUtf8());
1870           }
1871         });
1872     // Normal methods
1873     EXPECT_TRUE(seen.find("Loading ") != seen.end());
1874     EXPECT_TRUE(seen.find("Starting up") != seen.end());
1875     EXPECT_TRUE(seen.find("abcd.apk") != seen.end());
1876     EXPECT_TRUE(seen.find("Unexpected error") == seen.end());
1877     EXPECT_TRUE(seen.find("Shutting down!") == seen.end());
1878     // Classes initializers
1879     EXPECT_TRUE(seen.find("Startup init") != seen.end());
1880     EXPECT_TRUE(seen.find("Other class init") == seen.end());
1881     // Expect the sets match.
1882     EXPECT_GE(seen.size(), seen.size());
1883 
1884     // Verify what strings are marked as boot image.
1885     std::set<std::string> boot_image_strings;
1886     std::set<std::string> app_image_strings;
1887 
1888     MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
1889     intern_table.VisitInterns(
1890         [&](const GcRoot<mirror::String>& root) REQUIRES_SHARED(Locks::mutator_lock_) {
1891           boot_image_strings.insert(root.Read()->ToModifiedUtf8());
1892         },
1893         /*visit_boot_images=*/true,
1894         /*visit_non_boot_images=*/false);
1895     intern_table.VisitInterns(
1896         [&](const GcRoot<mirror::String>& root) REQUIRES_SHARED(Locks::mutator_lock_) {
1897           app_image_strings.insert(root.Read()->ToModifiedUtf8());
1898         },
1899         /*visit_boot_images=*/false,
1900         /*visit_non_boot_images=*/true);
1901     EXPECT_EQ(boot_image_strings.size(), 0u);
1902     EXPECT_TRUE(app_image_strings == seen);
1903   }
1904 }
1905 
TEST_F(Dex2oatClassLoaderContextTest,StoredClassLoaderContext)1906 TEST_F(Dex2oatClassLoaderContextTest, StoredClassLoaderContext) {
1907   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("MultiDex");
1908   const std::string out_dir = GetScratchDir();
1909   const std::string odex_location = out_dir + "/base.odex";
1910   const std::string valid_context = "PCL[" + dex_files[0]->GetLocation() + "]";
1911   const std::string stored_context = "PCL[/system/not_real_lib.jar]";
1912   uint32_t checksum = DexFileLoader::GetMultiDexChecksum(dex_files);
1913   std::string expected_stored_context =
1914       "PCL[/system/not_real_lib.jar*" + std::to_string(checksum) + "]";
1915   // The class path should not be valid and should fail being stored.
1916   EXPECT_TRUE(GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
1917                                   odex_location,
1918                                   CompilerFilter::Filter::kVerify,
1919                                   {"--class-loader-context=" + stored_context},
1920                                   /*expect_success=*/true,
1921                                   /*use_fd=*/false,
1922                                   /*use_zip_fd=*/false,
1923                                   [&](const OatFile& oat_file) {
1924                                     EXPECT_NE(oat_file.GetClassLoaderContext(), stored_context)
1925                                         << output_;
1926                                     EXPECT_NE(oat_file.GetClassLoaderContext(), valid_context)
1927                                         << output_;
1928                                   }));
1929   // The stored context should match what we expect even though it's invalid.
1930   EXPECT_TRUE(GenerateOdexForTest(
1931       GetTestDexFileName("ManyMethods"),
1932       odex_location,
1933       CompilerFilter::Filter::kVerify,
1934       {"--class-loader-context=" + valid_context,
1935        "--stored-class-loader-context=" + stored_context},
1936       /*expect_success=*/true,
1937       /*use_fd=*/false,
1938       /*use_zip_fd=*/false,
1939       [&](const OatFile& oat_file) {
1940         EXPECT_EQ(oat_file.GetClassLoaderContext(), expected_stored_context) << output_;
1941       }));
1942 }
1943 
1944 class Dex2oatISAFeaturesRuntimeDetectionTest : public Dex2oatTest {
1945  protected:
RunTest(const std::vector<std::string> & extra_args={})1946   void RunTest(const std::vector<std::string>& extra_args = {}) {
1947     std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
1948     std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
1949 
1950     Copy(GetTestDexFileName(), dex_location);
1951 
1952     ASSERT_TRUE(
1953         GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, extra_args));
1954   }
1955 
GetTestDexFileName()1956   std::string GetTestDexFileName() { return GetDexSrc1(); }
1957 };
1958 
TEST_F(Dex2oatISAFeaturesRuntimeDetectionTest,TestCurrentRuntimeFeaturesAsDex2OatArguments)1959 TEST_F(Dex2oatISAFeaturesRuntimeDetectionTest, TestCurrentRuntimeFeaturesAsDex2OatArguments) {
1960   std::vector<std::string> argv;
1961   Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
1962   auto option_pos =
1963       std::find(std::begin(argv), std::end(argv), "--instruction-set-features=runtime");
1964   if (InstructionSetFeatures::IsRuntimeDetectionSupported()) {
1965     EXPECT_TRUE(kIsTargetBuild);
1966     EXPECT_NE(option_pos, std::end(argv));
1967   } else {
1968     EXPECT_EQ(option_pos, std::end(argv));
1969   }
1970 
1971   RunTest();
1972 }
1973 
1974 class LinkageTest : public Dex2oatTest {};
1975 
TEST_F(LinkageTest,LinkageEnabled)1976 TEST_F(LinkageTest, LinkageEnabled) {
1977   TEST_DISABLED_FOR_TARGET();
1978   std::unique_ptr<const DexFile> dex(OpenTestDexFile("LinkageTest"));
1979   std::string out_dir = GetScratchDir();
1980   const std::string base_oat_name = out_dir + "/base.oat";
1981   std::string error_msg;
1982   const int res_fail =
1983       GenerateOdexForTestWithStatus({dex->GetLocation()},
1984                                     base_oat_name,
1985                                     CompilerFilter::Filter::kSpeed,
1986                                     &error_msg,
1987                                     {"--check-linkage-conditions", "--crash-on-linkage-violation"});
1988   EXPECT_NE(0, res_fail);
1989 
1990   const int res_no_fail = GenerateOdexForTestWithStatus({dex->GetLocation()},
1991                                                         base_oat_name,
1992                                                         CompilerFilter::Filter::kSpeed,
1993                                                         &error_msg,
1994                                                         {"--check-linkage-conditions"});
1995   EXPECT_EQ(0, res_no_fail);
1996 }
1997 
1998 // Regression test for bug 179221298.
TEST_F(Dex2oatTest,LoadOutOfDateOatFile)1999 TEST_F(Dex2oatTest, LoadOutOfDateOatFile) {
2000   std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
2001   std::string out_dir = GetScratchDir();
2002   const std::string base_oat_name = out_dir + "/base.oat";
2003   ASSERT_TRUE(GenerateOdexForTest(dex->GetLocation(),
2004                                   base_oat_name,
2005                                   CompilerFilter::Filter::kSpeed,
2006                                   {"--deduplicate-code=false"},
2007                                   /*expect_success=*/true,
2008                                   /*use_fd=*/false,
2009                                   /*use_zip_fd=*/false));
2010 
2011   // Check that we can open the oat file as executable.
2012   {
2013     std::string error_msg;
2014     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
2015                                                      base_oat_name,
2016                                                      base_oat_name,
2017                                                      /*executable=*/true,
2018                                                      /*low_4gb=*/false,
2019                                                      dex->GetLocation(),
2020                                                      &error_msg));
2021     ASSERT_TRUE(odex_file != nullptr) << error_msg;
2022   }
2023 
2024   // Rewrite the oat file with wrong version and bogus contents.
2025   {
2026     std::unique_ptr<File> file(OS::OpenFileReadWrite(base_oat_name.c_str()));
2027     ASSERT_TRUE(file != nullptr);
2028     // Retrieve the offset and size of the embedded oat file.
2029     size_t oatdata_offset;
2030     size_t oatdata_size;
2031     {
2032       std::string error_msg;
2033       std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(),
2034                                                       /*writable=*/false,
2035                                                       /*program_header_only=*/true,
2036                                                       /*low_4gb=*/false,
2037                                                       &error_msg));
2038       ASSERT_TRUE(elf_file != nullptr) << error_msg;
2039       ASSERT_TRUE(elf_file->Load(file.get(),
2040                                  /*executable=*/false,
2041                                  /*low_4gb=*/false,
2042                                  /*reservation=*/nullptr,
2043                                  &error_msg))
2044           << error_msg;
2045       const uint8_t* base_address = elf_file->Is64Bit() ? elf_file->GetImpl64()->GetBaseAddress() :
2046                                                           elf_file->GetImpl32()->GetBaseAddress();
2047       const uint8_t* oatdata = elf_file->FindDynamicSymbolAddress("oatdata");
2048       ASSERT_TRUE(oatdata != nullptr);
2049       ASSERT_TRUE(oatdata > base_address);
2050       // Note: We're assuming here that the virtual address offset is the same
2051       // as file offset. This is currently true for all oat files we generate.
2052       oatdata_offset = static_cast<size_t>(oatdata - base_address);
2053       const uint8_t* oatlastword = elf_file->FindDynamicSymbolAddress("oatlastword");
2054       ASSERT_TRUE(oatlastword != nullptr);
2055       ASSERT_TRUE(oatlastword > oatdata);
2056       oatdata_size = oatlastword - oatdata;
2057     }
2058 
2059     // Check that we have the right `oatdata_offset`.
2060     int64_t length = file->GetLength();
2061     ASSERT_GE(length, static_cast<ssize_t>(oatdata_offset + sizeof(OatHeader)));
2062     alignas(OatHeader) uint8_t header_data[sizeof(OatHeader)];
2063     ASSERT_TRUE(file->PreadFully(header_data, sizeof(header_data), oatdata_offset));
2064     const OatHeader& header = reinterpret_cast<const OatHeader&>(header_data);
2065     ASSERT_TRUE(header.IsValid()) << header.GetValidationErrorMessage();
2066 
2067     // Overwrite all oat data from version onwards with bytes with value 4.
2068     // (0x04040404 is not a valid version, we're using three decimal digits and '\0'.)
2069     //
2070     // We previously tried to find the value for key "debuggable" (bug 179221298)
2071     // in the key-value store before checking the oat header. This test tries to
2072     // ensure that such early processing of the key-value store shall crash.
2073     // Reading 0x04040404 as the size of the key-value store yields a bit over
2074     // 64MiB which should hopefully include some unmapped memory beyond the end
2075     // of the loaded oat file. Overwriting the whole embedded oat file ensures
2076     // that we do not match the key within the oat file but we could still
2077     // accidentally match it in the additional sections of the elf file, so this
2078     // approach could fail to catch similar issues. At the time of writing, this
2079     // test crashed when run without the fix on 64-bit host (but not 32-bit).
2080     static constexpr size_t kVersionOffset = sizeof(OatHeader::kOatMagic);
2081     static_assert(kVersionOffset < sizeof(OatHeader));
2082     std::vector<uint8_t> data(oatdata_size - kVersionOffset, 4u);
2083     ASSERT_TRUE(file->PwriteFully(data.data(), data.size(), oatdata_offset + kVersionOffset));
2084     UNUSED(oatdata_size);
2085     CHECK_EQ(file->FlushClose(), 0) << "Could not flush and close oat file";
2086   }
2087 
2088   // Check that we reject the oat file without crashing.
2089   {
2090     std::string error_msg;
2091     std::unique_ptr<OatFile> odex_file(OatFile::Open(/*zip_fd=*/-1,
2092                                                      base_oat_name,
2093                                                      base_oat_name,
2094                                                      /*executable=*/true,
2095                                                      /*low_4gb=*/false,
2096                                                      dex->GetLocation(),
2097                                                      &error_msg));
2098     ASSERT_FALSE(odex_file != nullptr);
2099   }
2100 }
2101 
2102 }  // namespace art
2103