130 lines
4.0 KiB
C++
130 lines
4.0 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_
|
|
#define BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_
|
|
|
|
#include <elf.h>
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "base/containers/span.h"
|
|
#include "base/memory/raw_ptr.h"
|
|
#include "base/strings/string_piece.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.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 {
|
|
|
|
// In-memory ELF image constructed by TestElfImageBuilder.
|
|
class TestElfImage {
|
|
public:
|
|
// |buffer| is a memory buffer containing the ELF image. |elf_start| is the
|
|
// start address of the ELF image within the buffer.
|
|
TestElfImage(std::vector<uint8_t> buffer, const void* elf_start);
|
|
~TestElfImage();
|
|
|
|
TestElfImage(TestElfImage&&);
|
|
TestElfImage& operator=(TestElfImage&&);
|
|
|
|
// The start address of the ELF image.
|
|
const void* elf_start() const { return elf_start_; }
|
|
|
|
private:
|
|
std::vector<uint8_t> buffer_;
|
|
raw_ptr<const void> elf_start_;
|
|
};
|
|
|
|
// Builds an in-memory image of an ELF file for testing.
|
|
class TestElfImageBuilder {
|
|
public:
|
|
// The type of mapping to use for virtual addresses in the ELF file.
|
|
enum MappingType {
|
|
RELOCATABLE, // Virtual address == file offset.
|
|
RELOCATABLE_WITH_BIAS, // Virtual address == file offset + load bias.
|
|
NON_RELOCATABLE, // Virtual address == mapped address.
|
|
};
|
|
|
|
// The load bias to use for RELOCATABLE_WITH_BIAS. 0xc000 is a commonly used
|
|
// load bias for Android system ELF images.
|
|
static constexpr size_t kLoadBias = 0xc000;
|
|
|
|
explicit TestElfImageBuilder(MappingType mapping_type);
|
|
~TestElfImageBuilder();
|
|
|
|
TestElfImageBuilder(const TestElfImageBuilder&) = delete;
|
|
TestElfImageBuilder& operator=(const TestElfImageBuilder&) = delete;
|
|
|
|
// Add a PT_LOAD segment with the specified rwx |flags|. The contents will be
|
|
// filled with |size| bytes of zeros.
|
|
TestElfImageBuilder& AddLoadSegment(Word flags, size_t size);
|
|
|
|
// Add a PT_NOTE segment with the specified state.
|
|
TestElfImageBuilder& AddNoteSegment(Word type,
|
|
StringPiece name,
|
|
span<const uint8_t> desc);
|
|
|
|
// Adds a DT_SONAME dynamic section and the necessary state to support it. May
|
|
// be invoked at most once.
|
|
TestElfImageBuilder& AddSoName(StringPiece soname);
|
|
|
|
TestElfImage Build();
|
|
|
|
private:
|
|
// Properties of a load segment to create.
|
|
struct LoadSegment;
|
|
|
|
// Computed sizing state for parts of the ELF image.
|
|
struct ImageMeasures;
|
|
|
|
// Gets the 'virtual address' corresponding to |offset| to write into the
|
|
// image, according to |mapping_type_|. Relocatable ELF images have virtual
|
|
// addresses equal to the offset with a possible constant load bias.
|
|
// Non-relocatable ELF images have virtual addresses equal to the actual
|
|
// memory address.
|
|
Addr GetVirtualAddressForOffset(Off offset, const uint8_t* elf_start) const;
|
|
|
|
// Measures sizes/start offset of segments in the image.
|
|
ImageMeasures MeasureSizesAndOffsets() const;
|
|
|
|
// Appends a header of type |T| at |loc|, a memory address within the ELF
|
|
// image being constructed, and returns the address past the header.
|
|
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_;
|
|
absl::optional<std::string> soname_;
|
|
};
|
|
|
|
} // namespace base
|
|
|
|
#endif // BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_
|