diff options
author | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-11-29 06:37:28 +0000 |
---|---|---|
committer | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2012-11-29 06:37:28 +0000 |
commit | 75a083b77c03fce102322d65a9ebc686ed45d948 (patch) | |
tree | 900d3f46cbfb6031e39f0c9eff644744ae365f94 /compiler | |
parent | a574da5652af6b3a65ce34754443278661fbff55 (diff) | |
download | fpc-75a083b77c03fce102322d65a9ebc686ed45d948.tar.gz |
* Factored code for allocating GOT slots into TElfExeOutput.AllocGOTSlot.
* Changed signature of GOTRelocPass1 to pass relocation index instead of relocation itself, because sometimes (e.g. when doing TLS relaxation) we need to process several subsequent relocations at once.
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@23077 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/i386/cpuelf.pas | 36 | ||||
-rw-r--r-- | compiler/ogelf.pas | 39 | ||||
-rw-r--r-- | compiler/x86_64/cpuelf.pas | 51 |
3 files changed, 64 insertions, 62 deletions
diff --git a/compiler/i386/cpuelf.pas b/compiler/i386/cpuelf.pas index 382cc30e1a..a68942f50c 100644 --- a/compiler/i386/cpuelf.pas +++ b/compiler/i386/cpuelf.pas @@ -45,7 +45,7 @@ implementation procedure WriteFirstPLTEntry;override; procedure WritePLTEntry(exesym:TExeSymbol);override; procedure WriteIndirectPLTEntry(exesym:TExeSymbol);override; - procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);override; + procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);override; procedure DoRelocationFixup(objsec:TObjSection);override; end; @@ -191,12 +191,13 @@ implementation end; - procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation); + procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;var idx:longint); var objsym:TObjSymbol; - sym:TExeSymbol; + objreloc:TObjRelocation; reltyp:byte; begin + objreloc:=TObjRelocation(objsec.ObjRelocations[idx]); if (ObjReloc.flags and rf_raw)=0 then reltyp:=ElfTarget.encodereloc(ObjReloc) else @@ -209,30 +210,15 @@ implementation objsym.refs:=objsym.refs or symref_plt; end; - R_386_TLS_IE, - R_386_GOT32: + R_386_TLS_IE: begin - sym:=ObjReloc.symbol.exesymbol; - { Although local symbols should not be accessed through GOT, - this isn't strictly forbidden. In this case we need to fake up - the exesym to store the GOT offset in it. - TODO: name collision; maybe use a different symbol list object? } - if sym=nil then - begin - sym:=TExeSymbol.Create(ExeSymbolList,objreloc.symbol.name+'*local*'); - sym.objsymbol:=objreloc.symbol; - objreloc.symbol.exesymbol:=sym; - end; - if sym.GotOffset>0 then - exit; - gotobjsec.alloc(sizeof(pint)); - sym.GotOffset:=gotobjsec.size; - { In shared library, every GOT entry needs a RELATIVE dynamic reloc, - imported/exported symbols need GLOB_DAT instead. For executables, - only the latter applies. } - if IsSharedLibrary or (sym.dynindex>0) then - dynrelocsec.alloc(dynrelocsec.shentsize); + AllocGOTSlot(objreloc.symbol); + end; + + R_386_GOT32: + begin + AllocGOTSlot(objreloc.symbol); end; R_386_32: diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index ac7a3a0ab2..12fb241f86 100644 --- a/compiler/ogelf.pas +++ b/compiler/ogelf.pas @@ -222,11 +222,12 @@ interface dynreloclist: TFPObjectList; tlsseg: TElfSegment; relative_reloc_count: longint; + procedure AllocGOTSlot(objsym: TObjSymbol); procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword); procedure WriteFirstPLTEntry;virtual;abstract; procedure WritePLTEntry(exesym:TExeSymbol);virtual; procedure WriteIndirectPLTEntry(exesym:TExeSymbol);virtual; - procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);virtual;abstract; + procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);virtual;abstract; public constructor Create;override; destructor Destroy;override; @@ -2316,6 +2317,34 @@ implementation end; + procedure TElfExeOutput.AllocGOTSlot(objsym:TObjSymbol); + var + exesym: TExeSymbol; + begin + exesym:=objsym.exesymbol; + + { Although local symbols should not be accessed through GOT, + this isn't strictly forbidden. In this case we need to fake up + the exesym to store the GOT offset in it. + TODO: name collision; maybe use a different symbol list object? } + if exesym=nil then + begin + exesym:=TExeSymbol.Create(ExeSymbolList,objsym.name+'*local*'); + exesym.objsymbol:=objsym; + objsym.exesymbol:=exesym; + end; + if exesym.GotOffset>0 then + exit; + gotobjsec.alloc(sizeof(pint)); + exesym.GotOffset:=gotobjsec.size; + { In shared library, every GOT entry needs a RELATIVE dynamic reloc, + imported/exported symbols need GLOB_DAT instead. For executables, + only the latter applies. } + if IsSharedLibrary or (exesym.dynindex>0) then + dynrelocsec.alloc(dynrelocsec.shentsize); + end; + + procedure TElfExeOutput.PrepareGOT; var i,j,k: longint; @@ -2333,8 +2362,12 @@ implementation continue; if not objsec.Used then internalerror(2012060901); - for k:=0 to objsec.ObjRelocations.Count-1 do - GOTRelocPass1(objsec,TObjRelocation(objsec.ObjRelocations[k])); + k:=0; + while k<objsec.ObjRelocations.Count do + begin + GOTRelocPass1(objsec,k); + inc(k); + end; end; end; { remember sizes for sanity checking } diff --git a/compiler/x86_64/cpuelf.pas b/compiler/x86_64/cpuelf.pas index 9a68f0db15..60053fbcb6 100644 --- a/compiler/x86_64/cpuelf.pas +++ b/compiler/x86_64/cpuelf.pas @@ -48,7 +48,7 @@ implementation procedure WriteFirstPLTEntry;override; procedure WritePLTEntry(exesym:TExeSymbol);override; procedure WriteIndirectPLTEntry(exesym:TExeSymbol);override; - procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);override; + procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);override; procedure DoRelocationFixup(objsec:TObjSection);override; end; @@ -217,12 +217,13 @@ implementation end; - procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation); + procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;var idx:longint); var objsym:TObjSymbol; - sym:TExeSymbol; + objreloc:TObjRelocation; reltyp:byte; begin + objreloc:=TObjRelocation(objsec.ObjRelocations[idx]); if (ObjReloc.flags and rf_raw)=0 then reltyp:=ElfTarget.encodereloc(ObjReloc) else @@ -239,20 +240,14 @@ implementation end; case reltyp of - R_X86_64_GOT32, - R_X86_64_GOT64, - R_X86_64_GOTTPOFF, - R_X86_64_GOTPCREL, - R_X86_64_GOTPCREL64: + R_X86_64_GOTTPOFF: begin - sym:=ObjReloc.symbol.exesymbol; { TLS IE to locally defined symbol, convert into LE so GOT entry isn't needed (Is TLS IE allowed in shared libs at all? Yes it is, when lib is accessing a threadvar in main program or in other *statically* loaded lib; TLS IE access to own threadvars may render library not loadable dynamically) } (* - if (reltyp=R_X86_64_GOTTPOFF) and not - (IsSharedLibrary or (sym.dynindex>0)) then + if not (IsSharedLibrary or (sym.dynindex>0)) then begin if not IsValidIEtoLE(objsec,ObjReloc) then Comment(v_error,'Cannot transform TLS IE to LE'); @@ -261,29 +256,17 @@ implementation exit; end; *) - { Although local symbols should not be accessed through GOT, - this isn't strictly forbidden. In this case we need to fake up - the exesym to store the GOT offset in it. - TODO: name collision; maybe use a different symbol list object? } - if sym=nil then - begin - sym:=TExeSymbol.Create(ExeSymbolList,objreloc.symbol.name+'*local*'); - sym.objsymbol:=objreloc.symbol; - objreloc.symbol.exesymbol:=sym; - end; - if sym.GotOffset>0 then - exit; - gotobjsec.alloc(sizeof(pint)); - sym.GotOffset:=gotobjsec.size; - { In shared library, every GOT entry needs a RELATIVE dynamic reloc, - imported/exported symbols need GLOB_DAT instead. For executables, - only the latter applies. } - if IsSharedLibrary or (sym.dynindex>0) then - begin - dynrelocsec.alloc(dynrelocsec.shentsize); - if (sym.dynindex=0) and (reltyp<>R_X86_64_GOTTPOFF) then - Inc(relative_reloc_count); - end; + AllocGOTSlot(objreloc.symbol); + end; + + R_X86_64_GOT32, + R_X86_64_GOT64, + R_X86_64_GOTPCREL, + R_X86_64_GOTPCREL64: + begin + AllocGOTSlot(objreloc.symbol); + if IsSharedLibrary and (objreloc.symbol.exesymbol.dynindex=0) then + Inc(relative_reloc_count); end; //R_X86_64_TLSGD, |