Home | History | Annotate | Download | only in runtime
      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 "dex_file.h"
     18 
     19 #include <memory>
     20 
     21 #include "base/stl_util.h"
     22 #include "base/unix_file/fd_file.h"
     23 #include "common_runtime_test.h"
     24 #include "os.h"
     25 #include "scoped_thread_state_change.h"
     26 #include "thread-inl.h"
     27 
     28 namespace art {
     29 
     30 class DexFileTest : public CommonRuntimeTest {};
     31 
     32 TEST_F(DexFileTest, Open) {
     33   ScopedObjectAccess soa(Thread::Current());
     34   const DexFile* dex(OpenTestDexFile("Nested"));
     35   ASSERT_TRUE(dex != NULL);
     36 }
     37 
     38 static const byte kBase64Map[256] = {
     39   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     40   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     41   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     42   255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
     43   52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
     44   255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
     45     7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT
     46    19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT
     47   255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
     48    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT
     49    49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT
     50   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     51   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     52   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     53   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     54   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     55   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     56   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     57   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     58   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     59   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
     60   255, 255, 255, 255
     61 };
     62 
     63 static inline byte* DecodeBase64(const char* src, size_t* dst_size) {
     64   std::vector<byte> tmp;
     65   uint32_t t = 0, y = 0;
     66   int g = 3;
     67   for (size_t i = 0; src[i] != '\0'; ++i) {
     68     byte c = kBase64Map[src[i] & 0xFF];
     69     if (c == 255) continue;
     70     // the final = symbols are read and used to trim the remaining bytes
     71     if (c == 254) {
     72       c = 0;
     73       // prevent g < 0 which would potentially allow an overflow later
     74       if (--g < 0) {
     75         *dst_size = 0;
     76         return nullptr;
     77       }
     78     } else if (g != 3) {
     79       // we only allow = to be at the end
     80       *dst_size = 0;
     81       return nullptr;
     82     }
     83     t = (t << 6) | c;
     84     if (++y == 4) {
     85       tmp.push_back((t >> 16) & 255);
     86       if (g > 1) {
     87         tmp.push_back((t >> 8) & 255);
     88       }
     89       if (g > 2) {
     90         tmp.push_back(t & 255);
     91       }
     92       y = t = 0;
     93     }
     94   }
     95   if (y != 0) {
     96     *dst_size = 0;
     97     return nullptr;
     98   }
     99   std::unique_ptr<byte[]> dst(new byte[tmp.size()]);
    100   if (dst_size != nullptr) {
    101     *dst_size = tmp.size();
    102   } else {
    103     *dst_size = 0;
    104   }
    105   std::copy(tmp.begin(), tmp.end(), dst.get());
    106   return dst.release();
    107 }
    108 
    109 // Although this is the same content logically as the Nested test dex,
    110 // the DexFileHeader test is sensitive to subtle changes in the
    111 // contents due to the checksum etc, so we embed the exact input here.
    112 //
    113 // class Nested {
    114 //     class Inner {
    115 //     }
    116 // }
    117 static const char kRawDex[] =
    118   "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
    119   "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
    120   "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
    121   "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
    122   "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
    123   "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
    124   "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
    125   "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
    126   "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
    127   "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
    128   "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
    129   "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
    130   "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
    131   "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
    132   "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
    133   "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
    134 
    135 static const DexFile* OpenDexFileBase64(const char* base64,
    136                                         const char* location) {
    137   // decode base64
    138   CHECK(base64 != NULL);
    139   size_t length;
    140   std::unique_ptr<byte[]> dex_bytes(DecodeBase64(base64, &length));
    141   CHECK(dex_bytes.get() != NULL);
    142 
    143   // write to provided file
    144   std::unique_ptr<File> file(OS::CreateEmptyFile(location));
    145   CHECK(file.get() != NULL);
    146   if (!file->WriteFully(dex_bytes.get(), length)) {
    147     PLOG(FATAL) << "Failed to write base64 as dex file";
    148   }
    149   if (file->FlushCloseOrErase() != 0) {
    150     PLOG(FATAL) << "Could not flush and close test file.";
    151   }
    152   file.reset();
    153 
    154   // read dex file
    155   ScopedObjectAccess soa(Thread::Current());
    156   std::string error_msg;
    157   std::vector<const DexFile*> tmp;
    158   bool success = DexFile::Open(location, location, &error_msg, &tmp);
    159   CHECK(success) << error_msg;
    160   EXPECT_EQ(1U, tmp.size());
    161   const DexFile* dex_file = tmp[0];
    162   EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
    163   EXPECT_TRUE(dex_file->IsReadOnly());
    164   return dex_file;
    165 }
    166 
    167 TEST_F(DexFileTest, Header) {
    168   ScratchFile tmp;
    169   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
    170   ASSERT_TRUE(raw.get() != NULL);
    171 
    172   const DexFile::Header& header = raw->GetHeader();
    173   // TODO: header.magic_
    174   EXPECT_EQ(0x00d87910U, header.checksum_);
    175   // TODO: header.signature_
    176   EXPECT_EQ(904U, header.file_size_);
    177   EXPECT_EQ(112U, header.header_size_);
    178   EXPECT_EQ(0U, header.link_size_);
    179   EXPECT_EQ(0U, header.link_off_);
    180   EXPECT_EQ(15U, header.string_ids_size_);
    181   EXPECT_EQ(112U, header.string_ids_off_);
    182   EXPECT_EQ(7U, header.type_ids_size_);
    183   EXPECT_EQ(172U, header.type_ids_off_);
    184   EXPECT_EQ(2U, header.proto_ids_size_);
    185   EXPECT_EQ(200U, header.proto_ids_off_);
    186   EXPECT_EQ(1U, header.field_ids_size_);
    187   EXPECT_EQ(224U, header.field_ids_off_);
    188   EXPECT_EQ(3U, header.method_ids_size_);
    189   EXPECT_EQ(232U, header.method_ids_off_);
    190   EXPECT_EQ(2U, header.class_defs_size_);
    191   EXPECT_EQ(256U, header.class_defs_off_);
    192   EXPECT_EQ(584U, header.data_size_);
    193   EXPECT_EQ(320U, header.data_off_);
    194 
    195   EXPECT_EQ(header.checksum_, raw->GetLocationChecksum());
    196 }
    197 
    198 TEST_F(DexFileTest, GetLocationChecksum) {
    199   ScopedObjectAccess soa(Thread::Current());
    200   const DexFile* raw(OpenTestDexFile("Main"));
    201   EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
    202 }
    203 
    204 TEST_F(DexFileTest, GetChecksum) {
    205   uint32_t checksum;
    206   ScopedObjectAccess soa(Thread::Current());
    207   std::string error_msg;
    208   EXPECT_TRUE(DexFile::GetChecksum(GetLibCoreDexFileName().c_str(), &checksum, &error_msg))
    209       << error_msg;
    210   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksum);
    211 }
    212 
    213 TEST_F(DexFileTest, ClassDefs) {
    214   ScopedObjectAccess soa(Thread::Current());
    215   const DexFile* raw(OpenTestDexFile("Nested"));
    216   ASSERT_TRUE(raw != NULL);
    217   EXPECT_EQ(2U, raw->NumClassDefs());
    218 
    219   const DexFile::ClassDef& c0 = raw->GetClassDef(0);
    220   EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
    221 
    222   const DexFile::ClassDef& c1 = raw->GetClassDef(1);
    223   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
    224 }
    225 
    226 TEST_F(DexFileTest, GetMethodSignature) {
    227   ScopedObjectAccess soa(Thread::Current());
    228   const DexFile* raw(OpenTestDexFile("GetMethodSignature"));
    229   ASSERT_TRUE(raw != NULL);
    230   EXPECT_EQ(1U, raw->NumClassDefs());
    231 
    232   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
    233   ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
    234 
    235   const byte* class_data = raw->GetClassData(class_def);
    236   ASSERT_TRUE(class_data != NULL);
    237   ClassDataItemIterator it(*raw, class_data);
    238 
    239   EXPECT_EQ(1u, it.NumDirectMethods());
    240 
    241   // Check the signature for the static initializer.
    242   {
    243     ASSERT_EQ(1U, it.NumDirectMethods());
    244     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    245     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    246     ASSERT_STREQ("<init>", name);
    247     std::string signature(raw->GetMethodSignature(method_id).ToString());
    248     ASSERT_EQ("()V", signature);
    249   }
    250 
    251   // Check both virtual methods.
    252   ASSERT_EQ(2U, it.NumVirtualMethods());
    253   {
    254     it.Next();
    255     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    256 
    257     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    258     ASSERT_STREQ("m1", name);
    259 
    260     std::string signature(raw->GetMethodSignature(method_id).ToString());
    261     ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
    262   }
    263 
    264   {
    265     it.Next();
    266     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    267 
    268     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    269     ASSERT_STREQ("m2", name);
    270 
    271     std::string signature(raw->GetMethodSignature(method_id).ToString());
    272     ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
    273   }
    274 }
    275 
    276 TEST_F(DexFileTest, FindStringId) {
    277   ScopedObjectAccess soa(Thread::Current());
    278   const DexFile* raw(OpenTestDexFile("GetMethodSignature"));
    279   ASSERT_TRUE(raw != NULL);
    280   EXPECT_EQ(1U, raw->NumClassDefs());
    281 
    282   const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
    283       "D", "I", "J", NULL };
    284   for (size_t i = 0; strings[i] != NULL; i++) {
    285     const char* str = strings[i];
    286     const DexFile::StringId* str_id = raw->FindStringId(str);
    287     const char* dex_str = raw->GetStringData(*str_id);
    288     EXPECT_STREQ(dex_str, str);
    289   }
    290 }
    291 
    292 TEST_F(DexFileTest, FindTypeId) {
    293   for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
    294     const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
    295     const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
    296     ASSERT_TRUE(type_str_id != NULL);
    297     uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
    298     const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
    299     ASSERT_TRUE(type_id != NULL);
    300     EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
    301   }
    302 }
    303 
    304 TEST_F(DexFileTest, FindProtoId) {
    305   for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
    306     const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
    307     const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
    308     std::vector<uint16_t> to_find_types;
    309     if (to_find_tl != NULL) {
    310       for (size_t j = 0; j < to_find_tl->Size(); j++) {
    311         to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
    312       }
    313     }
    314     const DexFile::ProtoId* found =
    315         java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
    316     ASSERT_TRUE(found != NULL);
    317     EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
    318   }
    319 }
    320 
    321 TEST_F(DexFileTest, FindMethodId) {
    322   for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
    323     const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
    324     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    325     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    326     const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
    327     const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
    328     ASSERT_TRUE(found != NULL) << "Didn't find method " << i << ": "
    329         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    330         << java_lang_dex_file_->GetStringData(name)
    331         << java_lang_dex_file_->GetMethodSignature(to_find);
    332     EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
    333   }
    334 }
    335 
    336 TEST_F(DexFileTest, FindFieldId) {
    337   for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
    338     const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
    339     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    340     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    341     const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
    342     const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
    343     ASSERT_TRUE(found != NULL) << "Didn't find field " << i << ": "
    344         << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
    345         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    346         << java_lang_dex_file_->GetStringData(name);
    347     EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
    348   }
    349 }
    350 
    351 TEST_F(DexFileTest, GetMultiDexClassesDexName) {
    352   std::string dex_location_str = "/system/app/framework.jar";
    353   const char* dex_location = dex_location_str.c_str();
    354   ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexClassesDexName(0, dex_location));
    355   ASSERT_EQ("/system/app/framework.jar:classes2.dex", DexFile::GetMultiDexClassesDexName(1, dex_location));
    356   ASSERT_EQ("/system/app/framework.jar:classes101.dex", DexFile::GetMultiDexClassesDexName(100, dex_location));
    357 }
    358 
    359 TEST_F(DexFileTest, GetDexCanonicalLocation) {
    360   ScratchFile file;
    361   UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
    362   std::string dex_location(dex_location_real.get());
    363 
    364   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str()));
    365   std::string multidex_location = DexFile::GetMultiDexClassesDexName(1, dex_location.c_str());
    366   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location.c_str()));
    367 
    368   std::string dex_location_sym = dex_location + "symlink";
    369   ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
    370 
    371   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location_sym.c_str()));
    372 
    373   std::string multidex_location_sym = DexFile::GetMultiDexClassesDexName(1, dex_location_sym.c_str());
    374   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str()));
    375 
    376   ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
    377 }
    378 
    379 }  // namespace art
    380