blob: dc935a36e8c884e4b0e6afd0de7db9f4178ca470 [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
Mark Salyzyn9f1cf252018-11-12 12:45:59 -080024#include <android-base/file.h>
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000025#include <gtest/gtest.h>
Christopher Ferris0b06a592018-01-19 10:26:36 -080026#include <unwindstack/MapInfo.h>
27#include <unwindstack/Memory.h>
28
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080029#include "DexFile.h"
Christopher Ferris7747b602018-01-31 19:05:19 -080030#include "DexFileData.h"
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080031#include "MemoryFake.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080032
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080033namespace unwindstack {
Christopher Ferris0b06a592018-01-19 10:26:36 -080034
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080035TEST(DexFileTest, from_file_open_non_exist) {
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000036 EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080037}
38
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080039TEST(DexFileTest, from_file_open_too_small) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080040 TemporaryFile tf;
41 ASSERT_TRUE(tf.fd != -1);
42
Martin Stjernholm2677b802019-01-09 23:26:33 +000043 ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
Christopher Ferris0b06a592018-01-19 10:26:36 -080044
45 // Header too small.
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000046 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080047
48 // Header correct, file too small.
49 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
Martin Stjernholm2677b802019-01-09 23:26:33 +000050 ASSERT_EQ(sizeof(kDexData) - 1,
51 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000052 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080053}
54
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080055TEST(DexFileTest, from_file_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080056 TemporaryFile tf;
57 ASSERT_TRUE(tf.fd != -1);
58
59 ASSERT_EQ(sizeof(kDexData),
60 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
61
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000062 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080063}
64
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080065TEST(DexFileTest, from_file_open_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080066 TemporaryFile tf;
67 ASSERT_TRUE(tf.fd != -1);
68
69 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
70 ASSERT_EQ(sizeof(kDexData),
71 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
72
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000073 EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080074}
75
Yong Li489c3a82020-03-19 18:43:06 +000076static constexpr size_t kNumLeakLoops = 5000;
77static constexpr size_t kMaxAllowedLeakBytes = 1024;
78
79static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) {
80 size_t allocated_bytes = mallinfo().uordblks;
81 if (*first_allocated_bytes == 0) {
82 *first_allocated_bytes = allocated_bytes;
83 } else if (*last_allocated_bytes > *first_allocated_bytes) {
84 // Check that the total memory did not increase too much over the first loop.
85 ASSERT_LE(*last_allocated_bytes - *first_allocated_bytes, kMaxAllowedLeakBytes)
86 << "Failed in loop " << loop << " first_allocated_bytes " << *first_allocated_bytes
87 << " last_allocated_bytes " << *last_allocated_bytes;
88 }
89 *last_allocated_bytes = allocated_bytes;
90}
91
92TEST(DexFileTest, from_file_no_leak) {
93 TemporaryFile tf;
94 ASSERT_TRUE(tf.fd != -1);
95
96 ASSERT_EQ(sizeof(kDexData),
97 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
98
99 size_t first_allocated_bytes = 0;
100 size_t last_allocated_bytes = 0;
101 for (size_t i = 0; i < kNumLeakLoops; i++) {
102 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
103 ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
104 }
105}
106
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800107TEST(DexFileTest, from_memory_fail_too_small_for_header) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800108 MemoryFake memory;
109
Martin Stjernholm2677b802019-01-09 23:26:33 +0000110 memory.SetMemory(0x1000, kDexData, 10);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800111
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000112 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800113}
114
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800115TEST(DexFileTest, from_memory_fail_too_small_for_data) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800116 MemoryFake memory;
117
118 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800119
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000120 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800121}
122
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800123TEST(DexFileTest, from_memory_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800124 MemoryFake memory;
125
126 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800127
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000128 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800129}
130
Yong Li489c3a82020-03-19 18:43:06 +0000131TEST(DexFileTest, from_memory_no_leak) {
132 MemoryFake memory;
133
134 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
135
136 size_t first_allocated_bytes = 0;
137 size_t last_allocated_bytes = 0;
138 for (size_t i = 0; i < kNumLeakLoops; i++) {
139 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
140 ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
141 }
142}
143
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800144TEST(DexFileTest, create_using_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800145 TemporaryFile tf;
146 ASSERT_TRUE(tf.fd != -1);
147
148 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
149 ASSERT_EQ(sizeof(kDexData),
150 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
151
152 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800153 MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000154 EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800155}
156
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800157TEST(DexFileTest, create_using_file_non_zero_start) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800158 TemporaryFile tf;
159 ASSERT_TRUE(tf.fd != -1);
160
161 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
162 ASSERT_EQ(sizeof(kDexData),
163 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
164
165 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800166 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000167 EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800168}
169
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800170TEST(DexFileTest, create_using_file_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800171 TemporaryFile tf;
172 ASSERT_TRUE(tf.fd != -1);
173
174 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
175 ASSERT_EQ(sizeof(kDexData),
176 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
177
178 MemoryFake memory;
Christopher Ferris0f40a052020-01-22 12:17:06 -0800179 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000180 EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800181}
182
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800183TEST(DexFileTest, create_using_memory_empty_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800184 MemoryFake memory;
185 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800186 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000187 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800188}
189
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800190TEST(DexFileTest, create_using_memory_file_does_not_exist) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800191 MemoryFake memory;
192 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800193 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000194 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800195}
196
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800197TEST(DexFileTest, create_using_memory_file_is_malformed) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800198 TemporaryFile tf;
199 ASSERT_TRUE(tf.fd != -1);
200
201 ASSERT_EQ(sizeof(kDexData) - 10,
202 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
203
204 MemoryFake memory;
205 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800206 MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000207 std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800208 ASSERT_TRUE(dex_file != nullptr);
209
210 // Check it came from memory by clearing memory and verifying it fails.
211 memory.Clear();
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000212 dex_file = DexFile::Create(0x4000, &memory, &info);
213 EXPECT_TRUE(dex_file == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800214}
215
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800216TEST(DexFileTest, get_method) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800217 MemoryFake memory;
218 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800219 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800220 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800221 ASSERT_TRUE(dex_file != nullptr);
222
223 std::string method;
224 uint64_t method_offset;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000225 ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800226 EXPECT_EQ("Main.<init>", method);
227 EXPECT_EQ(2U, method_offset);
228
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000229 ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
David Srbecky02d0f792018-03-24 00:29:14 +0000230 EXPECT_EQ("Main.main", method);
231 EXPECT_EQ(0U, method_offset);
David Srbecky02d0f792018-03-24 00:29:14 +0000232}
233
234TEST(DexFileTest, get_method_empty) {
235 MemoryFake memory;
236 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris0f40a052020-01-22 12:17:06 -0800237 MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
David Srbecky02d0f792018-03-24 00:29:14 +0000238 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
239 ASSERT_TRUE(dex_file != nullptr);
240
241 std::string method;
242 uint64_t method_offset;
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000243 EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
David Srbecky02d0f792018-03-24 00:29:14 +0000244
David Srbeckyb9cc4fb2019-04-05 18:23:32 +0000245 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800246}
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800247
248} // namespace unwindstack