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