• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 <string>
18 #include <vector>
19 
20 #include "common_runtime_test.h"
21 #include "dex2oat_environment_test.h"
22 
23 #include "vdex_file.h"
24 #include "verifier/verifier_deps.h"
25 #include "ziparchive/zip_writer.h"
26 
27 namespace art {
28 
29 using verifier::VerifierDeps;
30 
31 class Dex2oatVdexTest : public Dex2oatEnvironmentTest {
32  public:
TearDown()33   void TearDown() override {
34     Dex2oatEnvironmentTest::TearDown();
35 
36     output_ = "";
37     error_msg_ = "";
38     opened_vdex_files_.clear();
39   }
40 
41  protected:
RunDex2oat(const std::string & dex_location,const std::string & odex_location,bool copy_dex_files=false,const std::vector<std::string> & extra_args={})42   bool RunDex2oat(const std::string& dex_location,
43                   const std::string& odex_location,
44                   bool copy_dex_files = false,
45                   const std::vector<std::string>& extra_args = {}) {
46     std::vector<std::string> args;
47     args.push_back("--dex-file=" + dex_location);
48     args.push_back("--oat-file=" + odex_location);
49     args.push_back("--compiler-filter=" +
50         CompilerFilter::NameOfFilter(CompilerFilter::Filter::kVerify));
51     args.push_back("--runtime-arg");
52     args.push_back("-Xnorelocate");
53     if (!copy_dex_files) {
54       args.push_back("--copy-dex-files=false");
55     }
56     args.push_back("--runtime-arg");
57     args.push_back("-verbose:verifier,compiler");
58     // Use a single thread to facilitate debugging. We only compile tiny dex files.
59     args.push_back("-j1");
60 
61     args.insert(args.end(), extra_args.begin(), extra_args.end());
62 
63     return Dex2Oat(args, &output_, &error_msg_) == 0;
64   }
65 
CreateDexMetadata(const std::string & vdex,const std::string & out_dm)66   void CreateDexMetadata(const std::string& vdex, const std::string& out_dm) {
67     // Read the vdex bytes.
68     std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex.c_str()));
69     std::vector<uint8_t> data(vdex_file->GetLength());
70     ASSERT_TRUE(vdex_file->ReadFully(data.data(), data.size()));
71 
72     // Zip the content.
73     FILE* file = fopen(out_dm.c_str(), "wb");
74     ZipWriter writer(file);
75     writer.StartEntry("primary.vdex", ZipWriter::kAlign32);
76     writer.WriteBytes(data.data(), data.size());
77     writer.FinishEntry();
78     writer.Finish();
79     fflush(file);
80     fclose(file);
81   }
82 
GetFilename(const std::unique_ptr<const DexFile> & dex_file)83   std::string GetFilename(const std::unique_ptr<const DexFile>& dex_file) {
84     const std::string& str = dex_file->GetLocation();
85     size_t idx = str.rfind('/');
86     if (idx == std::string::npos) {
87       return str;
88     }
89     return str.substr(idx + 1);
90   }
91 
GetOdex(const std::unique_ptr<const DexFile> & dex_file,const std::string & suffix="")92   std::string GetOdex(const std::unique_ptr<const DexFile>& dex_file,
93                       const std::string& suffix = "") {
94     return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".odex";
95   }
96 
GetVdex(const std::unique_ptr<const DexFile> & dex_file,const std::string & suffix="")97   std::string GetVdex(const std::unique_ptr<const DexFile>& dex_file,
98                       const std::string& suffix = "") {
99     return GetScratchDir() + "/" + GetFilename(dex_file) + suffix + ".vdex";
100   }
101 
102   std::string output_;
103   std::string error_msg_;
104   std::vector<std::unique_ptr<VdexFile>> opened_vdex_files_;
105 };
106 
107 // Check that if the input dm does contain dex files then the compilation fails
TEST_F(Dex2oatVdexTest,VerifyPublicSdkStubsWithDexFiles)108 TEST_F(Dex2oatVdexTest, VerifyPublicSdkStubsWithDexFiles) {
109   std::string error_msg;
110 
111   // Dex2oatVdexTestDex is the subject app using normal APIs found in the boot classpath.
112   std::unique_ptr<const DexFile> dex_file(OpenTestDexFile("Dex2oatVdexTestDex"));
113 
114   // Compile the subject app using the predefined API-stubs
115   ASSERT_TRUE(RunDex2oat(
116       dex_file->GetLocation(),
117       GetOdex(dex_file),
118       /*copy_dex_files=*/ true));
119 
120   // Create the .dm file with the output.
121   std::string dm_file = GetScratchDir() + "/base.dm";
122   CreateDexMetadata(GetVdex(dex_file), dm_file);
123   std::vector<std::string> extra_args;
124   extra_args.push_back("--dm-file=" + dm_file);
125 
126   // Recompile again with the .dm file which contains a vdex with code.
127   // The compilation should fail.
128   ASSERT_FALSE(RunDex2oat(
129       dex_file->GetLocation(),
130       GetOdex(dex_file, "v2"),
131       /*copy_dex_files=*/ true,
132       extra_args));
133 }
134 
135 }  // namespace art
136