1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <elf.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <string.h>
19*eb293b8fSAndroid Build Coastguard Worker
20*eb293b8fSAndroid Build Coastguard Worker #include <memory>
21*eb293b8fSAndroid Build Coastguard Worker #include <vector>
22*eb293b8fSAndroid Build Coastguard Worker
23*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
24*eb293b8fSAndroid Build Coastguard Worker
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DexFiles.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
28*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
30*eb293b8fSAndroid Build Coastguard Worker
31*eb293b8fSAndroid Build Coastguard Worker #include "DexFile.h"
32*eb293b8fSAndroid Build Coastguard Worker #include "DexFileData.h"
33*eb293b8fSAndroid Build Coastguard Worker #include "ElfFake.h"
34*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
35*eb293b8fSAndroid Build Coastguard Worker
36*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
37*eb293b8fSAndroid Build Coastguard Worker
38*eb293b8fSAndroid Build Coastguard Worker class DexFilesTest : public ::testing::Test {
39*eb293b8fSAndroid Build Coastguard Worker protected:
CreateFakeElf(MapInfo * map_info,uint64_t global_offset,uint64_t data_offset,uint64_t data_vaddr,uint64_t data_size)40*eb293b8fSAndroid Build Coastguard Worker void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
41*eb293b8fSAndroid Build Coastguard Worker uint64_t data_vaddr, uint64_t data_size) {
42*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> fake_memory(new MemoryFake);
43*eb293b8fSAndroid Build Coastguard Worker ElfFake* elf = new ElfFake(fake_memory);
44*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetValid(true);
45*eb293b8fSAndroid Build Coastguard Worker ElfInterfaceFake* interface = new ElfInterfaceFake(fake_memory);
46*eb293b8fSAndroid Build Coastguard Worker elf->FakeSetInterface(interface);
47*eb293b8fSAndroid Build Coastguard Worker
48*eb293b8fSAndroid Build Coastguard Worker interface->FakeSetGlobalVariable("__dex_debug_descriptor", global_offset);
49*eb293b8fSAndroid Build Coastguard Worker interface->FakeSetDataOffset(data_offset);
50*eb293b8fSAndroid Build Coastguard Worker interface->FakeSetDataVaddrStart(data_vaddr);
51*eb293b8fSAndroid Build Coastguard Worker interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
52*eb293b8fSAndroid Build Coastguard Worker map_info->set_elf(elf);
53*eb293b8fSAndroid Build Coastguard Worker }
54*eb293b8fSAndroid Build Coastguard Worker
Init(ArchEnum arch)55*eb293b8fSAndroid Build Coastguard Worker void Init(ArchEnum arch) {
56*eb293b8fSAndroid Build Coastguard Worker dex_files_ = CreateDexFiles(arch, process_memory_);
57*eb293b8fSAndroid Build Coastguard Worker
58*eb293b8fSAndroid Build Coastguard Worker maps_.reset(
59*eb293b8fSAndroid Build Coastguard Worker new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
60*eb293b8fSAndroid Build Coastguard Worker "4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
61*eb293b8fSAndroid Build Coastguard Worker "6000-8000 -wxs 00002000 00:00 0 /fake/elf\n"
62*eb293b8fSAndroid Build Coastguard Worker "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
63*eb293b8fSAndroid Build Coastguard Worker "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
64*eb293b8fSAndroid Build Coastguard Worker "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
65*eb293b8fSAndroid Build Coastguard Worker "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n"
66*eb293b8fSAndroid Build Coastguard Worker "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
67*eb293b8fSAndroid Build Coastguard Worker "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"
68*eb293b8fSAndroid Build Coastguard Worker "500000-501000 r--p 0000000 00:00 0 /fake/elf4\n"
69*eb293b8fSAndroid Build Coastguard Worker "501000-502000 ---p 0000000 00:00 0\n"
70*eb293b8fSAndroid Build Coastguard Worker "503000-510000 rw-p 0003000 00:00 0 /fake/elf4\n"
71*eb293b8fSAndroid Build Coastguard Worker "510000-520000 rw-p 0010000 00:00 0 /fake/elf4\n"
72*eb293b8fSAndroid Build Coastguard Worker "600000-601000 r--p 0000000 00:00 0 /fake/elf5\n"
73*eb293b8fSAndroid Build Coastguard Worker "601000-602000 ---p 0000000 00:00 0 [page size compat]\n"
74*eb293b8fSAndroid Build Coastguard Worker "603000-610000 rw-p 0003000 00:00 0 /fake/elf5\n"));
75*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(maps_->Parse());
76*eb293b8fSAndroid Build Coastguard Worker
77*eb293b8fSAndroid Build Coastguard Worker // Global variable in a section that is not readable.
78*eb293b8fSAndroid Build Coastguard Worker MapInfo* map_info = maps_->Get(kMapGlobalNonReadable).get();
79*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
80*eb293b8fSAndroid Build Coastguard Worker CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
81*eb293b8fSAndroid Build Coastguard Worker
82*eb293b8fSAndroid Build Coastguard Worker // Global variable not set by default.
83*eb293b8fSAndroid Build Coastguard Worker map_info = maps_->Get(kMapGlobalSetToZero).get();
84*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
85*eb293b8fSAndroid Build Coastguard Worker CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
86*eb293b8fSAndroid Build Coastguard Worker
87*eb293b8fSAndroid Build Coastguard Worker // Global variable set in this map.
88*eb293b8fSAndroid Build Coastguard Worker map_info = maps_->Get(kMapGlobal).get();
89*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
90*eb293b8fSAndroid Build Coastguard Worker CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000);
91*eb293b8fSAndroid Build Coastguard Worker
92*eb293b8fSAndroid Build Coastguard Worker // Global variable set in this map, but there is an empty map before rw map.
93*eb293b8fSAndroid Build Coastguard Worker map_info = maps_->Get(kMapGlobalAfterEmpty).get();
94*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
95*eb293b8fSAndroid Build Coastguard Worker CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000);
96*eb293b8fSAndroid Build Coastguard Worker
97*eb293b8fSAndroid Build Coastguard Worker // Global variable set in this map, but there is a page size compat map before rw map.
98*eb293b8fSAndroid Build Coastguard Worker map_info = maps_->Get(kMapGlobalAfterPageSizeCompat).get();
99*eb293b8fSAndroid Build Coastguard Worker ASSERT_TRUE(map_info != nullptr);
100*eb293b8fSAndroid Build Coastguard Worker CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000);
101*eb293b8fSAndroid Build Coastguard Worker }
102*eb293b8fSAndroid Build Coastguard Worker
SetUp()103*eb293b8fSAndroid Build Coastguard Worker void SetUp() override {
104*eb293b8fSAndroid Build Coastguard Worker memory_ = new MemoryFake;
105*eb293b8fSAndroid Build Coastguard Worker process_memory_.reset(memory_);
106*eb293b8fSAndroid Build Coastguard Worker
107*eb293b8fSAndroid Build Coastguard Worker Init(ARCH_ARM);
108*eb293b8fSAndroid Build Coastguard Worker }
109*eb293b8fSAndroid Build Coastguard Worker
110*eb293b8fSAndroid Build Coastguard Worker void WriteDescriptor32(uint64_t addr, uint32_t head);
111*eb293b8fSAndroid Build Coastguard Worker void WriteDescriptor64(uint64_t addr, uint64_t head);
112*eb293b8fSAndroid Build Coastguard Worker void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file,
113*eb293b8fSAndroid Build Coastguard Worker uint64_t dex_size);
114*eb293b8fSAndroid Build Coastguard Worker void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file,
115*eb293b8fSAndroid Build Coastguard Worker uint64_t dex_size);
116*eb293b8fSAndroid Build Coastguard Worker void WriteDex(uint64_t dex_file);
117*eb293b8fSAndroid Build Coastguard Worker
118*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobalNonReadable = 2;
119*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobalSetToZero = 3;
120*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobal = 5;
121*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobalRw = 6;
122*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapDexFileEntries = 7;
123*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapDexFiles = 8;
124*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobalAfterEmpty = 9;
125*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapDexFilesAfterEmpty = 12;
126*eb293b8fSAndroid Build Coastguard Worker static constexpr size_t kMapGlobalAfterPageSizeCompat = 13;
127*eb293b8fSAndroid Build Coastguard Worker
128*eb293b8fSAndroid Build Coastguard Worker std::shared_ptr<Memory> process_memory_;
129*eb293b8fSAndroid Build Coastguard Worker MemoryFake* memory_;
130*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<DexFiles> dex_files_;
131*eb293b8fSAndroid Build Coastguard Worker std::unique_ptr<BufferMaps> maps_;
132*eb293b8fSAndroid Build Coastguard Worker };
133*eb293b8fSAndroid Build Coastguard Worker
WriteDescriptor32(uint64_t addr,uint32_t entry)134*eb293b8fSAndroid Build Coastguard Worker void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t entry) {
135*eb293b8fSAndroid Build Coastguard Worker // uint32_t version
136*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr, 1);
137*eb293b8fSAndroid Build Coastguard Worker // uint32_t action_flag
138*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr + 4, 0);
139*eb293b8fSAndroid Build Coastguard Worker // uint32_t relevant_entry
140*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr + 8, 0);
141*eb293b8fSAndroid Build Coastguard Worker // uint32_t first_entry
142*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr + 12, entry);
143*eb293b8fSAndroid Build Coastguard Worker }
144*eb293b8fSAndroid Build Coastguard Worker
WriteDescriptor64(uint64_t addr,uint64_t entry)145*eb293b8fSAndroid Build Coastguard Worker void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t entry) {
146*eb293b8fSAndroid Build Coastguard Worker // uint32_t version
147*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr, 1);
148*eb293b8fSAndroid Build Coastguard Worker // uint32_t action_flag
149*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(addr + 4, 0);
150*eb293b8fSAndroid Build Coastguard Worker // uint64_t relevant_entry
151*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(addr + 8, 0);
152*eb293b8fSAndroid Build Coastguard Worker // uint64_t first_entry
153*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(addr + 16, entry);
154*eb293b8fSAndroid Build Coastguard Worker }
155*eb293b8fSAndroid Build Coastguard Worker
WriteEntry32(uint64_t entry_addr,uint32_t next,uint32_t prev,uint32_t dex_file,uint64_t dex_size)156*eb293b8fSAndroid Build Coastguard Worker void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
157*eb293b8fSAndroid Build Coastguard Worker uint32_t dex_file, uint64_t dex_size) {
158*eb293b8fSAndroid Build Coastguard Worker // Format of the 32 bit DEXFileEntry structure:
159*eb293b8fSAndroid Build Coastguard Worker // uint32_t next
160*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(entry_addr, next);
161*eb293b8fSAndroid Build Coastguard Worker // uint32_t prev
162*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(entry_addr + 4, prev);
163*eb293b8fSAndroid Build Coastguard Worker // uint32_t dex_file
164*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(entry_addr + 8, dex_file);
165*eb293b8fSAndroid Build Coastguard Worker // uint32_t dex_size (present in the struct, but we ignore it)
166*eb293b8fSAndroid Build Coastguard Worker memory_->SetData32(entry_addr + 12, 0); // Align.
167*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(entry_addr + 16, dex_size);
168*eb293b8fSAndroid Build Coastguard Worker }
169*eb293b8fSAndroid Build Coastguard Worker
WriteEntry64(uint64_t entry_addr,uint64_t next,uint64_t prev,uint64_t dex_file,uint64_t dex_size)170*eb293b8fSAndroid Build Coastguard Worker void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev,
171*eb293b8fSAndroid Build Coastguard Worker uint64_t dex_file, uint64_t dex_size) {
172*eb293b8fSAndroid Build Coastguard Worker // Format of the 64 bit DEXFileEntry structure:
173*eb293b8fSAndroid Build Coastguard Worker // uint64_t next
174*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(entry_addr, next);
175*eb293b8fSAndroid Build Coastguard Worker // uint64_t prev
176*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(entry_addr + 8, prev);
177*eb293b8fSAndroid Build Coastguard Worker // uint64_t dex_file
178*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(entry_addr + 16, dex_file);
179*eb293b8fSAndroid Build Coastguard Worker // uint32_t dex_size (present in the struct, but we ignore it)
180*eb293b8fSAndroid Build Coastguard Worker memory_->SetData64(entry_addr + 24, dex_size);
181*eb293b8fSAndroid Build Coastguard Worker }
182*eb293b8fSAndroid Build Coastguard Worker
WriteDex(uint64_t dex_file)183*eb293b8fSAndroid Build Coastguard Worker void DexFilesTest::WriteDex(uint64_t dex_file) {
184*eb293b8fSAndroid Build Coastguard Worker memory_->SetMemory(dex_file, kDexData, sizeof(kDexData));
185*eb293b8fSAndroid Build Coastguard Worker }
186*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_invalid)187*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_invalid) {
188*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
189*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
190*eb293b8fSAndroid Build Coastguard Worker
191*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0, &method_name, &method_offset);
192*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("nothing", method_name);
193*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x124U, method_offset);
194*eb293b8fSAndroid Build Coastguard Worker }
195*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_32)196*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_32) {
197*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
198*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
199*eb293b8fSAndroid Build Coastguard Worker
200*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x100800, 0x200000);
201*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
202*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
203*eb293b8fSAndroid Build Coastguard Worker
204*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
205*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
206*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
207*eb293b8fSAndroid Build Coastguard Worker }
208*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_64)209*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_64) {
210*eb293b8fSAndroid Build Coastguard Worker Init(ARCH_ARM64);
211*eb293b8fSAndroid Build Coastguard Worker
212*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
213*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
214*eb293b8fSAndroid Build Coastguard Worker
215*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0x100800, 0x200000);
216*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(0x200000, 0, 0, 0x301000, sizeof(kDexData));
217*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x301000);
218*eb293b8fSAndroid Build Coastguard Worker
219*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x301102, &method_name, &method_offset);
220*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
221*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(2U, method_offset);
222*eb293b8fSAndroid Build Coastguard Worker }
223*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_not_first_entry_32)224*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
225*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
226*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
227*eb293b8fSAndroid Build Coastguard Worker
228*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x100800, 0x200000);
229*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
230*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
231*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
232*eb293b8fSAndroid Build Coastguard Worker
233*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
234*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
235*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(4U, method_offset);
236*eb293b8fSAndroid Build Coastguard Worker }
237*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_not_first_entry_64)238*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
239*eb293b8fSAndroid Build Coastguard Worker Init(ARCH_ARM64);
240*eb293b8fSAndroid Build Coastguard Worker
241*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
242*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
243*eb293b8fSAndroid Build Coastguard Worker
244*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0x100800, 0x200000);
245*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
246*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
247*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
248*eb293b8fSAndroid Build Coastguard Worker
249*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300106, &method_name, &method_offset);
250*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
251*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(6U, method_offset);
252*eb293b8fSAndroid Build Coastguard Worker }
253*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_cached)254*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_cached) {
255*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
256*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
257*eb293b8fSAndroid Build Coastguard Worker
258*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x100800, 0x200000);
259*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
260*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
261*eb293b8fSAndroid Build Coastguard Worker
262*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
263*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
264*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
265*eb293b8fSAndroid Build Coastguard Worker
266*eb293b8fSAndroid Build Coastguard Worker // Clear all memory and make sure that data is acquired from the cache.
267*eb293b8fSAndroid Build Coastguard Worker memory_->Clear();
268*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
269*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
270*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
271*eb293b8fSAndroid Build Coastguard Worker }
272*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_search_libs)273*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_search_libs) {
274*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
275*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
276*eb293b8fSAndroid Build Coastguard Worker
277*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x100800, 0x200000);
278*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
279*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
280*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
281*eb293b8fSAndroid Build Coastguard Worker
282*eb293b8fSAndroid Build Coastguard Worker // Only search a given named list of libs.
283*eb293b8fSAndroid Build Coastguard Worker std::vector<std::string> libs{"libart.so"};
284*eb293b8fSAndroid Build Coastguard Worker dex_files_ = CreateDexFiles(ARCH_ARM, process_memory_, libs);
285*eb293b8fSAndroid Build Coastguard Worker
286*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
287*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("nothing", method_name);
288*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x124U, method_offset);
289*eb293b8fSAndroid Build Coastguard Worker
290*eb293b8fSAndroid Build Coastguard Worker auto map_info = maps_->Get(kMapGlobal);
291*eb293b8fSAndroid Build Coastguard Worker map_info->set_name("/system/lib/libart.so");
292*eb293b8fSAndroid Build Coastguard Worker dex_files_ = CreateDexFiles(ARCH_ARM, process_memory_, libs);
293*eb293b8fSAndroid Build Coastguard Worker // Set the rw map to the same name or this will not scan this entry.
294*eb293b8fSAndroid Build Coastguard Worker map_info = maps_->Get(kMapGlobalRw);
295*eb293b8fSAndroid Build Coastguard Worker map_info->set_name("/system/lib/libart.so");
296*eb293b8fSAndroid Build Coastguard Worker // Make sure that clearing out copy of the libs doesn't affect the
297*eb293b8fSAndroid Build Coastguard Worker // DexFiles object.
298*eb293b8fSAndroid Build Coastguard Worker libs.clear();
299*eb293b8fSAndroid Build Coastguard Worker
300*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
301*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
302*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(4U, method_offset);
303*eb293b8fSAndroid Build Coastguard Worker }
304*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_global_skip_zero_32)305*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
306*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
307*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
308*eb293b8fSAndroid Build Coastguard Worker
309*eb293b8fSAndroid Build Coastguard Worker // First global variable found, but value is zero.
310*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0xc800, 0);
311*eb293b8fSAndroid Build Coastguard Worker
312*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x100800, 0x200000);
313*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
314*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
315*eb293b8fSAndroid Build Coastguard Worker
316*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
317*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
318*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
319*eb293b8fSAndroid Build Coastguard Worker
320*eb293b8fSAndroid Build Coastguard Worker // Verify that second is ignored when first is set to non-zero
321*eb293b8fSAndroid Build Coastguard Worker dex_files_ = CreateDexFiles(ARCH_ARM, process_memory_);
322*eb293b8fSAndroid Build Coastguard Worker method_name = "fail";
323*eb293b8fSAndroid Build Coastguard Worker method_offset = 0x123;
324*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0xc800, 0x100000);
325*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
326*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("fail", method_name);
327*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x123U, method_offset);
328*eb293b8fSAndroid Build Coastguard Worker }
329*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_global_skip_zero_64)330*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
331*eb293b8fSAndroid Build Coastguard Worker Init(ARCH_ARM64);
332*eb293b8fSAndroid Build Coastguard Worker
333*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
334*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
335*eb293b8fSAndroid Build Coastguard Worker
336*eb293b8fSAndroid Build Coastguard Worker // First global variable found, but value is zero.
337*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0xc800, 0);
338*eb293b8fSAndroid Build Coastguard Worker
339*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0x100800, 0x200000);
340*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(0x200000, 0, 0, 0x300000, sizeof(kDexData));
341*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x300000);
342*eb293b8fSAndroid Build Coastguard Worker
343*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
344*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
345*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
346*eb293b8fSAndroid Build Coastguard Worker
347*eb293b8fSAndroid Build Coastguard Worker // Verify that second is ignored when first is set to non-zero
348*eb293b8fSAndroid Build Coastguard Worker dex_files_ = CreateDexFiles(ARCH_ARM64, process_memory_);
349*eb293b8fSAndroid Build Coastguard Worker method_name = "fail";
350*eb293b8fSAndroid Build Coastguard Worker method_offset = 0x123;
351*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0xc800, 0x100000);
352*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
353*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("fail", method_name);
354*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0x123U, method_offset);
355*eb293b8fSAndroid Build Coastguard Worker }
356*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_with_empty_map)357*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_with_empty_map) {
358*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
359*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
360*eb293b8fSAndroid Build Coastguard Worker
361*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x503800, 0x506000);
362*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x506000, 0, 0, 0x510000, sizeof(kDexData));
363*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x510000);
364*eb293b8fSAndroid Build Coastguard Worker
365*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x510100, &method_name, &method_offset);
366*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
367*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
368*eb293b8fSAndroid Build Coastguard Worker }
369*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_with_page_size_compat_map)370*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_with_page_size_compat_map) {
371*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
372*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
373*eb293b8fSAndroid Build Coastguard Worker
374*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor32(0x603800, 0x606000);
375*eb293b8fSAndroid Build Coastguard Worker WriteEntry32(0x606000, 0, 0, 0x610000, sizeof(kDexData));
376*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x610000);
377*eb293b8fSAndroid Build Coastguard Worker
378*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x610100, &method_name, &method_offset);
379*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
380*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(0U, method_offset);
381*eb293b8fSAndroid Build Coastguard Worker }
382*eb293b8fSAndroid Build Coastguard Worker
TEST_F(DexFilesTest,get_method_information_tagged_descriptor_entry_addr_arm64)383*eb293b8fSAndroid Build Coastguard Worker TEST_F(DexFilesTest, get_method_information_tagged_descriptor_entry_addr_arm64) {
384*eb293b8fSAndroid Build Coastguard Worker Init(ARCH_ARM64);
385*eb293b8fSAndroid Build Coastguard Worker
386*eb293b8fSAndroid Build Coastguard Worker SharedString method_name = "nothing";
387*eb293b8fSAndroid Build Coastguard Worker uint64_t method_offset = 0x124;
388*eb293b8fSAndroid Build Coastguard Worker
389*eb293b8fSAndroid Build Coastguard Worker // Descriptor-stored adddress (first_entry) with a tag in the top byte, which
390*eb293b8fSAndroid Build Coastguard Worker // should be masked out.
391*eb293b8fSAndroid Build Coastguard Worker WriteDescriptor64(0x100800, 0xb400'0000'0020'0000ull);
392*eb293b8fSAndroid Build Coastguard Worker WriteEntry64(0x200000, 0, 0, 0x301000, sizeof(kDexData));
393*eb293b8fSAndroid Build Coastguard Worker WriteDex(0x301000);
394*eb293b8fSAndroid Build Coastguard Worker
395*eb293b8fSAndroid Build Coastguard Worker dex_files_->GetFunctionName(maps_.get(), 0x301102, &method_name, &method_offset);
396*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ("Main.<init>", method_name);
397*eb293b8fSAndroid Build Coastguard Worker EXPECT_EQ(2U, method_offset);
398*eb293b8fSAndroid Build Coastguard Worker }
399*eb293b8fSAndroid Build Coastguard Worker
400*eb293b8fSAndroid Build Coastguard Worker } // namespace unwindstack
401