summaryrefslogtreecommitdiff
path: root/compiler/cfidwarf.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/cfidwarf.pas')
-rw-r--r--compiler/cfidwarf.pas365
1 files changed, 289 insertions, 76 deletions
diff --git a/compiler/cfidwarf.pas b/compiler/cfidwarf.pas
index 45958bbc68..f55410cfd6 100644
--- a/compiler/cfidwarf.pas
+++ b/compiler/cfidwarf.pas
@@ -23,13 +23,15 @@ unit cfidwarf;
{$i fpcdefs.inc}
+{ $define debug_eh}
+
interface
uses
cclasses,
globtype,
cgbase,cpubase,
- aasmbase,aasmtai,aasmdata;
+ aasmbase,aasmcfi,aasmtai,aasmdata;
const
maxdwarfops = 2;
@@ -54,12 +56,18 @@ interface
constructor create(aop:byte);
constructor create_reg(aop:byte;enc1:tdwarfoperenc;reg:tregister);
constructor create_const(aop:byte;enc1:tdwarfoperenc;val:int64);
+ constructor create_sym(aop: byte; enc1: tdwarfoperenc; sym: TAsmSymbol);
constructor create_reloffset(aop:byte;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
constructor create_reg_const(aop:byte;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);
procedure generate_code(list:TAsmList);
end;
TDwarfAsmCFI=class(TAsmCFI)
+ use_eh_frame : boolean;
+ constructor create;override;
+ end;
+
+ TDwarfAsmCFILowLevel=class(TDwarfAsmCFI)
private
FDwarfList : TLinkedList;
FFrameStartLabel,
@@ -75,9 +83,14 @@ interface
constructor create;override;
destructor destroy;override;
procedure generate_code(list:TAsmList);override;
+
+ function get_frame_start: TAsmLabel;override;
+ function get_cfa_list : TAsmList;override;
+
{ operations }
procedure start_frame(list:TAsmList);override;
procedure end_frame(list:TAsmList);override;
+ procedure outmost_frame(list: TAsmList);override;
procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);override;
procedure cfa_restore(list:TAsmList;reg:tregister);override;
procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);override;
@@ -85,47 +98,27 @@ interface
end;
+ TDwarfAsmCFIHighLevel=class(TDwarfAsmCFILowLevel)
+ public
+ procedure generate_code(list:TAsmList);override;
+
+ { operations }
+ procedure start_frame(list:TAsmList);override;
+ procedure end_frame(list:TAsmList);override;
+ procedure outmost_frame(list: TAsmList);override;
+ procedure cfa_offset(list:TAsmList;reg:tregister;ofs:longint);override;
+ procedure cfa_restore(list:TAsmList;reg:tregister);override;
+ procedure cfa_def_cfa_register(list:TAsmList;reg:tregister);override;
+ procedure cfa_def_cfa_offset(list:TAsmList;ofs:longint);override;
+ end;
+
implementation
uses
systems,
- verbose;
-
- const
- { Call frame information }
- DW_CFA_set_loc = $01;
- DW_CFA_advance_loc1 = $02;
- DW_CFA_advance_loc2 = $03;
- DW_CFA_advance_loc4 = $04;
- DW_CFA_offset_extended = $05;
- DW_CFA_restore_extended = $06;
- DW_CFA_def_cfa = $0c;
- DW_CFA_def_cfa_register = $0d;
- DW_CFA_def_cfa_offset = $0e;
- { Own additions }
- DW_CFA_start_frame = $f0;
- DW_CFA_end_frame = $f1;
-
- DW_LNS_copy = $01;
- DW_LNS_advance_pc = $02;
- DW_LNS_advance_line = $03;
- DW_LNS_set_file = $04;
- DW_LNS_set_column = $05;
- DW_LNS_negate_stmt = $06;
- DW_LNS_set_basic_block = $07;
- DW_LNS_const_add_pc = $08;
-
- DW_LNS_fixed_advance_pc = $09;
- DW_LNS_set_prologue_end = $0a;
- DW_LNS_set_epilogue_begin = $0b;
- DW_LNS_set_isa = $0c;
-
- DW_LNE_end_sequence = $01;
- DW_LNE_set_address = $02;
- DW_LNE_define_file = $03;
- DW_LNE_lo_user = $80;
- DW_LNE_hi_user = $ff;
-
+ cutils,
+ verbose,
+ dwarfbase;
{****************************************************************************
TDWARFITEM
@@ -161,6 +154,17 @@ implementation
end;
+ constructor tdwarfitem.create_sym(aop:byte;enc1:tdwarfoperenc;sym:TAsmSymbol);
+ begin
+ inherited create;
+ op:=aop;
+ ops:=1;
+ oper[0].typ:=dop_sym;
+ oper[0].enc:=enc1;
+ oper[0].sym:=sym;
+ end;
+
+
constructor tdwarfitem.create_reloffset(aop:byte;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);
begin
inherited create;
@@ -224,6 +228,19 @@ implementation
constructor TDwarfAsmCFI.create;
begin
+ inherited;
+ if tf_use_psabieh in target_info.flags then
+ use_eh_frame:=true;
+ end;
+
+
+
+{****************************************************************************
+ TDwarfAsmCFILowLevel
+****************************************************************************}
+
+ constructor TDwarfAsmCFILowLevel.create;
+ begin
inherited create;
FFrameStartLabel:=nil;
FFrameEndLabel:=nil;
@@ -234,7 +251,7 @@ implementation
end;
- destructor TDwarfAsmCFI.destroy;
+ destructor TDwarfAsmCFILowLevel.destroy;
begin
FDwarfList.Free;
end;
@@ -242,7 +259,7 @@ implementation
{$ifdef i386}
{ if more cpu dependend stuff is implemented, this needs more refactoring }
- procedure TDwarfAsmCFI.generate_initial_instructions(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.generate_initial_instructions(list:TAsmList);
begin
list.concat(tai_const.create_8bit(DW_CFA_def_cfa));
list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_STACK_POINTER_REG)));
@@ -253,7 +270,7 @@ implementation
end;
{$else i386}
{ if more cpu dependend stuff is implemented, this needs more refactoring }
- procedure TDwarfAsmCFI.generate_initial_instructions(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.generate_initial_instructions(list:TAsmList);
begin
list.concat(tai_const.create_8bit(DW_CFA_def_cfa));
list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_STACK_POINTER_REG)));
@@ -264,24 +281,46 @@ implementation
end;
{$endif i386}
- procedure TDwarfAsmCFI.generate_code(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.generate_code(list:TAsmList);
var
hp : tdwarfitem;
+ CurrentLSDALabel,
cielabel,
lenstartlabel,
- lenendlabel : tasmlabel;
+ lenendlabel,
+ augendlabel,
+ augstartlabel,
+ fdeofslabel, curpos: tasmlabel;
tc : tai_const;
begin
- new_section(list,sec_debug_frame,'',0);
- { CIE
- DWORD length
- DWORD CIE_Id = 0xffffffff
- BYTE version = 1
- STRING augmentation = "" = BYTE 0
- ULEB128 code alignment factor = 1
- ULEB128 data alignment factor = -1
- BYTE return address register
- <...> start sequence
+ CurrentLSDALabel:=nil;
+ if use_eh_frame then
+ new_section(list,sec_eh_frame,'',0)
+ else
+ new_section(list,sec_debug_frame,'',0);
+ { debug_frame:
+ CIE
+ DWORD length
+ DWORD CIE_Id = 0xffffffff
+ BYTE version = 1
+ STRING augmentation = "" = BYTE 0
+ ULEB128 code alignment factor = 1
+ ULEB128 data alignment factor = -1
+ BYTE return address register
+ <...> augmentation
+ <...> start sequence
+
+ eh_frame:
+ CIE
+ DWORD length
+ DWORD CIE_Id = 0
+ BYTE version = 1
+ STRING augmentation = 'zPLR'#0
+ ULEB128 code alignment factor = 1
+ ULEB128 data alignment factor = -1
+ BYTE return address register
+ <...> start sequence
+
}
current_asmdata.getlabel(cielabel,alt_dbgframe);
list.concat(tai_label.create(cielabel));
@@ -289,12 +328,47 @@ implementation
current_asmdata.getlabel(lenendlabel,alt_dbgframe);
list.concat(tai_const.create_rel_sym(aitconst_32bit,lenstartlabel,lenendlabel));
list.concat(tai_label.create(lenstartlabel));
- list.concat(tai_const.create_32bit(longint($ffffffff)));
- list.concat(tai_const.create_8bit(1));
- list.concat(tai_const.create_8bit(0)); { empty string }
+ if use_eh_frame then
+ begin
+ list.concat(tai_const.create_32bit(0));
+ list.concat(tai_const.create_8bit(1));
+ list.concat(tai_const.create_8bit(ord('z')));
+ list.concat(tai_const.create_8bit(ord('P')));
+ list.concat(tai_const.create_8bit(ord('L')));
+ list.concat(tai_const.create_8bit(ord('R')));
+ list.concat(tai_const.create_8bit(0));
+ end
+ else
+ begin
+ list.concat(tai_const.create_32bit(longint($ffffffff)));
+ list.concat(tai_const.create_8bit(1));
+ list.concat(tai_const.create_8bit(0)); { empty string }
+ end;
list.concat(tai_const.create_uleb128bit(code_alignment_factor));
list.concat(tai_const.create_sleb128bit(data_alignment_factor));
list.concat(tai_const.create_8bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));
+ { augmentation data }
+ if use_eh_frame then
+ begin
+ current_asmdata.getlabel(augstartlabel,alt_dbgframe);
+ current_asmdata.getlabel(augendlabel,alt_dbgframe);
+ { size of augmentation data ('z') }
+ list.concat(tai_const.create_rel_sym(aitconst_uleb128bit,augstartlabel,augendlabel));
+ list.concat(tai_label.create(augstartlabel));
+ { personality function ('P') }
+ { encoding }
+ list.concat(tai_const.create_8bit({DW_EH_PE_indirect or DW_EH_PE_pcrel or} DW_EH_PE_sdata4));
+ { address of personality function }
+ list.concat(tai_const.Createname('_FPC_psabieh_personality_v0',AT_FUNCTION,0));
+
+ { LSDA encoding ('L')}
+ list.concat(tai_const.create_8bit({DW_EH_PE_pcrel or }DW_EH_PE_sdata4));
+
+ { FDE encoding ('R') }
+ list.concat(tai_const.create_8bit({DW_EH_PE_pcrel or }DW_EH_PE_sdata4));
+ list.concat(tai_label.create(augendlabel));
+ end;
+
{ Generate standard code
def_cfa(stackpointer,sizeof(aint))
cfa_offset_extended(returnaddres,-sizeof(aint))
@@ -327,13 +401,40 @@ implementation
}
list.concat(tai_const.create_rel_sym(aitconst_32bit,lenstartlabel,lenendlabel));
list.concat(tai_label.create(lenstartlabel));
- tc:=tai_const.create_sym(cielabel);
- { force label offset to secrel32 for windows systems }
- if (target_info.system in systems_windows+systems_wince) then
- tc.consttype:=aitconst_secrel32_symbol;
- list.concat(tc);
- list.concat(tai_const.create_sym(hp.oper[0].beginsym));
+ if use_eh_frame then
+ begin
+ { relative offset to the CIE }
+ current_asmdata.getlabel(fdeofslabel,alt_dbgframe);
+ list.concat(tai_label.create(fdeofslabel));
+ list.concat(tai_const.create_rel_sym(aitconst_32bit,cielabel,fdeofslabel));
+ end
+ else
+ begin
+ tc:=tai_const.create_sym(cielabel);
+ { force label offset to secrel32 for windows systems }
+ if (target_info.system in systems_windows+systems_wince) then
+ tc.consttype:=aitconst_secrel32_symbol;
+ list.concat(tc);
+ end;
+
+ current_asmdata.getlabel(curpos,alt_dbgframe);
+ list.concat(tai_label.create(curpos));
+ list.concat(tai_const.Create_sym(hp.oper[0].beginsym));
list.concat(tai_const.create_rel_sym(aitconst_ptr,hp.oper[0].beginsym,hp.oper[0].endsym));
+
+ { we wrote a 'z' into the CIE augmentation data }
+ if use_eh_frame then
+ begin
+ { size of augmentation }
+ list.concat(tai_const.create_8bit(sizeof(pint)));
+{$ifdef debug_eh}
+ list.concat(tai_comment.Create(strpnew('LSDA')));
+{$endif debug_eh}
+ { address of LSDA}
+ list.concat(tai_const.Create_sym(CurrentLSDALabel));
+ { do not reuse LSDA label }
+ CurrentLSDALabel:=nil;
+ end;
end;
DW_CFA_End_Frame :
begin
@@ -342,6 +443,8 @@ implementation
lenstartlabel:=nil;
lenendlabel:=nil;
end;
+ DW_Set_LSDALabel:
+ CurrentLSDALabel:=hp.oper[0].sym as TAsmLabel;
else
hp.generate_code(list);
end;
@@ -355,19 +458,37 @@ implementation
end;
- procedure TDwarfAsmCFI.start_frame(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.start_frame(list:TAsmList);
begin
- if assigned(FFrameStartLabel) then
- internalerror(200404129);
- current_asmdata.getlabel(FFrameStartLabel,alt_dbgframe);
current_asmdata.getlabel(FFrameEndLabel,alt_dbgframe);
- FLastloclabel:=FFrameStartLabel;
- list.concat(tai_label.create(FFrameStartLabel));
- DwarfList.concat(tdwarfitem.create_reloffset(DW_CFA_start_frame,doe_32bit,FFrameStartLabel,FFrameEndLabel));
+ FLastloclabel:=get_frame_start;
+ list.concat(tai_label.create(get_frame_start));
+ DwarfList.concat(tdwarfitem.create_reloffset(DW_CFA_start_frame,doe_32bit,get_frame_start,FFrameEndLabel));
+ end;
+
+
+ function TDwarfAsmCFILowLevel.get_frame_start : TAsmLabel;
+ begin
+ if not(assigned(FFrameStartLabel)) then
+ current_asmdata.getlabel(FFrameStartLabel,alt_dbgframe);
+ Result:=FFrameStartLabel;
+ end;
+
+
+ function TDwarfAsmCFILowLevel.get_cfa_list: TAsmList;
+ begin
+ Result:=TAsmList(DwarfList);
+ end;
+
+
+ procedure TDwarfAsmCFILowLevel.outmost_frame(list: TAsmList);
+ begin
+ cfa_advance_loc(list);
+ DwarfList.concat(tdwarfitem.create_reg(DW_CFA_undefined,doe_uleb,NR_RETURN_ADDRESS_REG));
end;
- procedure TDwarfAsmCFI.end_frame(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.end_frame(list:TAsmList);
begin
if not assigned(FFrameStartLabel) then
internalerror(2004041213);
@@ -379,7 +500,7 @@ implementation
end;
- procedure TDwarfAsmCFI.cfa_advance_loc(list:TAsmList);
+ procedure TDwarfAsmCFILowLevel.cfa_advance_loc(list:TAsmList);
var
currloclabel : tasmlabel;
begin
@@ -392,7 +513,7 @@ implementation
end;
- procedure TDwarfAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
+ procedure TDwarfAsmCFILowLevel.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);
begin
cfa_advance_loc(list);
{ TODO: check if ref is a temp}
@@ -401,27 +522,119 @@ implementation
end;
- procedure TDwarfAsmCFI.cfa_restore(list:TAsmList;reg:tregister);
+ procedure TDwarfAsmCFILowLevel.cfa_restore(list:TAsmList;reg:tregister);
begin
cfa_advance_loc(list);
DwarfList.concat(tdwarfitem.create_reg(DW_CFA_restore_extended,doe_uleb,reg));
end;
- procedure TDwarfAsmCFI.cfa_def_cfa_register(list:TAsmList;reg:tregister);
+ procedure TDwarfAsmCFILowLevel.cfa_def_cfa_register(list:TAsmList;reg:tregister);
begin
cfa_advance_loc(list);
DwarfList.concat(tdwarfitem.create_reg(DW_CFA_def_cfa_register,doe_uleb,reg));
end;
- procedure TDwarfAsmCFI.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
+ procedure TDwarfAsmCFILowLevel.cfa_def_cfa_offset(list:TAsmList;ofs:longint);
begin
cfa_advance_loc(list);
DwarfList.concat(tdwarfitem.create_const(DW_CFA_def_cfa_offset,doe_uleb,ofs));
end;
+{****************************************************************************
+ TDwarfAsmCFILowLevel
+****************************************************************************}
+
+
+ procedure TDwarfAsmCFIHighLevel.generate_code(list: TAsmList);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.start_frame(list: TAsmList);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_none.create(cfi_startproc));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.end_frame(list: TAsmList);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_none.create(cfi_endproc));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.outmost_frame(list: TAsmList);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_reg.create(cfi_undefined,NR_RETURN_ADDRESS_REG));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.cfa_offset(list: TAsmList; reg: tregister; ofs: longint);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_reg_val.create(cfi_offset,reg,ofs));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.cfa_restore(list: TAsmList; reg: tregister);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_reg.create(cfi_restore,reg));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.cfa_def_cfa_register(list: TAsmList; reg: tregister);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_reg.create(cfi_def_cfa_register,reg));
+ end;
+
+
+ procedure TDwarfAsmCFIHighLevel.cfa_def_cfa_offset(list: TAsmList; ofs: longint);
+ begin
+ if not(tf_use_hlcfi in target_info.flags) then
+ begin
+ inherited;
+ exit;
+ end;
+ list.concat(tai_cfi_op_val.create(cfi_def_cfa_offset,ofs));
+ end;
+
+
begin
- CAsmCFI:=TDwarfAsmCFI;
+ CAsmCFI:=TDwarfAsmCFIHighLevel;
end.