TPDE
Loading...
Searching...
No Matches
FunctionWriterX64.hpp
1// SPDX-FileCopyrightText: 2025 Contributors to TPDE <https://tpde.org>
2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3#pragma once
4
5#include "tpde/FunctionWriter.hpp"
6#include "tpde/base.hpp"
7#include <fadec-enc2.h>
8
9namespace tpde::x64 {
10
11/// Helper class to write function text for X64.
12class FunctionWriterX64 : public FunctionWriter<FunctionWriterX64> {
13 friend class FunctionWriter<FunctionWriterX64>;
14
15 static const TargetCIEInfo CIEInfo;
16
17public:
18 FunctionWriterX64() noexcept : FunctionWriter(CIEInfo) {}
19
20 void align(size_t align) noexcept {
21 u32 old_off = offset();
22 FunctionWriter::align(align);
23 // Pad text section with NOPs.
24 if (u32 cur_off = offset(); cur_off > old_off) {
25 fe64_NOP(cur_ptr() - (cur_off - old_off), cur_off - old_off);
26 }
27 }
28
29private:
30 void handle_fixups() noexcept;
31};
32
33inline void FunctionWriterX64::handle_fixups() noexcept {
34 for (const LabelFixup &fixup : label_fixups) {
35 u32 label_off = label_offset(fixup.label);
36 u32 fixup_off = fixup.off - label_skew;
37 u8 *dst_ptr = begin_ptr() + fixup_off;
38 switch (fixup.kind) {
39 case LabelFixupKind::X64_JMP_OR_MEM_DISP: {
40 // fix the jump immediate
41 u32 value = (label_off - fixup_off) - 4;
42 std::memcpy(dst_ptr, &value, sizeof(u32));
43 break;
44 }
45 case LabelFixupKind::X64_JUMP_TABLE: {
46 const auto table_off = *reinterpret_cast<u32 *>(dst_ptr) - label_skew;
47 const auto diff = (i32)label_off - (i32)table_off;
48 std::memcpy(dst_ptr, &diff, sizeof(u32));
49 break;
50 }
51 default: TPDE_UNREACHABLE("unexpected label fixup kind");
52 }
53 }
54}
55
56} // namespace tpde::x64
util::SmallVector< LabelFixup > label_fixups
Fixups for labels placed after their first use, processed at function end.
u8 *& cur_ptr() noexcept
Modifiable pointer to current writing position of the section.
u8 * begin_ptr() noexcept
Pointer to beginning of section data.
size_t offset() const noexcept
Get the current offset into the section.
u32 label_skew
Offset to subtract from all label offsets.