+ support for the gnu2 general-dynamic tls model on arm, use it instead of the gnu one as the gnu2 one can be relaxed (access optimizations by the linker)

+ support pic relocations in the internal assembler writer

git-svn-id: trunk@43128 -
This commit is contained in:
florian 2019-10-05 20:48:26 +00:00
parent abb9401011
commit 16163b74ec
10 changed files with 98 additions and 10 deletions

View File

@ -154,7 +154,8 @@ interface
{ ARM TLS code }
aitconst_gottpoff,
aitconst_tpoff,
aitconst_tlsgd
aitconst_tlsgd,
aitconst_tlsdesc
);
tairealconsttype = (
@ -2105,6 +2106,8 @@ implementation
result:=4;
aitconst_tpoff:
result:=4;
aitconst_tlsdesc:
result:=4;
else
internalerror(200603253);
end;

View File

@ -997,6 +997,11 @@ implementation
writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
writer.Asmln;
end;
aitconst_tlsdesc:
begin
writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsdesc)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
writer.Asmln;
end;
aitconst_tpoff:
begin
if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then

View File

@ -1161,7 +1161,7 @@ implementation
if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label) and
{ gottpoff and tlsgd symbols are PC relative, so we cannot reuse them }
(not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd])) then
(not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc])) then
begin
with taicpu(curtai).oper[curop]^.ref^ do
begin
@ -3051,13 +3051,23 @@ implementation
begin
currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
{ tlscall is not relative so ignore the offset }
if oper[0]^.ref^.refaddr<>addr_tlscall then
bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
if (opcode<>A_BL) or (condition<>C_None) then
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_24)
else
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
case oper[0]^.ref^.refaddr of
addr_pic:
objdata.writereloc(aint(bytes),4,currsym,RELOC_ARM_CALL);
addr_full:
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
addr_tlscall:
objdata.writereloc(aint(bytes),4,currsym,RELOC_TLS_CALL);
else
Internalerror(2019092903);
end;
exit;
end;
end;

View File

@ -194,7 +194,9 @@ unit agarmgas;
if offset<>0 then
s:=s+tostr_with_plus(offset);
if refaddr=addr_pic then
s:=s+'(PLT)';
s:=s+'(PLT)'
else if refaddr=addr_tlscall then
s:=s+'(tlscall)';
end
else
begin

View File

@ -2495,6 +2495,8 @@ unit cgcpu;
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsgd then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsdesc then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tpoff then
begin
if assigned(ref.relsymbol) or (ref.offset<>0) then
@ -5140,6 +5142,8 @@ unit cgcpu;
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsgd then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsdesc then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tpoff then
begin
if assigned(ref.relsymbol) or (ref.offset<>0) then

View File

@ -342,6 +342,14 @@ implementation
result:=R_ARM_TLS_LE32
else
Internalerror(2019092901);
RELOC_TLSGD:
result:=R_ARM_TLS_GD32;
RELOC_TLSDESC:
result:=R_ARM_TLS_GOTDESC;
RELOC_TLS_CALL:
result:=R_ARM_TLS_CALL;
RELOC_ARM_CALL:
result:=R_ARM_CALL;
else
InternalError(2012110602);
end;

View File

@ -41,7 +41,7 @@ implementation
uses
globals,verbose,
cgbase,cgobj,cgutils,
aasmdata,
aasmdata,aasmcpu,
systems,
symcpu,symdef,
nld,
@ -70,6 +70,7 @@ implementation
case current_settings.tlsmodel of
tlsm_general_dynamic:
begin
{$ifdef use_tls_dialect_gnu}
current_asmdata.getjumplabel(l);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),-8,sizeof(AInt),[]);
href.refaddr:=addr_tlsgd;
@ -79,12 +80,49 @@ implementation
cg.a_label(current_asmdata.CurrAsmList,l);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,NR_PC,NR_R0);
cg.g_call(current_asmdata.CurrAsmList,'___tls_get_addr');
cg.g_call(current_asmdata.CurrAsmList,'__tls_get_addr');
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
location.reference.base:=hregister;
{$else use_tls_dialect_gnu}
{ On arm, we use the gnu2 tls dialect. It has the advantage that it can be relaxed (optimized) by the linker,
this is not possible with the gnu tls dialect.
gnu2 is proposed and documented in
Glauber de Oliveira Costa, Alexandre Oliva: Speeding Up Thread-Local Storage Access in DynamicLibraries in the ARM platform, 2006.
Link: https://www.fsfla.org/~lxoliva/writeups/TLS/paper-lk2006.pdf
}
current_asmdata.getjumplabel(l);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),0,sizeof(AInt),[]);
href.refaddr:=addr_tlsdesc;
href.relsymbol:=l;
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,NR_R0);
cg.a_label(current_asmdata.CurrAsmList,l);
{ we have to go the ugly way so we can set addr_tlscall }
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
cg.a_call_name(current_asmdata.CurrAsmList,gvs.mangledname,false);
with taicpu(current_asmdata.CurrAsmList.Last) do
begin
if opcode<>A_BL then
Internalerror(2019092902);
oper[0]^.ref^.refaddr:=addr_tlscall;
end;
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
location.reference.base:=current_procinfo.tlsoffset;
include(current_procinfo.flags,pi_needs_tls);
location.reference.index:=hregister;
{$endif use_tls_dialect_gnu}
handled:=true;
end;
tlsm_initial_exec:

View File

@ -1764,7 +1764,7 @@ Implementation
begin
objsym:=Objdata.SymbolRef(tai_const(hp).sym);
objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then
if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc] then
begin
if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092801);
@ -1991,12 +1991,18 @@ Implementation
objsym:=Objdata.SymbolRef(tai_const(hp).sym);
objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
relative_reloc:=(objsym.objsection<>objsymend.objsection);
if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then
if Tai_const(hp).consttype in [aitconst_gottpoff] then
begin
if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092802);
Tai_const(hp).value:=objsymend.address-ObjData.CurrObjSec.Size+Tai_const(hp).symofs;
end
else if Tai_const(hp).consttype in [aitconst_tlsgd,aitconst_tlsdesc] then
begin
if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092802);
Tai_const(hp).value:=ObjData.CurrObjSec.Size-objsymend.address+Tai_const(hp).symofs;
end
else if objsymend.objsection<>objsym.objsection then
begin
if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
@ -2066,6 +2072,13 @@ Implementation
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TPOFF);
aitconst_tlsgd:
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSGD);
aitconst_tlsdesc:
begin
{ must be a relative symbol, thus value being valid }
if not(assigned(tai_const(hp).sym)) or not(assigned(tai_const(hp).endsym)) then
Internalerror(2019092904);
ObjData.writereloc(Tai_const(hp).value,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSDESC);
end;
{$endif arm}
aitconst_gotoff_symbol:
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);

View File

@ -126,6 +126,8 @@ interface
,addr_gottpoff
,addr_tpoff
,addr_tlsgd
,addr_tlsdesc
,addr_tlscall
{$ENDIF}
{$IFDEF i386}
,addr_ntpoff

View File

@ -93,6 +93,9 @@ interface
RELOC_GOT32,
RELOC_TPOFF,
RELOC_TLSGD,
RELOC_TLSDESC,
RELOC_TLS_CALL,
RELOC_ARM_CALL,
{$endif arm}
{ Relative relocation }
RELOC_RELATIVE,