12#include "tpde/Assembler.hpp"
13#include "tpde/ELF.hpp"
14#include "tpde/StringTable.hpp"
15#include "util/SmallVector.hpp"
19class AssemblerElf :
public Assembler {
20 friend class ElfMapper;
23 struct TargetInfoElf : Assembler::TargetInfo {
31 enum class SymVisibility : u8 {
32 DEFAULT = STV_DEFAULT,
33 INTERNAL = STV_INTERNAL,
35 PROTECTED = STV_PROTECTED,
39 std::vector<Elf64_Sym> global_symbols, local_symbols;
41 util::SmallVector<u32, 0> global_shndx, local_shndx;
45 StringTable shstrtab_extra;
48 explicit AssemblerElf(
const TargetInfoElf &target_info)
49 : Assembler(target_info) {
50 local_symbols.resize(1);
54 void reset() noexcept override;
57 void init_sections() noexcept;
59 std::span<Relocation> get_relocs(SecRef ref) {
60 return get_section(ref).relocs;
63 [[nodiscard]] SymRef create_section_symbol(SecRef ref,
64 std::string_view name)
noexcept;
67 SecRef create_structor_section(
bool init, SecRef group = SecRef()) noexcept;
69 void rename_section(SecRef, std::string_view) noexcept override;
71 SymRef section_symbol(SecRef) noexcept override;
74 [[nodiscard]] SecRef create_group_section(SymRef signature_sym,
75 bool is_comdat) noexcept;
78 void add_to_group(SecRef group_ref, SecRef sec_ref) noexcept;
80 const
char *sec_name(SecRef ref) const noexcept;
83 bool sec_is_xindex(SecRef ref) const noexcept {
84 return ref.id() >= SHN_LORESERVE;
90 void sym_copy(SymRef dst, SymRef src)
noexcept;
94 sym_add(std::string_view name,
SymBinding binding, u32 type)
noexcept;
97 [[nodiscard]] SymRef sym_add_undef(std::string_view name,
99 return sym_add(name, binding, STT_NOTYPE);
102 [[nodiscard]] SymRef sym_predef_func(std::string_view name,
104 return sym_add(name, binding, STT_FUNC);
107 [[nodiscard]] SymRef sym_predef_data(std::string_view name,
109 return sym_add(name, binding, STT_OBJECT);
112 [[nodiscard]] SymRef sym_predef_tls(std::string_view name,
114 return sym_add(name, binding, STT_TLS);
119 void sym_def_xindex(SymRef sym_ref, SecRef sec_ref)
noexcept;
122 void sym_def(SymRef sym_ref,
125 u64 size)
noexcept override {
126 Elf64_Sym *sym = sym_ptr(sym_ref);
127 assert(sym->st_shndx == SHN_UNDEF &&
"cannot redefined symbol");
130 if (!sec_is_xindex(sec_ref)) [[likely]] {
131 sym->st_shndx = sec_ref.id();
133 sym->st_shndx = SHN_XINDEX;
134 sym_def_xindex(sym_ref, sec_ref);
139 void sym_set_visibility(SymRef sym, SymVisibility visibility)
noexcept {
140 sym_ptr(sym)->st_other =
static_cast<u8
>(visibility);
143 const char *sym_name(SymRef sym)
const noexcept {
144 return strtab.data() + sym_ptr(sym)->st_name;
147 SecRef sym_section(SymRef sym)
const noexcept {
148 auto shndx = sym_ptr(sym)->st_shndx;
149 if (shndx < SHN_LORESERVE && shndx != SHN_UNDEF) [[likely]] {
150 return SecRef(shndx);
152 assert(shndx == SHN_XINDEX);
153 const auto &shndx_tab = sym_is_local(sym) ? local_shndx : global_shndx;
154 return SecRef(shndx_tab[sym_idx(sym)]);
158 [[nodiscard]]
static bool sym_is_local(
const SymRef sym)
noexcept {
159 return (sym.id() & 0x8000'0000) == 0;
162 [[nodiscard]]
static u32 sym_idx(
const SymRef sym)
noexcept {
163 return sym.id() & ~0x8000'0000;
166 [[nodiscard]] Elf64_Sym *sym_ptr(
const SymRef sym)
noexcept {
167 if (sym_is_local(sym)) {
168 return &local_symbols[sym_idx(sym)];
170 return &global_symbols[sym_idx(sym)];
174 [[nodiscard]]
const Elf64_Sym *sym_ptr(
const SymRef sym)
const noexcept {
175 if (sym_is_local(sym)) {
176 return &local_symbols[sym_idx(sym)];
178 return &global_symbols[sym_idx(sym)];
185 std::vector<u8> build_object_file() noexcept override;
191class AssemblerElfA64 final : public AssemblerElf {
192 static const TargetInfoElf TARGET_INFO;
195 explicit AssemblerElfA64() noexcept : AssemblerElf(TARGET_INFO) {}
198class AssemblerElfX64 final :
public AssemblerElf {
199 static const TargetInfoElf TARGET_INFO;
202 explicit AssemblerElfX64() noexcept : AssemblerElf(TARGET_INFO) {}