Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sys/mman.h>
     18 
     19 #include <fstream>
     20 #include <memory>
     21 
     22 #include "art_dex_file_loader.h"
     23 #include "base/file_utils.h"
     24 #include "base/os.h"
     25 #include "base/stl_util.h"
     26 #include "base/unix_file/fd_file.h"
     27 #include "common_runtime_test.h"
     28 #include "dex/base64_test_util.h"
     29 #include "dex/code_item_accessors-inl.h"
     30 #include "dex/descriptors_names.h"
     31 #include "dex/dex_file.h"
     32 #include "dex/dex_file-inl.h"
     33 #include "dex/dex_file_loader.h"
     34 #include "mem_map.h"
     35 #include "scoped_thread_state_change-inl.h"
     36 #include "thread-current-inl.h"
     37 
     38 namespace art {
     39 
     40 static void Copy(const std::string& src, const std::string& dst) {
     41   std::ifstream  src_stream(src, std::ios::binary);
     42   std::ofstream  dst_stream(dst, std::ios::binary);
     43   dst_stream << src_stream.rdbuf();
     44 }
     45 
     46 class ArtDexFileLoaderTest : public CommonRuntimeTest {};
     47 
     48 // TODO: Port OpenTestDexFile(s) need to be ported to use non-ART utilities, and
     49 // the tests that depend upon them should be moved to dex_file_loader_test.cc
     50 
     51 TEST_F(ArtDexFileLoaderTest, Open) {
     52   ScopedObjectAccess soa(Thread::Current());
     53   std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
     54   ASSERT_TRUE(dex.get() != nullptr);
     55 }
     56 
     57 TEST_F(ArtDexFileLoaderTest, GetLocationChecksum) {
     58   ScopedObjectAccess soa(Thread::Current());
     59   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
     60   EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
     61 }
     62 
     63 TEST_F(ArtDexFileLoaderTest, GetChecksum) {
     64   std::vector<uint32_t> checksums;
     65   ScopedObjectAccess soa(Thread::Current());
     66   std::string error_msg;
     67   const ArtDexFileLoader dex_file_loader;
     68   EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(GetLibCoreDexFileNames()[0].c_str(),
     69                                                     &checksums,
     70                                                     &error_msg))
     71       << error_msg;
     72   ASSERT_EQ(1U, checksums.size());
     73   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksums[0]);
     74 }
     75 
     76 TEST_F(ArtDexFileLoaderTest, GetMultiDexChecksums) {
     77   std::string error_msg;
     78   std::vector<uint32_t> checksums;
     79   std::string multidex_file = GetTestDexFileName("MultiDex");
     80   const ArtDexFileLoader dex_file_loader;
     81   EXPECT_TRUE(dex_file_loader.GetMultiDexChecksums(multidex_file.c_str(),
     82                                                     &checksums,
     83                                                     &error_msg)) << error_msg;
     84 
     85   std::vector<std::unique_ptr<const DexFile>> dexes = OpenTestDexFiles("MultiDex");
     86   ASSERT_EQ(2U, dexes.size());
     87   ASSERT_EQ(2U, checksums.size());
     88 
     89   EXPECT_EQ(dexes[0]->GetLocation(), DexFileLoader::GetMultiDexLocation(0, multidex_file.c_str()));
     90   EXPECT_EQ(dexes[0]->GetLocationChecksum(), checksums[0]);
     91 
     92   EXPECT_EQ(dexes[1]->GetLocation(), DexFileLoader::GetMultiDexLocation(1, multidex_file.c_str()));
     93   EXPECT_EQ(dexes[1]->GetLocationChecksum(), checksums[1]);
     94 }
     95 
     96 TEST_F(ArtDexFileLoaderTest, ClassDefs) {
     97   ScopedObjectAccess soa(Thread::Current());
     98   std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
     99   ASSERT_TRUE(raw.get() != nullptr);
    100   EXPECT_EQ(3U, raw->NumClassDefs());
    101 
    102   const DexFile::ClassDef& c0 = raw->GetClassDef(0);
    103   EXPECT_STREQ("LNested$1;", raw->GetClassDescriptor(c0));
    104 
    105   const DexFile::ClassDef& c1 = raw->GetClassDef(1);
    106   EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c1));
    107 
    108   const DexFile::ClassDef& c2 = raw->GetClassDef(2);
    109   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c2));
    110 }
    111 
    112 TEST_F(ArtDexFileLoaderTest, GetMethodSignature) {
    113   ScopedObjectAccess soa(Thread::Current());
    114   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
    115   ASSERT_TRUE(raw.get() != nullptr);
    116   EXPECT_EQ(1U, raw->NumClassDefs());
    117 
    118   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
    119   ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
    120 
    121   const uint8_t* class_data = raw->GetClassData(class_def);
    122   ASSERT_TRUE(class_data != nullptr);
    123   ClassDataItemIterator it(*raw, class_data);
    124 
    125   EXPECT_EQ(1u, it.NumDirectMethods());
    126 
    127   // Check the signature for the static initializer.
    128   {
    129     ASSERT_EQ(1U, it.NumDirectMethods());
    130     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    131     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    132     ASSERT_STREQ("<init>", name);
    133     std::string signature(raw->GetMethodSignature(method_id).ToString());
    134     ASSERT_EQ("()V", signature);
    135   }
    136 
    137   // Check all virtual methods.
    138   struct Result {
    139     const char* name;
    140     const char* signature;
    141     const char* pretty_method;
    142   };
    143   static const Result results[] = {
    144       {
    145           "m1",
    146           "(IDJLjava/lang/Object;)Ljava/lang/Float;",
    147           "java.lang.Float GetMethodSignature.m1(int, double, long, java.lang.Object)"
    148       },
    149       {
    150           "m2",
    151           "(ZSC)LGetMethodSignature;",
    152           "GetMethodSignature GetMethodSignature.m2(boolean, short, char)"
    153       },
    154       {
    155           "m3",
    156           "()V",
    157           "void GetMethodSignature.m3()"
    158       },
    159       {
    160           "m4",
    161           "(I)V",
    162           "void GetMethodSignature.m4(int)"
    163       },
    164       {
    165           "m5",
    166           "(II)V",
    167           "void GetMethodSignature.m5(int, int)"
    168       },
    169       {
    170           "m6",
    171           "(II[[I)V",
    172           "void GetMethodSignature.m6(int, int, int[][])"
    173       },
    174       {
    175           "m7",
    176           "(II[[ILjava/lang/Object;)V",
    177           "void GetMethodSignature.m7(int, int, int[][], java.lang.Object)"
    178       },
    179       {
    180           "m8",
    181           "(II[[ILjava/lang/Object;[[Ljava/lang/Object;)V",
    182           "void GetMethodSignature.m8(int, int, int[][], java.lang.Object, java.lang.Object[][])"
    183       },
    184       {
    185           "m9",
    186           "()I",
    187           "int GetMethodSignature.m9()"
    188       },
    189       {
    190           "mA",
    191           "()[[I",
    192           "int[][] GetMethodSignature.mA()"
    193       },
    194       {
    195           "mB",
    196           "()[[Ljava/lang/Object;",
    197           "java.lang.Object[][] GetMethodSignature.mB()"
    198       },
    199   };
    200   ASSERT_EQ(arraysize(results), it.NumVirtualMethods());
    201   for (const Result& r : results) {
    202     it.Next();
    203     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    204 
    205     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    206     ASSERT_STREQ(r.name, name);
    207 
    208     std::string signature(raw->GetMethodSignature(method_id).ToString());
    209     ASSERT_EQ(r.signature, signature);
    210 
    211     std::string plain_method = std::string("GetMethodSignature.") + r.name;
    212     ASSERT_EQ(plain_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ false));
    213     ASSERT_EQ(r.pretty_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ true));
    214   }
    215 }
    216 
    217 TEST_F(ArtDexFileLoaderTest, FindStringId) {
    218   ScopedObjectAccess soa(Thread::Current());
    219   std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
    220   ASSERT_TRUE(raw.get() != nullptr);
    221   EXPECT_EQ(1U, raw->NumClassDefs());
    222 
    223   const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
    224       "D", "I", "J", nullptr };
    225   for (size_t i = 0; strings[i] != nullptr; i++) {
    226     const char* str = strings[i];
    227     const DexFile::StringId* str_id = raw->FindStringId(str);
    228     const char* dex_str = raw->GetStringData(*str_id);
    229     EXPECT_STREQ(dex_str, str);
    230   }
    231 }
    232 
    233 TEST_F(ArtDexFileLoaderTest, FindTypeId) {
    234   for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
    235     const char* type_str = java_lang_dex_file_->StringByTypeIdx(dex::TypeIndex(i));
    236     const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
    237     ASSERT_TRUE(type_str_id != nullptr);
    238     dex::StringIndex type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
    239     const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
    240     ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
    241     ASSERT_TRUE(type_id != nullptr);
    242     EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id).index_, i);
    243   }
    244 }
    245 
    246 TEST_F(ArtDexFileLoaderTest, FindProtoId) {
    247   for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
    248     const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
    249     const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
    250     std::vector<dex::TypeIndex> to_find_types;
    251     if (to_find_tl != nullptr) {
    252       for (size_t j = 0; j < to_find_tl->Size(); j++) {
    253         to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
    254       }
    255     }
    256     const DexFile::ProtoId* found =
    257         java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
    258     ASSERT_TRUE(found != nullptr);
    259     EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
    260   }
    261 }
    262 
    263 TEST_F(ArtDexFileLoaderTest, FindMethodId) {
    264   for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
    265     const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
    266     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    267     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    268     const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
    269     const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
    270     ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
    271         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    272         << java_lang_dex_file_->GetStringData(name)
    273         << java_lang_dex_file_->GetMethodSignature(to_find);
    274     EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
    275   }
    276 }
    277 
    278 TEST_F(ArtDexFileLoaderTest, FindFieldId) {
    279   for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
    280     const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
    281     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    282     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    283     const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
    284     const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
    285     ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
    286         << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
    287         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    288         << java_lang_dex_file_->GetStringData(name);
    289     EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
    290   }
    291 }
    292 
    293 TEST_F(ArtDexFileLoaderTest, GetDexCanonicalLocation) {
    294   ScratchFile file;
    295   UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
    296   std::string dex_location(dex_location_real.get());
    297 
    298   ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location.c_str()));
    299   std::string multidex_location = DexFileLoader::GetMultiDexLocation(1, dex_location.c_str());
    300   ASSERT_EQ(multidex_location, DexFileLoader::GetDexCanonicalLocation(multidex_location.c_str()));
    301 
    302   std::string dex_location_sym = dex_location + "symlink";
    303   ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
    304 
    305   ASSERT_EQ(dex_location, DexFileLoader::GetDexCanonicalLocation(dex_location_sym.c_str()));
    306 
    307   std::string multidex_location_sym = DexFileLoader::GetMultiDexLocation(
    308       1, dex_location_sym.c_str());
    309   ASSERT_EQ(multidex_location,
    310             DexFileLoader::GetDexCanonicalLocation(multidex_location_sym.c_str()));
    311 
    312   ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
    313 }
    314 
    315 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir) {
    316   // Load file from a non-system directory and check that it is not flagged as framework.
    317   std::string data_location_path = android_data_ + "/foo.jar";
    318   ASSERT_FALSE(LocationIsOnSystemFramework(data_location_path.c_str()));
    319 
    320   Copy(GetTestDexFileName("Main"), data_location_path);
    321 
    322   ArtDexFileLoader loader;
    323   std::vector<std::unique_ptr<const DexFile>> dex_files;
    324   std::string error_msg;
    325   bool success = loader.Open(data_location_path.c_str(),
    326                              data_location_path,
    327                              /* verify */ false,
    328                              /* verify_checksum */ false,
    329                              &error_msg,
    330                              &dex_files);
    331   ASSERT_TRUE(success) << error_msg;
    332 
    333   ASSERT_GE(dex_files.size(), 1u);
    334   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    335     ASSERT_FALSE(dex_file->IsPlatformDexFile());
    336   }
    337 
    338   dex_files.clear();
    339 
    340   ASSERT_EQ(0, remove(data_location_path.c_str()));
    341 }
    342 
    343 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir) {
    344   // Load file from a system, non-framework directory and check that it is not flagged as framework.
    345   std::string system_location_path = GetAndroidRoot() + "/foo.jar";
    346   ASSERT_FALSE(LocationIsOnSystemFramework(system_location_path.c_str()));
    347 
    348   Copy(GetTestDexFileName("Main"), system_location_path);
    349 
    350   ArtDexFileLoader loader;
    351   std::vector<std::unique_ptr<const DexFile>> dex_files;
    352   std::string error_msg;
    353   bool success = loader.Open(system_location_path.c_str(),
    354                              system_location_path,
    355                              /* verify */ false,
    356                              /* verify_checksum */ false,
    357                              &error_msg,
    358                              &dex_files);
    359   ASSERT_TRUE(success) << error_msg;
    360 
    361   ASSERT_GE(dex_files.size(), 1u);
    362   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    363     ASSERT_FALSE(dex_file->IsPlatformDexFile());
    364   }
    365 
    366   dex_files.clear();
    367 
    368   ASSERT_EQ(0, remove(system_location_path.c_str()));
    369 }
    370 
    371 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir) {
    372   // Load file from a system/framework directory and check that it is flagged as a framework dex.
    373   std::string system_framework_location_path = GetAndroidRoot() + "/framework/foo.jar";
    374   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_location_path.c_str()));
    375 
    376   Copy(GetTestDexFileName("Main"), system_framework_location_path);
    377 
    378   ArtDexFileLoader loader;
    379   std::vector<std::unique_ptr<const DexFile>> dex_files;
    380   std::string error_msg;
    381   bool success = loader.Open(system_framework_location_path.c_str(),
    382                              system_framework_location_path,
    383                              /* verify */ false,
    384                              /* verify_checksum */ false,
    385                              &error_msg,
    386                              &dex_files);
    387   ASSERT_TRUE(success) << error_msg;
    388 
    389   ASSERT_GE(dex_files.size(), 1u);
    390   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    391     ASSERT_TRUE(dex_file->IsPlatformDexFile());
    392   }
    393 
    394   dex_files.clear();
    395 
    396   ASSERT_EQ(0, remove(system_framework_location_path.c_str()));
    397 }
    398 
    399 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_DataDir_MultiDex) {
    400   // Load multidex file from a non-system directory and check that it is not flagged as framework.
    401   std::string data_multi_location_path = android_data_ + "/multifoo.jar";
    402   ASSERT_FALSE(LocationIsOnSystemFramework(data_multi_location_path.c_str()));
    403 
    404   Copy(GetTestDexFileName("MultiDex"), data_multi_location_path);
    405 
    406   ArtDexFileLoader loader;
    407   std::vector<std::unique_ptr<const DexFile>> dex_files;
    408   std::string error_msg;
    409   bool success = loader.Open(data_multi_location_path.c_str(),
    410                              data_multi_location_path,
    411                              /* verify */ false,
    412                              /* verify_checksum */ false,
    413                              &error_msg,
    414                              &dex_files);
    415   ASSERT_TRUE(success) << error_msg;
    416 
    417   ASSERT_GT(dex_files.size(), 1u);
    418   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    419     ASSERT_FALSE(dex_file->IsPlatformDexFile());
    420   }
    421 
    422   dex_files.clear();
    423 
    424   ASSERT_EQ(0, remove(data_multi_location_path.c_str()));
    425 }
    426 
    427 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemDir_MultiDex) {
    428   // Load multidex file from a system, non-framework directory and check that it is not flagged
    429   // as framework.
    430   std::string system_multi_location_path = GetAndroidRoot() + "/multifoo.jar";
    431   ASSERT_FALSE(LocationIsOnSystemFramework(system_multi_location_path.c_str()));
    432 
    433   Copy(GetTestDexFileName("MultiDex"), system_multi_location_path);
    434 
    435   ArtDexFileLoader loader;
    436   std::vector<std::unique_ptr<const DexFile>> dex_files;
    437   std::string error_msg;
    438   bool success = loader.Open(system_multi_location_path.c_str(),
    439                              system_multi_location_path,
    440                              /* verify */ false,
    441                              /* verify_checksum */ false,
    442                              &error_msg,
    443                              &dex_files);
    444   ASSERT_TRUE(success) << error_msg;
    445 
    446   ASSERT_GT(dex_files.size(), 1u);
    447   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    448     ASSERT_FALSE(dex_file->IsPlatformDexFile());
    449   }
    450 
    451   dex_files.clear();
    452 
    453   ASSERT_EQ(0, remove(system_multi_location_path.c_str()));
    454 }
    455 
    456 TEST_F(ArtDexFileLoaderTest, IsPlatformDexFile_SystemFrameworkDir_MultiDex) {
    457   // Load multidex file from a system/framework directory and check that it is flagged as a
    458   // framework dex.
    459   std::string system_framework_multi_location_path = GetAndroidRoot() + "/framework/multifoo.jar";
    460   ASSERT_TRUE(LocationIsOnSystemFramework(system_framework_multi_location_path.c_str()));
    461 
    462   Copy(GetTestDexFileName("MultiDex"), system_framework_multi_location_path);
    463 
    464   ArtDexFileLoader loader;
    465   std::vector<std::unique_ptr<const DexFile>> dex_files;
    466   std::string error_msg;
    467   bool success = loader.Open(system_framework_multi_location_path.c_str(),
    468                              system_framework_multi_location_path,
    469                              /* verify */ false,
    470                              /* verify_checksum */ false,
    471                              &error_msg,
    472                              &dex_files);
    473   ASSERT_TRUE(success) << error_msg;
    474 
    475   ASSERT_GT(dex_files.size(), 1u);
    476   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
    477     ASSERT_TRUE(dex_file->IsPlatformDexFile());
    478   }
    479 
    480   dex_files.clear();
    481 
    482   ASSERT_EQ(0, remove(system_framework_multi_location_path.c_str()));
    483 }
    484 
    485 }  // namespace art
    486