blob: 6a06177bb6cf8cccbdb9a67feb8013f5c0dbb137 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Carl Shapiro1fb86202011-06-27 17:43:13 -070016
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "dex_file.h"
Carl Shapiro1fb86202011-06-27 17:43:13 -070018
Ian Rogers700a4022014-05-19 16:49:03 -070019#include <memory>
20
Ian Rogerse63db272014-07-15 15:36:11 -070021#include "base/stl_util.h"
22#include "base/unix_file/fd_file.h"
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080023#include "common_runtime_test.h"
Elliott Hughes956af0f2014-12-11 14:34:28 -080024#include "dex_file-inl.h"
Orion Hodsona4c2a052016-08-17 10:51:42 +010025#include "mem_map.h"
Ian Rogerse63db272014-07-15 15:36:11 -070026#include "os.h"
27#include "scoped_thread_state_change.h"
28#include "thread-inl.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070029
Carl Shapiro1fb86202011-06-27 17:43:13 -070030namespace art {
31
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080032class DexFileTest : public CommonRuntimeTest {};
Brian Carlstrom9f30b382011-08-28 22:41:38 -070033
34TEST_F(DexFileTest, Open) {
Ian Rogers33e95662013-05-20 20:29:14 -070035 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -080036 std::unique_ptr<const DexFile> dex(OpenTestDexFile("Nested"));
Mathieu Chartier2cebb242015-04-21 16:50:40 -070037 ASSERT_TRUE(dex.get() != nullptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070038}
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070039
Ian Rogers13735952014-10-08 12:43:28 -070040static const uint8_t kBase64Map[256] = {
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080041 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
42 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
43 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
44 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
45 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
46 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
47 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT
48 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT
49 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
50 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT
51 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
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, 255, 255, 255, 255, 255, 255, 255, 255,
61 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62 255, 255, 255, 255
63};
64
Orion Hodsona4c2a052016-08-17 10:51:42 +010065static inline std::vector<uint8_t> DecodeBase64(const char* src) {
Ian Rogers13735952014-10-08 12:43:28 -070066 std::vector<uint8_t> tmp;
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080067 uint32_t t = 0, y = 0;
68 int g = 3;
69 for (size_t i = 0; src[i] != '\0'; ++i) {
Ian Rogers13735952014-10-08 12:43:28 -070070 uint8_t c = kBase64Map[src[i] & 0xFF];
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080071 if (c == 255) continue;
72 // the final = symbols are read and used to trim the remaining bytes
73 if (c == 254) {
74 c = 0;
75 // prevent g < 0 which would potentially allow an overflow later
76 if (--g < 0) {
Orion Hodsona4c2a052016-08-17 10:51:42 +010077 return std::vector<uint8_t>();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080078 }
79 } else if (g != 3) {
80 // we only allow = to be at the end
Orion Hodsona4c2a052016-08-17 10:51:42 +010081 return std::vector<uint8_t>();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080082 }
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) {
Orion Hodsona4c2a052016-08-17 10:51:42 +010096 return std::vector<uint8_t>();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080097 }
Orion Hodsona4c2a052016-08-17 10:51:42 +010098 return tmp;
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080099}
100
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700101// Although this is the same content logically as the Nested test dex,
102// the DexFileHeader test is sensitive to subtle changes in the
103// contents due to the checksum etc, so we embed the exact input here.
104//
105// class Nested {
106// class Inner {
107// }
108// }
109static const char kRawDex[] =
110 "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP"
111 "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B"
112 "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA"
113 "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA"
114 "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA"
115 "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA"
116 "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA"
117 "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu"
118 "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2"
119 "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz"
120 "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA"
121 "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA"
122 "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH"
123 "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ"
124 "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA"
125 "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA==";
126
Narayan Kamath52e66502016-08-01 14:20:31 +0100127// kRawDex38 and 39 are dex'ed versions of the following Java source :
128//
129// public class Main {
130// public static void main(String[] foo) {
131// }
132// }
133//
134// The dex file was manually edited to change its dex version code to 38
135// or 39, respectively.
136static const char kRawDex38[] =
137 "ZGV4CjAzOAC4OovJlJ1089ikzK6asMf/f8qp3Kve5VsgAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAI"
138 "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAwAQAA8AAAACIB"
139 "AAAqAQAAMgEAAEYBAABRAQAAVAEAAFgBAABtAQAAAQAAAAIAAAAEAAAABgAAAAQAAAACAAAAAAAA"
140 "AAUAAAACAAAAHAEAAAAAAAAAAAAAAAABAAcAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAADAAAA"
141 "AAAAAH4BAAAAAAAAAQABAAEAAABzAQAABAAAAHAQAgAAAA4AAQABAAAAAAB4AQAAAQAAAA4AAAAB"
142 "AAAAAwAGPGluaXQ+AAZMTWFpbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwAJTWFpbi5qYXZhAAFWAAJW"
143 "TAATW0xqYXZhL2xhbmcvU3RyaW5nOwAEbWFpbgABAAcOAAMBAAcOAAAAAgAAgYAE8AEBCYgCDAAA"
144 "AAAAAAABAAAAAAAAAAEAAAAIAAAAcAAAAAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAA"
145 "uAAAAAYAAAABAAAA0AAAAAEgAAACAAAA8AAAAAEQAAABAAAAHAEAAAIgAAAIAAAAIgEAAAMgAAAC"
146 "AAAAcwEAAAAgAAABAAAAfgEAAAAQAAABAAAAjAEAAA==";
147
148static const char kRawDex39[] =
149 "ZGV4CjAzOQC4OovJlJ1089ikzK6asMf/f8qp3Kve5VsgAgAAcAAAAHhWNBIAAAAAAAAAAIwBAAAI"
150 "AAAAcAAAAAQAAACQAAAAAgAAAKAAAAAAAAAAAAAAAAMAAAC4AAAAAQAAANAAAAAwAQAA8AAAACIB"
151 "AAAqAQAAMgEAAEYBAABRAQAAVAEAAFgBAABtAQAAAQAAAAIAAAAEAAAABgAAAAQAAAACAAAAAAAA"
152 "AAUAAAACAAAAHAEAAAAAAAAAAAAAAAABAAcAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAADAAAA"
153 "AAAAAH4BAAAAAAAAAQABAAEAAABzAQAABAAAAHAQAgAAAA4AAQABAAAAAAB4AQAAAQAAAA4AAAAB"
154 "AAAAAwAGPGluaXQ+AAZMTWFpbjsAEkxqYXZhL2xhbmcvT2JqZWN0OwAJTWFpbi5qYXZhAAFWAAJW"
155 "TAATW0xqYXZhL2xhbmcvU3RyaW5nOwAEbWFpbgABAAcOAAMBAAcOAAAAAgAAgYAE8AEBCYgCDAAA"
156 "AAAAAAABAAAAAAAAAAEAAAAIAAAAcAAAAAIAAAAEAAAAkAAAAAMAAAACAAAAoAAAAAUAAAADAAAA"
157 "uAAAAAYAAAABAAAA0AAAAAEgAAACAAAA8AAAAAEQAAABAAAAHAEAAAIgAAAIAAAAIgEAAAMgAAAC"
158 "AAAAcwEAAAAgAAABAAAAfgEAAAAQAAABAAAAjAEAAA==";
159
ganxiaolincd16d0a2016-07-18 11:21:44 +0800160static const char kRawDexZeroLength[] =
161 "UEsDBAoAAAAAAOhxAkkAAAAAAAAAAAAAAAALABwAY2xhc3Nlcy5kZXhVVAkAA2QNoVdnDaFXdXgL"
162 "AAEE5AMBAASIEwAAUEsBAh4DCgAAAAAA6HECSQAAAAAAAAAAAAAAAAsAGAAAAAAAAAAAAKCBAAAA"
163 "AGNsYXNzZXMuZGV4VVQFAANkDaFXdXgLAAEE5AMBAASIEwAAUEsFBgAAAAABAAEAUQAAAEUAAAAA"
164 "AA==";
165
Narayan Kamath52e66502016-08-01 14:20:31 +0100166static void DecodeAndWriteDexFile(const char* base64, const char* location) {
Ian Rogers33e95662013-05-20 20:29:14 -0700167 // decode base64
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700168 CHECK(base64 != nullptr);
Orion Hodsona4c2a052016-08-17 10:51:42 +0100169 std::vector<uint8_t> dex_bytes = DecodeBase64(base64);
170 CHECK_NE(dex_bytes.size(), 0u);
Ian Rogers33e95662013-05-20 20:29:14 -0700171
172 // write to provided file
Ian Rogers700a4022014-05-19 16:49:03 -0700173 std::unique_ptr<File> file(OS::CreateEmptyFile(location));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700174 CHECK(file.get() != nullptr);
Orion Hodsona4c2a052016-08-17 10:51:42 +0100175 if (!file->WriteFully(dex_bytes.data(), dex_bytes.size())) {
Ian Rogers33e95662013-05-20 20:29:14 -0700176 PLOG(FATAL) << "Failed to write base64 as dex file";
177 }
Andreas Gampe4303ba92014-11-06 01:00:46 -0800178 if (file->FlushCloseOrErase() != 0) {
179 PLOG(FATAL) << "Could not flush and close test file.";
180 }
Narayan Kamath52e66502016-08-01 14:20:31 +0100181}
182
183static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
184 const char* location) {
185 DecodeAndWriteDexFile(base64, location);
Ian Rogers33e95662013-05-20 20:29:14 -0700186
187 // read dex file
188 ScopedObjectAccess soa(Thread::Current());
Aart Bik37d6a3b2016-06-21 18:30:10 -0700189 static constexpr bool kVerifyChecksum = true;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700190 std::string error_msg;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800191 std::vector<std::unique_ptr<const DexFile>> tmp;
Aart Bik37d6a3b2016-06-21 18:30:10 -0700192 bool success = DexFile::Open(location, location, kVerifyChecksum, &error_msg, &tmp);
Andreas Gampe833a4852014-05-21 18:46:59 -0700193 CHECK(success) << error_msg;
194 EXPECT_EQ(1U, tmp.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800195 std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
Brian Carlstrome0948e12013-08-29 09:36:15 -0700196 EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
197 EXPECT_TRUE(dex_file->IsReadOnly());
Ian Rogers33e95662013-05-20 20:29:14 -0700198 return dex_file;
199}
200
Orion Hodsona4c2a052016-08-17 10:51:42 +0100201static std::unique_ptr<const DexFile> OpenDexFileInMemoryBase64(const char* base64,
202 const char* location,
203 uint32_t location_checksum) {
204 CHECK(base64 != nullptr);
205 std::vector<uint8_t> dex_bytes = DecodeBase64(base64);
206 CHECK_NE(dex_bytes.size(), 0u);
207
208 std::string error_message;
209 std::unique_ptr<MemMap> region(MemMap::MapAnonymous("test-region",
210 nullptr,
211 dex_bytes.size(),
212 PROT_READ | PROT_WRITE,
213 /* low_4gb */ false,
214 /* reuse */ false,
215 &error_message));
216 memcpy(region->Begin(), dex_bytes.data(), dex_bytes.size());
217 std::unique_ptr<const DexFile> dex_file(DexFile::Open(location,
218 location_checksum,
219 std::move(region),
220 /* verify */ true,
221 /* verify_checksum */ true,
222 &error_message));
223 CHECK(dex_file != nullptr) << error_message;
224 return dex_file;
225}
226
Orion Hodsoncffc5292016-09-05 13:43:11 +0100227static void ValidateDexFileHeader(std::unique_ptr<const DexFile> dex_file) {
228 static const uint8_t kExpectedDexFileMagic[8] = {
229 /* d */ 0x64, /* e */ 0x64, /* x */ 0x78, /* \n */ 0x0d,
230 /* 0 */ 0x30, /* 3 */ 0x33, /* 5 */ 0x35, /* \0 */ 0x00
231 };
232 static const uint8_t kExpectedSha1[DexFile::kSha1DigestSize] = {
233 0x7b, 0xb8, 0x0c, 0xd4, 0x1f, 0xd6, 0x1e, 0xc5,
234 0x89, 0xe8, 0xbe, 0xe5, 0x18, 0x02, 0x12, 0x18,
235 0x2e, 0xf2, 0x8c, 0x3d,
236 };
Orion Hodsona4c2a052016-08-17 10:51:42 +0100237
Orion Hodsoncffc5292016-09-05 13:43:11 +0100238 const DexFile::Header& header = dex_file->GetHeader();
239 EXPECT_EQ(*kExpectedDexFileMagic, *header.magic_);
Orion Hodsona4c2a052016-08-17 10:51:42 +0100240 EXPECT_EQ(0x00d87910U, header.checksum_);
Orion Hodsoncffc5292016-09-05 13:43:11 +0100241 EXPECT_EQ(*kExpectedSha1, *header.signature_);
Orion Hodsona4c2a052016-08-17 10:51:42 +0100242 EXPECT_EQ(904U, header.file_size_);
243 EXPECT_EQ(112U, header.header_size_);
244 EXPECT_EQ(0U, header.link_size_);
245 EXPECT_EQ(0U, header.link_off_);
246 EXPECT_EQ(15U, header.string_ids_size_);
247 EXPECT_EQ(112U, header.string_ids_off_);
248 EXPECT_EQ(7U, header.type_ids_size_);
249 EXPECT_EQ(172U, header.type_ids_off_);
250 EXPECT_EQ(2U, header.proto_ids_size_);
251 EXPECT_EQ(200U, header.proto_ids_off_);
252 EXPECT_EQ(1U, header.field_ids_size_);
253 EXPECT_EQ(224U, header.field_ids_off_);
254 EXPECT_EQ(3U, header.method_ids_size_);
255 EXPECT_EQ(232U, header.method_ids_off_);
256 EXPECT_EQ(2U, header.class_defs_size_);
257 EXPECT_EQ(256U, header.class_defs_off_);
258 EXPECT_EQ(584U, header.data_size_);
259 EXPECT_EQ(320U, header.data_off_);
260
Orion Hodsoncffc5292016-09-05 13:43:11 +0100261 EXPECT_EQ(header.checksum_, dex_file->GetLocationChecksum());
262}
263
264TEST_F(DexFileTest, Header) {
265 ScratchFile tmp;
266 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex, tmp.GetFilename().c_str()));
267 ValidateDexFileHeader(std::move(raw));
Orion Hodsona4c2a052016-08-17 10:51:42 +0100268}
269
270TEST_F(DexFileTest, HeaderInMemory) {
271 ScratchFile tmp;
272 std::unique_ptr<const DexFile> raw =
273 OpenDexFileInMemoryBase64(kRawDex, tmp.GetFilename().c_str(), 0x00d87910U);
Orion Hodsoncffc5292016-09-05 13:43:11 +0100274 ValidateDexFileHeader(std::move(raw));
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800275}
276
Narayan Kamath52e66502016-08-01 14:20:31 +0100277TEST_F(DexFileTest, Version38Accepted) {
278 ScratchFile tmp;
279 std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kRawDex38, tmp.GetFilename().c_str()));
280 ASSERT_TRUE(raw.get() != nullptr);
281
282 const DexFile::Header& header = raw->GetHeader();
283 EXPECT_EQ(38u, header.GetVersion());
284}
285
286TEST_F(DexFileTest, Version39Rejected) {
287 ScratchFile tmp;
288 const char* location = tmp.GetFilename().c_str();
289 DecodeAndWriteDexFile(kRawDex39, location);
290
291 ScopedObjectAccess soa(Thread::Current());
292 static constexpr bool kVerifyChecksum = true;
293 std::string error_msg;
294 std::vector<std::unique_ptr<const DexFile>> dex_files;
295 ASSERT_FALSE(DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files));
296}
297
ganxiaolincd16d0a2016-07-18 11:21:44 +0800298TEST_F(DexFileTest, ZeroLengthDexRejected) {
299 ScratchFile tmp;
300 const char* location = tmp.GetFilename().c_str();
301 DecodeAndWriteDexFile(kRawDexZeroLength, location);
302
303 ScopedObjectAccess soa(Thread::Current());
304 static constexpr bool kVerifyChecksum = true;
305 std::string error_msg;
306 std::vector<std::unique_ptr<const DexFile>> dex_files;
307 ASSERT_FALSE(DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files));
308}
309
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800310TEST_F(DexFileTest, GetLocationChecksum) {
Ian Rogers33e95662013-05-20 20:29:14 -0700311 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800312 std::unique_ptr<const DexFile> raw(OpenTestDexFile("Main"));
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800313 EXPECT_NE(raw->GetHeader().checksum_, raw->GetLocationChecksum());
314}
315
316TEST_F(DexFileTest, GetChecksum) {
317 uint32_t checksum;
Ian Rogers33e95662013-05-20 20:29:14 -0700318 ScopedObjectAccess soa(Thread::Current());
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700319 std::string error_msg;
Przemyslaw Szczepaniak5b8e6e32015-09-30 14:40:33 +0100320 EXPECT_TRUE(DexFile::GetChecksum(GetLibCoreDexFileNames()[0].c_str(), &checksum, &error_msg))
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700321 << error_msg;
Brian Carlstrom5b332c82012-02-01 15:02:31 -0800322 EXPECT_EQ(java_lang_dex_file_->GetLocationChecksum(), checksum);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700323}
324
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700325TEST_F(DexFileTest, ClassDefs) {
Ian Rogers33e95662013-05-20 20:29:14 -0700326 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800327 std::unique_ptr<const DexFile> raw(OpenTestDexFile("Nested"));
328 ASSERT_TRUE(raw.get() != nullptr);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700329 EXPECT_EQ(2U, raw->NumClassDefs());
330
Brian Carlstromf615a612011-07-23 12:50:34 -0700331 const DexFile::ClassDef& c0 = raw->GetClassDef(0);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700332 EXPECT_STREQ("LNested$Inner;", raw->GetClassDescriptor(c0));
333
Brian Carlstromf615a612011-07-23 12:50:34 -0700334 const DexFile::ClassDef& c1 = raw->GetClassDef(1);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700335 EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
Carl Shapiro1fb86202011-06-27 17:43:13 -0700336}
337
Ian Rogersd91d6d62013-09-25 20:26:14 -0700338TEST_F(DexFileTest, GetMethodSignature) {
Ian Rogers33e95662013-05-20 20:29:14 -0700339 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800340 std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
341 ASSERT_TRUE(raw.get() != nullptr);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700342 EXPECT_EQ(1U, raw->NumClassDefs());
343
344 const DexFile::ClassDef& class_def = raw->GetClassDef(0);
Ian Rogersd91d6d62013-09-25 20:26:14 -0700345 ASSERT_STREQ("LGetMethodSignature;", raw->GetClassDescriptor(class_def));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700346
Ian Rogers13735952014-10-08 12:43:28 -0700347 const uint8_t* class_data = raw->GetClassData(class_def);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700348 ASSERT_TRUE(class_data != nullptr);
Elliott Hughes4d6850c2012-01-18 15:55:06 -0800349 ClassDataItemIterator it(*raw, class_data);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700350
Ian Rogers0571d352011-11-03 19:51:38 -0700351 EXPECT_EQ(1u, it.NumDirectMethods());
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700352
Ian Rogers0571d352011-11-03 19:51:38 -0700353 // Check the signature for the static initializer.
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700354 {
Ian Rogers0571d352011-11-03 19:51:38 -0700355 ASSERT_EQ(1U, it.NumDirectMethods());
356 const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
Ian Rogers0571d352011-11-03 19:51:38 -0700357 const char* name = raw->StringDataByIdx(method_id.name_idx_);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700358 ASSERT_STREQ("<init>", name);
Ian Rogersd91d6d62013-09-25 20:26:14 -0700359 std::string signature(raw->GetMethodSignature(method_id).ToString());
Ian Rogers0571d352011-11-03 19:51:38 -0700360 ASSERT_EQ("()V", signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700361 }
362
363 // Check both virtual methods.
Ian Rogers0571d352011-11-03 19:51:38 -0700364 ASSERT_EQ(2U, it.NumVirtualMethods());
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700365 {
Ian Rogers0571d352011-11-03 19:51:38 -0700366 it.Next();
367 const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700368
Ian Rogers0571d352011-11-03 19:51:38 -0700369 const char* name = raw->StringDataByIdx(method_id.name_idx_);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700370 ASSERT_STREQ("m1", name);
371
Ian Rogersd91d6d62013-09-25 20:26:14 -0700372 std::string signature(raw->GetMethodSignature(method_id).ToString());
Ian Rogers0571d352011-11-03 19:51:38 -0700373 ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700374 }
375
376 {
Ian Rogers0571d352011-11-03 19:51:38 -0700377 it.Next();
378 const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700379
Ian Rogers0571d352011-11-03 19:51:38 -0700380 const char* name = raw->StringDataByIdx(method_id.name_idx_);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700381 ASSERT_STREQ("m2", name);
382
Ian Rogersd91d6d62013-09-25 20:26:14 -0700383 std::string signature(raw->GetMethodSignature(method_id).ToString());
384 ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
Ian Rogers0571d352011-11-03 19:51:38 -0700385 }
386}
387
388TEST_F(DexFileTest, FindStringId) {
Ian Rogers33e95662013-05-20 20:29:14 -0700389 ScopedObjectAccess soa(Thread::Current());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800390 std::unique_ptr<const DexFile> raw(OpenTestDexFile("GetMethodSignature"));
391 ASSERT_TRUE(raw.get() != nullptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700392 EXPECT_EQ(1U, raw->NumClassDefs());
393
Ian Rogersd91d6d62013-09-25 20:26:14 -0700394 const char* strings[] = { "LGetMethodSignature;", "Ljava/lang/Float;", "Ljava/lang/Object;",
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700395 "D", "I", "J", nullptr };
396 for (size_t i = 0; strings[i] != nullptr; i++) {
Ian Rogers0571d352011-11-03 19:51:38 -0700397 const char* str = strings[i];
398 const DexFile::StringId* str_id = raw->FindStringId(str);
399 const char* dex_str = raw->GetStringData(*str_id);
400 EXPECT_STREQ(dex_str, str);
401 }
402}
403
404TEST_F(DexFileTest, FindTypeId) {
405 for (size_t i = 0; i < java_lang_dex_file_->NumTypeIds(); i++) {
406 const char* type_str = java_lang_dex_file_->StringByTypeIdx(i);
407 const DexFile::StringId* type_str_id = java_lang_dex_file_->FindStringId(type_str);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700408 ASSERT_TRUE(type_str_id != nullptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700409 uint32_t type_str_idx = java_lang_dex_file_->GetIndexForStringId(*type_str_id);
410 const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(type_str_idx);
Mathieu Chartier9507fa22015-10-29 15:08:57 -0700411 ASSERT_EQ(type_id, java_lang_dex_file_->FindTypeId(type_str));
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700412 ASSERT_TRUE(type_id != nullptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700413 EXPECT_EQ(java_lang_dex_file_->GetIndexForTypeId(*type_id), i);
414 }
415}
416
417TEST_F(DexFileTest, FindProtoId) {
418 for (size_t i = 0; i < java_lang_dex_file_->NumProtoIds(); i++) {
419 const DexFile::ProtoId& to_find = java_lang_dex_file_->GetProtoId(i);
420 const DexFile::TypeList* to_find_tl = java_lang_dex_file_->GetProtoParameters(to_find);
421 std::vector<uint16_t> to_find_types;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700422 if (to_find_tl != nullptr) {
Ian Rogers0571d352011-11-03 19:51:38 -0700423 for (size_t j = 0; j < to_find_tl->Size(); j++) {
424 to_find_types.push_back(to_find_tl->GetTypeItem(j).type_idx_);
425 }
426 }
427 const DexFile::ProtoId* found =
428 java_lang_dex_file_->FindProtoId(to_find.return_type_idx_, to_find_types);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700429 ASSERT_TRUE(found != nullptr);
Ian Rogers0571d352011-11-03 19:51:38 -0700430 EXPECT_EQ(java_lang_dex_file_->GetIndexForProtoId(*found), i);
431 }
432}
433
434TEST_F(DexFileTest, FindMethodId) {
435 for (size_t i = 0; i < java_lang_dex_file_->NumMethodIds(); i++) {
436 const DexFile::MethodId& to_find = java_lang_dex_file_->GetMethodId(i);
437 const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
438 const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
439 const DexFile::ProtoId& signature = java_lang_dex_file_->GetProtoId(to_find.proto_idx_);
440 const DexFile::MethodId* found = java_lang_dex_file_->FindMethodId(klass, name, signature);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700441 ASSERT_TRUE(found != nullptr) << "Didn't find method " << i << ": "
Ian Rogers0571d352011-11-03 19:51:38 -0700442 << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
443 << java_lang_dex_file_->GetStringData(name)
Ian Rogersd91d6d62013-09-25 20:26:14 -0700444 << java_lang_dex_file_->GetMethodSignature(to_find);
Ian Rogers0571d352011-11-03 19:51:38 -0700445 EXPECT_EQ(java_lang_dex_file_->GetIndexForMethodId(*found), i);
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700446 }
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700447}
448
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800449TEST_F(DexFileTest, FindFieldId) {
450 for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
451 const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
452 const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
453 const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
454 const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
455 const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700456 ASSERT_TRUE(found != nullptr) << "Didn't find field " << i << ": "
Ian Rogers9b1a4f42011-11-14 18:35:10 -0800457 << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
458 << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
459 << java_lang_dex_file_->GetStringData(name);
460 EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
461 }
462}
463
Calin Juravle4e1d5792014-07-15 23:56:47 +0100464TEST_F(DexFileTest, GetMultiDexClassesDexName) {
Andreas Gampe90e34042015-04-27 20:01:52 -0700465 ASSERT_EQ("classes.dex", DexFile::GetMultiDexClassesDexName(0));
466 ASSERT_EQ("classes2.dex", DexFile::GetMultiDexClassesDexName(1));
467 ASSERT_EQ("classes3.dex", DexFile::GetMultiDexClassesDexName(2));
468 ASSERT_EQ("classes100.dex", DexFile::GetMultiDexClassesDexName(99));
469}
470
471TEST_F(DexFileTest, GetMultiDexLocation) {
Calin Juravle4e1d5792014-07-15 23:56:47 +0100472 std::string dex_location_str = "/system/app/framework.jar";
473 const char* dex_location = dex_location_str.c_str();
Andreas Gampe90e34042015-04-27 20:01:52 -0700474 ASSERT_EQ("/system/app/framework.jar", DexFile::GetMultiDexLocation(0, dex_location));
475 ASSERT_EQ("/system/app/framework.jar:classes2.dex",
476 DexFile::GetMultiDexLocation(1, dex_location));
477 ASSERT_EQ("/system/app/framework.jar:classes101.dex",
478 DexFile::GetMultiDexLocation(100, dex_location));
Calin Juravle4e1d5792014-07-15 23:56:47 +0100479}
480
481TEST_F(DexFileTest, GetDexCanonicalLocation) {
482 ScratchFile file;
Vladimir Markoaa4497d2014-09-05 14:01:17 +0100483 UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr));
484 std::string dex_location(dex_location_real.get());
Calin Juravle4e1d5792014-07-15 23:56:47 +0100485
Calin Juravle61281dc2014-08-07 11:54:36 +0100486 ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str()));
Andreas Gampe90e34042015-04-27 20:01:52 -0700487 std::string multidex_location = DexFile::GetMultiDexLocation(1, dex_location.c_str());
Calin Juravle4e1d5792014-07-15 23:56:47 +0100488 ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location.c_str()));
489
490 std::string dex_location_sym = dex_location + "symlink";
491 ASSERT_EQ(0, symlink(dex_location.c_str(), dex_location_sym.c_str()));
492
493 ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location_sym.c_str()));
494
Andreas Gampe90e34042015-04-27 20:01:52 -0700495 std::string multidex_location_sym = DexFile::GetMultiDexLocation(1, dex_location_sym.c_str());
Calin Juravle4e1d5792014-07-15 23:56:47 +0100496 ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str()));
497
498 ASSERT_EQ(0, unlink(dex_location_sym.c_str()));
499}
500
Richard Uhlere5fed032015-03-18 08:21:11 -0700501TEST(DexFileUtilsTest, GetBaseLocationAndMultiDexSuffix) {
502 EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar"));
503 EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes2.dex"));
504 EXPECT_EQ("/foo/bar/baz.jar", DexFile::GetBaseLocation("/foo/bar/baz.jar:classes8.dex"));
505 EXPECT_EQ("", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar"));
506 EXPECT_EQ(":classes2.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes2.dex"));
507 EXPECT_EQ(":classes8.dex", DexFile::GetMultiDexSuffix("/foo/bar/baz.jar:classes8.dex"));
508}
509
Carl Shapiro1fb86202011-06-27 17:43:13 -0700510} // namespace art