Skip to main content

luaur_code_gen/methods/
unwind_builder_dwarf_2_start_info.rs

1use crate::enums::arch::Arch;
2use crate::functions::align_position::align_position;
3use crate::functions::define_cfa_expression::define_cfa_expression;
4use crate::functions::define_saved_register_location::define_saved_register_location;
5use crate::functions::writeu_32::writeu_32;
6use crate::functions::writeu_8::writeu_8;
7use crate::functions::writeuleb_128::writeuleb_128;
8use crate::macros::codegen_assert::CODEGEN_ASSERT;
9use crate::macros::dw_reg_a_64_lr::DW_REG_A64_LR;
10use crate::macros::dw_reg_a_64_sp::DW_REG_A64_SP;
11use crate::macros::dw_reg_x_64_ra::DW_REG_X64_RA;
12use crate::macros::dw_reg_x_64_rsp::DW_REG_X64_RSP;
13use crate::records::unwind_builder_dwarf_2::UnwindBuilderDwarf2;
14
15impl UnwindBuilderDwarf2 {
16    pub fn start_info(&mut self, arch: Arch) {
17        CODEGEN_ASSERT!(arch == Arch::A64 || arch == Arch::X64);
18
19        self.begin_offset = 0;
20        self.unwind_functions.clear();
21        self.pos = self.raw_data.as_mut_ptr();
22        self.fde_entry_start = core::ptr::null_mut();
23
24        let cie_length = self.pos;
25        unsafe {
26            self.pos = writeu_32(self.pos, 0); // Length (to be filled later)
27        }
28
29        unsafe {
30            self.pos = writeu_32(self.pos, 0); // CIE id. 0 -- .eh_frame
31        }
32        unsafe {
33            self.pos = writeu_8(self.pos, 1); // Version
34        }
35
36        unsafe {
37            self.pos = writeu_8(self.pos, 0); // CIE augmentation String ""
38        }
39
40        let ra = if arch == Arch::A64 {
41            DW_REG_A64_LR
42        } else {
43            DW_REG_X64_RA
44        };
45
46        unsafe {
47            self.pos = writeuleb_128(self.pos, Self::kCodeAlignFactor as u64); // Code align factor
48        }
49        unsafe {
50            self.pos = writeuleb_128(self.pos, (-Self::kDataAlignFactor as i32 & 0x7f) as u64);
51            // Data align factor of (as signed LEB128)
52        }
53        unsafe {
54            self.pos = writeu_8(self.pos, ra as u8); // Return address register
55        }
56
57        // Optional CIE augmentation section (not present)
58
59        // Call frame instructions (common for all FDEs)
60        if arch == Arch::A64 {
61            unsafe {
62                self.pos = define_cfa_expression(self.pos, DW_REG_A64_SP, 0); // Define CFA to be the sp
63            }
64        } else {
65            unsafe {
66                self.pos = define_cfa_expression(self.pos, DW_REG_X64_RSP, 8); // Define CFA to be the rsp + 8
67            }
68            unsafe {
69                self.pos = define_saved_register_location(self.pos, DW_REG_X64_RA, 8);
70                // Define return address register (RA) to be located at CFA - 8
71            }
72        }
73
74        unsafe {
75            self.pos = align_position(cie_length, self.pos);
76        }
77        unsafe {
78            writeu_32(
79                cie_length,
80                (self.pos as usize - cie_length as usize - 4) as u32,
81            ); // Length field itself is excluded from length
82        }
83    }
84}