summaryrefslogtreecommitdiff
path: root/compiler/ogelf.pas
diff options
context:
space:
mode:
authorsergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-01-13 06:36:39 +0000
committersergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2>2013-01-13 06:36:39 +0000
commitcd12b2f9ca95821116d99b8811df1e7267b0a930 (patch)
tree72f276a73a67f8054df9654c022bfa2cca3c5cd5 /compiler/ogelf.pas
parent77ce5265aa15fad4e0973272e9ab2a4f4231e0fb (diff)
downloadfpc-cd12b2f9ca95821116d99b8811df1e7267b0a930.tar.gz
+ Enable CPU-specific descendants to write specific dynamic tags.
+ Read version definitions from shared objects. git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@23370 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/ogelf.pas')
-rw-r--r--compiler/ogelf.pas103
1 files changed, 96 insertions, 7 deletions
diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas
index 1d5996248f..2578fceeb6 100644
--- a/compiler/ogelf.pas
+++ b/compiler/ogelf.pas
@@ -132,6 +132,7 @@ interface
localsyms: longword;
symversions: PWord;
dynobj: boolean;
+ verdefs: TFPHashObjectList;
function LoadHeader:word;
procedure LoadSection(const shdr:TElfsechdr;index:longint;objdata:TObjData);
procedure LoadRelocations(const secrec:TSectionRec);
@@ -146,6 +147,22 @@ interface
out secname:string):TElfObjSection;
end;
+ TElfVersionDef = class(TFPHashObject)
+ public
+ index: longword;
+ end;
+
+ TElfDynamicObjData = class(TElfObjData)
+ private
+ FVersionDefs: TFPHashObjectList;
+ public
+ soname_strofs: longword;
+ vernaux_count: longword;
+ constructor create(const n:string);override;
+ destructor destroy;override;
+ property versiondefs:TFPHashObjectList read FVersionDefs;
+ end;
+
TRelocNameProc=function(reltyp:byte):string;
TEncodeRelocProc=function(objrel:TObjRelocation):byte;
TLoadRelocProc=procedure(objrel:TObjRelocation);
@@ -241,8 +258,6 @@ interface
procedure WriteStaticSymtable;
procedure InitDynlink;
procedure PrepareGOT;
- procedure WriteDynTag(aTag:longword;aValue:longword);
- procedure WriteDynTag(aTag:longword;aSection:TObjSection;aOffs:aword=0);
protected
hastextrelocs: boolean;
gotsymbol: TObjSymbol;
@@ -264,9 +279,12 @@ interface
procedure WriteFirstPLTEntry;virtual;abstract;
procedure WritePLTEntry(exesym:TExeSymbol);virtual;
procedure WriteIndirectPLTEntry(exesym:TExeSymbol);virtual;
+ procedure WriteTargetDynamicTags;virtual;
procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);virtual;abstract;
procedure ReportNonDSOReloc(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
procedure ReportRelocOverflow(reltyp:byte;objsec:TObjSection;ObjReloc:TObjRelocation);
+ procedure WriteDynTag(aTag:longword;aValue:longword);
+ procedure WriteDynTag(aTag:longword;aSection:TObjSection;aOffs:aword=0);
public
constructor Create;override;
destructor Destroy;override;
@@ -854,6 +872,27 @@ implementation
{****************************************************************************
+ TElfDynamicObjData
+****************************************************************************}
+
+ constructor TElfDynamicObjData.create(const n:string);
+ begin
+ inherited Create(n);
+ FVersionDefs:=TFPHashObjectList.create(true);
+ { Default symversions with indices 0 and 1 }
+ TElfVersionDef.create(FVersionDefs,'*local*');
+ TElfVersionDef.create(FVersionDefs,'*global*');
+ end;
+
+
+ destructor TElfDynamicObjData.destroy;
+ begin
+ FVersionDefs.free;
+ inherited Destroy;
+ end;
+
+
+{****************************************************************************
TElfSymtab
****************************************************************************}
@@ -1371,6 +1410,7 @@ implementation
end;
{ If reading DSO, we're interested only in global symbols defined there.
Symbols with non-current version should also be ignored. }
+ ver:=0;
if dynobj then
begin
if assigned(symversions) then
@@ -1381,6 +1421,8 @@ implementation
end;
if (bind=AB_LOCAL) or (sym.st_shndx=SHN_UNDEF) then
continue;
+ if ver>=verdefs.count then
+ InternalError(2012120505);
end;
{ validity of name and objsection has been checked above }
{ !! all AT_SECTION symbols have duplicate (null) name,
@@ -1604,6 +1646,9 @@ implementation
grp: TObjSectionGroup;
tmp: longword;
count: longint;
+ vd: TElfverdef;
+ vda: TElfverdaux;
+ vdoffset: aword;
begin
FReader:=AReader;
InputFileName:=AReader.FileName;
@@ -1622,7 +1667,13 @@ implementation
if shentsize<>sizeof(TElfsechdr) then
InternalError(2012062701);
- objdata:=CObjData.Create(InputFilename);
+ if dynobj then
+ begin
+ objdata:=TElfDynamicObjData.Create(InputFilename);
+ verdefs:=TElfDynamicObjData(objdata).versiondefs;
+ end
+ else
+ objdata:=CObjData.Create(InputFilename);
FSecTbl:=AllocMem(nsects*sizeof(TSectionRec));
FLoaded:=AllocMem(nsects*sizeof(boolean));
@@ -1726,8 +1777,34 @@ implementation
if verdefndx<>0 then
InternalError(2012102006);
verdefndx:=i;
- //sh_link->.dynstr
- //sh_info->.hash
+ if shdrs[i].sh_link<>strndx then
+ InternalError(2012120501);
+ vdoffset:=shdrs[i].sh_offset;
+ { TODO: can we rely on sh_info, or must read until vd_next=0? }
+ for j:=1 to shdrs[i].sh_info do
+ begin
+ FReader.seek(vdoffset);
+ FReader.Read(vd,sizeof(TElfverdef));
+ MaybeSwapElfverdef(vd);
+ if vd.vd_version<>VER_DEF_CURRENT then
+ InternalError(2012120502);
+ FReader.seek(vdoffset+vd.vd_aux);
+ vdoffset:=vdoffset+vd.vd_next;
+ { First verdaux entry holds name of version (unless VER_FLG_BASE flag is set),
+ subsequent one(s) point to parent(s). For our purposes, version hierarchy
+ looks irrelevant. }
+ FReader.Read(vda,sizeof(TElfverdaux));
+ MaybeSwapElfverdaux(vda);
+ if vda.vda_name>=strtablen then
+ InternalError(2012120503);
+ if (vd.vd_flags and VER_FLG_BASE)<>0 then
+ continue;
+ { Assuming verdef indices assigned continuously starting from 2,
+ at least BFD produces files that way. }
+ if verdefs.count<>vd.vd_ndx then
+ InternalError(2012120504);
+ TElfVersionDef.Create(verdefs,string(PChar(@strtab[vda.vda_name])));
+ end;
end;
SHT_GNU_verneed:
@@ -1736,7 +1813,7 @@ implementation
InternalError(2012102007);
verneedndx:=i;
//sh_link->.dynstr
- //sh_info->hash
+ //sh_info->number of entries
end;
end;
end;
@@ -2779,16 +2856,25 @@ implementation
end;
+ procedure TElfExeOutput.WriteTargetDynamicTags;
+ begin
+ { to be overridden by CPU-specific descendants }
+ end;
+
+
procedure TElfExeOutput.WriteDynamicTags;
var
s: aword;
i: longint;
sym: TExeSymbol;
hs:string;
+ dynobj: TElfDynamicObjData;
begin
for i:=0 to neededlist.Count-1 do
begin
- s:=dynsymtable.fstrsec.writestr(neededlist.NameOfIndex(i));
+ dynobj:=TElfDynamicObjData(neededlist[i]);
+ s:=dynsymtable.fstrsec.writestr(dynobj.name);
+ dynobj.soname_strofs:=s;
WriteDynTag(DT_NEEDED,s);
end;
@@ -2863,6 +2949,9 @@ implementation
if (relative_reloc_count>0) then
writeDynTag(relcnttags[rela],relative_reloc_count);
end;
+
+ WriteTargetDynamicTags;
+
if (verdefcount>0) or (verneedcount>0) then
begin
if (verdefcount>0) then