mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 21:40:34 +02:00
+ 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:
parent
d1440c7483
commit
277200e7ae
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user