blob: 95d217631b5ca71a019591bd2c2e3948786f0227 [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
17#include <stdint.h>
18#include <sys/types.h>
19#include <unistd.h>
20
21#include <unordered_map>
22
Mark Salyzyn9f1cf252018-11-12 12:45:59 -080023#include <android-base/file.h>
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000024
Christopher Ferris0b06a592018-01-19 10:26:36 -080025#include <unwindstack/MapInfo.h>
26#include <unwindstack/Memory.h>
27
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000028#include <dex/code_item_accessors-inl.h>
29#include <dex/standard_dex_file.h>
30
31#include <gtest/gtest.h>
32
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080033#include "DexFile.h"
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000034
Christopher Ferris7747b602018-01-31 19:05:19 -080035#include "DexFileData.h"
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080036#include "MemoryFake.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080037
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080038namespace unwindstack {
Christopher Ferris0b06a592018-01-19 10:26:36 -080039
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080040TEST(DexFileTest, from_file_open_non_exist) {
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000041 DexFileFromFile dex_file;
42 ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
Christopher Ferris0b06a592018-01-19 10:26:36 -080043}
44
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080045TEST(DexFileTest, from_file_open_too_small) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080046 TemporaryFile tf;
47 ASSERT_TRUE(tf.fd != -1);
48
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000049 ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
Christopher Ferris0b06a592018-01-19 10:26:36 -080050 static_cast<size_t>(
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000051 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
Christopher Ferris0b06a592018-01-19 10:26:36 -080052
53 // Header too small.
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000054 DexFileFromFile dex_file;
55 ASSERT_FALSE(dex_file.Open(0, tf.path));
Christopher Ferris0b06a592018-01-19 10:26:36 -080056
57 // Header correct, file too small.
58 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
59 ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
60 tf.fd, kDexData, sizeof(art::DexFile::Header)))));
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000061 ASSERT_FALSE(dex_file.Open(0, tf.path));
Christopher Ferris0b06a592018-01-19 10:26:36 -080062}
63
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080064TEST(DexFileTest, from_file_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080065 TemporaryFile tf;
66 ASSERT_TRUE(tf.fd != -1);
67
68 ASSERT_EQ(sizeof(kDexData),
69 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
70
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000071 DexFileFromFile dex_file;
72 ASSERT_TRUE(dex_file.Open(0, tf.path));
Christopher Ferris0b06a592018-01-19 10:26:36 -080073}
74
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080075TEST(DexFileTest, from_file_open_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080076 TemporaryFile tf;
77 ASSERT_TRUE(tf.fd != -1);
78
79 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
80 ASSERT_EQ(sizeof(kDexData),
81 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
82
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000083 DexFileFromFile dex_file;
84 ASSERT_TRUE(dex_file.Open(0x100, tf.path));
Christopher Ferris0b06a592018-01-19 10:26:36 -080085}
86
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080087TEST(DexFileTest, from_memory_fail_too_small_for_header) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080088 MemoryFake memory;
89
90 memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000091 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080092
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +000093 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
Christopher Ferris0b06a592018-01-19 10:26:36 -080094}
95
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080096TEST(DexFileTest, from_memory_fail_too_small_for_data) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080097 MemoryFake memory;
98
99 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000100 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800101
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000102 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800103}
104
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800105TEST(DexFileTest, from_memory_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800106 MemoryFake memory;
107
108 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000109 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800110
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000111 ASSERT_TRUE(dex_file.Open(0x1000, &memory));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800112}
113
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800114TEST(DexFileTest, create_using_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800115 TemporaryFile tf;
116 ASSERT_TRUE(tf.fd != -1);
117
118 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
119 ASSERT_EQ(sizeof(kDexData),
120 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
121
122 MemoryFake memory;
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700123 MapInfo info(nullptr, 0, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000124 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
125 ASSERT_TRUE(dex_file != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800126}
127
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800128TEST(DexFileTest, create_using_file_non_zero_start) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800129 TemporaryFile tf;
130 ASSERT_TRUE(tf.fd != -1);
131
132 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
133 ASSERT_EQ(sizeof(kDexData),
134 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
135
136 MemoryFake memory;
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700137 MapInfo info(nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000138 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
139 ASSERT_TRUE(dex_file != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800140}
141
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800142TEST(DexFileTest, create_using_file_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800143 TemporaryFile tf;
144 ASSERT_TRUE(tf.fd != -1);
145
146 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
147 ASSERT_EQ(sizeof(kDexData),
148 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
149
150 MemoryFake memory;
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700151 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000152 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
153 ASSERT_TRUE(dex_file != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800154}
155
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800156TEST(DexFileTest, create_using_memory_empty_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800157 MemoryFake memory;
158 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700159 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000160 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
161 ASSERT_TRUE(dex_file != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800162}
163
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800164TEST(DexFileTest, create_using_memory_file_does_not_exist) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800165 MemoryFake memory;
166 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700167 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000168 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
169 ASSERT_TRUE(dex_file != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800170}
171
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800172TEST(DexFileTest, create_using_memory_file_is_malformed) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800173 TemporaryFile tf;
174 ASSERT_TRUE(tf.fd != -1);
175
176 ASSERT_EQ(sizeof(kDexData) - 10,
177 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
178
179 MemoryFake memory;
180 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700181 MapInfo info(nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000182 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800183 ASSERT_TRUE(dex_file != nullptr);
184
185 // Check it came from memory by clearing memory and verifying it fails.
186 memory.Clear();
Martin Stjernholmcacf5bf2018-12-19 00:09:41 +0000187 dex_file.reset(DexFile::Create(0x4000, &memory, &info));
188 ASSERT_TRUE(dex_file == nullptr);
189}
190
191TEST(DexFileTest, get_method_not_opened) {
192 std::string method("something");
193 uint64_t method_offset = 100;
194 DexFile dex_file;
195 dex_file.GetMethodInformation(0x100, &method, &method_offset);
196 EXPECT_EQ("something", method);
197 EXPECT_EQ(100U, method_offset);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800198}
199
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800200TEST(DexFileTest, get_method) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800201 MemoryFake memory;
202 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700203 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800204 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800205 ASSERT_TRUE(dex_file != nullptr);
206
207 std::string method;
208 uint64_t method_offset;
David Srbecky02d0f792018-03-24 00:29:14 +0000209 ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800210 EXPECT_EQ("Main.<init>", method);
211 EXPECT_EQ(2U, method_offset);
212
David Srbecky02d0f792018-03-24 00:29:14 +0000213 ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
214 EXPECT_EQ("Main.main", method);
215 EXPECT_EQ(0U, method_offset);
216
217 // Make sure that any data that is cached is still retrievable.
218 ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
219 EXPECT_EQ("Main.<init>", method);
220 EXPECT_EQ(4U, method_offset);
221
222 ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
223 EXPECT_EQ("Main.main", method);
224 EXPECT_EQ(1U, method_offset);
225}
226
227TEST(DexFileTest, get_method_empty) {
228 MemoryFake memory;
229 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700230 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
David Srbecky02d0f792018-03-24 00:29:14 +0000231 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
232 ASSERT_TRUE(dex_file != nullptr);
233
234 std::string method;
235 uint64_t method_offset;
236 EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
237
238 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
239
240 // Make sure that once the whole dex file has been cached, no problems occur.
241 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
242
243 // Choose a value that is in the cached map, but not in a valid method.
244 EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800245}
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800246
247} // namespace unwindstack