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