diff options
Diffstat (limited to 'compiler/cfidwarf.pas')
-rw-r--r-- | compiler/cfidwarf.pas | 365 |
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. |