//===-- NativeProcessELFTest.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "TestingSupport/Host/NativeProcessTestUtils.h"

#include "Plugins/Process/POSIX/NativeProcessELF.h"
#include "Plugins/Process/Utility/AuxVector.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/DataExtractor.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/MemoryBuffer.h"

#include "gmock/gmock.h"

using namespace lldb_private;
using namespace lldb;
using namespace testing;

namespace {
class MockProcessELF : public MockProcess<NativeProcessELF> {
public:
  using MockProcess::MockProcess;
  using NativeProcessELF::GetAuxValue;
  using NativeProcessELF::GetELFImageInfoAddress;
};

std::unique_ptr<llvm::MemoryBuffer> CreateAuxvData(
    MockProcessELF &process,
    llvm::ArrayRef<std::pair<AuxVector::EntryType, uint32_t>> auxv_data) {
  auto addr_size = process.GetAddressByteSize();
  DataBufferSP buffer_sp(
      new DataBufferHeap(auxv_data.size() * addr_size * 2, 0));
  DataEncoder encoder(buffer_sp, process.GetByteOrder(), addr_size);
  uint32_t offset = 0;
  for (auto &pair : auxv_data) {
    offset = encoder.PutAddress(offset, pair.first);
    offset = encoder.PutAddress(offset, pair.second);
  }
  return llvm::MemoryBuffer::getMemBufferCopy(
      llvm::toStringRef(buffer_sp->GetData()), "");
}

} // namespace

TEST(NativeProcessELFTest, GetAuxValue) {
  NiceMock<MockDelegate> DummyDelegate;
  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));

  uint64_t phdr_addr = 0x42;
  auto auxv_buffer = CreateAuxvData(
      process, {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr)});
  EXPECT_CALL(process, GetAuxvData())
      .WillOnce(Return(ByMove(std::move(auxv_buffer))));

  ASSERT_EQ(phdr_addr, process.GetAuxValue(AuxVector::AUXV_AT_PHDR));
}

TEST(NativeProcessELFTest, GetELFImageInfoAddress) {
  NiceMock<MockDelegate> DummyDelegate;
  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));

  uint32_t load_base = 0x1000;
  uint32_t info_addr = 0x3741;
  uint32_t phdr_addr = load_base + sizeof(llvm::ELF::Elf32_Ehdr);

  auto auxv_buffer = CreateAuxvData(
      process,
      {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr),
       std::make_pair(AuxVector::AUXV_AT_PHENT, sizeof(llvm::ELF::Elf32_Phdr)),
       std::make_pair(AuxVector::AUXV_AT_PHNUM, 2)});
  EXPECT_CALL(process, GetAuxvData())
      .WillOnce(Return(ByMove(std::move(auxv_buffer))));

  // We're going to set up a fake memory with 2 program headers and 1 entry in
  // the dynamic section. For simplicity sake they will be contiguous in memory.
  struct MemoryContents {
    llvm::ELF::Elf32_Phdr phdr_load;
    llvm::ELF::Elf32_Phdr phdr_dynamic;
    llvm::ELF::Elf32_Dyn dyn_debug;
  } MC;
  // Setup the 2 program header entries
  MC.phdr_load.p_type = llvm::ELF::PT_PHDR;
  MC.phdr_load.p_vaddr = phdr_addr - load_base;

  MC.phdr_dynamic.p_type = llvm::ELF::PT_DYNAMIC;
  MC.phdr_dynamic.p_vaddr =
      (phdr_addr + 2 * sizeof(llvm::ELF::Elf32_Phdr)) - load_base;
  MC.phdr_dynamic.p_memsz = sizeof(llvm::ELF::Elf32_Dyn);

  // Setup the single entry in the .dynamic section
  MC.dyn_debug.d_tag = llvm::ELF::DT_DEBUG;
  MC.dyn_debug.d_un.d_ptr = info_addr;

  FakeMemory M(&MC, sizeof(MC), phdr_addr);
  EXPECT_CALL(process, ReadMemory(_, _))
      .WillRepeatedly(Invoke(&M, &FakeMemory::Read));

  lldb::addr_t elf_info_addr = process.GetELFImageInfoAddress<
      llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();

  // Read the address at the elf_info_addr location to make sure we're reading
  // the correct one.
  lldb::offset_t info_addr_offset = elf_info_addr - phdr_addr;
  DataExtractor mem_extractor(&MC, sizeof(MC), process.GetByteOrder(),
                              process.GetAddressByteSize());
  ASSERT_EQ(mem_extractor.GetAddress(&info_addr_offset), info_addr);
}

TEST(NativeProcessELFTest, GetELFImageInfoAddress_NoDebugEntry) {
  NiceMock<MockDelegate> DummyDelegate;
  MockProcessELF process(DummyDelegate, ArchSpec("i386-pc-linux"));

  uint32_t phdr_addr = sizeof(llvm::ELF::Elf32_Ehdr);

  auto auxv_buffer = CreateAuxvData(
      process,
      {std::make_pair(AuxVector::AUXV_AT_PHDR, phdr_addr),
       std::make_pair(AuxVector::AUXV_AT_PHENT, sizeof(llvm::ELF::Elf32_Phdr)),
       std::make_pair(AuxVector::AUXV_AT_PHNUM, 2)});
  EXPECT_CALL(process, GetAuxvData())
      .WillOnce(Return(ByMove(std::move(auxv_buffer))));

  // We're going to set up a fake memory with 2 program headers and 1 entry in
  // the dynamic section. For simplicity sake they will be contiguous in memory.
  struct MemoryContents {
    llvm::ELF::Elf32_Phdr phdr_load;
    llvm::ELF::Elf32_Phdr phdr_dynamic;
    llvm::ELF::Elf32_Dyn dyn_notdebug;
  } MC;
  // Setup the 2 program header entries
  MC.phdr_load.p_type = llvm::ELF::PT_PHDR;
  MC.phdr_load.p_vaddr = phdr_addr;

  MC.phdr_dynamic.p_type = llvm::ELF::PT_DYNAMIC;
  MC.phdr_dynamic.p_vaddr = (phdr_addr + 2 * sizeof(llvm::ELF::Elf32_Phdr));
  MC.phdr_dynamic.p_memsz = sizeof(llvm::ELF::Elf32_Dyn);

  // Setup the single entry in the .dynamic section
  MC.dyn_notdebug.d_tag = llvm::ELF::DT_NULL;

  FakeMemory M(&MC, sizeof(MC), phdr_addr);
  EXPECT_CALL(process, ReadMemory(_, _))
      .WillRepeatedly(Invoke(&M, &FakeMemory::Read));

  lldb::addr_t elf_info_addr = process.GetELFImageInfoAddress<
      llvm::ELF::Elf32_Ehdr, llvm::ELF::Elf32_Phdr, llvm::ELF::Elf32_Dyn>();

  ASSERT_EQ(elf_info_addr, LLDB_INVALID_ADDRESS);
}
