#ifndef BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_
#define BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_
#include <elf.h>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#if __SIZEOF_POINTER__ == 4
using Addr = Elf32_Addr;
using Ehdr = Elf32_Ehdr;
using Half = Elf32_Half;
using Off = Elf32_Off;
using Phdr = Elf32_Phdr;
using Word = Elf32_Word;
#else
using Addr = Elf64_Addr;
using Ehdr = Elf64_Ehdr;
using Half = Elf64_Half;
using Off = Elf64_Off;
using Phdr = Elf64_Phdr;
using Word = Elf64_Word;
#endif
namespace base {
class TestElfImage {
public:
TestElfImage(std::vector<uint8_t> buffer, const void* elf_start);
~TestElfImage();
TestElfImage(TestElfImage&&);
TestElfImage& operator=(TestElfImage&&);
const void* elf_start() const { return elf_start_; }
private:
std::vector<uint8_t> buffer_;
raw_ptr<const void> elf_start_;
};
class TestElfImageBuilder {
public:
enum MappingType {
RELOCATABLE,
RELOCATABLE_WITH_BIAS,
NON_RELOCATABLE,
};
static constexpr size_t kLoadBias = 0xc000;
explicit TestElfImageBuilder(MappingType mapping_type);
~TestElfImageBuilder();
TestElfImageBuilder(const TestElfImageBuilder&) = delete;
TestElfImageBuilder& operator=(const TestElfImageBuilder&) = delete;
TestElfImageBuilder& AddLoadSegment(Word flags, size_t size);
TestElfImageBuilder& AddNoteSegment(Word type,
std::string_view name,
span<const uint8_t> desc);
TestElfImageBuilder& AddSoName(std::string_view soname);
TestElfImage Build();
private:
struct LoadSegment;
struct ImageMeasures;
Addr GetVirtualAddressForOffset(Off offset, const uint8_t* elf_start) const;
ImageMeasures MeasureSizesAndOffsets() const;
template <typename T>
static uint8_t* AppendHdr(const T& hdr, uint8_t* loc);
Ehdr CreateEhdr(Half phnum);
Phdr CreatePhdr(Word type,
Word flags,
size_t align,
Off offset,
Addr vaddr,
size_t size);
const MappingType mapping_type_;
std::vector<std::vector<uint8_t>> note_contents_;
std::vector<LoadSegment> load_segments_;
std::optional<std::string> soname_;
};
}
#endif