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