brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · ff7b422 Raw
152 lines · cpp
1//===-- NativeProcessELFTest.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "TestingSupport/Host/NativeProcessTestUtils.h"10 11#include "Plugins/Process/POSIX/NativeProcessELF.h"12#include "Plugins/Process/Utility/AuxVector.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/DataEncoder.h"15#include "lldb/Utility/DataExtractor.h"16#include "llvm/BinaryFormat/ELF.h"17#include "llvm/Support/MemoryBuffer.h"18 19#include "gmock/gmock.h"20 21using namespace lldb_private;22using namespace lldb;23using namespace testing;24 25namespace {26class MockProcessELF : public MockProcess<NativeProcessELF> {27public:28  using MockProcess::MockProcess;29  using NativeProcessELF::GetAuxValue;30  using NativeProcessELF::GetELFImageInfoAddress;31};32 33std::unique_ptr<llvm::MemoryBuffer> CreateAuxvData(34    MockProcessELF &process,35    llvm::ArrayRef<std::pair<AuxVector::EntryType, uint32_t>> auxv_data) {36  DataEncoder encoder(process.GetByteOrder(), process.GetAddressByteSize());37  for (auto &pair : auxv_data) {38    encoder.AppendAddress(pair.first);39    encoder.AppendAddress(pair.second);40  }41  return llvm::MemoryBuffer::getMemBufferCopy(42      llvm::toStringRef(encoder.GetData()), "");43}44 45} // namespace46 47TEST(NativeProcessELFTest, GetAuxValue) {48  NiceMock<MockDelegate> DummyDelegate;49  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));50 51  uint64_t phdr_addr = 0x42;52  auto auxv_buffer = CreateAuxvData(53      process, {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr)});54  EXPECT_CALL(process, GetAuxvData())55      .WillOnce(Return(ByMove(std::move(auxv_buffer))));56 57  ASSERT_EQ(phdr_addr, process.GetAuxValue(AuxVector::AUXV_AT_PHDR));58}59 60TEST(NativeProcessELFTest, GetELFImageInfoAddress) {61  NiceMock<MockDelegate> DummyDelegate;62  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));63 64  uint32_t load_base = 0x1000;65  uint32_t info_addr = 0x3741;66  uint32_t phdr_addr = load_base + sizeof(llvm::ELF::Elf32_Ehdr);67 68  auto auxv_buffer = CreateAuxvData(69      process,70      {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr),71       std::make_pair(AuxVector::AUXV_AT_PHENT, sizeof(llvm::ELF::Elf32_Phdr)),72       std::make_pair(AuxVector::AUXV_AT_PHNUM, 2)});73  EXPECT_CALL(process, GetAuxvData())74      .WillOnce(Return(ByMove(std::move(auxv_buffer))));75 76  // We're going to set up a fake memory with 2 program headers and 1 entry in77  // the dynamic section. For simplicity sake they will be contiguous in memory.78  struct MemoryContents {79    llvm::ELF::Elf32_Phdr phdr_load;80    llvm::ELF::Elf32_Phdr phdr_dynamic;81    llvm::ELF::Elf32_Dyn dyn_debug;82  } MC;83  // Setup the 2 program header entries84  MC.phdr_load.p_type = llvm::ELF::PT_PHDR;85  MC.phdr_load.p_vaddr = phdr_addr - load_base;86 87  MC.phdr_dynamic.p_type = llvm::ELF::PT_DYNAMIC;88  MC.phdr_dynamic.p_vaddr =89      (phdr_addr + 2 * sizeof(llvm::ELF::Elf32_Phdr)) - load_base;90  MC.phdr_dynamic.p_memsz = sizeof(llvm::ELF::Elf32_Dyn);91 92  // Setup the single entry in the .dynamic section93  MC.dyn_debug.d_tag = llvm::ELF::DT_DEBUG;94  MC.dyn_debug.d_un.d_ptr = info_addr;95 96  FakeMemory M(&MC, sizeof(MC), phdr_addr);97  EXPECT_CALL(process, ReadMemory(_, _))98      .WillRepeatedly(Invoke(&M, &FakeMemory::Read));99 100  lldb::addr_t elf_info_addr = process.GetELFImageInfoAddress<101      llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();102 103  // Read the address at the elf_info_addr location to make sure we're reading104  // the correct one.105  lldb::offset_t info_addr_offset = elf_info_addr - phdr_addr;106  DataExtractor mem_extractor(&MC, sizeof(MC), process.GetByteOrder(),107                              process.GetAddressByteSize());108  ASSERT_EQ(mem_extractor.GetAddress(&info_addr_offset), info_addr);109}110 111TEST(NativeProcessELFTest, GetELFImageInfoAddress_NoDebugEntry) {112  NiceMock<MockDelegate> DummyDelegate;113  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));114 115  uint32_t phdr_addr = sizeof(llvm::ELF::Elf32_Ehdr);116 117  auto auxv_buffer = CreateAuxvData(118      process,119      {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr),120       std::make_pair(AuxVector::AUXV_AT_PHENT, sizeof(llvm::ELF::Elf32_Phdr)),121       std::make_pair(AuxVector::AUXV_AT_PHNUM, 2)});122  EXPECT_CALL(process, GetAuxvData())123      .WillOnce(Return(ByMove(std::move(auxv_buffer))));124 125  // We're going to set up a fake memory with 2 program headers and 1 entry in126  // the dynamic section. For simplicity sake they will be contiguous in memory.127  struct MemoryContents {128    llvm::ELF::Elf32_Phdr phdr_load;129    llvm::ELF::Elf32_Phdr phdr_dynamic;130    llvm::ELF::Elf32_Dyn dyn_notdebug;131  } MC;132  // Setup the 2 program header entries133  MC.phdr_load.p_type = llvm::ELF::PT_PHDR;134  MC.phdr_load.p_vaddr = phdr_addr;135 136  MC.phdr_dynamic.p_type = llvm::ELF::PT_DYNAMIC;137  MC.phdr_dynamic.p_vaddr = (phdr_addr + 2 * sizeof(llvm::ELF::Elf32_Phdr));138  MC.phdr_dynamic.p_memsz = sizeof(llvm::ELF::Elf32_Dyn);139 140  // Setup the single entry in the .dynamic section141  MC.dyn_notdebug.d_tag = llvm::ELF::DT_NULL;142 143  FakeMemory M(&MC, sizeof(MC), phdr_addr);144  EXPECT_CALL(process, ReadMemory(_, _))145      .WillRepeatedly(Invoke(&M, &FakeMemory::Read));146 147  lldb::addr_t elf_info_addr = process.GetELFImageInfoAddress<148      llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();149 150  ASSERT_EQ(elf_info_addr, LLDB_INVALID_ADDRESS);151}152