• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
23 #include <android-base/test_utils.h>
24 
25 #include <unwindstack/MapInfo.h>
26 #include <unwindstack/Memory.h>
27 
28 #include <dex/code_item_accessors-inl.h>
29 #include <dex/standard_dex_file.h>
30 
31 #include <gtest/gtest.h>
32 
33 #include "DexFile.h"
34 
35 #include "DexFileData.h"
36 #include "MemoryFake.h"
37 
38 namespace unwindstack {
39 
TEST(DexFileTest,from_file_open_non_exist)40 TEST(DexFileTest, from_file_open_non_exist) {
41   DexFileFromFile dex_file;
42   ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
43 }
44 
TEST(DexFileTest,from_file_open_too_small)45 TEST(DexFileTest, from_file_open_too_small) {
46   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.
54   DexFileFromFile dex_file;
55   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 
TEST(DexFileTest,from_file_open)64 TEST(DexFileTest, from_file_open) {
65   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 
71   DexFileFromFile dex_file;
72   ASSERT_TRUE(dex_file.Open(0, tf.path));
73 }
74 
TEST(DexFileTest,from_file_open_non_zero_offset)75 TEST(DexFileTest, from_file_open_non_zero_offset) {
76   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 
83   DexFileFromFile dex_file;
84   ASSERT_TRUE(dex_file.Open(0x100, tf.path));
85 }
86 
TEST(DexFileTest,from_memory_fail_too_small_for_header)87 TEST(DexFileTest, from_memory_fail_too_small_for_header) {
88   MemoryFake memory;
89 
90   memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
91   DexFileFromMemory dex_file;
92 
93   ASSERT_FALSE(dex_file.Open(0x1000, &memory));
94 }
95 
TEST(DexFileTest,from_memory_fail_too_small_for_data)96 TEST(DexFileTest, from_memory_fail_too_small_for_data) {
97   MemoryFake memory;
98 
99   memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
100   DexFileFromMemory dex_file;
101 
102   ASSERT_FALSE(dex_file.Open(0x1000, &memory));
103 }
104 
TEST(DexFileTest,from_memory_open)105 TEST(DexFileTest, from_memory_open) {
106   MemoryFake memory;
107 
108   memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
109   DexFileFromMemory dex_file;
110 
111   ASSERT_TRUE(dex_file.Open(0x1000, &memory));
112 }
113 
TEST(DexFileTest,create_using_file)114 TEST(DexFileTest, create_using_file) {
115   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;
123   MapInfo info(0, 0x10000, 0, 0x5, tf.path);
124   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
125   ASSERT_TRUE(dex_file != nullptr);
126 }
127 
TEST(DexFileTest,create_using_file_non_zero_start)128 TEST(DexFileTest, create_using_file_non_zero_start) {
129   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;
137   MapInfo info(0x100, 0x10000, 0, 0x5, tf.path);
138   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
139   ASSERT_TRUE(dex_file != nullptr);
140 }
141 
TEST(DexFileTest,create_using_file_non_zero_offset)142 TEST(DexFileTest, create_using_file_non_zero_offset) {
143   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;
151   MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path);
152   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
153   ASSERT_TRUE(dex_file != nullptr);
154 }
155 
TEST(DexFileTest,create_using_memory_empty_file)156 TEST(DexFileTest, create_using_memory_empty_file) {
157   MemoryFake memory;
158   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
159   MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
160   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
161   ASSERT_TRUE(dex_file != nullptr);
162 }
163 
TEST(DexFileTest,create_using_memory_file_does_not_exist)164 TEST(DexFileTest, create_using_memory_file_does_not_exist) {
165   MemoryFake memory;
166   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
167   MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
168   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
169   ASSERT_TRUE(dex_file != nullptr);
170 }
171 
TEST(DexFileTest,create_using_memory_file_is_malformed)172 TEST(DexFileTest, create_using_memory_file_is_malformed) {
173   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));
181   MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
182   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
183   ASSERT_TRUE(dex_file != nullptr);
184 
185   // Check it came from memory by clearing memory and verifying it fails.
186   memory.Clear();
187   dex_file.reset(DexFile::Create(0x4000, &memory, &info));
188   ASSERT_TRUE(dex_file == nullptr);
189 }
190 
TEST(DexFileTest,get_method_not_opened)191 TEST(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);
198 }
199 
TEST(DexFileTest,get_method)200 TEST(DexFileTest, get_method) {
201   MemoryFake memory;
202   memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
203   MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
204   std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
205   ASSERT_TRUE(dex_file != nullptr);
206 
207   std::string method;
208   uint64_t method_offset;
209   dex_file->GetMethodInformation(0x102, &method, &method_offset);
210   EXPECT_EQ("Main.<init>", method);
211   EXPECT_EQ(2U, method_offset);
212 
213   method = "not_in_a_method";
214   method_offset = 0x123;
215   dex_file->GetMethodInformation(0x100000, &method, &method_offset);
216   EXPECT_EQ("not_in_a_method", method);
217   EXPECT_EQ(0x123U, method_offset);
218 }
219 
220 }  // namespace unwindstack
221