84a1b114cd
This CL pulls out the refactorings used to support the new MachOWriter in a followup CL to allow them to be reviewed separately. Rename Elf -> ElfWriter. Also rename model classes used by ElfWriter for concepts that exist both in ELF and Mach-O to ElfX. For example, the old ELF-specific SymbolTable is renamed to ElfSymbolTable. Adds SharedObjectWriter to serve as a base class for both ElfWriter and the upcoming MachOWriter. Adds a new AbstractWriteStream that serves as a common superclass of both BaseWriteStream and SharedObjectWriter::WriteStream and allows the creation of fully delegating WriteStreams that do not maintain a local buffer. Abstract the old Elf::SymbolData class into SharedObjectWriter::SymbolData, which stores an enum value as the type of the symbol instead of storing the ELF encoding of the type. Rename the DwarfElfStream (which actually wasn't ELF specific, as all the ELF-specific DWARF information is handled by ElfWriter) to DwarfSharedObjectStream and put it in a separate header file. Rename Image::compiled_to_elf() to Image::compiled_to_shared_object() and add a separate Image::compiled_to_elf() that checks for the ELF magic value at the DSO base. Also add Image::shared_object_start() and Image::build_id_start() to return pointers to the DSO base and the build ID note, respectively. Refactor Image::build_id() and Image::build_id_length() to check compiled_for_elf() prior to decoding the data pointed to by build_id_start() as an ELF note section. Create an AOTSnapshotType enum to specific the snapshot writer to use in CreateAppAOTSnapshot instead of using an as_elf boolean. TEST=refactorings, so existing tests on ci Change-Id: Ia3ab37a4dff93b6e00390b123753be5a51fbdaaa Cq-Include-Trybots: luci.dart.try:vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-dwarf-linux-product-x64-try,vm-linux-debug-x64-try,vm-mac-debug-arm64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421301 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Tess Strickland <sstrickl@google.com>
227 lines
5.1 KiB
C++
227 lines
5.1 KiB
C++
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef RUNTIME_PLATFORM_ELF_H_
|
|
#define RUNTIME_PLATFORM_ELF_H_
|
|
|
|
#include "platform/globals.h"
|
|
|
|
namespace dart {
|
|
namespace elf {
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
static constexpr uint8_t ELFMAG[] = {'\x7f', 'E', 'L', 'F'};
|
|
|
|
struct ElfHeader {
|
|
uint8_t ident[16];
|
|
uint16_t type;
|
|
uint16_t machine;
|
|
uint32_t version;
|
|
#if defined(TARGET_ARCH_IS_32_BIT)
|
|
uint32_t entry_point;
|
|
uint32_t program_table_offset;
|
|
uint32_t section_table_offset;
|
|
#else
|
|
uint64_t entry_point;
|
|
uint64_t program_table_offset;
|
|
uint64_t section_table_offset;
|
|
#endif
|
|
uint32_t flags;
|
|
uint16_t header_size;
|
|
uint16_t program_table_entry_size;
|
|
uint16_t num_program_headers;
|
|
uint16_t section_table_entry_size;
|
|
uint16_t num_section_headers;
|
|
uint16_t shstrtab_section_index;
|
|
};
|
|
|
|
enum class ProgramHeaderType : uint32_t {
|
|
PT_NULL = 0,
|
|
PT_LOAD = 1,
|
|
PT_DYNAMIC = 2,
|
|
PT_NOTE = 4,
|
|
PT_PHDR = 6,
|
|
PT_GNU_STACK = 0x6474e551,
|
|
};
|
|
|
|
struct ProgramHeader {
|
|
#if defined(TARGET_ARCH_IS_32_BIT)
|
|
ProgramHeaderType type;
|
|
uint32_t file_offset;
|
|
uint32_t memory_offset;
|
|
uint32_t physical_memory_offset;
|
|
uint32_t file_size;
|
|
uint32_t memory_size;
|
|
uint32_t flags;
|
|
uint32_t alignment;
|
|
#else
|
|
ProgramHeaderType type;
|
|
uint32_t flags;
|
|
uint64_t file_offset;
|
|
uint64_t memory_offset;
|
|
uint64_t physical_memory_offset;
|
|
uint64_t file_size;
|
|
uint64_t memory_size;
|
|
uint64_t alignment;
|
|
#endif
|
|
};
|
|
|
|
enum class SectionHeaderType : uint32_t {
|
|
SHT_NULL = 0,
|
|
SHT_PROGBITS = 1,
|
|
SHT_SYMTAB = 2,
|
|
SHT_STRTAB = 3,
|
|
SHT_HASH = 5,
|
|
SHT_NOTE = 7,
|
|
SHT_NOBITS = 8,
|
|
SHT_DYNAMIC = 6,
|
|
SHT_DYNSYM = 11,
|
|
};
|
|
|
|
struct SectionHeader {
|
|
#if defined(TARGET_ARCH_IS_32_BIT)
|
|
uint32_t name;
|
|
SectionHeaderType type;
|
|
uint32_t flags;
|
|
uint32_t memory_offset;
|
|
uint32_t file_offset;
|
|
uint32_t file_size;
|
|
uint32_t link;
|
|
uint32_t info;
|
|
uint32_t alignment;
|
|
uint32_t entry_size;
|
|
#else
|
|
uint32_t name;
|
|
SectionHeaderType type;
|
|
uint64_t flags;
|
|
uint64_t memory_offset;
|
|
uint64_t file_offset;
|
|
uint64_t file_size;
|
|
uint32_t link;
|
|
uint32_t info;
|
|
uint64_t alignment;
|
|
uint64_t entry_size;
|
|
#endif
|
|
};
|
|
|
|
struct Symbol {
|
|
#if defined(TARGET_ARCH_IS_32_BIT)
|
|
uint32_t name;
|
|
uint32_t value;
|
|
uint32_t size;
|
|
uint8_t info;
|
|
uint8_t other; // Reserved by ELF.
|
|
uint16_t section;
|
|
#else
|
|
uint32_t name;
|
|
uint8_t info;
|
|
uint8_t other; // Reserved by ELF.
|
|
uint16_t section;
|
|
uint64_t value;
|
|
uint64_t size;
|
|
#endif
|
|
};
|
|
|
|
enum class DynamicEntryType : uint32_t {
|
|
DT_NULL = 0,
|
|
DT_HASH = 4,
|
|
DT_STRTAB = 5,
|
|
DT_SYMTAB = 6,
|
|
DT_STRSZ = 10,
|
|
DT_SYMENT = 11,
|
|
};
|
|
|
|
struct DynamicEntry {
|
|
#if defined(TARGET_ARCH_IS_32_BIT)
|
|
uint32_t tag;
|
|
uint32_t value;
|
|
#else
|
|
uint64_t tag;
|
|
uint64_t value;
|
|
#endif
|
|
};
|
|
|
|
enum class NoteType : uint32_t {
|
|
NT_GNU_BUILD_ID = 3,
|
|
};
|
|
|
|
struct Note {
|
|
uint32_t name_size;
|
|
uint32_t description_size;
|
|
NoteType type;
|
|
uint8_t data[];
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
|
|
static constexpr intptr_t ELFCLASS32 = 1;
|
|
static constexpr intptr_t ELFCLASS64 = 2;
|
|
|
|
static constexpr intptr_t EI_DATA = 5;
|
|
static constexpr intptr_t ELFDATA2LSB = 1;
|
|
|
|
static constexpr intptr_t ELFOSABI_SYSV = 0;
|
|
|
|
static constexpr intptr_t ET_DYN = 3;
|
|
|
|
static constexpr intptr_t EF_ARM_ABI_FLOAT_HARD = 0x00000400;
|
|
static constexpr intptr_t EF_ARM_ABI_FLOAT_SOFT = 0x00000200;
|
|
static constexpr intptr_t EF_ARM_ABI = 0x05000000;
|
|
|
|
static constexpr intptr_t EF_RISCV_RVC = 0x1;
|
|
static constexpr intptr_t EF_RISCV_FLOAT_ABI_DOUBLE = 0x4;
|
|
|
|
static constexpr intptr_t EM_386 = 3;
|
|
static constexpr intptr_t EM_ARM = 40;
|
|
static constexpr intptr_t EM_X86_64 = 62;
|
|
static constexpr intptr_t EM_AARCH64 = 183;
|
|
static constexpr intptr_t EM_RISCV = 243;
|
|
|
|
static constexpr intptr_t EV_CURRENT = 1;
|
|
|
|
static constexpr intptr_t PF_X = 1;
|
|
static constexpr intptr_t PF_W = 2;
|
|
static constexpr intptr_t PF_R = 4;
|
|
|
|
static constexpr intptr_t SHF_WRITE = 0x1;
|
|
static constexpr intptr_t SHF_ALLOC = 0x2;
|
|
static constexpr intptr_t SHF_EXECINSTR = 0x4;
|
|
|
|
static constexpr intptr_t SHN_UNDEF = 0;
|
|
|
|
static constexpr intptr_t STN_UNDEF = 0;
|
|
|
|
static constexpr intptr_t STB_LOCAL = 0;
|
|
static constexpr intptr_t STB_GLOBAL = 1;
|
|
|
|
static constexpr intptr_t STT_NOTYPE = 0;
|
|
static constexpr intptr_t STT_OBJECT = 1; // I.e., data.
|
|
static constexpr intptr_t STT_FUNC = 2;
|
|
static constexpr intptr_t STT_SECTION = 3;
|
|
|
|
static constexpr const char ELF_NOTE_GNU[] = "GNU";
|
|
|
|
// Creates symbol info from the given STB and STT values.
|
|
constexpr decltype(Symbol::info) SymbolInfo(intptr_t binding, intptr_t type) {
|
|
// Take the low nibble of each value in case, though the upper bits should
|
|
// all be zero as long as STB/STT constants are used.
|
|
return (binding & 0xf) << 4 | (type & 0xf);
|
|
}
|
|
|
|
// Retrieves the STB binding value for the given symbol info.
|
|
constexpr intptr_t SymbolBinding(const decltype(Symbol::info) info) {
|
|
return (info >> 4) & 0xf;
|
|
}
|
|
|
|
// Retrieves the STT type value for the given symbol info.
|
|
constexpr intptr_t SymbolType(const decltype(Symbol::info) info) {
|
|
return info & 0xf;
|
|
}
|
|
|
|
} // namespace elf
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_PLATFORM_ELF_H_
|