blob: 1deba01455fd9f0ae17f8fef7f70626705e3704f [file] [log] [blame]
Christopher Ferris0b06a592018-01-19 10:26:36 -08001/*
2 * Copyright (C) 2018 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
Yong Li489c3a82020-03-19 18:43:06 +000017#include <malloc.h>
Christopher Ferris0b06a592018-01-19 10:26:36 -080018#include <stdint.h>
19#include <sys/types.h>
20#include <unistd.h>
21
22#include <unordered_map>
23
Sim Sun273d3f02020-04-07 02:21:32 -070024#include <MemoryLocal.h>
Mark Salyzyn9f1cf252018-11-12 12:45:59 -080025#include <android-base/file.h>
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000026#include <gtest/gtest.h>
Christopher Ferris0b06a592018-01-19 10:26:36 -080027#include <unwindstack/MapInfo.h>
28#include <unwindstack/Memory.h>
29
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080030#include "DexFile.h"
Christopher Ferris7747b602018-01-31 19:05:19 -080031#include "DexFileData.h"
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080032#include "MemoryFake.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080033
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080034namespace unwindstack {
Christopher Ferris0b06a592018-01-19 10:26:36 -080035
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080036TEST(DexFileTest, from_file_open_non_exist) {
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000037 EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080038}
39
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080040TEST(DexFileTest, from_file_open_too_small) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080041 TemporaryFile tf;
42 ASSERT_TRUE(tf.fd != -1);
43
Martin Stjernholm2677b802019-01-09 23:26:33 +000044 ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
Christopher Ferris0b06a592018-01-19 10:26:36 -080045
46 // Header too small.
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000047 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080048
49 // Header correct, file too small.
50 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
Martin Stjernholm2677b802019-01-09 23:26:33 +000051 ASSERT_EQ(sizeof(kDexData) - 1,
52 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000053 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080054}
55
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080056TEST(DexFileTest, from_file_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080057 TemporaryFile tf;
58 ASSERT_TRUE(tf.fd != -1);
59
60 ASSERT_EQ(sizeof(kDexData),
61 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
62
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000063 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080064}
65
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080066TEST(DexFileTest, from_file_open_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080067 TemporaryFile tf;
68 ASSERT_TRUE(tf.fd != -1);
69
70 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
71 ASSERT_EQ(sizeof(kDexData),
72 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
73
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000074 EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080075}
76
Yong Li489c3a82020-03-19 18:43:06 +000077static constexpr size_t kNumLeakLoops = 5000;
78static constexpr size_t kMaxAllowedLeakBytes = 1024;
79
80static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) {
81 size_t allocated_bytes = mallinfo().uordblks;
82 if (*first_allocated_bytes == 0) {
83 *first_allocated_bytes = allocated_bytes;
84 } else if (*last_allocated_bytes > *first_allocated_bytes) {
85 // Check that the total memory did not increase too much over the first loop.
86 ASSERT_LE(*last_allocated_bytes - *first_allocated_bytes, kMaxAllowedLeakBytes)
87 << "Failed in loop " << loop << " first_allocated_bytes " << *first_allocated_bytes
88 << " last_allocated_bytes " << *last_allocated_bytes;
89 }
90 *last_allocated_bytes = allocated_bytes;
91}
92
93TEST(DexFileTest, from_file_no_leak) {
94 TemporaryFile tf;
95 ASSERT_TRUE(tf.fd != -1);
96
97 ASSERT_EQ(sizeof(kDexData),
98 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
99
100 size_t first_allocated_bytes = 0;
101 size_t last_allocated_bytes = 0;
102 for (size_t i = 0; i < kNumLeakLoops; i++) {
103 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
104 ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
105 }
106}
107
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800108TEST(DexFileTest, from_memory_fail_too_small_for_header) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800109 MemoryFake memory;
110
Martin Stjernholm2677b802019-01-09 23:26:33 +0000111 memory.SetMemory(0x1000, kDexData, 10);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800112
Sim Sun273d3f02020-04-07 02:21:32 -0700113 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800114}
115
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800116TEST(DexFileTest, from_memory_fail_too_small_for_data) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800117 MemoryFake memory;
118
119 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800120
Sim Sun273d3f02020-04-07 02:21:32 -0700121 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800122}
123
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800124TEST(DexFileTest, from_memory_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800125 MemoryFake memory;
126
127 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800128
Sim Sun273d3f02020-04-07 02:21:32 -0700129 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800130}
131
Yong Li489c3a82020-03-19 18:43:06 +0000132TEST(DexFileTest, from_memory_no_leak) {
133 MemoryFake memory;
134
135 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
136
137 size_t first_allocated_bytes = 0;
138 size_t last_allocated_bytes = 0;
139 for (size_t i = 0; i < kNumLeakLoops; i++) {
Sim Sun273d3f02020-04-07 02:21:32 -0700140 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
Yong Li489c3a82020-03-19 18:43:06 +0000141 ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
142 }
143}
144
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800145TEST(DexFileTest, create_using_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800146 TemporaryFile tf;
147 ASSERT_TRUE(tf.fd != -1);
148
149 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
150 ASSERT_EQ(sizeof(kDexData),
151 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
152
153 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800154 MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000155 EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800156}
157
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800158TEST(DexFileTest, create_using_file_non_zero_start) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800159 TemporaryFile tf;
160 ASSERT_TRUE(tf.fd != -1);
161
162 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
163 ASSERT_EQ(sizeof(kDexData),
164 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
165
166 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800167 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000168 EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800169}
170
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800171TEST(DexFileTest, create_using_file_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800172 TemporaryFile tf;
173 ASSERT_TRUE(tf.fd != -1);
174
175 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
176 ASSERT_EQ(sizeof(kDexData),
177 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
178
179 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800180 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000181 EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800182}
183
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800184TEST(DexFileTest, create_using_memory_empty_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800185 MemoryFake memory;
186 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800187 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000188 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800189}
190
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800191TEST(DexFileTest, create_using_memory_file_does_not_exist) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800192 MemoryFake memory;
193 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800194 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000195 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800196}
197
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800198TEST(DexFileTest, create_using_memory_file_is_malformed) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800199 TemporaryFile tf;
200 ASSERT_TRUE(tf.fd != -1);
201
202 ASSERT_EQ(sizeof(kDexData) - 10,
203 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
204
205 MemoryFake memory;
206 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800207 MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000208 std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800209 ASSERT_TRUE(dex_file != nullptr);
210
211 // Check it came from memory by clearing memory and verifying it fails.
212 memory.Clear();
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000213 dex_file = DexFile::Create(0x4000, &memory, &info);
214 EXPECT_TRUE(dex_file == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800215}
216
Sim Sun273d3f02020-04-07 02:21:32 -0700217TEST(DexFileTest, create_using_memory_size_too_small) {
218 MemoryFake memory;
219 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
220 MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist");
221 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
222}
223
224class MemoryLocalFake : public MemoryLocal {
225 public:
226 MemoryLocalFake(size_t memory_size) : backing_(memory_size) {}
227 virtual ~MemoryLocalFake() = default;
228
229 void* Data() { return backing_.data(); }
230
231 private:
232 std::vector<void*> backing_;
233};
234
235TEST(DexFileTest, create_using_local_memory) {
236 MemoryLocalFake memory(sizeof(kDexData));
237
238 memcpy(memory.Data(), kDexData, sizeof(kDexData));
239 uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
240 MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist");
241 EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr);
242}
243
244TEST(DexFileTest, create_using_local_memory_size_too_small) {
245 MemoryLocalFake memory(sizeof(kDexData));
246
247 memcpy(memory.Data(), kDexData, sizeof(kDexData));
248 uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
249 MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5,
250 "/does/not/exist");
251 EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr);
252}
253
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800254TEST(DexFileTest, get_method) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800255 MemoryFake memory;
256 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800257 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800258 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800259 ASSERT_TRUE(dex_file != nullptr);
260
261 std::string method;
262 uint64_t method_offset;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000263 ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800264 EXPECT_EQ("Main.<init>", method);
265 EXPECT_EQ(2U, method_offset);
266
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000267 ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
David Srbecky02d0f792018-03-24 00:29:14 +0000268 EXPECT_EQ("Main.main", method);
269 EXPECT_EQ(0U, method_offset);
David Srbecky02d0f792018-03-24 00:29:14 +0000270}
271
272TEST(DexFileTest, get_method_empty) {
273 MemoryFake memory;
274 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800275 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
David Srbecky02d0f792018-03-24 00:29:14 +0000276 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
277 ASSERT_TRUE(dex_file != nullptr);
278
279 std::string method;
280 uint64_t method_offset;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000281 EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
David Srbecky02d0f792018-03-24 00:29:14 +0000282
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000283 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800284}
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800285
286} // namespace unwindstack