blob: 655dcc8e322719dada5430732d84fab4da6cccfd [file] [log] [blame]
Christopher Ferris7747b602018-01-31 19:05:19 -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 <elf.h>
18#include <string.h>
19
20#include <memory>
21#include <vector>
22
23#include <gtest/gtest.h>
24
Christopher Ferris7747b602018-01-31 19:05:19 -080025#include <unwindstack/Elf.h>
David Srbecky85b5fec2018-02-23 18:06:13 +000026#include <unwindstack/JitDebug.h>
Christopher Ferris7747b602018-01-31 19:05:19 -080027#include <unwindstack/MapInfo.h>
28#include <unwindstack/Maps.h>
29#include <unwindstack/Memory.h>
30
31#include "DexFileData.h"
32#include "ElfFake.h"
33#include "MemoryFake.h"
34
David Srbecky85b5fec2018-02-23 18:06:13 +000035#if !defined(NO_LIBDEXFILE_SUPPORT)
36#include <DexFile.h>
37#endif
38
Christopher Ferris7747b602018-01-31 19:05:19 -080039namespace unwindstack {
40
41class DexFilesTest : public ::testing::Test {
42 protected:
Christopher Ferris4568f4b2018-10-23 17:42:41 -070043 void CreateFakeElf(MapInfo* map_info) {
44 MemoryFake* memory = new MemoryFake;
45 ElfFake* elf = new ElfFake(memory);
46 elf->FakeSetValid(true);
47 ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
48 elf->FakeSetInterface(interface);
Christopher Ferris7747b602018-01-31 19:05:19 -080049
Christopher Ferris4568f4b2018-10-23 17:42:41 -070050 interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
51 map_info->elf.reset(elf);
52 }
53
54 void Init(ArchEnum arch) {
David Srbecky85b5fec2018-02-23 18:06:13 +000055 dex_files_ = JitDebug<DexFile>::Create(arch, process_memory_);
Christopher Ferris7747b602018-01-31 19:05:19 -080056
57 maps_.reset(
Christopher Ferris56d0e072018-10-17 10:57:53 -070058 new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
59 "4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
60 "6000-8000 -wxs 00000000 00:00 0 /fake/elf\n"
61 "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
62 "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
63 "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
64 "100000-110000 rw-p 0001000 00:00 0 /fake/elf3\n"
65 "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
66 "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"));
Christopher Ferris7747b602018-01-31 19:05:19 -080067 ASSERT_TRUE(maps_->Parse());
68
Christopher Ferris1f34c0e2018-10-08 17:39:39 -070069 // Global variable in a section that is not readable.
70 MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
Christopher Ferris7747b602018-01-31 19:05:19 -080071 ASSERT_TRUE(map_info != nullptr);
Christopher Ferris4568f4b2018-10-23 17:42:41 -070072 CreateFakeElf(map_info);
Christopher Ferris7747b602018-01-31 19:05:19 -080073
74 // Global variable not set by default.
75 map_info = maps_->Get(kMapGlobalSetToZero);
76 ASSERT_TRUE(map_info != nullptr);
Christopher Ferris4568f4b2018-10-23 17:42:41 -070077 CreateFakeElf(map_info);
Christopher Ferris7747b602018-01-31 19:05:19 -080078
79 // Global variable set in this map.
80 map_info = maps_->Get(kMapGlobal);
81 ASSERT_TRUE(map_info != nullptr);
Christopher Ferris4568f4b2018-10-23 17:42:41 -070082 CreateFakeElf(map_info);
83 }
84
85 void SetUp() override {
86 memory_ = new MemoryFake;
87 process_memory_.reset(memory_);
88
89 Init(ARCH_ARM);
Christopher Ferris7747b602018-01-31 19:05:19 -080090 }
91
David Srbecky85b5fec2018-02-23 18:06:13 +000092 void WriteDescriptor32(uint64_t addr, uint32_t entry);
93 void WriteDescriptor64(uint64_t addr, uint64_t entry);
94 void WriteEntry32Pack(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex);
95 void WriteEntry32Pad(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex);
96 void WriteEntry64(uint64_t addr, uint64_t next, uint64_t prev, uint64_t dex);
Christopher Ferris7747b602018-01-31 19:05:19 -080097 void WriteDex(uint64_t dex_file);
98
Christopher Ferris1f34c0e2018-10-08 17:39:39 -070099 static constexpr size_t kMapGlobalNonReadable = 2;
Christopher Ferris56d0e072018-10-17 10:57:53 -0700100 static constexpr size_t kMapGlobalSetToZero = 3;
Christopher Ferris7747b602018-01-31 19:05:19 -0800101 static constexpr size_t kMapGlobal = 5;
Christopher Ferris56d0e072018-10-17 10:57:53 -0700102 static constexpr size_t kMapGlobalRw = 6;
Christopher Ferris7747b602018-01-31 19:05:19 -0800103 static constexpr size_t kMapDexFileEntries = 7;
104 static constexpr size_t kMapDexFiles = 8;
105
106 std::shared_ptr<Memory> process_memory_;
107 MemoryFake* memory_;
David Srbecky85b5fec2018-02-23 18:06:13 +0000108 std::unique_ptr<JitDebug<DexFile>> dex_files_;
Christopher Ferris7747b602018-01-31 19:05:19 -0800109 std::unique_ptr<BufferMaps> maps_;
110};
111
David Srbecky85b5fec2018-02-23 18:06:13 +0000112void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t entry) {
113 // Format of the 32 bit JITDescriptor structure:
114 // uint32_t version
115 memory_->SetData32(addr, 1);
116 // uint32_t action_flag
117 memory_->SetData32(addr + 4, 0);
118 // uint32_t relevant_entry
119 memory_->SetData32(addr + 8, 0);
120 // uint32_t first_entry
121 memory_->SetData32(addr + 12, entry);
David Srbecky4015ef42018-02-15 17:57:16 +0000122}
123
David Srbecky85b5fec2018-02-23 18:06:13 +0000124void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t entry) {
125 // Format of the 64 bit JITDescriptor structure:
126 // uint32_t version
127 memory_->SetData32(addr, 1);
128 // uint32_t action_flag
129 memory_->SetData32(addr + 4, 0);
130 // uint64_t relevant_entry
131 memory_->SetData64(addr + 8, 0);
132 // uint64_t first_entry
133 memory_->SetData64(addr + 16, entry);
David Srbecky4015ef42018-02-15 17:57:16 +0000134}
135
David Srbecky85b5fec2018-02-23 18:06:13 +0000136void DexFilesTest::WriteEntry32Pack(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex) {
137 // Format of the 32 bit JITCodeEntry structure:
Christopher Ferris7747b602018-01-31 19:05:19 -0800138 // uint32_t next
David Srbecky85b5fec2018-02-23 18:06:13 +0000139 memory_->SetData32(addr, next);
Christopher Ferris7747b602018-01-31 19:05:19 -0800140 // uint32_t prev
David Srbecky85b5fec2018-02-23 18:06:13 +0000141 memory_->SetData32(addr + 4, prev);
142 // uint32_t dex
143 memory_->SetData32(addr + 8, dex);
144 // uint64_t symfile_size
145 memory_->SetData64(addr + 12, sizeof(kDexData) * sizeof(uint32_t));
Christopher Ferris7747b602018-01-31 19:05:19 -0800146}
147
David Srbecky85b5fec2018-02-23 18:06:13 +0000148void DexFilesTest::WriteEntry32Pad(uint64_t addr, uint32_t next, uint32_t prev, uint32_t dex) {
149 // Format of the 32 bit JITCodeEntry structure:
150 // uint32_t next
151 memory_->SetData32(addr, next);
152 // uint32_t prev
153 memory_->SetData32(addr + 4, prev);
154 // uint32_t dex
155 memory_->SetData32(addr + 8, dex);
156 // uint32_t pad
157 memory_->SetData32(addr + 12, 0);
158 // uint64_t symfile_size
159 memory_->SetData64(addr + 16, sizeof(kDexData) * sizeof(uint32_t));
160}
161
162void DexFilesTest::WriteEntry64(uint64_t addr, uint64_t next, uint64_t prev, uint64_t dex) {
163 // Format of the 64 bit JITCodeEntry structure:
Christopher Ferris7747b602018-01-31 19:05:19 -0800164 // uint64_t next
David Srbecky85b5fec2018-02-23 18:06:13 +0000165 memory_->SetData64(addr, next);
Christopher Ferris7747b602018-01-31 19:05:19 -0800166 // uint64_t prev
David Srbecky85b5fec2018-02-23 18:06:13 +0000167 memory_->SetData64(addr + 8, prev);
168 // uint64_t dex
169 memory_->SetData64(addr + 16, dex);
170 // uint64_t symfile_size
171 memory_->SetData64(addr + 24, sizeof(kDexData) * sizeof(uint32_t));
Christopher Ferris7747b602018-01-31 19:05:19 -0800172}
173
174void DexFilesTest::WriteDex(uint64_t dex_file) {
175 memory_->SetMemory(dex_file, kDexData, sizeof(kDexData) * sizeof(uint32_t));
176}
177
178TEST_F(DexFilesTest, get_method_information_invalid) {
179 std::string method_name = "nothing";
180 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800181
David Srbecky85b5fec2018-02-23 18:06:13 +0000182 dex_files_->GetFunctionName(maps_.get(), 0, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800183 EXPECT_EQ("nothing", method_name);
184 EXPECT_EQ(0x124U, method_offset);
185}
186
187TEST_F(DexFilesTest, get_method_information_32) {
188 std::string method_name = "nothing";
189 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800190
David Srbecky4015ef42018-02-15 17:57:16 +0000191 WriteDescriptor32(0xf800, 0x200000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000192 WriteEntry32Pad(0x200000, 0, 0, 0x300000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800193 WriteDex(0x300000);
194
David Srbecky85b5fec2018-02-23 18:06:13 +0000195 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800196 EXPECT_EQ("Main.<init>", method_name);
197 EXPECT_EQ(0U, method_offset);
198}
199
200TEST_F(DexFilesTest, get_method_information_64) {
Christopher Ferris4568f4b2018-10-23 17:42:41 -0700201 Init(ARCH_ARM64);
202
Christopher Ferris7747b602018-01-31 19:05:19 -0800203 std::string method_name = "nothing";
204 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800205
David Srbecky4015ef42018-02-15 17:57:16 +0000206 WriteDescriptor64(0xf800, 0x200000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800207 WriteEntry64(0x200000, 0, 0, 0x301000);
208 WriteDex(0x301000);
209
David Srbecky85b5fec2018-02-23 18:06:13 +0000210 dex_files_->GetFunctionName(maps_.get(), 0x301102, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800211 EXPECT_EQ("Main.<init>", method_name);
212 EXPECT_EQ(2U, method_offset);
213}
214
215TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
216 std::string method_name = "nothing";
217 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800218
David Srbecky4015ef42018-02-15 17:57:16 +0000219 WriteDescriptor32(0xf800, 0x200000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000220 WriteEntry32Pad(0x200000, 0x200100, 0, 0x100000);
221 WriteDex(0x100000);
222 WriteEntry32Pad(0x200100, 0, 0x200000, 0x300000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800223 WriteDex(0x300000);
224
David Srbecky85b5fec2018-02-23 18:06:13 +0000225 dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800226 EXPECT_EQ("Main.<init>", method_name);
227 EXPECT_EQ(4U, method_offset);
228}
229
230TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
Christopher Ferris4568f4b2018-10-23 17:42:41 -0700231 Init(ARCH_ARM64);
232
Christopher Ferris7747b602018-01-31 19:05:19 -0800233 std::string method_name = "nothing";
234 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800235
David Srbecky4015ef42018-02-15 17:57:16 +0000236 WriteDescriptor64(0xf800, 0x200000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800237 WriteEntry64(0x200000, 0x200100, 0, 0x100000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000238 WriteDex(0x100000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800239 WriteEntry64(0x200100, 0, 0x200000, 0x300000);
240 WriteDex(0x300000);
241
David Srbecky85b5fec2018-02-23 18:06:13 +0000242 dex_files_->GetFunctionName(maps_.get(), 0x300106, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800243 EXPECT_EQ("Main.<init>", method_name);
244 EXPECT_EQ(6U, method_offset);
245}
246
247TEST_F(DexFilesTest, get_method_information_cached) {
248 std::string method_name = "nothing";
249 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800250
David Srbecky4015ef42018-02-15 17:57:16 +0000251 WriteDescriptor32(0xf800, 0x200000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000252 WriteEntry32Pad(0x200000, 0, 0, 0x300000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800253 WriteDex(0x300000);
254
David Srbecky85b5fec2018-02-23 18:06:13 +0000255 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800256 EXPECT_EQ("Main.<init>", method_name);
257 EXPECT_EQ(0U, method_offset);
258
259 // Clear all memory and make sure that data is acquired from the cache.
260 memory_->Clear();
David Srbecky85b5fec2018-02-23 18:06:13 +0000261 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800262 EXPECT_EQ("Main.<init>", method_name);
263 EXPECT_EQ(0U, method_offset);
264}
265
266TEST_F(DexFilesTest, get_method_information_search_libs) {
267 std::string method_name = "nothing";
268 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800269
David Srbecky4015ef42018-02-15 17:57:16 +0000270 WriteDescriptor32(0xf800, 0x200000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000271 WriteEntry32Pad(0x200000, 0x200100, 0, 0x100000);
272 WriteDex(0x100000);
273 WriteEntry32Pad(0x200100, 0, 0x200000, 0x300000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800274 WriteDex(0x300000);
275
276 // Only search a given named list of libs.
277 std::vector<std::string> libs{"libart.so"};
David Srbecky85b5fec2018-02-23 18:06:13 +0000278 dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_, libs);
Christopher Ferris7747b602018-01-31 19:05:19 -0800279
David Srbecky85b5fec2018-02-23 18:06:13 +0000280 dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800281 EXPECT_EQ("nothing", method_name);
282 EXPECT_EQ(0x124U, method_offset);
283
284 MapInfo* map_info = maps_->Get(kMapGlobal);
285 map_info->name = "/system/lib/libart.so";
David Srbecky85b5fec2018-02-23 18:06:13 +0000286 dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_, libs);
Christopher Ferris56d0e072018-10-17 10:57:53 -0700287 // Set the rw map to the same name or this will not scan this entry.
288 map_info = maps_->Get(kMapGlobalRw);
289 map_info->name = "/system/lib/libart.so";
Christopher Ferris7747b602018-01-31 19:05:19 -0800290 // Make sure that clearing out copy of the libs doesn't affect the
291 // DexFiles object.
292 libs.clear();
293
David Srbecky85b5fec2018-02-23 18:06:13 +0000294 dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800295 EXPECT_EQ("Main.<init>", method_name);
296 EXPECT_EQ(4U, method_offset);
297}
298
299TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
300 std::string method_name = "nothing";
301 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800302
303 // First global variable found, but value is zero.
Christopher Ferris56d0e072018-10-17 10:57:53 -0700304 WriteDescriptor32(0xa800, 0);
Christopher Ferris7747b602018-01-31 19:05:19 -0800305
David Srbecky4015ef42018-02-15 17:57:16 +0000306 WriteDescriptor32(0xf800, 0x200000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000307 WriteEntry32Pad(0x200000, 0, 0, 0x300000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800308 WriteDex(0x300000);
309
David Srbecky85b5fec2018-02-23 18:06:13 +0000310 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800311 EXPECT_EQ("Main.<init>", method_name);
312 EXPECT_EQ(0U, method_offset);
313
314 // Verify that second is ignored when first is set to non-zero
David Srbecky85b5fec2018-02-23 18:06:13 +0000315 dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM, process_memory_);
Christopher Ferris7747b602018-01-31 19:05:19 -0800316 method_name = "fail";
317 method_offset = 0x123;
Christopher Ferris56d0e072018-10-17 10:57:53 -0700318 WriteDescriptor32(0xa800, 0x100000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000319 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800320 EXPECT_EQ("fail", method_name);
321 EXPECT_EQ(0x123U, method_offset);
322}
323
324TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
Christopher Ferris4568f4b2018-10-23 17:42:41 -0700325 Init(ARCH_ARM64);
326
Christopher Ferris7747b602018-01-31 19:05:19 -0800327 std::string method_name = "nothing";
328 uint64_t method_offset = 0x124;
Christopher Ferris7747b602018-01-31 19:05:19 -0800329
330 // First global variable found, but value is zero.
Christopher Ferris56d0e072018-10-17 10:57:53 -0700331 WriteDescriptor64(0xa800, 0);
Christopher Ferris7747b602018-01-31 19:05:19 -0800332
David Srbecky4015ef42018-02-15 17:57:16 +0000333 WriteDescriptor64(0xf800, 0x200000);
Christopher Ferris7747b602018-01-31 19:05:19 -0800334 WriteEntry64(0x200000, 0, 0, 0x300000);
335 WriteDex(0x300000);
336
David Srbecky85b5fec2018-02-23 18:06:13 +0000337 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800338 EXPECT_EQ("Main.<init>", method_name);
339 EXPECT_EQ(0U, method_offset);
340
341 // Verify that second is ignored when first is set to non-zero
David Srbecky85b5fec2018-02-23 18:06:13 +0000342 dex_files_ = JitDebug<DexFile>::Create(ARCH_ARM64, process_memory_);
Christopher Ferris7747b602018-01-31 19:05:19 -0800343 method_name = "fail";
344 method_offset = 0x123;
Christopher Ferris56d0e072018-10-17 10:57:53 -0700345 WriteDescriptor64(0xa800, 0x100000);
David Srbecky85b5fec2018-02-23 18:06:13 +0000346 dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
Christopher Ferris7747b602018-01-31 19:05:19 -0800347 EXPECT_EQ("fail", method_name);
348 EXPECT_EQ(0x123U, method_offset);
349}
350
351} // namespace unwindstack