xref: /llvm-project/lldb/unittests/Process/POSIX/NativeProcessELFTest.cpp (revision cfe5d768be95ae0a62cf430e56e7762cebf81a65)
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-exception
6 //
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 
21 using namespace lldb_private;
22 using namespace lldb;
23 using namespace testing;
24 
25 namespace {
26 class MockProcessELF : public MockProcess<NativeProcessELF> {
27 public:
28   using MockProcess::MockProcess;
29   using NativeProcessELF::GetAuxValue;
30   using NativeProcessELF::GetELFImageInfoAddress;
31 };
32 
CreateAuxvData(MockProcessELF & process,llvm::ArrayRef<std::pair<AuxVector::EntryType,uint32_t>> auxv_data)33 std::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 } // namespace
46 
TEST(NativeProcessELFTest,GetAuxValue)47 TEST(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 
TEST(NativeProcessELFTest,GetELFImageInfoAddress)60 TEST(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 in
77   // 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 entries
84   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 section
93   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 reading
104   // 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 
TEST(NativeProcessELFTest,GetELFImageInfoAddress_NoDebugEntry)111 TEST(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 in
126   // 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 entries
133   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 section
141   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