blob: 21ca47b52c633fced70e8a3b983c5df6d4197fc4 [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 Stjernholmbb4f2b42018-12-19 14:28:33 +000024#include <dex/dex_file.h>
25#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 Stjernholmbb4f2b42018-12-19 14:28:33 +000043 ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
Christopher Ferris0b06a592018-01-19 10:26:36 -080044 static_cast<size_t>(
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000045 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
Christopher Ferris0b06a592018-01-19 10:26:36 -080046
47 // Header too small.
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000048 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080049
50 // Header correct, file too small.
51 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
52 ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
53 tf.fd, kDexData, sizeof(art::DexFile::Header)))));
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000054 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080055}
56
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080057TEST(DexFileTest, from_file_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080058 TemporaryFile tf;
59 ASSERT_TRUE(tf.fd != -1);
60
61 ASSERT_EQ(sizeof(kDexData),
62 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
63
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000064 EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080065}
66
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080067TEST(DexFileTest, from_file_open_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080068 TemporaryFile tf;
69 ASSERT_TRUE(tf.fd != -1);
70
71 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
72 ASSERT_EQ(sizeof(kDexData),
73 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
74
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000075 EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080076}
77
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080078TEST(DexFileTest, from_memory_fail_too_small_for_header) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080079 MemoryFake memory;
80
81 memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
Christopher Ferris0b06a592018-01-19 10:26:36 -080082
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000083 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080084}
85
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080086TEST(DexFileTest, from_memory_fail_too_small_for_data) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080087 MemoryFake memory;
88
89 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
Christopher Ferris0b06a592018-01-19 10:26:36 -080090
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000091 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -080092}
93
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080094TEST(DexFileTest, from_memory_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080095 MemoryFake memory;
96
97 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
Christopher Ferris0b06a592018-01-19 10:26:36 -080098
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +000099 EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800100}
101
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800102TEST(DexFileTest, create_using_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800103 TemporaryFile tf;
104 ASSERT_TRUE(tf.fd != -1);
105
106 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
107 ASSERT_EQ(sizeof(kDexData),
108 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
109
110 MemoryFake memory;
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700111 MapInfo info(nullptr, 0, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000112 EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800113}
114
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800115TEST(DexFileTest, create_using_file_non_zero_start) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800116 TemporaryFile tf;
117 ASSERT_TRUE(tf.fd != -1);
118
119 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
120 ASSERT_EQ(sizeof(kDexData),
121 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
122
123 MemoryFake memory;
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700124 MapInfo info(nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000125 EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800126}
127
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800128TEST(DexFileTest, create_using_file_non_zero_offset) {
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, 0x200, 0x5, tf.path);
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000138 EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800139}
140
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800141TEST(DexFileTest, create_using_memory_empty_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800142 MemoryFake memory;
143 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700144 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000145 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800146}
147
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800148TEST(DexFileTest, create_using_memory_file_does_not_exist) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800149 MemoryFake memory;
150 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700151 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000152 EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800153}
154
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800155TEST(DexFileTest, create_using_memory_file_is_malformed) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800156 TemporaryFile tf;
157 ASSERT_TRUE(tf.fd != -1);
158
159 ASSERT_EQ(sizeof(kDexData) - 10,
160 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
161
162 MemoryFake memory;
163 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700164 MapInfo info(nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000165 std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800166 ASSERT_TRUE(dex_file != nullptr);
167
168 // Check it came from memory by clearing memory and verifying it fails.
169 memory.Clear();
Martin Stjernholmbb4f2b42018-12-19 14:28:33 +0000170 dex_file = DexFile::Create(0x4000, &memory, &info);
171 EXPECT_TRUE(dex_file == nullptr);
Christopher Ferris0b06a592018-01-19 10:26:36 -0800172}
173
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800174TEST(DexFileTest, get_method) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800175 MemoryFake memory;
176 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700177 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800178 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800179 ASSERT_TRUE(dex_file != nullptr);
180
181 std::string method;
182 uint64_t method_offset;
David Srbecky02d0f792018-03-24 00:29:14 +0000183 ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800184 EXPECT_EQ("Main.<init>", method);
185 EXPECT_EQ(2U, method_offset);
186
David Srbecky02d0f792018-03-24 00:29:14 +0000187 ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
188 EXPECT_EQ("Main.main", method);
189 EXPECT_EQ(0U, method_offset);
190
191 // Make sure that any data that is cached is still retrievable.
192 ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
193 EXPECT_EQ("Main.<init>", method);
194 EXPECT_EQ(4U, method_offset);
195
196 ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
197 EXPECT_EQ("Main.main", method);
198 EXPECT_EQ(1U, method_offset);
199}
200
201TEST(DexFileTest, get_method_empty) {
202 MemoryFake memory;
203 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferris9d5712c2018-10-01 21:01:09 -0700204 MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
David Srbecky02d0f792018-03-24 00:29:14 +0000205 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
206 ASSERT_TRUE(dex_file != nullptr);
207
208 std::string method;
209 uint64_t method_offset;
210 EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
211
212 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
213
214 // Make sure that once the whole dex file has been cached, no problems occur.
215 EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
216
217 // Choose a value that is in the cached map, but not in a valid method.
218 EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800219}
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800220
221} // namespace unwindstack