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()
override;
59 std::span<Relocation> get_relocs(SecRef ref) {
60 return get_section(ref).relocs;
63 [[nodiscard]] SymRef create_section_symbol(SecRef ref, std::string_view name);
66 SecRef create_structor_section(
bool init, SecRef group = SecRef());
68 void rename_section(SecRef, std::string_view)
override;
70 SymRef section_symbol(SecRef)
override;
73 [[nodiscard]] SecRef create_group_section(SymRef signature_sym,
77 void add_to_group(SecRef group_ref, SecRef sec_ref);
79 const char *sec_name(SecRef ref)
const;
82 bool sec_is_xindex(SecRef ref)
const {
return ref.id() >= SHN_LORESERVE; }
87 void sym_copy(SymRef dst, SymRef src);
91 sym_add(std::string_view name,
SymBinding binding, u32 type);
94 [[nodiscard]] SymRef sym_add_undef(std::string_view name,
96 return sym_add(name, binding, STT_NOTYPE);
99 [[nodiscard]] SymRef sym_predef_func(std::string_view name,
101 return sym_add(name, binding, STT_FUNC);
104 [[nodiscard]] SymRef sym_predef_data(std::string_view name,
106 return sym_add(name, binding, STT_OBJECT);
109 [[nodiscard]] SymRef sym_predef_tls(std::string_view name,
111 return sym_add(name, binding, STT_TLS);
116 void sym_def_xindex(SymRef sym_ref, SecRef sec_ref);
119 void sym_def(SymRef sym_ref, SecRef sec_ref, u64 pos, u64 size)
override {
120 Elf64_Sym *sym = sym_ptr(sym_ref);
121 assert(sym->st_shndx == SHN_UNDEF &&
"cannot redefined symbol");
124 if (!sec_is_xindex(sec_ref)) [[likely]] {
125 sym->st_shndx = sec_ref.id();
127 sym->st_shndx = SHN_XINDEX;
128 sym_def_xindex(sym_ref, sec_ref);
133 void sym_set_visibility(SymRef sym, SymVisibility visibility) {
134 sym_ptr(sym)->st_other =
static_cast<u8
>(visibility);
137 const char *sym_name(SymRef sym)
const {
138 return strtab.data() + sym_ptr(sym)->st_name;
141 SecRef sym_section(SymRef sym)
const {
142 auto shndx = sym_ptr(sym)->st_shndx;
143 if (shndx < SHN_LORESERVE && shndx != SHN_UNDEF) [[likely]] {
144 return SecRef(shndx);
146 assert(shndx == SHN_XINDEX);
147 const auto &shndx_tab = sym_is_local(sym) ? local_shndx : global_shndx;
148 return SecRef(shndx_tab[sym_idx(sym)]);
152 [[nodiscard]]
static bool sym_is_local(
const SymRef sym) {
153 return (sym.id() & 0x8000'0000) == 0;
156 [[nodiscard]]
static u32 sym_idx(
const SymRef sym) {
157 return sym.id() & ~0x8000'0000;
160 [[nodiscard]] Elf64_Sym *sym_ptr(
const SymRef sym) {
161 if (sym_is_local(sym)) {
162 return &local_symbols[sym_idx(sym)];
164 return &global_symbols[sym_idx(sym)];
168 [[nodiscard]]
const Elf64_Sym *sym_ptr(
const SymRef sym)
const {
169 if (sym_is_local(sym)) {
170 return &local_symbols[sym_idx(sym)];
172 return &global_symbols[sym_idx(sym)];
179 std::vector<u8> build_object_file()
override;
185class AssemblerElfA64 final :
public AssemblerElf {
186 static const TargetInfoElf TARGET_INFO;
189 explicit AssemblerElfA64() : AssemblerElf(TARGET_INFO) {}
192class AssemblerElfX64 final :
public AssemblerElf {
193 static const TargetInfoElf TARGET_INFO;
196 explicit AssemblerElfX64() : AssemblerElf(TARGET_INFO) {}