Home | History | Annotate | Download | only in tests
      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 "DexFileData.h"
     32 #include "ElfFake.h"
     33 #include "MemoryFake.h"
     34 
     35 namespace unwindstack {
     36 
     37 class DexFilesTest : public ::testing::Test {
     38  protected:
     39   void SetUp() override {
     40     memory_ = new MemoryFake;
     41     process_memory_.reset(memory_);
     42 
     43     dex_files_.reset(new DexFiles(process_memory_));
     44     dex_files_->SetArch(ARCH_ARM);
     45 
     46     maps_.reset(
     47         new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
     48                        "4000-6000 r--s 00000000 00:00 0\n"
     49                        "6000-8000 -w-s 00000000 00:00 0\n"
     50                        "a000-c000 r-xp 00000000 00:00 0\n"
     51                        "c000-f000 rwxp 00000000 00:00 0\n"
     52                        "f000-11000 r-xp 00000000 00:00 0\n"
     53                        "100000-110000 rw-p 0000000 00:00 0\n"
     54                        "200000-210000 rw-p 0000000 00:00 0\n"
     55                        "300000-400000 rw-p 0000000 00:00 0\n"));
     56     ASSERT_TRUE(maps_->Parse());
     57 
     58     // Global variable in a section that is not readable/executable.
     59     MapInfo* map_info = maps_->Get(kMapGlobalNonReadableExectable);
     60     ASSERT_TRUE(map_info != nullptr);
     61     MemoryFake* memory = new MemoryFake;
     62     ElfFake* elf = new ElfFake(memory);
     63     elf->FakeSetValid(true);
     64     ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
     65     elf->FakeSetInterface(interface);
     66     interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
     67     map_info->elf.reset(elf);
     68 
     69     // Global variable not set by default.
     70     map_info = maps_->Get(kMapGlobalSetToZero);
     71     ASSERT_TRUE(map_info != nullptr);
     72     memory = new MemoryFake;
     73     elf = new ElfFake(memory);
     74     elf->FakeSetValid(true);
     75     interface = new ElfInterfaceFake(memory);
     76     elf->FakeSetInterface(interface);
     77     interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
     78     map_info->elf.reset(elf);
     79 
     80     // Global variable set in this map.
     81     map_info = maps_->Get(kMapGlobal);
     82     ASSERT_TRUE(map_info != nullptr);
     83     memory = new MemoryFake;
     84     elf = new ElfFake(memory);
     85     elf->FakeSetValid(true);
     86     interface = new ElfInterfaceFake(memory);
     87     elf->FakeSetInterface(interface);
     88     interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
     89     map_info->elf.reset(elf);
     90   }
     91 
     92   void WriteDescriptor32(uint64_t addr, uint32_t head);
     93   void WriteDescriptor64(uint64_t addr, uint64_t head);
     94   void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file);
     95   void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
     96   void WriteDex(uint64_t dex_file);
     97 
     98   static constexpr size_t kMapGlobalNonReadableExectable = 3;
     99   static constexpr size_t kMapGlobalSetToZero = 4;
    100   static constexpr size_t kMapGlobal = 5;
    101   static constexpr size_t kMapDexFileEntries = 7;
    102   static constexpr size_t kMapDexFiles = 8;
    103 
    104   std::shared_ptr<Memory> process_memory_;
    105   MemoryFake* memory_;
    106   std::unique_ptr<DexFiles> dex_files_;
    107   std::unique_ptr<BufferMaps> maps_;
    108 };
    109 
    110 void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) {
    111   //   void* first_entry_
    112   memory_->SetData32(addr + 12, head);
    113 }
    114 
    115 void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) {
    116   //   void* first_entry_
    117   memory_->SetData64(addr + 16, head);
    118 }
    119 
    120 void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
    121                                 uint32_t dex_file) {
    122   // Format of the 32 bit DEXFileEntry structure:
    123   //   uint32_t next
    124   memory_->SetData32(entry_addr, next);
    125   //   uint32_t prev
    126   memory_->SetData32(entry_addr + 4, prev);
    127   //   uint32_t dex_file
    128   memory_->SetData32(entry_addr + 8, dex_file);
    129 }
    130 
    131 void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev,
    132                                 uint64_t dex_file) {
    133   // Format of the 64 bit DEXFileEntry structure:
    134   //   uint64_t next
    135   memory_->SetData64(entry_addr, next);
    136   //   uint64_t prev
    137   memory_->SetData64(entry_addr + 8, prev);
    138   //   uint64_t dex_file
    139   memory_->SetData64(entry_addr + 16, dex_file);
    140 }
    141 
    142 void DexFilesTest::WriteDex(uint64_t dex_file) {
    143   memory_->SetMemory(dex_file, kDexData, sizeof(kDexData) * sizeof(uint32_t));
    144 }
    145 
    146 TEST_F(DexFilesTest, get_method_information_invalid) {
    147   std::string method_name = "nothing";
    148   uint64_t method_offset = 0x124;
    149   MapInfo* info = maps_->Get(kMapDexFileEntries);
    150 
    151   dex_files_->GetMethodInformation(maps_.get(), info, 0, &method_name, &method_offset);
    152   EXPECT_EQ("nothing", method_name);
    153   EXPECT_EQ(0x124U, method_offset);
    154 }
    155 
    156 TEST_F(DexFilesTest, get_method_information_32) {
    157   std::string method_name = "nothing";
    158   uint64_t method_offset = 0x124;
    159   MapInfo* info = maps_->Get(kMapDexFiles);
    160 
    161   WriteDescriptor32(0xf800, 0x200000);
    162   WriteEntry32(0x200000, 0, 0, 0x300000);
    163   WriteDex(0x300000);
    164 
    165   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    166   EXPECT_EQ("Main.<init>", method_name);
    167   EXPECT_EQ(0U, method_offset);
    168 }
    169 
    170 TEST_F(DexFilesTest, get_method_information_64) {
    171   std::string method_name = "nothing";
    172   uint64_t method_offset = 0x124;
    173   MapInfo* info = maps_->Get(kMapDexFiles);
    174 
    175   dex_files_->SetArch(ARCH_ARM64);
    176   WriteDescriptor64(0xf800, 0x200000);
    177   WriteEntry64(0x200000, 0, 0, 0x301000);
    178   WriteDex(0x301000);
    179 
    180   dex_files_->GetMethodInformation(maps_.get(), info, 0x301102, &method_name, &method_offset);
    181   EXPECT_EQ("Main.<init>", method_name);
    182   EXPECT_EQ(2U, method_offset);
    183 }
    184 
    185 TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
    186   std::string method_name = "nothing";
    187   uint64_t method_offset = 0x124;
    188   MapInfo* info = maps_->Get(kMapDexFiles);
    189 
    190   WriteDescriptor32(0xf800, 0x200000);
    191   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
    192   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
    193   WriteDex(0x300000);
    194 
    195   dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
    196   EXPECT_EQ("Main.<init>", method_name);
    197   EXPECT_EQ(4U, method_offset);
    198 }
    199 
    200 TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
    201   std::string method_name = "nothing";
    202   uint64_t method_offset = 0x124;
    203   MapInfo* info = maps_->Get(kMapDexFiles);
    204 
    205   dex_files_->SetArch(ARCH_ARM64);
    206   WriteDescriptor64(0xf800, 0x200000);
    207   WriteEntry64(0x200000, 0x200100, 0, 0x100000);
    208   WriteEntry64(0x200100, 0, 0x200000, 0x300000);
    209   WriteDex(0x300000);
    210 
    211   dex_files_->GetMethodInformation(maps_.get(), info, 0x300106, &method_name, &method_offset);
    212   EXPECT_EQ("Main.<init>", method_name);
    213   EXPECT_EQ(6U, method_offset);
    214 }
    215 
    216 TEST_F(DexFilesTest, get_method_information_cached) {
    217   std::string method_name = "nothing";
    218   uint64_t method_offset = 0x124;
    219   MapInfo* info = maps_->Get(kMapDexFiles);
    220 
    221   WriteDescriptor32(0xf800, 0x200000);
    222   WriteEntry32(0x200000, 0, 0, 0x300000);
    223   WriteDex(0x300000);
    224 
    225   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    226   EXPECT_EQ("Main.<init>", method_name);
    227   EXPECT_EQ(0U, method_offset);
    228 
    229   // Clear all memory and make sure that data is acquired from the cache.
    230   memory_->Clear();
    231   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    232   EXPECT_EQ("Main.<init>", method_name);
    233   EXPECT_EQ(0U, method_offset);
    234 }
    235 
    236 TEST_F(DexFilesTest, get_method_information_search_libs) {
    237   std::string method_name = "nothing";
    238   uint64_t method_offset = 0x124;
    239   MapInfo* info = maps_->Get(kMapDexFiles);
    240 
    241   WriteDescriptor32(0xf800, 0x200000);
    242   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
    243   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
    244   WriteDex(0x300000);
    245 
    246   // Only search a given named list of libs.
    247   std::vector<std::string> libs{"libart.so"};
    248   dex_files_.reset(new DexFiles(process_memory_, libs));
    249   dex_files_->SetArch(ARCH_ARM);
    250 
    251   dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
    252   EXPECT_EQ("nothing", method_name);
    253   EXPECT_EQ(0x124U, method_offset);
    254 
    255   MapInfo* map_info = maps_->Get(kMapGlobal);
    256   map_info->name = "/system/lib/libart.so";
    257   dex_files_.reset(new DexFiles(process_memory_, libs));
    258   dex_files_->SetArch(ARCH_ARM);
    259   // Make sure that clearing out copy of the libs doesn't affect the
    260   // DexFiles object.
    261   libs.clear();
    262 
    263   dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset);
    264   EXPECT_EQ("Main.<init>", method_name);
    265   EXPECT_EQ(4U, method_offset);
    266 }
    267 
    268 TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
    269   std::string method_name = "nothing";
    270   uint64_t method_offset = 0x124;
    271   MapInfo* info = maps_->Get(kMapDexFiles);
    272 
    273   // First global variable found, but value is zero.
    274   WriteDescriptor32(0xc800, 0);
    275 
    276   WriteDescriptor32(0xf800, 0x200000);
    277   WriteEntry32(0x200000, 0, 0, 0x300000);
    278   WriteDex(0x300000);
    279 
    280   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    281   EXPECT_EQ("Main.<init>", method_name);
    282   EXPECT_EQ(0U, method_offset);
    283 
    284   // Verify that second is ignored when first is set to non-zero
    285   dex_files_.reset(new DexFiles(process_memory_));
    286   dex_files_->SetArch(ARCH_ARM);
    287   method_name = "fail";
    288   method_offset = 0x123;
    289   WriteDescriptor32(0xc800, 0x100000);
    290   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    291   EXPECT_EQ("fail", method_name);
    292   EXPECT_EQ(0x123U, method_offset);
    293 }
    294 
    295 TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
    296   std::string method_name = "nothing";
    297   uint64_t method_offset = 0x124;
    298   MapInfo* info = maps_->Get(kMapDexFiles);
    299 
    300   // First global variable found, but value is zero.
    301   WriteDescriptor64(0xc800, 0);
    302 
    303   WriteDescriptor64(0xf800, 0x200000);
    304   WriteEntry64(0x200000, 0, 0, 0x300000);
    305   WriteDex(0x300000);
    306 
    307   dex_files_->SetArch(ARCH_ARM64);
    308   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    309   EXPECT_EQ("Main.<init>", method_name);
    310   EXPECT_EQ(0U, method_offset);
    311 
    312   // Verify that second is ignored when first is set to non-zero
    313   dex_files_.reset(new DexFiles(process_memory_));
    314   dex_files_->SetArch(ARCH_ARM64);
    315   method_name = "fail";
    316   method_offset = 0x123;
    317   WriteDescriptor64(0xc800, 0x100000);
    318   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
    319   EXPECT_EQ("fail", method_name);
    320   EXPECT_EQ(0x123U, method_offset);
    321 }
    322 
    323 }  // namespace unwindstack
    324