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>
Christopher Ferris0b06a592018-01-19 10:26:36 -080024
25#include <unwindstack/MapInfo.h>
26#include <unwindstack/Memory.h>
27
David Sehr892e6752018-02-07 15:19:22 -080028#include <dex/code_item_accessors-inl.h>
Christopher Ferris0b06a592018-01-19 10:26:36 -080029#include <dex/standard_dex_file.h>
30
31#include <gtest/gtest.h>
32
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080033#include "DexFile.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080034
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) {
41 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080042 ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
43}
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
49 ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
50 static_cast<size_t>(
51 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
52
53 // Header too small.
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080054 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080055 ASSERT_FALSE(dex_file.Open(0, tf.path));
56
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)))));
61 ASSERT_FALSE(dex_file.Open(0, tf.path));
62}
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
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080071 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080072 ASSERT_TRUE(dex_file.Open(0, tf.path));
73}
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
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080083 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080084 ASSERT_TRUE(dex_file.Open(0x100, tf.path));
85}
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);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080091 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080092
93 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
94}
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);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800100 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800101
102 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
103}
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));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800109 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800110
111 ASSERT_TRUE(dex_file.Open(0x1000, &memory));
112}
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);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800124 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800125 ASSERT_TRUE(dex_file != nullptr);
126}
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);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800138 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800139 ASSERT_TRUE(dex_file != nullptr);
140}
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);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800152 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800153 ASSERT_TRUE(dex_file != nullptr);
154}
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, "");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800160 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800161 ASSERT_TRUE(dex_file != nullptr);
162}
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");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800168 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800169 ASSERT_TRUE(dex_file != nullptr);
170}
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");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800182 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();
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800187 dex_file.reset(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800188 ASSERT_TRUE(dex_file == nullptr);
189}
190
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800191TEST(DexFileTest, get_method_not_opened) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800192 std::string method("something");
193 uint64_t method_offset = 100;
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800194 DexFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800195 dex_file.GetMethodInformation(0x100, &method, &method_offset);
196 EXPECT_EQ("something", method);
197 EXPECT_EQ(100U, method_offset);
198}
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