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   file.reset();
    150 
    151   // read dex file
    152   ScopedObjectAccess soa(Thread::Current());
    153   std::string error_msg;
    154   std::vector<const DexFile*> tmp;
    155   bool success = DexFile::Open(location, location, &error_msg, &tmp);
    156   CHECK(success) << error_msg;
    157   EXPECT_EQ(1U, tmp.size());
    158   const DexFile* dex_file = tmp[0];
    159   EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
    160   EXPECT_TRUE(dex_file->IsReadOnly());
    161   return dex_file;
    162 }
    163 
    164 TEST_F(DexFileTest, Header) {
    165   ScratchFile tmp;
    166   std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
    167   ASSERT_TRUE(raw.get() != NULL);
    168 
    169   const DexFile::Header& header = raw->GetHeader();
    170   // TODO: header.magic_
    171   EXPECT_EQ(0x00d87910U, header.checksum_);
    172   // TODO: header.signature_
    173   EXPECT_EQ(904U, header.file_size_);
    174   EXPECT_EQ(112U, header.header_size_);
    175   EXPECT_EQ(0U, header.link_size_);
    176   EXPECT_EQ(0U, header.link_off_);
    177   EXPECT_EQ(15U, header.string_ids_size_);
    178   EXPECT_EQ(112U, header.string_ids_off_);
    179   EXPECT_EQ(7U, header.type_ids_size_);
    180   EXPECT_EQ(172U, header.type_ids_off_);
    181   EXPECT_EQ(2U, header.proto_ids_size_);
    182   EXPECT_EQ(200U, header.proto_ids_off_);
    183   EXPECT_EQ(1U, header.field_ids_size_);
    184   EXPECT_EQ(224U, header.field_ids_off_);
    185   EXPECT_EQ(3U, header.method_ids_size_);
    186   EXPECT_EQ(232U, header.method_ids_off_);
    187   EXPECT_EQ(2U, header.class_defs_size_);
    188   EXPECT_EQ(256U, header.class_defs_off_);
    189   EXPECT_EQ(584U, header.data_size_);
    190   EXPECT_EQ(320U, header.data_off_);
    191 
    192   EXPECT_EQ(header.checksum_, raw->GetLocationChecksum());
    193 }
    194 
    195 TEST_F(DexFileTest, GetLocationChecksum) {
    196   ScopedObjectAccess soa(Thread::Current());
    197   const DexFile* raw(OpenTestDexFile("Main"));
    198   EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
    199 }
    200 
    201 TEST_F(DexFileTest, GetChecksum) {
    202   uint32_t checksum;
    203   ScopedObjectAccess soa(Thread::Current());
    204   std::string error_msg;
    205   EXPECT_TRUE(DexFile::GetChecksum(GetLibCoreDexFileName().c_str(), &checksum, &error_msg))
    206       << error_msg;
    207   EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksum);
    208 }
    209 
    210 TEST_F(DexFileTest, ClassDefs) {
    211   ScopedObjectAccess soa(Thread::Current());
    212   const DexFile* raw(OpenTestDexFile("Nested"));
    213   ASSERT_TRUE(raw != NULL);
    214   EXPECT_EQ(2U, raw->NumClassDefs());
    215 
    216   const DexFile::ClassDef& c0 = raw->GetClassDef(0);
    217   EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
    218 
    219   const DexFile::ClassDef& c1 = raw->GetClassDef(1);
    220   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
    221 }
    222 
    223 TEST_F(DexFileTest, GetMethodSignature) {
    224   ScopedObjectAccess soa(Thread::Current());
    225   const DexFile* raw(OpenTestDexFile("GetMethodSignature"));
    226   ASSERT_TRUE(raw != NULL);
    227   EXPECT_EQ(1U, raw->NumClassDefs());
    228 
    229   const DexFile::ClassDef& class_def = raw->GetClassDef(0);
    230   ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
    231 
    232   const byte* class_data = raw->GetClassData(class_def);
    233   ASSERT_TRUE(class_data != NULL);
    234   ClassDataItemIterator it(*raw, class_data);
    235 
    236   EXPECT_EQ(1u, it.NumDirectMethods());
    237 
    238   // Check the signature for the static initializer.
    239   {
    240     ASSERT_EQ(1U, it.NumDirectMethods());
    241     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    242     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    243     ASSERT_STREQ("<init>", name);
    244     std::string signature(raw->GetMethodSignature(method_id).ToString());
    245     ASSERT_EQ("()V", signature);
    246   }
    247 
    248   // Check both virtual methods.
    249   ASSERT_EQ(2U, it.NumVirtualMethods());
    250   {
    251     it.Next();
    252     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    253 
    254     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    255     ASSERT_STREQ("m1", name);
    256 
    257     std::string signature(raw->GetMethodSignature(method_id).ToString());
    258     ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
    259   }
    260 
    261   {
    262     it.Next();
    263     const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
    264 
    265     const char* name = raw->StringDataByIdx(method_id.name_idx_);
    266     ASSERT_STREQ("m2", name);
    267 
    268     std::string signature(raw->GetMethodSignature(method_id).ToString());
    269     ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
    270   }
    271 }
    272 
    273 TEST_F(DexFileTest, FindStringId) {
    274   ScopedObjectAccess soa(Thread::Current());
    275   const DexFile* raw(OpenTestDexFile("GetMethodSignature"));
    276   ASSERT_TRUE(raw != NULL);
    277   EXPECT_EQ(1U, raw->NumClassDefs());
    278 
    279   const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
    280       "D", "I", "J", NULL };
    281   for (size_t i = 0; strings[i] != NULL; i++) {
    282     const char* str = strings[i];
    283     const DexFile::StringId* str_id = raw->FindStringId(str);
    284     const char* dex_str = raw->GetStringData(*str_id);
    285     EXPECT_STREQ(dex_str, str);
    286   }
    287 }
    288 
    289 TEST_F(DexFileTest, FindTypeId) {
    290   for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
    291     const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
    292     const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
    293     ASSERT_TRUE(type_str_id != NULL);
    294     uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
    295     const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
    296     ASSERT_TRUE(type_id != NULL);
    297     EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
    298   }
    299 }
    300 
    301 TEST_F(DexFileTest, FindProtoId) {
    302   for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
    303     const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
    304     const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
    305     std::vector<uint16_t> to_find_types;
    306     if (to_find_tl != NULL) {
    307       for (size_t j = 0; j < to_find_tl->Size(); j++) {
    308         to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
    309       }
    310     }
    311     const DexFile::ProtoId* found =
    312         java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
    313     ASSERT_TRUE(found != NULL);
    314     EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
    315   }
    316 }
    317 
    318 TEST_F(DexFileTest, FindMethodId) {
    319   for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
    320     const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
    321     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    322     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    323     const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
    324     const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
    325     ASSERT_TRUE(found != NULL) << "Didn't find method " << i << ": "
    326         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    327         << java_lang_dex_file_->GetStringData(name)
    328         << java_lang_dex_file_->GetMethodSignature(to_find);
    329     EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
    330   }
    331 }
    332 
    333 TEST_F(DexFileTest, FindFieldId) {
    334   for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
    335     const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
    336     const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
    337     const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
    338     const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
    339     const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
    340     ASSERT_TRUE(found != NULL) << "Didn't find field " << i << ": "
    341         << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
    342         << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
    343         << java_lang_dex_file_->GetStringData(name);
    344     EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
    345   }
    346 }
    347 
    348 TEST_F(DexFileTest, GetMultiDexClassesDexName) {
    349   std::string dex_location_str = "/system/app/framework.jar";
    350   const char* dex_location = dex_location_str.c_str();
    351   ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexClassesDexName(0, dex_location));
    352   ASSERT_EQ("/system/app/framework.jar:classes2.dex", DexFile::GetMultiDexClassesDexName(1, dex_location));
    353   ASSERT_EQ("/system/app/framework.jar:classes101.dex", DexFile::GetMultiDexClassesDexName(100, dex_location));
    354 }
    355 
    356 TEST_F(DexFileTest, GetDexCanonicalLocation) {
    357   ScratchFile file;
    358   UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
    359   std::string dex_location(dex_location_real.get());
    360 
    361   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str()));
    362   std::string multidex_location = DexFile::GetMultiDexClassesDexName(1, dex_location.c_str());
    363   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location.c_str()));
    364 
    365   std::string dex_location_sym = dex_location + "symlink";
    366   ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
    367 
    368   ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location_sym.c_str()));
    369 
    370   std::string multidex_location_sym = DexFile::GetMultiDexClassesDexName(1, dex_location_sym.c_str());
    371   ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str()));
    372 
    373   ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
    374 }
    375 
    376 }  // namespace art
    377