summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorsergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-11-29 06:37:28 +0000
committersergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2012-11-29 06:37:28 +0000
commit75a083b77c03fce102322d65a9ebc686ed45d948 (patch)
tree900d3f46cbfb6031e39f0c9eff644744ae365f94 /compiler
parenta574da5652af6b3a65ce34754443278661fbff55 (diff)
downloadfpc-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.pas36
-rw-r--r--compiler/ogelf.pas39
-rw-r--r--compiler/x86_64/cpuelf.pas51
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,