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