+ ELF linker: Support writing RELATIVE dynamic relocations ahead of the rest, and their number in DT_REL[A]COUNT dynamic tag (still needs changes in CPU-specific code to function properly).

* TElfObjInput.LoadSymbols: ignore STT_SECTION symbols for sections that were ignored in LoadSections().
* TElfObjInput: changed symtabndx (index of .symtab/.dynsym section) into field and its type to unsigned.

git-svn-id: trunk@22951 -
This commit is contained in:
sergei 2012-11-08 11:10:01 +00:00
parent d1440c7483
commit 277200e7ae

View File

@ -118,6 +118,7 @@ interface
shentsize: longword; shentsize: longword;
shoffset: aword; shoffset: aword;
shstrndx: longword; shstrndx: longword;
symtabndx: longword;
shstrtab: PChar; shstrtab: PChar;
strtab: PChar; strtab: PChar;
shstrtablen: longword; shstrtablen: longword;
@ -216,7 +217,9 @@ interface
pltrelocsec, pltrelocsec,
ipltrelocsec, ipltrelocsec,
dynrelocsec: TElfObjSection; dynrelocsec: TElfObjSection;
dynreloclist: TFPObjectList;
tlsseg: TElfSegment; tlsseg: TElfSegment;
relative_reloc_count: longint;
procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword); procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
procedure WriteFirstPLTEntry;virtual;abstract; procedure WriteFirstPLTEntry;virtual;abstract;
procedure WritePLTEntry(exesym:TExeSymbol);virtual; procedure WritePLTEntry(exesym:TExeSymbol);virtual;
@ -315,6 +318,7 @@ implementation
{$endif x86_64} {$endif x86_64}
SHN_UNDEF = 0; SHN_UNDEF = 0;
SHN_LORESERVE = $FF00;
SHN_ABS = $fff1; SHN_ABS = $fff1;
SHN_COMMON = $fff2; SHN_COMMON = $fff2;
@ -1568,16 +1572,8 @@ implementation
Continue Continue
else if sym.st_shndx=SHN_COMMON then else if sym.st_shndx=SHN_COMMON then
bind:=AB_COMMON bind:=AB_COMMON
else if (sym.st_shndx>=nsects) or else if (sym.st_shndx>=nsects) then
( InternalError(2012060206)
(sym.st_shndx>0) and
(FSecTbl[sym.st_shndx].sec=nil) and
(not dynobj)
) then
begin
writeln(objdata.name,' ',i);
InternalError(2012060206)
end
else else
case (sym.st_info shr 4) of case (sym.st_info shr 4) of
STB_LOCAL: STB_LOCAL:
@ -1593,6 +1589,19 @@ implementation
InternalError(2012060207); InternalError(2012060207);
end; end;
{ Ignore section symbol if we didn't create the corresponding objsection
(examples are SHT_GROUP or .note.GNU-stack sections). }
if (sym.st_shndx>0) and (sym.st_shndx<SHN_LORESERVE) and
(FSecTbl[sym.st_shndx].sec=nil) and
(not dynobj) then
if ((sym.st_info and $0F)=STT_SECTION) then
Continue
else
begin
writeln(objdata.name,' ',i);
InternalError(2012110701)
end;
case (sym.st_info and $0F) of case (sym.st_info and $0F) of
STT_NOTYPE: STT_NOTYPE:
typ:=AT_NONE; typ:=AT_NONE;
@ -1802,7 +1811,7 @@ implementation
function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean; function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
var var
i,j,symtabndx,strndx,dynndx, i,j,strndx,dynndx,
versymndx,verdefndx,verneedndx: longint; versymndx,verdefndx,verneedndx: longint;
objsec: TElfObjSection; objsec: TElfObjSection;
shdrs: array of TElfsechdr; shdrs: array of TElfsechdr;
@ -1854,7 +1863,7 @@ implementation
Note that is is legal to have no symtable. Note that is is legal to have no symtable.
For DSO, locate .dynsym instead, this one is near the beginning, but For DSO, locate .dynsym instead, this one is near the beginning, but
overall number of sections won't be big. } overall number of sections won't be big. }
symtabndx:=-1; symtabndx:=0;
for i:=nsects-1 downto 1 do for i:=nsects-1 downto 1 do
begin begin
if (shdrs[i].sh_type<>symsectypes[dynobj]) then if (shdrs[i].sh_type<>symsectypes[dynobj]) then
@ -1880,6 +1889,9 @@ implementation
break; break;
end; end;
if symtabndx=0 then
InternalError(2012110706);
if dynobj then if dynobj then
begin begin
{ Locate .dynamic and version sections. Expect a single one of a kind. } { Locate .dynamic and version sections. Expect a single one of a kind. }
@ -2031,6 +2043,7 @@ implementation
neededlist.Free; neededlist.Free;
segmentlist.Free; segmentlist.Free;
dynsymlist.Free; dynsymlist.Free;
dynreloclist.Free;
if assigned(dynsymnames) then if assigned(dynsymnames) then
FreeMem(dynsymnames); FreeMem(dynsymnames);
inherited Destroy; inherited Destroy;
@ -2629,8 +2642,25 @@ implementation
i,j: longint; i,j: longint;
exesec: TExeSection; exesec: TExeSection;
seg: TElfSegment; seg: TElfSegment;
objreloc: TObjRelocation;
begin begin
gotwritten:=true; gotwritten:=true;
{ If target does not support sorted relocations, it is expected to write the
entire .rel[a].dyn section during FixupRelocations. Otherwise, only RELATIVE ones
should be written, space for non-relative relocations should remain. }
if assigned(dynrelocsec) and (relative_reloc_count>0) then
begin
if (dynrelocsec.size+(dynreloclist.count*dynrelocsec.shentsize)<>dynrelsize) then
InternalError(2012110601);
{ Write out non-RELATIVE dynamic relocations
TODO: additional sorting? }
for i:=0 to dynreloclist.count-1 do
begin
objreloc:=TObjRelocation(dynreloclist[i]);
WriteDynRelocEntry(objreloc.dataoffset,objreloc.ftype,objreloc.symbol.exesymbol.dynindex,0);
end;
end;
{ sanity checks } { sanity checks }
if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
InternalError(2012092501); InternalError(2012092501);
@ -2743,6 +2773,8 @@ implementation
dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true); dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
dynrelocsec.SecOptions:=[oso_keep]; dynrelocsec.SecOptions:=[oso_keep];
dynreloclist:=TFPObjectList.Create(true);
end; end;
@ -2902,6 +2934,7 @@ implementation
pltreltags: array[boolean] of longword=(DT_REL,DT_RELA); pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
relsztags: array[boolean] of longword=(DT_RELSZ,DT_RELASZ); relsztags: array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT); relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
relcnttags: array[boolean] of longword=(DT_RELCOUNT,DT_RELACOUNT);
procedure TElfExeOutput.FinishDynamicTags; procedure TElfExeOutput.FinishDynamicTags;
begin begin
@ -2924,6 +2957,8 @@ implementation
writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size); writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize); writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
end; end;
if (relative_reloc_count>0) then
writeDynTag(relcnttags[relocs_use_addend],relative_reloc_count);
writeDynTag(DT_NULL,0); writeDynTag(DT_NULL,0);
end; end;