Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2016 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 <errno.h>
     19 #include <signal.h>
     20 #include <string.h>
     21 #include <sys/mman.h>
     22 #include <sys/ptrace.h>
     23 #include <sys/types.h>
     24 #include <unistd.h>
     25 
     26 #include <atomic>
     27 #include <memory>
     28 #include <thread>
     29 #include <vector>
     30 
     31 #include <android-base/file.h>
     32 #include <android-base/test_utils.h>
     33 #include <gtest/gtest.h>
     34 
     35 #include <unwindstack/Elf.h>
     36 #include <unwindstack/MapInfo.h>
     37 #include <unwindstack/Maps.h>
     38 #include <unwindstack/Memory.h>
     39 
     40 #include "ElfTestUtils.h"
     41 #include "MemoryFake.h"
     42 
     43 namespace unwindstack {
     44 
     45 class MapInfoGetElfTest : public ::testing::Test {
     46  protected:
     47   void SetUp() override {
     48     memory_ = new MemoryFake;
     49     process_memory_.reset(memory_);
     50   }
     51 
     52   template <typename Ehdr, typename Shdr>
     53   static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
     54     memset(ehdr, 0, sizeof(*ehdr));
     55     memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
     56     ehdr->e_ident[EI_CLASS] = class_type;
     57     ehdr->e_machine = machine_type;
     58     ehdr->e_shoff = sh_offset;
     59     ehdr->e_shentsize = sizeof(Shdr) + 100;
     60     ehdr->e_shnum = 4;
     61   }
     62 
     63   const size_t kMapSize = 4096;
     64 
     65   std::shared_ptr<Memory> process_memory_;
     66   MemoryFake* memory_;
     67 
     68   TemporaryFile elf_;
     69 };
     70 
     71 TEST_F(MapInfoGetElfTest, invalid) {
     72   MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
     73 
     74   // The map is empty, but this should still create an invalid elf object.
     75   Elf* elf = info.GetElf(process_memory_, false);
     76   ASSERT_TRUE(elf != nullptr);
     77   ASSERT_FALSE(elf->valid());
     78 }
     79 
     80 TEST_F(MapInfoGetElfTest, valid32) {
     81   MapInfo info(0x3000, 0x4000, 0, PROT_READ, "");
     82 
     83   Elf32_Ehdr ehdr;
     84   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
     85   memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
     86 
     87   Elf* elf = info.GetElf(process_memory_, false);
     88   ASSERT_TRUE(elf != nullptr);
     89   ASSERT_TRUE(elf->valid());
     90   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
     91   EXPECT_EQ(ELFCLASS32, elf->class_type());
     92 }
     93 
     94 TEST_F(MapInfoGetElfTest, valid64) {
     95   MapInfo info(0x8000, 0x9000, 0, PROT_READ, "");
     96 
     97   Elf64_Ehdr ehdr;
     98   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
     99   memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
    100 
    101   Elf* elf = info.GetElf(process_memory_, false);
    102   ASSERT_TRUE(elf != nullptr);
    103   ASSERT_TRUE(elf->valid());
    104   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
    105   EXPECT_EQ(ELFCLASS64, elf->class_type());
    106 }
    107 
    108 TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
    109   MapInfo info(0x4000, 0x8000, 0, PROT_READ, "");
    110 
    111   TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
    112                                                [&](uint64_t offset, const void* ptr, size_t size) {
    113                                                  memory_->SetMemory(0x4000 + offset, ptr, size);
    114                                                });
    115 
    116   Elf* elf = info.GetElf(process_memory_, false);
    117   ASSERT_TRUE(elf != nullptr);
    118   ASSERT_TRUE(elf->valid());
    119   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
    120   EXPECT_EQ(ELFCLASS32, elf->class_type());
    121   EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
    122 }
    123 
    124 TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
    125   MapInfo info(0x6000, 0x8000, 0, PROT_READ, "");
    126 
    127   TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
    128                                                [&](uint64_t offset, const void* ptr, size_t size) {
    129                                                  memory_->SetMemory(0x6000 + offset, ptr, size);
    130                                                });
    131 
    132   Elf* elf = info.GetElf(process_memory_, false);
    133   ASSERT_TRUE(elf != nullptr);
    134   ASSERT_TRUE(elf->valid());
    135   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
    136   EXPECT_EQ(ELFCLASS64, elf->class_type());
    137   EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
    138 }
    139 
    140 TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
    141   MapInfo info(0x2000, 0x3000, 0, PROT_READ, "");
    142 
    143   TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
    144                                                [&](uint64_t offset, const void* ptr, size_t size) {
    145                                                  memory_->SetMemory(0x2000 + offset, ptr, size);
    146                                                });
    147 
    148   Elf* elf = info.GetElf(process_memory_, true);
    149   ASSERT_TRUE(elf != nullptr);
    150   ASSERT_TRUE(elf->valid());
    151   EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
    152   EXPECT_EQ(ELFCLASS32, elf->class_type());
    153   EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
    154 }
    155 
    156 TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
    157   MapInfo info(0x5000, 0x8000, 0, PROT_READ, "");
    158 
    159   TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
    160                                                [&](uint64_t offset, const void* ptr, size_t size) {
    161                                                  memory_->SetMemory(0x5000 + offset, ptr, size);
    162                                                });
    163 
    164   Elf* elf = info.GetElf(process_memory_, true);
    165   ASSERT_TRUE(elf != nullptr);
    166   ASSERT_TRUE(elf->valid());
    167   EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
    168   EXPECT_EQ(ELFCLASS64, elf->class_type());
    169   EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
    170 }
    171 
    172 TEST_F(MapInfoGetElfTest, end_le_start) {
    173   MapInfo info(0x1000, 0x1000, 0, PROT_READ, elf_.path);
    174 
    175   Elf32_Ehdr ehdr;
    176   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
    177   ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
    178 
    179   Elf* elf = info.GetElf(process_memory_, false);
    180   ASSERT_TRUE(elf != nullptr);
    181   ASSERT_FALSE(elf->valid());
    182 
    183   info.elf.reset();
    184   info.end = 0xfff;
    185   elf = info.GetElf(process_memory_, false);
    186   ASSERT_TRUE(elf != nullptr);
    187   ASSERT_FALSE(elf->valid());
    188 
    189   // Make sure this test is valid.
    190   info.elf.reset();
    191   info.end = 0x2000;
    192   elf = info.GetElf(process_memory_, false);
    193   ASSERT_TRUE(elf != nullptr);
    194   ASSERT_TRUE(elf->valid());
    195 }
    196 
    197 // Verify that if the offset is non-zero but there is no elf at the offset,
    198 // that the full file is used.
    199 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
    200   MapInfo info(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
    201 
    202   std::vector<uint8_t> buffer(0x1000);
    203   memset(buffer.data(), 0, buffer.size());
    204   Elf32_Ehdr ehdr;
    205   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
    206   memcpy(buffer.data(), &ehdr, sizeof(ehdr));
    207   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
    208 
    209   Elf* elf = info.GetElf(process_memory_, false);
    210   ASSERT_TRUE(elf != nullptr);
    211   ASSERT_TRUE(elf->valid());
    212   ASSERT_TRUE(elf->memory() != nullptr);
    213   ASSERT_EQ(0x100U, info.elf_offset);
    214 
    215   // Read the entire file.
    216   memset(buffer.data(), 0, buffer.size());
    217   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size()));
    218   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
    219   for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
    220     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
    221   }
    222 
    223   ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1));
    224 }
    225 
    226 // Verify that if the offset is non-zero and there is an elf at that
    227 // offset, that only part of the file is used.
    228 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
    229   MapInfo info(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
    230 
    231   std::vector<uint8_t> buffer(0x4000);
    232   memset(buffer.data(), 0, buffer.size());
    233   Elf32_Ehdr ehdr;
    234   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
    235   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
    236   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
    237 
    238   Elf* elf = info.GetElf(process_memory_, false);
    239   ASSERT_TRUE(elf != nullptr);
    240   ASSERT_TRUE(elf->valid());
    241   ASSERT_TRUE(elf->memory() != nullptr);
    242   ASSERT_EQ(0U, info.elf_offset);
    243 
    244   // Read the valid part of the file.
    245   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
    246   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
    247   for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
    248     ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
    249   }
    250 
    251   ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
    252 }
    253 
    254 // Verify that if the offset is non-zero and there is an elf at that
    255 // offset, that only part of the file is used. Further verify that if the
    256 // embedded elf is bigger than the initial map, the new object is larger
    257 // than the original map size. Do this for a 32 bit elf and a 64 bit elf.
    258 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
    259   MapInfo info(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
    260 
    261   std::vector<uint8_t> buffer(0x4000);
    262   memset(buffer.data(), 0, buffer.size());
    263   Elf32_Ehdr ehdr;
    264   TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
    265   ehdr.e_shoff = 0x2000;
    266   ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
    267   ehdr.e_shnum = 4;
    268   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
    269   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
    270 
    271   Elf* elf = info.GetElf(process_memory_, false);
    272   ASSERT_TRUE(elf != nullptr);
    273   ASSERT_TRUE(elf->valid());
    274   ASSERT_TRUE(elf->memory() != nullptr);
    275   ASSERT_EQ(0U, info.elf_offset);
    276 
    277   // Verify the memory is a valid elf.
    278   memset(buffer.data(), 0, buffer.size());
    279   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
    280   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
    281 
    282   // Read past the end of what would normally be the size of the map.
    283   ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
    284 }
    285 
    286 TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
    287   MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
    288 
    289   std::vector<uint8_t> buffer(0x4000);
    290   memset(buffer.data(), 0, buffer.size());
    291   Elf64_Ehdr ehdr;
    292   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
    293   ehdr.e_shoff = 0x2000;
    294   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
    295   ehdr.e_shnum = 4;
    296   memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
    297   ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
    298 
    299   Elf* elf = info.GetElf(process_memory_, false);
    300   ASSERT_TRUE(elf != nullptr);
    301   ASSERT_TRUE(elf->valid());
    302   ASSERT_TRUE(elf->memory() != nullptr);
    303   ASSERT_EQ(0U, info.elf_offset);
    304 
    305   // Verify the memory is a valid elf.
    306   memset(buffer.data(), 0, buffer.size());
    307   ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
    308   ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
    309 
    310   // Read past the end of what would normally be the size of the map.
    311   ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
    312 }
    313 
    314 TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
    315   MapInfo info(0x9000, 0xa000, 0x1000, 0, "");
    316 
    317   // Create valid elf data in process memory only.
    318   Elf64_Ehdr ehdr;
    319   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
    320   ehdr.e_shoff = 0x2000;
    321   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
    322   ehdr.e_shnum = 4;
    323   memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
    324 
    325   Elf* elf = info.GetElf(process_memory_, false);
    326   ASSERT_TRUE(elf != nullptr);
    327   ASSERT_FALSE(elf->valid());
    328 
    329   info.elf.reset();
    330   info.flags = PROT_READ;
    331   elf = info.GetElf(process_memory_, false);
    332   ASSERT_TRUE(elf->valid());
    333 }
    334 
    335 TEST_F(MapInfoGetElfTest, check_device_maps) {
    336   MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
    337 
    338   // Create valid elf data in process memory for this to verify that only
    339   // the name is causing invalid elf data.
    340   Elf64_Ehdr ehdr;
    341   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
    342   ehdr.e_shoff = 0x2000;
    343   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
    344   ehdr.e_shnum = 4;
    345   memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
    346 
    347   Elf* elf = info.GetElf(process_memory_, false);
    348   ASSERT_TRUE(elf != nullptr);
    349   ASSERT_FALSE(elf->valid());
    350 
    351   // Set the name to nothing to verify that it still fails.
    352   info.elf.reset();
    353   info.name = "";
    354   elf = info.GetElf(process_memory_, false);
    355   ASSERT_FALSE(elf->valid());
    356 
    357   // Change the flags and verify the elf is valid now.
    358   info.elf.reset();
    359   info.flags = PROT_READ;
    360   elf = info.GetElf(process_memory_, false);
    361   ASSERT_TRUE(elf->valid());
    362 }
    363 
    364 TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
    365   static constexpr size_t kNumConcurrentThreads = 100;
    366 
    367   Elf64_Ehdr ehdr;
    368   TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
    369   ehdr.e_shoff = 0x2000;
    370   ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
    371   ehdr.e_shnum = 4;
    372   memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
    373 
    374   Elf* elf_in_threads[kNumConcurrentThreads];
    375   std::vector<std::thread*> threads;
    376 
    377   std::atomic_bool wait;
    378   wait = true;
    379   // Create all of the threads and have them do the GetElf at the same time
    380   // to make it likely that a race will occur.
    381   MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, "");
    382   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
    383     std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
    384       while (wait)
    385         ;
    386       Elf* elf = info.GetElf(process_memory_, false);
    387       elf_in_threads[i] = elf;
    388     });
    389     threads.push_back(thread);
    390   }
    391   ASSERT_TRUE(info.elf == nullptr);
    392 
    393   // Set them all going and wait for the threads to finish.
    394   wait = false;
    395   for (auto thread : threads) {
    396     thread->join();
    397     delete thread;
    398   }
    399 
    400   // Now verify that all of the elf files are exactly the same and valid.
    401   Elf* elf = info.elf.get();
    402   ASSERT_TRUE(elf != nullptr);
    403   EXPECT_TRUE(elf->valid());
    404   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
    405     EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched.";
    406   }
    407 }
    408 
    409 }  // namespace unwindstack
    410