diff options
author | Tristan Gingold <tgingold@free.fr> | 2021-12-14 18:19:42 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2021-12-14 18:19:42 +0100 |
commit | c661e58db492f14b22e2ab59e58a8abde6e74c10 (patch) | |
tree | f3145768f859db5f5468865e05fc0d3e2772bd56 /src/ortho/mcode/ortho_code-x86-emits.adb | |
parent | 8d75953b65e81e404ea193b8994c638b5a8c470d (diff) | |
download | ghdl-c661e58db492f14b22e2ab59e58a8abde6e74c10.tar.gz ghdl-c661e58db492f14b22e2ab59e58a8abde6e74c10.tar.bz2 ghdl-c661e58db492f14b22e2ab59e58a8abde6e74c10.zip |
mcode: generate and register .eh_frame on linux x86/64
This is needed to generate backtraces.
Diffstat (limited to 'src/ortho/mcode/ortho_code-x86-emits.adb')
-rw-r--r-- | src/ortho/mcode/ortho_code-x86-emits.adb | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/src/ortho/mcode/ortho_code-x86-emits.adb b/src/ortho/mcode/ortho_code-x86-emits.adb index 132f7287b..84336818c 100644 --- a/src/ortho/mcode/ortho_code-x86-emits.adb +++ b/src/ortho/mcode/ortho_code-x86-emits.adb @@ -46,11 +46,6 @@ package body Ortho_Code.X86.Emits is Mode_U32 | Mode_I32 => Sz_32, Mode_U64 | Mode_I64 => Sz_64); - -- Well known sections. - Sect_Text : Binary_File.Section_Acc; - Sect_Rodata : Binary_File.Section_Acc; - Sect_Bss : Binary_File.Section_Acc; - -- For 64 bit to 32 bit conversion, we need an extra register. Just before -- the conversion, there is an OE_Reg instruction containing the extra -- register. Its value is saved here. @@ -2936,7 +2931,7 @@ package body Ortho_Code.X86.Emits is -- Emit prolog. -- push %ebp / push %rbp Push_Reg (R_Bp); - -- movl %esp, %ebp / movl %rsp, %rbp + -- movl %esp, %ebp / movq %rsp, %rbp Start_Insn; Gen_Rex (16#48#); Gen_8 (Opc_Mov_Rm_Reg + 1); @@ -2971,7 +2966,7 @@ package body Ortho_Code.X86.Emits is end; end if; - -- subl XXX, %esp / subl XXX, %rsp + -- subl XXX, %esp / subq XXX, %rsp if Frame_Size /= 0 then if not X86.Flags.Flag_Alloca_Call or else Frame_Size <= 4096 @@ -3090,6 +3085,24 @@ package body Ortho_Code.X86.Emits is end if; end Emit_Epilogue; + procedure Gen_FDE + is + Subprg_Size : Unsigned_32; + begin + Subprg_Size := Unsigned_32 (Get_Current_Pc - Subprg_Pc); + + Set_Current_Section (Sect_Eh_Frame); + Prealloc (20); + Gen_32 (16); -- Length + Gen_32 (Unsigned_32 (Get_Current_Pc)); -- CIE pointer + Gen_32 (Unsigned_32 (Subprg_Pc)); -- Initial location (.text rel) + Gen_32 (Subprg_Size); -- Function size + Gen_8 (0); -- Length + Gen_8 (0); + Gen_8 (0); + Gen_8 (0); + end Gen_FDE; + procedure Emit_Subprg (Subprg : Subprogram_Data_Acc) is pragma Assert (Subprg = Cur_Subprg); @@ -3114,6 +3127,10 @@ package body Ortho_Code.X86.Emits is end loop; Emit_Epilogue (Subprg); + + if Flags.Eh_Frame then + Gen_FDE; + end if; end Emit_Subprg; procedure Emit_Var_Decl (Decl : O_Dnode) @@ -3295,6 +3312,51 @@ package body Ortho_Code.X86.Emits is Debug_Hex := True; end if; + if Flags.Eh_Frame then + Create_Section (Sect_Eh_Frame, ".eh_frame", 0); + Set_Current_Section (Sect_Eh_Frame); + Prealloc (32); + + -- Generate CIE + Gen_32 (28); -- Length + Gen_32 (0); -- CIE id = 0 + Gen_8 (1); -- Version = 1 + Gen_8 (Character'Pos ('z')); -- Augmentation + Gen_8 (Character'Pos ('R')); -- Augmentation + Gen_8 (0); -- End of Augmentation + Gen_8 (1); -- Code align factor + if Flags.M64 then + Dwarf.Gen_Sleb128 (-8); -- Data align factor + Dwarf.Gen_Uleb128 (16); -- Return address (16 = rip) + else + Dwarf.Gen_Sleb128 (-4); + Dwarf.Gen_Uleb128 (0); -- TODO + end if; + Dwarf.Gen_Uleb128 (1); -- z: length of the remainder of augmentation + Gen_8 (16#23#); -- R: pointer encoding: .text relative, udata4 + + -- CFIs (call frame instructions) + -- Initial state: cfa = rsp + 8, rip = -8@cfa + Gen_8 (16#0c#); -- DW_CFA_def_cfa + Gen_8 (16#07#); -- reg 7 (rsp) + Gen_8 (16#08#); -- offset 8 + Gen_8 (16#80# or 16#10#); -- DW_CFA_def_offset reg 16 (rip) + Gen_8 (16#01#); -- offset 1 * (-8) = -8 + -- push %rbp, cfa = rsp + 16 + Gen_8 (16#40# or 16#01#); -- DW_CFA_advance_loc +1 + Gen_8 (16#0e#); -- DW_CFA_def_cfa_offset + Gen_8 (16#10#); -- offset 16 + Gen_8 (16#80# or 16#06#); -- DW_CFA_def_offset reg 6 (rbp) + Gen_8 (16#02#); -- offset 2 * (-8) = -16 + -- movq %rsp, %rbp, cfa = rbp + 16 + Gen_8 (16#40# or 16#03#); -- DW_CFA_advance_loc +3 + Gen_8 (16#0d#); -- DW_CFA_def_cfa_register + Gen_8 (16#06#); -- reg 6 (rbp) + Gen_8 (0); -- nop + Gen_8 (0); -- nop + Set_Current_Section (Sect_Text); + end if; + if Flag_Debug /= Debug_None then Dwarf.Init; Set_Current_Section (Sect_Text); @@ -3309,6 +3371,12 @@ package body Ortho_Code.X86.Emits is Set_Current_Section (Sect_Text); Dwarf.Finish; end if; + + if Flags.Eh_Frame then + Set_Current_Section (Sect_Eh_Frame); + Prealloc (4); + Gen_32 (0); -- Size = 0 -> end. + end if; end Finish; end Ortho_Code.X86.Emits; |