mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-19 23:39:31 +02:00
+ Support classes for creating unwind bytecode for Win64.
git-svn-id: trunk@19071 -
This commit is contained in:
parent
6280ee2eed
commit
1365467b0d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -664,6 +664,7 @@ compiler/x86_64/r8664std.inc svneol=native#text/plain
|
||||
compiler/x86_64/rax64att.pas svneol=native#text/plain
|
||||
compiler/x86_64/rax64int.pas svneol=native#text/plain
|
||||
compiler/x86_64/rgcpu.pas svneol=native#text/plain
|
||||
compiler/x86_64/win64unw.pas svneol=native#text/plain
|
||||
compiler/x86_64/x8664ats.inc svneol=native#text/plain
|
||||
compiler/x86_64/x8664att.inc svneol=native#text/plain
|
||||
compiler/x86_64/x8664int.inc svneol=native#text/plain
|
||||
|
@ -86,7 +86,9 @@ interface
|
||||
{ used to mark assembler blocks and inlined functions }
|
||||
ait_marker,
|
||||
{ used to describe a new location of a variable }
|
||||
ait_varloc
|
||||
ait_varloc,
|
||||
{ SEH directives used in ARM,MIPS and x86_64 COFF targets }
|
||||
ait_seh_directive
|
||||
);
|
||||
|
||||
taiconst_type = (
|
||||
@ -173,7 +175,8 @@ interface
|
||||
'regalloc',
|
||||
'tempalloc',
|
||||
'marker',
|
||||
'varloc'
|
||||
'varloc',
|
||||
'seh_directive'
|
||||
);
|
||||
|
||||
type
|
||||
@ -237,7 +240,7 @@ interface
|
||||
SkipInstr = [ait_comment, ait_symbol,ait_section
|
||||
,ait_stab, ait_function_name, ait_force_line
|
||||
,ait_regalloc, ait_tempalloc, ait_symbol_end, ait_directive
|
||||
,ait_varloc];
|
||||
,ait_varloc,ait_seh_directive];
|
||||
|
||||
{ ait_* types which do not have line information (and hence which are of type
|
||||
tai, otherwise, they are of type tailineinfo }
|
||||
@ -250,7 +253,8 @@ interface
|
||||
ait_thumb_func,
|
||||
{$endif arm}
|
||||
ait_real_32bit,ait_real_64bit,ait_real_80bit,ait_comp_64bit,ait_real_128bit,
|
||||
ait_symbol
|
||||
ait_symbol,
|
||||
ait_seh_directive
|
||||
];
|
||||
|
||||
|
||||
@ -276,6 +280,15 @@ interface
|
||||
asd_weak_definition
|
||||
);
|
||||
|
||||
TAsmSehDirective=(
|
||||
ash_proc,ash_endproc,
|
||||
ash_endprologue,ash_handler,ash_handlerdata,
|
||||
ash_eh,ash_32,ash_no32,
|
||||
ash_setframe,ash_stackalloc,ash_pushreg,
|
||||
ash_savereg,ash_savexmm,ash_pushframe
|
||||
);
|
||||
|
||||
|
||||
const
|
||||
regallocstr : array[tregalloctype] of string[10]=('allocated','released','sync','resized');
|
||||
tempallocstr : array[boolean] of string[10]=('released','allocated');
|
||||
@ -285,6 +298,13 @@ interface
|
||||
'extern','nasm_import', 'tc', 'reference',
|
||||
'no_dead_strip','weak_reference','lazy_reference','weak_definition'
|
||||
);
|
||||
sehdirectivestr : array[TAsmSehDirective] of string[15]=(
|
||||
'seh_proc','seh_endproc',
|
||||
'seh_endprologue','seh_handler','seh_handlerdata',
|
||||
'seh_eh','seh_32','seh_no32',
|
||||
'seh_setframe','seh_stackalloc','seh_pushreg',
|
||||
'seh_savereg','seh_savexmm','seh_pushframe'
|
||||
);
|
||||
|
||||
type
|
||||
{ abstract assembler item }
|
||||
@ -399,7 +419,7 @@ interface
|
||||
private
|
||||
{ this constructor is made private on purpose }
|
||||
{ because sections should be created via new_section() }
|
||||
constructor Create(Asectype:TAsmSectiontype;Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
constructor Create(Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
end;
|
||||
|
||||
|
||||
@ -661,6 +681,31 @@ interface
|
||||
procedure derefimpl;override;
|
||||
end;
|
||||
|
||||
TSehDirectiveDatatype=(sd_none,sd_string,sd_reg,sd_offset,sd_regoffset);
|
||||
|
||||
TSehDirectiveData=record
|
||||
case typ: TSehDirectiveDatatype of
|
||||
sd_none: ();
|
||||
sd_string: (name:pshortstring);
|
||||
sd_reg,sd_offset,sd_regoffset: (reg:TRegister;offset:dword);
|
||||
end;
|
||||
|
||||
tai_seh_directive = class(tai)
|
||||
kind: TAsmSehDirective;
|
||||
data: TSehDirectiveData;
|
||||
constructor create(_kind:TAsmSehDirective);
|
||||
constructor create_name(_kind:TAsmSehDirective;const _name: string);
|
||||
constructor create_reg(_kind:TAsmSehDirective;r:TRegister);
|
||||
constructor create_offset(_kind:TAsmSehDirective;ofs:dword);
|
||||
constructor create_reg_offset(_kind:TAsmSehDirective;r:TRegister;ofs:dword);
|
||||
constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
|
||||
destructor destroy;override;
|
||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||
procedure generate_code(objdata:TObjData);virtual;
|
||||
property datatype: TSehDirectiveDatatype read data.typ;
|
||||
end;
|
||||
tai_seh_directive_class=class of tai_seh_directive;
|
||||
|
||||
var
|
||||
{ array with all class types for tais }
|
||||
aiclass : taiclassarray;
|
||||
@ -668,12 +713,13 @@ interface
|
||||
{ target specific tais, possibly overwritten in target specific aasmcpu }
|
||||
cai_align : tai_align_class = tai_align_abstract;
|
||||
cai_cpu : tai_cpu_class = tai_cpu_abstract;
|
||||
cai_seh_directive: tai_seh_directive_class = tai_seh_directive;
|
||||
|
||||
{ hook to notify uses of registers }
|
||||
add_reg_instruction_hook : tadd_reg_instruction_proc;
|
||||
|
||||
procedure maybe_new_object_file(list:TAsmList);
|
||||
procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
procedure section_symbol_start(list:TAsmList;const Aname:string;Asymtyp:Tasmsymtype;
|
||||
Aglobal:boolean;Asectype:TAsmSectiontype;Aalign:byte);
|
||||
procedure section_symbol_end(list:TAsmList;const Aname:string);
|
||||
@ -705,7 +751,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
procedure new_section(list:TAsmList;Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
begin
|
||||
list.concat(tai_section.create(Asectype,Aname,Aalign,Asecorder));
|
||||
list.concat(cai_align.create(Aalign));
|
||||
@ -893,7 +939,7 @@ implementation
|
||||
TAI_SECTION
|
||||
****************************************************************************}
|
||||
|
||||
constructor tai_section.Create(Asectype:TAsmSectiontype;Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
constructor tai_section.Create(Asectype:TAsmSectiontype;const Aname:string;Aalign:byte;Asecorder:TasmSectionorder=secorder_default);
|
||||
begin
|
||||
inherited Create;
|
||||
typ:=ait_section;
|
||||
@ -2486,6 +2532,110 @@ implementation
|
||||
ppufile.putbyte(fillop);
|
||||
ppufile.putbyte(byte(use_op));
|
||||
end;
|
||||
|
||||
{****************************************************************************
|
||||
tai_seh_directive
|
||||
****************************************************************************}
|
||||
|
||||
const
|
||||
datatypemap: array[TAsmSehDirective] of TSehDirectiveDatatype=(
|
||||
sd_string, { proc }
|
||||
sd_none, { endproc }
|
||||
sd_none, { endprologue }
|
||||
sd_none, { TODO: handler }
|
||||
sd_none, { handlerdata }
|
||||
sd_none,sd_none,sd_none, { eh, 32, no32 }
|
||||
sd_regoffset, { setframe }
|
||||
sd_offset, { stackalloc }
|
||||
sd_reg, { pushreg }
|
||||
sd_regoffset, { savereg }
|
||||
sd_regoffset, { savexmm }
|
||||
sd_none { pushframe }
|
||||
);
|
||||
|
||||
constructor tai_seh_directive.create(_kind:TAsmSehDirective);
|
||||
begin
|
||||
inherited Create;
|
||||
typ:=ait_seh_directive;
|
||||
kind:=_kind;
|
||||
data.typ:=datatypemap[_kind];
|
||||
end;
|
||||
|
||||
constructor tai_seh_directive.create_name(_kind:TAsmSehDirective;const _name:string);
|
||||
begin
|
||||
create(_kind);
|
||||
data.name:=stringdup(_name);
|
||||
end;
|
||||
|
||||
constructor tai_seh_directive.create_reg(_kind:TAsmSehDirective;r:TRegister);
|
||||
begin
|
||||
create(_kind);
|
||||
data.reg:=r;
|
||||
end;
|
||||
|
||||
constructor tai_seh_directive.create_offset(_kind:TAsmSehDirective;ofs:dword);
|
||||
begin
|
||||
create(_kind);
|
||||
data.offset:=ofs;
|
||||
end;
|
||||
|
||||
constructor tai_seh_directive.create_reg_offset(_kind:TAsmSehDirective;
|
||||
r:TRegister;ofs:dword);
|
||||
begin
|
||||
create(_kind);
|
||||
data.offset:=ofs;
|
||||
data.reg:=r;
|
||||
end;
|
||||
|
||||
constructor tai_seh_directive.ppuload(t:taitype;ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuload(t, ppufile);
|
||||
kind:=TAsmSehDirective(ppufile.getbyte);
|
||||
data.typ:=datatypemap[kind];
|
||||
case data.typ of
|
||||
sd_none: ;
|
||||
sd_string:
|
||||
data.name:=stringdup(ppufile.getstring);
|
||||
|
||||
sd_reg,sd_offset,sd_regoffset:
|
||||
begin
|
||||
ppufile.getdata(data.reg,sizeof(TRegister));
|
||||
data.offset:=ppufile.getdword;
|
||||
end;
|
||||
else
|
||||
InternalError(2011091201);
|
||||
end;
|
||||
end;
|
||||
|
||||
destructor tai_seh_directive.destroy;
|
||||
begin
|
||||
if data.typ=sd_string then
|
||||
stringdispose(data.name);
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
procedure tai_seh_directive.ppuwrite(ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuwrite(ppufile);
|
||||
ppufile.putbyte(ord(kind));
|
||||
case data.typ of
|
||||
sd_none: ;
|
||||
sd_string:
|
||||
ppufile.putstring(data.name^);
|
||||
sd_reg,sd_offset,sd_regoffset:
|
||||
begin
|
||||
ppufile.putdata(data.reg,sizeof(TRegister));
|
||||
ppufile.putdword(data.offset);
|
||||
end;
|
||||
else
|
||||
InternalError(2011091202);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure tai_seh_directive.generate_code(objdata:TObjData);
|
||||
begin
|
||||
end;
|
||||
|
||||
begin
|
||||
{ taitype should fit into a 4 byte set for speed reasons }
|
||||
if ord(high(taitype))>31 then
|
||||
|
@ -1236,6 +1236,24 @@ implementation
|
||||
AsmLn;
|
||||
end;
|
||||
|
||||
ait_seh_directive :
|
||||
begin
|
||||
AsmWrite('.'+sehdirectivestr[tai_seh_directive(hp).kind]);
|
||||
case tai_seh_directive(hp).datatype of
|
||||
sd_none:;
|
||||
sd_string:
|
||||
AsmWrite(' '+tai_seh_directive(hp).data.name^);
|
||||
sd_reg:
|
||||
AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
|
||||
sd_offset:
|
||||
AsmWrite(' '+tostr(tai_seh_directive(hp).data.offset));
|
||||
sd_regoffset:
|
||||
AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg)+', '+
|
||||
tostr(tai_seh_directive(hp).data.offset));
|
||||
end;
|
||||
AsmLn;
|
||||
end;
|
||||
|
||||
else
|
||||
internalerror(2006012201);
|
||||
end;
|
||||
|
@ -1393,6 +1393,8 @@ Implementation
|
||||
ait_cutobject :
|
||||
if SmartAsm then
|
||||
break;
|
||||
ait_seh_directive :
|
||||
tai_seh_directive(hp).generate_code(objdata);
|
||||
end;
|
||||
hp:=Tai(hp.next);
|
||||
end;
|
||||
|
@ -619,6 +619,7 @@ implementation
|
||||
aiclass[ait_regalloc]:=tai_regalloc;
|
||||
aiclass[ait_tempalloc]:=tai_tempalloc;
|
||||
aiclass[ait_marker]:=tai_marker;
|
||||
aiclass[ait_seh_directive]:=tai_seh_directive;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -44,6 +44,7 @@ implementation
|
||||
{$endif}
|
||||
{$ifndef NOTARGETWIN}
|
||||
,t_win
|
||||
,win64unw
|
||||
{$endif}
|
||||
{$ifndef NOTARGETSUNOS}
|
||||
,t_sunos
|
||||
|
361
compiler/x86_64/win64unw.pas
Normal file
361
compiler/x86_64/win64unw.pas
Normal file
@ -0,0 +1,361 @@
|
||||
{
|
||||
Copyright (c) 2011 by Free Pascal development team
|
||||
|
||||
Support for win64 unwind data
|
||||
|
||||
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 win64unw;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
cclasses,globtype,aasmbase,aasmdata,aasmtai,cgbase,ogbase;
|
||||
|
||||
type
|
||||
TWin64CFI=class
|
||||
private
|
||||
FFrameOffs, FFrameReg: Integer;
|
||||
FFlags: Integer;
|
||||
FCount: Integer;
|
||||
FElements:TLinkedList;
|
||||
FFrameStartSym:TObjSymbol;
|
||||
FPrologueEndPos:aword;
|
||||
FName: pshortstring;
|
||||
procedure AddElement(objdata:TObjData;aCode,aInfo:Integer;aOffs:dword);
|
||||
public
|
||||
constructor create;
|
||||
destructor destroy;override;
|
||||
procedure generate_code(objdata:TObjData);
|
||||
procedure start_frame(objdata:TObjData; const name: string);
|
||||
procedure end_frame(objdata:TObjData);
|
||||
procedure end_prologue(objdata:TObjData);
|
||||
procedure push_reg(objdata:TObjData;reg:tregister);
|
||||
procedure save_reg(objdata:TObjData;reg:tregister;ofs:dword);
|
||||
procedure save_xmm(objdata:TObjData;reg:tregister;ofs:dword);
|
||||
procedure set_frame(objdata:TObjData; reg:tregister;ofs:dword);
|
||||
procedure stack_alloc(objdata:TObjData;ofs:dword);
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,verbose,cpubase;
|
||||
|
||||
const
|
||||
UWOP_PUSH_NONVOL = 0; { info = register number }
|
||||
UWOP_ALLOC_LARGE = 1; { no info, alloc size in next 2 slots }
|
||||
UWOP_ALLOC_SMALL = 2; { info = size of allocation / 8 - 1 }
|
||||
UWOP_SET_FPREG = 3; { no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 }
|
||||
UWOP_SAVE_NONVOL = 4; { info = register number, offset in next slot }
|
||||
UWOP_SAVE_NONVOL_FAR = 5; { info = register number, offset in next 2 slots }
|
||||
UWOP_SAVE_XMM = 6;
|
||||
UWOP_SAVE_XMM_FAR = 7;
|
||||
UWOP_SAVE_XMM128 = 8; { info = XMM reg number, offset in next slot }
|
||||
UWOP_SAVE_XMM128_FAR = 9; { info = XMM reg number, offset in next 2 slots }
|
||||
UWOP_PUSH_MACHFRAME = 10; { info = 0: no error-code, 1: error-code }
|
||||
|
||||
UNW_FLAG_EHANDLER = $01; { exceptiion handler }
|
||||
UNW_FLAG_UHANDLER = $02; { termination handler }
|
||||
UNW_FLAG_FHANDLER = UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER;
|
||||
UNW_FLAG_CHAININFO = $04; { mutually exclusive with the above }
|
||||
|
||||
|
||||
type
|
||||
tai_seh_directive_x64=class(tai_seh_directive)
|
||||
procedure generate_code(objdata:TObjData);override;
|
||||
end;
|
||||
|
||||
TPrologueElement=class(TLinkedListItem)
|
||||
public
|
||||
opcode: Integer; { =(info shl 4) or code }
|
||||
ofs: dword;
|
||||
addr: aword;
|
||||
end;
|
||||
|
||||
var
|
||||
current_unw: TWin64Cfi;
|
||||
|
||||
{ This generally duplicates private aasmcpu.regval() }
|
||||
function EncodeReg(r: TRegister): integer;
|
||||
begin
|
||||
case r of
|
||||
NR_RAX: result:=0;
|
||||
NR_RCX: result:=1;
|
||||
NR_RDX: result:=2;
|
||||
NR_RBX: result:=3;
|
||||
NR_RSP: result:=4;
|
||||
NR_RBP: result:=5;
|
||||
NR_RSI: result:=6;
|
||||
NR_RDI: result:=7;
|
||||
NR_R8: result:=8;
|
||||
NR_R9: result:=9;
|
||||
NR_R10: result:=10;
|
||||
NR_R11: result:=11;
|
||||
NR_R12: result:=12;
|
||||
NR_R13: result:=13;
|
||||
NR_R14: result:=14;
|
||||
NR_R15: result:=15;
|
||||
else
|
||||
InternalError(2011072305);
|
||||
end;
|
||||
end;
|
||||
|
||||
function EncodeXMM(r: TRegister): integer;
|
||||
begin
|
||||
if getregtype(r)=R_MMREGISTER then
|
||||
result:=getsupreg(r)
|
||||
else
|
||||
InternalError(2011072305);
|
||||
end;
|
||||
|
||||
|
||||
{ TWin64CFI }
|
||||
|
||||
constructor TWin64CFI.create;
|
||||
begin
|
||||
inherited create;
|
||||
FElements:=TLinkedList.Create;
|
||||
end;
|
||||
|
||||
destructor TWin64CFI.destroy;
|
||||
begin
|
||||
FElements.Free;
|
||||
stringdispose(FName);
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.AddElement(objdata:TObjData;aCode,aInfo:Integer;aOffs:dword);
|
||||
var
|
||||
el:TPrologueElement;
|
||||
begin
|
||||
el:=TPrologueElement.Create;
|
||||
FElements.concat(el);
|
||||
el.opcode:=(aInfo shl 4) or aCode;
|
||||
el.ofs:=aOffs;
|
||||
el.addr:=objdata.CurrObjSec.Size;
|
||||
|
||||
{ a single element may occupy 1,2 or 3 word-sized slots }
|
||||
case aCode of
|
||||
UWOP_ALLOC_LARGE:
|
||||
Inc(FCount,2+ord(aInfo<>0));
|
||||
|
||||
UWOP_SAVE_NONVOL_FAR,
|
||||
UWOP_SAVE_XMM128_FAR:
|
||||
Inc(FCount,3);
|
||||
|
||||
UWOP_SAVE_NONVOL,
|
||||
UWOP_SAVE_XMM128:
|
||||
Inc(FCount,2);
|
||||
|
||||
else
|
||||
inc(FCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.generate_code(objdata:TObjData);
|
||||
var
|
||||
hp: TPrologueElement;
|
||||
uwcode: array [0..1] of byte;
|
||||
uwdata: array [0..3] of byte;
|
||||
cursec: TObjSection;
|
||||
xdatasym,pdatasym: TObjSymbol;
|
||||
zero: word;
|
||||
begin
|
||||
{ if FCount=0 then
|
||||
InternalError(2011072308); }
|
||||
if FCount>255 then
|
||||
InternalError(2011072301);
|
||||
|
||||
cursec:=objdata.CurrObjSec;
|
||||
objdata.createsection('.xdata.n_'+lower(FName^),4,[oso_data,oso_load]);
|
||||
xdatasym:=objdata.symboldefine('$unwind$'+FName^,AB_GLOBAL,AT_DATA);
|
||||
uwdata[0]:=(FFlags shl 3) or 1;
|
||||
uwdata[1]:=FPrologueEndPos-FFrameStartSym.offset;
|
||||
uwdata[2]:=FCount;
|
||||
{ Offset is multiple of 16, so it is already shifted into correct position }
|
||||
uwdata[3]:=FFrameOffs or FFrameReg;
|
||||
objdata.writebytes(uwdata,4);
|
||||
|
||||
{ write elements in reverse order (offset descending) }
|
||||
hp:=TPrologueElement(FElements.Last);
|
||||
while Assigned(hp) do
|
||||
begin
|
||||
uwcode[0]:=hp.addr-FFrameStartSym.address;
|
||||
uwcode[1]:=hp.opcode;
|
||||
objdata.writebytes(uwcode,2);
|
||||
case hp.opcode and $0F of
|
||||
UWOP_PUSH_NONVOL,
|
||||
UWOP_ALLOC_SMALL,
|
||||
UWOP_SET_FPREG,
|
||||
UWOP_PUSH_MACHFRAME: ; { These have no extra data }
|
||||
|
||||
UWOP_ALLOC_LARGE:
|
||||
if (hp.opcode and $F0)<>0 then
|
||||
objdata.writebytes(hp.ofs,4)
|
||||
else
|
||||
objdata.writebytes(hp.ofs,2);
|
||||
|
||||
UWOP_SAVE_NONVOL_FAR,
|
||||
UWOP_SAVE_XMM128_FAR:
|
||||
objdata.writebytes(hp.ofs,4);
|
||||
|
||||
UWOP_SAVE_NONVOL,
|
||||
UWOP_SAVE_XMM128:
|
||||
objdata.writebytes(hp.ofs,2);
|
||||
else
|
||||
InternalError(2011072302);
|
||||
end;
|
||||
|
||||
hp:=TPrologueElement(hp.Previous);
|
||||
end;
|
||||
{ pad with zeros to dword boundary }
|
||||
zero:=0;
|
||||
if odd(FCount) then
|
||||
objdata.writebytes(zero,2);
|
||||
{ TODO: handler rva and data should follow if flags specify a handler }
|
||||
|
||||
FElements.Clear;
|
||||
|
||||
objdata.createsection(sec_pdata,FName^);
|
||||
pdatasym:=objdata.symboldefine('$pdata$'+FName^,AB_LOCAL,AT_DATA);
|
||||
objdata.writereloc(0,4,FFrameStartSym,RELOC_RVA);
|
||||
objdata.writereloc(FFrameStartSym.Size,4,FFrameStartSym,RELOC_RVA);
|
||||
objdata.writereloc(0,4,xdatasym,RELOC_RVA);
|
||||
{ restore previous state }
|
||||
objdata.SetSection(cursec);
|
||||
{ create a dummy relocation, so pdata is not smartlinked away }
|
||||
objdata.writereloc(0,0,pdatasym,RELOC_NONE);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.start_frame(objdata:TObjData;const name:string);
|
||||
begin
|
||||
if assigned(FName) then
|
||||
internalerror(2011072306);
|
||||
FName:=stringdup(name);
|
||||
FFrameStartSym:=objdata.symbolref(name);
|
||||
FCount:=0;
|
||||
FFrameReg:=0;
|
||||
FFrameOffs:=0;
|
||||
FPrologueEndPos:=0;
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.end_frame(objdata:TObjData);
|
||||
begin
|
||||
if not assigned(FName) then
|
||||
internalerror(2011072307);
|
||||
generate_code(objdata);
|
||||
FFrameStartSym:=nil;
|
||||
stringdispose(FName);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.end_prologue(objdata:TObjData);
|
||||
begin
|
||||
FPrologueEndPos:=objdata.CurrObjSec.Size;
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.push_reg(objdata:TObjData;reg:tregister);
|
||||
begin
|
||||
AddElement(objdata,UWOP_PUSH_NONVOL,EncodeReg(reg),0);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.save_reg(objdata:TObjData;reg:tregister;ofs:dword);
|
||||
var
|
||||
info: Integer;
|
||||
begin
|
||||
info:=EncodeReg(reg);
|
||||
if ((ofs and 7) = 0) and (ofs<=$ffff*8) then
|
||||
AddElement(objdata,UWOP_SAVE_NONVOL,info,ofs shr 3)
|
||||
else
|
||||
AddElement(objdata,UWOP_SAVE_NONVOL_FAR,info,ofs);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.save_xmm(objdata:TObjData;reg:tregister;ofs:dword);
|
||||
var
|
||||
info: Integer;
|
||||
begin
|
||||
info:=EncodeXMM(reg);
|
||||
if ((ofs and 15)=0) and (ofs<=$ffff*16) then
|
||||
AddElement(objdata,UWOP_SAVE_XMM128, info, ofs shr 4)
|
||||
else
|
||||
AddElement(objdata,UWOP_SAVE_XMM128_FAR, info, ofs);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.set_frame(objdata:TObjData;reg:tregister;ofs:dword);
|
||||
var
|
||||
info: Integer;
|
||||
begin
|
||||
info:=EncodeReg(reg);
|
||||
if FFrameReg<>0 then
|
||||
InternalError(2011072303);
|
||||
if info=0 then { frame register cannot be RAX }
|
||||
InternalError(2011072304);
|
||||
if (ofs>240) or ((ofs and 15)<>0) then
|
||||
InternalError(2011072310);
|
||||
FFrameReg:=info;
|
||||
FFrameOffs:=ofs;
|
||||
{ !! looks like docs aren't correct and info should be set to register }
|
||||
AddElement(objdata,UWOP_SET_FPREG,0,0);
|
||||
end;
|
||||
|
||||
procedure TWin64CFI.stack_alloc(objdata:TObjData;ofs:dword);
|
||||
begin
|
||||
if ((ofs and 7)=0) and (ofs<=128) then
|
||||
AddElement(objdata,UWOP_ALLOC_SMALL,(ofs-8) shr 3,0)
|
||||
else if ((ofs and 7) = 0) and (ofs<=$ffff * 8) then
|
||||
AddElement(objdata,UWOP_ALLOC_LARGE,0,ofs shr 3)
|
||||
else
|
||||
AddElement(objdata,UWOP_ALLOC_LARGE,1,ofs);
|
||||
end;
|
||||
|
||||
procedure tai_seh_directive_x64.generate_code(objdata:TObjData);
|
||||
begin
|
||||
case kind of
|
||||
ash_proc:
|
||||
current_unw.start_frame(objdata,data.name^);
|
||||
ash_endproc:
|
||||
current_unw.end_frame(objdata);
|
||||
ash_endprologue:
|
||||
current_unw.end_prologue(objdata);
|
||||
ash_handler: {TBD};
|
||||
ash_handlerdata: {TBD};
|
||||
ash_eh,ash_32,ash_no32: ; { there are not for x86_64 }
|
||||
ash_setframe:
|
||||
current_unw.set_frame(objdata,data.reg,data.offset);
|
||||
ash_stackalloc:
|
||||
current_unw.stack_alloc(objdata,data.offset);
|
||||
ash_pushreg:
|
||||
current_unw.push_reg(objdata,data.reg);
|
||||
ash_savereg:
|
||||
current_unw.save_reg(objdata,data.reg,data.offset);
|
||||
ash_savexmm:
|
||||
current_unw.save_xmm(objdata,data.reg,data.offset);
|
||||
ash_pushframe: {TBD};
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
initialization
|
||||
cai_seh_directive:=tai_seh_directive_x64;
|
||||
current_unw:=TWin64CFI.Create;
|
||||
finalization
|
||||
current_unw.Free;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user