6#include "tpde/AssemblerElf.hpp"
7#include "tpde/util/SegmentedVector.hpp"
8#include "tpde/util/SmallVector.hpp"
17 static const TargetInfo TARGET_INFO;
19 class SectionWriter :
public Base::SectionWriterBase<SectionWriter> {
21 void more_space(u32 size)
noexcept;
23 bool try_write_inst(u32 inst)
noexcept {
31 void write_inst(u32 inst)
noexcept {
36 void write_inst_unchecked(u32 inst)
noexcept {
38 write_unchecked(inst);
42 enum class UnresolvedEntryKind : u8 {
54 u32 unresolved_test_brs = 0, unresolved_cond_brs = 0;
62 VeneerInfo &get_veneer_info(DataSection §ion)
noexcept {
63 if (!section.target_info) [[unlikely]] {
64 section.target_info = &veneer_infos.emplace_back();
66 return *
static_cast<VeneerInfo *
>(section.target_info);
70 void add_unresolved_entry(Label label,
73 UnresolvedEntryKind kind)
noexcept {
74 AssemblerElfBase::reloc_sec(sec, label,
static_cast<u8
>(kind), off);
75 if (kind == UnresolvedEntryKind::COND_BR) {
76 get_veneer_info(get_section(sec)).unresolved_cond_brs++;
77 }
else if (kind == UnresolvedEntryKind::TEST_BR) {
78 get_veneer_info(get_section(sec)).unresolved_test_brs++;
82 void handle_fixup(
const TempSymbolInfo &info,
83 const TempSymbolFixup &fixup)
noexcept;
85 void reset() noexcept;
89 AssemblerElfA64::handle_fixup(const TempSymbolInfo &info,
90 const TempSymbolFixup &fixup) noexcept {
92 assert(info.section == fixup.section &&
"multi-text section not supported");
93 DataSection §ion = get_section(fixup.section);
94 VeneerInfo &vi = get_veneer_info(section);
95 auto &veneers = vi.veneers;
97 u8 *section_data = section.data.data();
98 u32 *dst_ptr =
reinterpret_cast<u32 *
>(section_data + fixup.off);
100 auto fix_condbr = [&](
unsigned nbits) {
101 i64 diff = (i64)info.off - (i64)fixup.off;
102 assert(diff >= 0 && diff < 128 * 1024 * 1024);
104 if (diff >= (4 << (nbits - 1))) {
105 auto veneer = std::lower_bound(veneers.begin(), veneers.end(), fixup.off);
106 assert(veneer != veneers.end());
109 auto *br =
reinterpret_cast<u32 *
>(section_data + *veneer);
110 assert(*br == 0 &&
"overwriting instructions with veneer branch");
111 *br = de64_B((info.off - *veneer) / 4);
112 diff = *veneer - fixup.off;
115 u32 off_mask = ((1 << nbits) - 1) << 5;
116 *dst_ptr = (*dst_ptr & ~off_mask) | ((diff / 4) << 5);
119 switch (
static_cast<UnresolvedEntryKind
>(fixup.kind)) {
120 case UnresolvedEntryKind::BR: {
122 i64 diff = (i64)info.off - (i64)fixup.off;
123 assert(diff >= 0 && diff < 128 * 1024 * 1024);
124 *dst_ptr = de64_B(diff / 4);
127 case UnresolvedEntryKind::COND_BR:
128 if (veneers.empty() || veneers.back() < fixup.off) {
129 assert(vi.unresolved_cond_brs > 0);
130 vi.unresolved_cond_brs -= 1;
134 case UnresolvedEntryKind::TEST_BR:
135 if (veneers.empty() || veneers.back() < fixup.off) {
136 assert(vi.unresolved_test_brs > 0);
137 vi.unresolved_test_brs -= 1;
141 case UnresolvedEntryKind::JUMP_TABLE: {
142 auto table_off = *
reinterpret_cast<u32 *
>(section_data + fixup.off);
143 *dst_ptr = (i32)info.off - (i32)table_off;
149inline void AssemblerElfA64::SectionWriter::more_space(u32 size)
noexcept {
150 if (allocated_size() >= (128 * 1024 * 1024)) {
152 TPDE_FATAL(
"AArch64 doesn't support sections larger than 128 MiB");
157 VeneerInfo *vi =
static_cast<VeneerInfo *
>(section->target_info);
158 u32 unresolved_count =
159 vi ? vi->unresolved_test_brs + vi->unresolved_cond_brs : 0;
160 u32 veneer_size =
sizeof(u32) * unresolved_count;
161 SectionWriterBase::more_space(size + veneer_size + 4);
162 if (veneer_size == 0) {
167 u32 max_dist = vi->unresolved_test_brs ? 4 << (14 - 1) : 4 << (19 - 1);
168 max_dist -= veneer_size;
171 u32 first_condbr = vi->veneers.empty() ? 0 : vi->veneers.back();
173 if (first_condbr + max_dist > allocated_size()) {
177 u32 cur_off = offset();
178 vi->veneers.push_back(cur_off + 4);
179 vi->unresolved_test_brs = vi->unresolved_cond_brs = 0;
181 *
reinterpret_cast<u32 *
>(data_begin + cur_off) = de64_B(veneer_size / 4 + 1);
182 std::memset(data_begin + cur_off + 4, 0, veneer_size);
183 cur_ptr() += veneer_size + 4;
186inline void AssemblerElfA64::reset() noexcept {
188 veneer_infos.clear();
A vector with stable element addresses.
AssemblerElf contains the architecture-independent logic to emit ELF object files (currently linux-sp...
Information about veneers and unresolved branches for a section.
util::SmallVector< u32, 16 > veneers
The AArch64-specific implementation for the AssemblerElf.