diff options
author | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2013-01-13 06:36:39 +0000 |
---|---|---|
committer | sergei <sergei@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2013-01-13 06:36:39 +0000 |
commit | cd12b2f9ca95821116d99b8811df1e7267b0a930 (patch) | |
tree | 72f276a73a67f8054df9654c022bfa2cca3c5cd5 /compiler/ogelf.pas | |
parent | 77ce5265aa15fad4e0973272e9ab2a4f4231e0fb (diff) | |
download | fpc-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.pas | 103 |
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 |