| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 | {    Copyright (c) 2003-2004 by Peter Vreman and Florian Klaempfl    This units contains special support for DWARF debug info    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************}unit cfidwarf;{$i fpcdefs.inc}interface    uses      cclasses,      globtype,      cgbase,cpubase,      aasmbase,aasmtai,aasmdata;    const      maxdwarfops = 2;    type      tdwarfoperenc=(doe_uleb,doe_sleb,doe_ptr,doe_32bit,doe_16bit,doe_8bit);      tdwarfopertype=(dop_reg,dop_const,dop_sym,dop_reloffset);      tdwarfoper=record        enc : tdwarfoperenc;        case typ:tdwarfopertype of          dop_reg : (register:tregister);          dop_const : (value:int64);          dop_sym : (sym:tasmsymbol);          dop_reloffset : (beginsym,endsym:tasmsymbol);      end;      tdwarfitem=class(TLinkedListItem)        op   : byte;        ops  : byte;        oper : array[0..maxdwarfops-1] of tdwarfoper;        constructor create(aop:byte);        constructor create_reg(aop:byte;enc1:tdwarfoperenc;reg:tregister);        constructor create_const(aop:byte;enc1:tdwarfoperenc;val:int64);        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)      private        FDwarfList : TLinkedList;        FFrameStartLabel,        FFrameEndLabel,        FLastloclabel : tasmlabel;        procedure cfa_advance_loc(list:TAsmList);        procedure generate_initial_instructions(list:TAsmList);virtual;      protected        code_alignment_factor,        data_alignment_factor : shortint;        property DwarfList:TlinkedList read FDwarfList;      public        constructor create;override;        destructor destroy;override;        procedure generate_code(list:TAsmList);override;        { operations }        procedure start_frame(list:TAsmList);override;        procedure end_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;{****************************************************************************                                TDWARFITEM****************************************************************************}    constructor tdwarfitem.create(aop:byte);      begin        inherited create;        op:=aop;        ops:=0;      end;    constructor tdwarfitem.create_reg(aop:byte;enc1:tdwarfoperenc;reg:tregister);      begin        inherited create;        op:=aop;        ops:=1;        oper[0].typ:=dop_reg;        oper[0].enc:=enc1;        oper[0].register:=reg;      end;    constructor tdwarfitem.create_const(aop:byte;enc1:tdwarfoperenc;val:int64);      begin        inherited create;        op:=aop;        ops:=1;        oper[0].typ:=dop_const;        oper[0].enc:=enc1;        oper[0].value:=val;      end;    constructor tdwarfitem.create_reloffset(aop:byte;enc1:tdwarfoperenc;beginlab,endlab:tasmsymbol);      begin        inherited create;        op:=aop;        ops:=1;        { relative offsets are passed }        oper[0].typ:=dop_reloffset;        oper[0].enc:=enc1;        oper[0].beginsym:=beginlab;        oper[0].endsym:=endlab;      end;    constructor tdwarfitem.create_reg_const(aop:byte;enc1:tdwarfoperenc;reg:tregister;enc2:tdwarfoperenc;val:longint);      begin        inherited create;        op:=aop;        ops:=2;        oper[0].typ:=dop_reg;        oper[0].enc:=enc1;        oper[0].register:=reg;        oper[1].typ:=dop_const;        oper[1].enc:=enc2;        oper[1].value:=val;      end;    procedure tdwarfitem.generate_code(list:TAsmList);      const        enc2ait_const : array[tdwarfoperenc] of taiconst_type = (          aitconst_uleb128bit,aitconst_sleb128bit,aitconst_ptr,          aitconst_32bit,aitconst_16bit,aitconst_8bit        );      var        i : integer;      begin        list.concat(tai_const.create_8bit(op));        for i:=0 to ops-1 do          begin            case oper[i].typ of              dop_const :                list.concat(tai_const.create(enc2ait_const[oper[i].enc],oper[i].value));              dop_sym :                begin                  if oper[i].enc<>doe_ptr then                    internalerror(200404127);                  list.concat(tai_const.create_sym(oper[i].sym));                end;              dop_reloffset :                list.concat(tai_const.create_rel_sym(enc2ait_const[oper[i].enc],oper[i].beginsym,oper[i].endsym));              dop_reg :                list.concat(tai_const.create(enc2ait_const[oper[i].enc],dwarf_reg(oper[i].register)));              else                internalerror(200404128);            end;          end;      end;{****************************************************************************                                 TDwarfAsmCFI****************************************************************************}    constructor TDwarfAsmCFI.create;      begin        inherited create;        FFrameStartLabel:=nil;        FFrameEndLabel:=nil;        FLastLocLabel:=nil;        code_alignment_factor:=1;        data_alignment_factor:=-4;        FDwarfList:=TLinkedList.Create;      end;    destructor TDwarfAsmCFI.destroy;      begin        FDwarfList.Free;      end;{$ifdef i386}    { if more cpu dependend stuff is implemented, this needs more refactoring }    procedure TDwarfAsmCFI.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)));        list.concat(tai_const.create_uleb128bit(sizeof(aint)));        list.concat(tai_const.create_8bit(DW_CFA_offset_extended));        list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));        list.concat(tai_const.create_uleb128bit((-sizeof(aint)) div data_alignment_factor));      end;{$else i386}    { if more cpu dependend stuff is implemented, this needs more refactoring }    procedure TDwarfAsmCFI.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)));        list.concat(tai_const.create_uleb128bit(sizeof(aint)));        list.concat(tai_const.create_8bit(DW_CFA_offset_extended));        list.concat(tai_const.create_uleb128bit(dwarf_reg(NR_RETURN_ADDRESS_REG)));        list.concat(tai_const.create_uleb128bit((-sizeof(aint)) div data_alignment_factor));      end;{$endif i386}    procedure TDwarfAsmCFI.generate_code(list:TAsmList);      var        hp : tdwarfitem;        cielabel,        lenstartlabel,        lenendlabel    : 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        }        current_asmdata.getlabel(cielabel,alt_dbgframe);        list.concat(tai_label.create(cielabel));        current_asmdata.getlabel(lenstartlabel,alt_dbgframe);        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 }        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)));        { Generate standard code            def_cfa(stackpointer,sizeof(aint))            cfa_offset_extended(returnaddres,-sizeof(aint))        }        generate_initial_instructions(list);        list.concat(cai_align.create_zeros(4));        list.concat(tai_label.create(lenendlabel));        lenstartlabel:=nil;        lenendlabel:=nil;        hp:=TDwarfItem(DwarfList.first);        while assigned(hp) do          begin            case hp.op of              DW_CFA_Start_Frame :                begin                  if assigned(lenstartlabel) then                    internalerror(200404125);                  if (hp.ops<>1) or                     (hp.oper[0].typ<>dop_reloffset) then                    internalerror(200404126);                  current_asmdata.getlabel(lenstartlabel,alt_dbgframe);                  current_asmdata.getlabel(lenendlabel,alt_dbgframe);                  { FDE                     DWORD length                     DWORD CIE-pointer = cielabel relative to section start                     PTRSIZE initial location = oper[0]                     PTRSIZE function size = oper[1]                  }                  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));                  list.concat(tai_const.create_rel_sym(aitconst_ptr,hp.oper[0].beginsym,hp.oper[0].endsym));                end;              DW_CFA_End_Frame :                begin                  list.concat(cai_align.create_zeros(4));                  list.concat(tai_label.create(lenendlabel));                  lenstartlabel:=nil;                  lenendlabel:=nil;                end;              else                hp.generate_code(list);            end;            hp:=TDwarfItem(hp.next);          end;        { Check for open frames }        if assigned(lenstartlabel) then          internalerror(2004041210);        { DwarfList is processed, remove items }        DwarfList.Clear;      end;    procedure TDwarfAsmCFI.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));      end;    procedure TDwarfAsmCFI.end_frame(list:TAsmList);      begin        if not assigned(FFrameStartLabel) then          internalerror(2004041213);        DwarfList.concat(tdwarfitem.create(DW_CFA_end_frame));        list.concat(tai_label.create(FFrameEndLabel));        FFrameStartLabel:=nil;        FFrameEndLabel:=nil;        FLastLocLabel:=nil;      end;    procedure TDwarfAsmCFI.cfa_advance_loc(list:TAsmList);      var        currloclabel : tasmlabel;      begin        if FLastloclabel=nil then          internalerror(200404082);        current_asmdata.getlabel(currloclabel,alt_dbgframe);        list.concat(tai_label.create(currloclabel));        DwarfList.concat(tdwarfitem.create_reloffset(DW_CFA_advance_loc4,doe_32bit,FLastloclabel,currloclabel));        FLastloclabel:=currloclabel;      end;    procedure TDwarfAsmCFI.cfa_offset(list:TAsmList;reg:tregister;ofs:longint);      begin        cfa_advance_loc(list);{ TODO: check if ref is a temp}        { offset must be positive }        DwarfList.concat(tdwarfitem.create_reg_const(DW_CFA_offset_extended,doe_uleb,reg,doe_uleb,ofs div data_alignment_factor));      end;    procedure TDwarfAsmCFI.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);      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);      begin        cfa_advance_loc(list);        DwarfList.concat(tdwarfitem.create_const(DW_CFA_def_cfa_offset,doe_uleb,ofs));      end;begin  CAsmCFI:=TDwarfAsmCFI;end.
 |