From 14b7eaa46f2d80ec8db5efbd5fb71d4469002504 Mon Sep 17 00:00:00 2001 From: florian Date: Wed, 25 Sep 2019 21:18:59 +0000 Subject: [PATCH] + x86-64: implemented support for relocation needed by tls threadvars in the binary elf writer git-svn-id: trunk@43067 - --- compiler/ogbase.pas | 8 ++++-- compiler/ogelf.pas | 15 ++++++++++- compiler/x86/aasmcpu.pas | 52 +++++++++++++++++++++++++------------- compiler/x86_64/cpuelf.pas | 9 +++++++ 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas index 95b643c368..6551ae0f3f 100644 --- a/compiler/ogbase.pas +++ b/compiler/ogbase.pas @@ -60,6 +60,8 @@ interface { PIC } RELOC_GOTPCREL, RELOC_PLT32, + RELOC_TLSGD, + RELOC_TPOFF, {$endif x86_64} {$ifdef i386} { PIC } @@ -176,7 +178,9 @@ interface { Supports bss-like allocation of data, even though it is written in file (i.e. also has oso_Data) } oso_sparse_data, { Section to support the resolution of multiple symbols with the same name } - oso_comdat + oso_comdat, + { section containing thread variables } + oso_threadvar ); TObjSectionOptions = set of TObjSectionOption; @@ -1196,7 +1200,7 @@ implementation {roData} [oso_Data,oso_load,oso_write], {roData_norel} [oso_Data,oso_load], {bss} [oso_load,oso_write], - {threadvar} [oso_load,oso_write], + {threadvar} [oso_load,oso_write,oso_threadvar], {pdata} [oso_data,oso_load], {stub} [oso_Data,oso_load,oso_executable], {data_nonlazy} [oso_Data,oso_load,oso_write], diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index 4b052cd3e9..17a6cef447 100644 --- a/compiler/ogelf.pas +++ b/compiler/ogelf.pas @@ -401,6 +401,8 @@ implementation Ashflags:=Ashflags or SHF_EXECINSTR; if oso_write in aoptions then Ashflags:=Ashflags or SHF_WRITE; + if oso_threadvar in aoptions then + Ashflags:=Ashflags or SHF_TLS; end; @@ -419,6 +421,8 @@ implementation include(aoptions,oso_write); if Ashflags and SHF_EXECINSTR<>0 then include(aoptions,oso_executable); + if Ashflags and SHF_TLS<>0 then + include(aoptions,oso_threadvar); end; @@ -575,6 +579,15 @@ implementation result:=secname+'.'+aname; exit; end; + + if atype=sec_threadvar then + begin + if (target_info.system in (systems_windows+systems_wince)) then + secname:='.tls' + else if (target_info.system in systems_linux) then + secname:='.tbss'; + end; + if create_smartlink_sections and (aname<>'') then begin case aorder of @@ -653,7 +666,7 @@ implementation if assigned(objreloc) then begin objreloc.size:=len; - if reltype in [RELOC_RELATIVE{$ifdef x86},RELOC_PLT32{$endif}{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then + if reltype in [RELOC_RELATIVE{$ifdef x86},RELOC_PLT32{$endif}{$ifdef x86_64},RELOC_GOTPCREL,RELOC_TLSGD{$endif}] then dec(data,len); if ElfTarget.relocs_use_addend then begin diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index 422ba3f1c8..d174a8cc97 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -1510,7 +1510,7 @@ implementation end; top_ref : begin - if (ref^.refaddr=addr_no) + if (ref^.refaddr in [addr_no{$ifdef x86_64},addr_tpoff{$endif x86_64}]) {$ifdef i386} or ( (ref^.refaddr in [addr_pic]) and @@ -1519,7 +1519,7 @@ implementation {$endif i386} {$ifdef x86_64} or ( - (ref^.refaddr in [addr_pic,addr_pic_no_got]) and + (ref^.refaddr in [addr_pic,addr_pic_no_got,addr_tlsgd]) and (ref^.base<>NR_NO) ) {$endif x86_64} @@ -3592,6 +3592,18 @@ implementation currabsreloc:=RELOC_RELATIVE; currabsreloc32:=RELOC_RELATIVE; end + else if oper[opidx]^.ref^.refaddr=addr_tpoff then + begin + currrelreloc:=RELOC_TPOFF; + currabsreloc:=RELOC_TPOFF; + currabsreloc32:=RELOC_TPOFF; + end + else if oper[opidx]^.ref^.refaddr=addr_tlsgd then + begin + currrelreloc:=RELOC_TLSGD; + currabsreloc:=RELOC_TLSGD; + currabsreloc32:=RELOC_TLSGD; + end else {$endif x86_64} begin @@ -3630,22 +3642,22 @@ implementation procedure objdata_writereloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType); begin {$ifdef i386} - { Special case of '_GLOBAL_OFFSET_TABLE_' - which needs a special relocation type R_386_GOTPC } - if assigned (p) and - (p.name='_GLOBAL_OFFSET_TABLE_') and - (tf_pic_uses_got in target_info.flags) then - begin - { nothing else than a 4 byte relocation should occur - for GOT } - if len<>4 then - Message1(asmw_e_invalid_opcode_and_operands,GetString); - Reloctype:=RELOC_GOTPC; - { We need to add the offset of the relocation - of _GLOBAL_OFFSET_TABLE symbol within - the current instruction } - inc(data,objdata.currobjsec.size-insoffset); - end; + { Special case of '_GLOBAL_OFFSET_TABLE_' + which needs a special relocation type R_386_GOTPC } + if assigned (p) and + (p.name='_GLOBAL_OFFSET_TABLE_') and + (tf_pic_uses_got in target_info.flags) then + begin + { nothing else than a 4 byte relocation should occur + for GOT } + if len<>4 then + Message1(asmw_e_invalid_opcode_and_operands,GetString); + Reloctype:=RELOC_GOTPC; + { We need to add the offset of the relocation + of _GLOBAL_OFFSET_TABLE symbol within + the current instruction } + inc(data,objdata.currobjsec.size-insoffset); + end; {$endif i386} objdata.writereloc(data,len,p,Reloctype); end; @@ -4534,6 +4546,10 @@ implementation {$ifdef x86_64} if oper[opidx]^.ref^.refaddr=addr_pic then currabsreloc:=RELOC_GOTPCREL + else if oper[opidx]^.ref^.refaddr=addr_tlsgd then + currabsreloc:=RELOC_TLSGD + else if oper[opidx]^.ref^.refaddr=addr_tpoff then + currabsreloc:=RELOC_TPOFF else if oper[opidx]^.ref^.base=NR_RIP then begin diff --git a/compiler/x86_64/cpuelf.pas b/compiler/x86_64/cpuelf.pas index 7dacd47534..72920f2e2f 100644 --- a/compiler/x86_64/cpuelf.pas +++ b/compiler/x86_64/cpuelf.pas @@ -171,6 +171,15 @@ implementation result:=R_X86_64_GOTPCREL; RELOC_PLT32 : result:=R_X86_64_PLT32; + RELOC_TPOFF: + if objrel.size=8 then + result:=R_X86_64_TPOFF64 + else if objrel.size=4 then + result:=R_X86_64_TPOFF32 + else + InternalError(2019091701); + RELOC_TLSGD: + result:=R_X86_64_TLSGD else result:=0; InternalError(2012082302);