mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 09:50:38 +02:00
+ 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:
parent
abb9401011
commit
16163b74ec
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -126,6 +126,8 @@ interface
|
||||
,addr_gottpoff
|
||||
,addr_tpoff
|
||||
,addr_tlsgd
|
||||
,addr_tlsdesc
|
||||
,addr_tlscall
|
||||
{$ENDIF}
|
||||
{$IFDEF i386}
|
||||
,addr_ntpoff
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user