mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 03:48:07 +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;
|
||||
shoffset: aword;
|
||||
shstrndx: longword;
|
||||
symtabndx: longword;
|
||||
shstrtab: PChar;
|
||||
strtab: PChar;
|
||||
shstrtablen: longword;
|
||||
@ -216,7 +217,9 @@ interface
|
||||
pltrelocsec,
|
||||
ipltrelocsec,
|
||||
dynrelocsec: TElfObjSection;
|
||||
dynreloclist: TFPObjectList;
|
||||
tlsseg: TElfSegment;
|
||||
relative_reloc_count: longint;
|
||||
procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
|
||||
procedure WriteFirstPLTEntry;virtual;abstract;
|
||||
procedure WritePLTEntry(exesym:TExeSymbol);virtual;
|
||||
@ -315,6 +318,7 @@ implementation
|
||||
{$endif x86_64}
|
||||
|
||||
SHN_UNDEF = 0;
|
||||
SHN_LORESERVE = $FF00;
|
||||
SHN_ABS = $fff1;
|
||||
SHN_COMMON = $fff2;
|
||||
|
||||
@ -1568,16 +1572,8 @@ implementation
|
||||
Continue
|
||||
else if sym.st_shndx=SHN_COMMON then
|
||||
bind:=AB_COMMON
|
||||
else if (sym.st_shndx>=nsects) or
|
||||
(
|
||||
(sym.st_shndx>0) and
|
||||
(FSecTbl[sym.st_shndx].sec=nil) and
|
||||
(not dynobj)
|
||||
) then
|
||||
begin
|
||||
writeln(objdata.name,' ',i);
|
||||
InternalError(2012060206)
|
||||
end
|
||||
else if (sym.st_shndx>=nsects) then
|
||||
InternalError(2012060206)
|
||||
else
|
||||
case (sym.st_info shr 4) of
|
||||
STB_LOCAL:
|
||||
@ -1593,6 +1589,19 @@ implementation
|
||||
InternalError(2012060207);
|
||||
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
|
||||
STT_NOTYPE:
|
||||
typ:=AT_NONE;
|
||||
@ -1802,7 +1811,7 @@ implementation
|
||||
|
||||
function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
|
||||
var
|
||||
i,j,symtabndx,strndx,dynndx,
|
||||
i,j,strndx,dynndx,
|
||||
versymndx,verdefndx,verneedndx: longint;
|
||||
objsec: TElfObjSection;
|
||||
shdrs: array of TElfsechdr;
|
||||
@ -1854,7 +1863,7 @@ implementation
|
||||
Note that is is legal to have no symtable.
|
||||
For DSO, locate .dynsym instead, this one is near the beginning, but
|
||||
overall number of sections won't be big. }
|
||||
symtabndx:=-1;
|
||||
symtabndx:=0;
|
||||
for i:=nsects-1 downto 1 do
|
||||
begin
|
||||
if (shdrs[i].sh_type<>symsectypes[dynobj]) then
|
||||
@ -1880,6 +1889,9 @@ implementation
|
||||
break;
|
||||
end;
|
||||
|
||||
if symtabndx=0 then
|
||||
InternalError(2012110706);
|
||||
|
||||
if dynobj then
|
||||
begin
|
||||
{ Locate .dynamic and version sections. Expect a single one of a kind. }
|
||||
@ -2031,6 +2043,7 @@ implementation
|
||||
neededlist.Free;
|
||||
segmentlist.Free;
|
||||
dynsymlist.Free;
|
||||
dynreloclist.Free;
|
||||
if assigned(dynsymnames) then
|
||||
FreeMem(dynsymnames);
|
||||
inherited Destroy;
|
||||
@ -2629,8 +2642,25 @@ implementation
|
||||
i,j: longint;
|
||||
exesec: TExeSection;
|
||||
seg: TElfSegment;
|
||||
objreloc: TObjRelocation;
|
||||
begin
|
||||
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 }
|
||||
if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
|
||||
InternalError(2012092501);
|
||||
@ -2743,6 +2773,8 @@ implementation
|
||||
|
||||
dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
|
||||
dynrelocsec.SecOptions:=[oso_keep];
|
||||
|
||||
dynreloclist:=TFPObjectList.Create(true);
|
||||
end;
|
||||
|
||||
|
||||
@ -2902,6 +2934,7 @@ implementation
|
||||
pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
|
||||
relsztags: array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
|
||||
relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
|
||||
relcnttags: array[boolean] of longword=(DT_RELCOUNT,DT_RELACOUNT);
|
||||
|
||||
procedure TElfExeOutput.FinishDynamicTags;
|
||||
begin
|
||||
@ -2924,6 +2957,8 @@ implementation
|
||||
writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
|
||||
writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
|
||||
end;
|
||||
if (relative_reloc_count>0) then
|
||||
writeDynTag(relcnttags[relocs_use_addend],relative_reloc_count);
|
||||
writeDynTag(DT_NULL,0);
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user