mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-22 14:49:10 +02:00
* don't generate pdata and xdata if there is neither a relevant prologue nor a handler
This commit is contained in:
parent
f2d44148fb
commit
b67415d1a8
@ -447,99 +447,108 @@ unit agcpugas;
|
|||||||
if inprologue then
|
if inprologue then
|
||||||
cgmessage(asmw_e_missing_endprologue);
|
cgmessage(asmw_e_missing_endprologue);
|
||||||
|
|
||||||
|
{ only generate xdata and pdata if we have any
|
||||||
|
prologue or a handler is set }
|
||||||
unwinddata:=convert_unwinddata(sehlist);
|
unwinddata:=convert_unwinddata(sehlist);
|
||||||
|
|
||||||
writebyte($E4);
|
if unwinddata.size>0 then
|
||||||
|
|
||||||
{ fill up with NOPs }
|
|
||||||
while unwinddata.size mod 4<>0 do
|
|
||||||
writebyte($E3);
|
|
||||||
|
|
||||||
{ note: we can pass Nil here, because in case of a LLVM
|
|
||||||
backend this whole code shouldn't be required
|
|
||||||
anyway }
|
|
||||||
xdatasym:=current_asmdata.DefineAsmSymbol('xdata_'+lastsym.sym.name,AB_LOCAL,AT_DATA,nil);
|
|
||||||
|
|
||||||
tmplist:=tasmlist.create;
|
|
||||||
new_section(tmplist,sec_pdata,lastsec.name^,0);
|
|
||||||
tmplist.concat(tai_const.Create_rva_sym(lastsym.sym));
|
|
||||||
tmplist.concat(tai_const.Create_rva_sym(xdatasym));
|
|
||||||
|
|
||||||
new_section(tmplist,sec_rodata,xdatasym.name,0);
|
|
||||||
tmplist.concat(tai_symbol.Create(xdatasym,0));
|
|
||||||
|
|
||||||
tmplist.concat(tai_comment.Create(strpnew('instr: '+tostr(instrcount)+', data: '+tostr(datacount)+', unwind: '+tostr(unwinddata.size))));
|
|
||||||
|
|
||||||
{$ifdef EXTDEBUG}
|
|
||||||
comment(V_Debug,'got section: '+lastsec.name^);
|
|
||||||
comment(V_Debug,'got instructions: '+tostr(instrcount));
|
|
||||||
comment(V_Debug,'got data: '+tostr(datacount));
|
|
||||||
comment(V_Debug,'got unwinddata: '+tostr(unwinddata.size));
|
|
||||||
{$endif EXTDEBUG}
|
|
||||||
|
|
||||||
if datacount mod 4<>0 then
|
|
||||||
cgmessage(asmw_e_seh_invalid_data_size);
|
|
||||||
|
|
||||||
totalcount:=datacount div 4+instrcount;
|
|
||||||
|
|
||||||
{ splitting to multiple pdata/xdata sections is not yet
|
|
||||||
supported, so 1 MB is our limit for now }
|
|
||||||
if totalcount>(1 shl 18) then
|
|
||||||
comment(V_Error,'Function is larger than 1 MB which is not supported for SEH currently');
|
|
||||||
|
|
||||||
unwindrec:=min(totalcount,(1 shl 18)-1);
|
|
||||||
if handlerflags<>0 then
|
|
||||||
unwindrec:=unwindrec or (1 shl 20);
|
|
||||||
|
|
||||||
{ currently we only have one epilog, so E needs to be
|
|
||||||
set to 1 and epilog scope index needs to be 0, no
|
|
||||||
matter if we require the extension for the unwinddata
|
|
||||||
or not }
|
|
||||||
unwindrec:=unwindrec or (1 shl 21);
|
|
||||||
|
|
||||||
if unwinddata.size div 4<=31 then
|
|
||||||
unwindrec:=unwindrec or ((unwinddata.size div 4) shl 27);
|
|
||||||
|
|
||||||
{ exception record headers }
|
|
||||||
tmplist.concat(tai_const.Create_32bit(longint(unwindrec)));
|
|
||||||
if cs_asm_source in init_settings.globalswitches then
|
|
||||||
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
|
||||||
|
|
||||||
if unwinddata.size div 4>31 then
|
|
||||||
begin
|
begin
|
||||||
{ once we're able to split a .pdata entry this can be
|
writebyte($E4);
|
||||||
removed as well }
|
|
||||||
if unwinddata.size div 4>255 then
|
{ fill up with NOPs }
|
||||||
comment(V_Error,'Too many unwind codes for SEH');
|
while unwinddata.size mod 4<>0 do
|
||||||
unwindrec:=(unwinddata.size div 4) shl 16;
|
writebyte($E3);
|
||||||
tmplist.concat(tai_const.create_32bit(longint(unwindrec)));
|
|
||||||
if cs_asm_source in init_settings.globalswitches then
|
|
||||||
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ unwind codes }
|
if (handlerflags<>0) or (unwinddata.size<>0) then
|
||||||
unwinddata.seek(0);
|
|
||||||
while unwinddata.pos<unwinddata.size do
|
|
||||||
begin
|
begin
|
||||||
unwinddata.read(unwindrec,sizeof(longword));
|
{ note: we can pass Nil here, because in case of a LLVM
|
||||||
|
backend this whole code shouldn't be required
|
||||||
|
anyway }
|
||||||
|
xdatasym:=current_asmdata.DefineAsmSymbol('xdata_'+lastsym.sym.name,AB_LOCAL,AT_DATA,nil);
|
||||||
|
|
||||||
|
tmplist:=tasmlist.create;
|
||||||
|
new_section(tmplist,sec_pdata,lastsec.name^,0);
|
||||||
|
tmplist.concat(tai_const.Create_rva_sym(lastsym.sym));
|
||||||
|
tmplist.concat(tai_const.Create_rva_sym(xdatasym));
|
||||||
|
|
||||||
|
new_section(tmplist,sec_rodata,xdatasym.name,sizeof(int32));
|
||||||
|
tmplist.concat(tai_symbol.Create(xdatasym,0));
|
||||||
|
|
||||||
|
tmplist.concat(tai_comment.Create(strpnew('instr: '+tostr(instrcount)+', data: '+tostr(datacount)+', unwind: '+tostr(unwinddata.size))));
|
||||||
|
|
||||||
|
{$ifdef EXTDEBUG}
|
||||||
|
comment(V_Debug,'got section: '+lastsec.name^);
|
||||||
|
comment(V_Debug,'got instructions: '+tostr(instrcount));
|
||||||
|
comment(V_Debug,'got data: '+tostr(datacount));
|
||||||
|
comment(V_Debug,'got unwinddata: '+tostr(unwinddata.size));
|
||||||
|
{$endif EXTDEBUG}
|
||||||
|
|
||||||
|
if datacount mod 4<>0 then
|
||||||
|
cgmessage(asmw_e_seh_invalid_data_size);
|
||||||
|
|
||||||
|
totalcount:=datacount div 4+instrcount;
|
||||||
|
|
||||||
|
{ splitting to multiple pdata/xdata sections is not yet
|
||||||
|
supported, so 1 MB is our limit for now }
|
||||||
|
if totalcount>(1 shl 18) then
|
||||||
|
comment(V_Error,'Function is larger than 1 MB which is not supported for SEH currently');
|
||||||
|
|
||||||
|
unwindrec:=min(totalcount,(1 shl 18)-1);
|
||||||
|
if handlerflags<>0 then
|
||||||
|
unwindrec:=unwindrec or (1 shl 20);
|
||||||
|
|
||||||
|
{ currently we only have one epilog, so E needs to be
|
||||||
|
set to 1 and epilog scope index needs to be 0, no
|
||||||
|
matter if we require the extension for the unwinddata
|
||||||
|
or not }
|
||||||
|
unwindrec:=unwindrec or (1 shl 21);
|
||||||
|
|
||||||
|
if unwinddata.size div 4<=31 then
|
||||||
|
unwindrec:=unwindrec or ((unwinddata.size div 4) shl 27);
|
||||||
|
|
||||||
|
{ exception record headers }
|
||||||
tmplist.concat(tai_const.Create_32bit(longint(unwindrec)));
|
tmplist.concat(tai_const.Create_32bit(longint(unwindrec)));
|
||||||
if cs_asm_source in init_settings.globalswitches then
|
if cs_asm_source in init_settings.globalswitches then
|
||||||
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
||||||
end;
|
|
||||||
unwinddata.free;
|
|
||||||
|
|
||||||
if handlerflags<>0 then
|
if unwinddata.size div 4>31 then
|
||||||
begin
|
|
||||||
tmplist.concat(tai_const.Create_rva_sym(current_asmdata.RefAsmSymbol(handlername,AT_FUNCTION,false)));
|
|
||||||
if length(handlerdata)>0 then
|
|
||||||
begin
|
begin
|
||||||
tmplist.concat(handlerdatacount);
|
{ once we're able to split a .pdata entry this can be
|
||||||
for handlerdataidx:=0 to high(handlerdata) do
|
removed as well }
|
||||||
tmplist.concat(handlerdata[handlerdataidx]);
|
if unwinddata.size div 4>255 then
|
||||||
|
comment(V_Error,'Too many unwind codes for SEH');
|
||||||
|
unwindrec:=(unwinddata.size div 4) shl 16;
|
||||||
|
tmplist.concat(tai_const.create_32bit(longint(unwindrec)));
|
||||||
|
if cs_asm_source in init_settings.globalswitches then
|
||||||
|
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ unwind codes }
|
||||||
|
unwinddata.seek(0);
|
||||||
|
while unwinddata.pos<unwinddata.size do
|
||||||
|
begin
|
||||||
|
unwinddata.read(unwindrec,sizeof(longword));
|
||||||
|
tmplist.concat(tai_const.Create_32bit(longint(unwindrec)));
|
||||||
|
if cs_asm_source in init_settings.globalswitches then
|
||||||
|
tmplist.concat(tai_comment.create(strpnew(hexstr(unwindrec,8))));
|
||||||
|
end;
|
||||||
|
|
||||||
|
if handlerflags<>0 then
|
||||||
|
begin
|
||||||
|
tmplist.concat(tai_const.Create_rva_sym(current_asmdata.RefAsmSymbol(handlername,AT_FUNCTION,false)));
|
||||||
|
if length(handlerdata)>0 then
|
||||||
|
begin
|
||||||
|
tmplist.concat(handlerdatacount);
|
||||||
|
for handlerdataidx:=0 to high(handlerdata) do
|
||||||
|
tmplist.concat(handlerdata[handlerdataidx]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
handlerdata:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
handlerdata:=nil;
|
unwinddata.free;
|
||||||
|
|
||||||
sehlist.free;
|
sehlist.free;
|
||||||
sehlist:=nil;
|
sehlist:=nil;
|
||||||
|
Loading…
Reference in New Issue
Block a user