+ MIPS internal linker: support TLS IE/LE and GPREL32 relocations, is now able to link tw14265.

git-svn-id: trunk@25181 -
This commit is contained in:
sergei 2013-07-29 09:30:40 +00:00
parent 11b72b5515
commit e7f6b06969
2 changed files with 77 additions and 0 deletions

View File

@ -49,6 +49,7 @@ implementation
stubcount: longint;
trampolinesection: TObjSection;
procedure MaybeWriteGOTEntry(relocval:aint;objsym:TObjSymbol);
procedure MaybeWriteTLSIEGotEntry(relocval:aint;objsym:TObjSymbol);
procedure CreatePICStub(objsym:TObjSymbol);
protected
procedure PrepareGOT;override;
@ -225,9 +226,18 @@ implementation
function elf_mips_loadsection(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
var
ri: TElfReginfo;
begin
case shdr.sh_type of
SHT_MIPS_REGINFO:
begin
objinput.ReadBytes(shdr.sh_offset,ri,sizeof(ri));
MaybeSwapElfReginfo(ri);
TElfObjData(objdata).gp_value:=ri.ri_gp_value;
result:=true;
end;
SHT_MIPS_DWARF:
result:=true;
else
writeln('elf_mips_loadsection: ',hexstr(shdr.sh_type,8),' ',objdata.name);
@ -555,6 +565,31 @@ implementation
end;
end;
procedure TElfExeOutputMIPS.MaybeWriteTLSIEGotEntry(relocval:aint;objsym:TObjSymbol);
var
gotoff,tmp:aword;
begin
gotoff:=objsym.exesymbol.gotoffset;
if gotoff=0 then
InternalError(2012060903);
if gotoff=gotobjsec.Data.size+sizeof(pint) then
begin
tmp:=gotobjsec.mempos+gotoff-sizeof(pint);
if (objsym.exesymbol.dynindex>0) then
begin
gotobjsec.writezeros(sizeof(pint));
dynreloclist.Add(TObjRelocation.CreateRaw(tmp,objsym,R_MIPS_TLS_TPREL32));
end
else
begin
putword(gotobjsec,relocval);
if IsSharedLibrary then
dynreloclist.Add(TObjRelocation.CreateRaw(tmp,nil,R_MIPS_TLS_TPREL32));
end;
end;
end;
procedure TElfExeOutputMIPS.CreatePICStub(objsym:TObjSymbol);
var
textsec,newsec:TObjSection;
@ -722,6 +757,9 @@ implementation
local_got_relocs.add(objreloc);
end;
end;
R_MIPS_TLS_GOTTPREL:
inherited AllocGOTSlot(objreloc.symbol);
end;
end;
@ -918,6 +956,34 @@ implementation
//TODO: check overflow
address:=(address and $FFFF0000) or ((((SmallInt(address) shl 2)+relocval-curloc) shr 2) and $FFFF);
R_MIPS_GPREL32:
address:=address+relocval+TElfObjData(objsec.objdata).gp_value-gotsymbol.address;
R_MIPS_TLS_GOTTPREL:
begin
if IsSharedLibrary then
relocval:=relocval-tlsseg.MemPos
else
relocval:=relocval-(tlsseg.MemPos+TP_OFFSET);
MaybeWriteTLSIEGotEntry(relocval,objreloc.symbol);
relocval:=-(gotsymbol.offset-(objreloc.symbol.exesymbol.gotoffset-sizeof(pint)));
// TODO: check overflow
address:=(address and $FFFF0000) or (relocval and $FFFF);
end;
R_MIPS_TLS_TPREL_HI16:
begin
tmp:=SmallInt(address)+relocval-(tlsseg.MemPos+TP_OFFSET);
tmp:=(tmp+$8000) shr 16;
address:=(address and $FFFF0000) or (tmp and $FFFF);
end;
R_MIPS_TLS_TPREL_LO16:
begin
tmp:=SmallInt(address)+relocval-(tlsseg.MemPos+TP_OFFSET);
address:=(address and $FFFF0000) or (tmp and $FFFF);
end;
R_MIPS_JALR: {optimization hint, ignore for now }
;
else

View File

@ -76,6 +76,9 @@ interface
public
ident: TElfIdent;
flags: longword;
{$ifdef mips}
gp_value: longword;
{$endif mips}
constructor create(const n:string);override;
function sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
procedure CreateDebugSections;override;
@ -148,6 +151,7 @@ interface
class function CanReadObjData(AReader:TObjectreader):boolean;override;
function CreateSection(const shdr:TElfsechdr;index:longint;objdata:TObjData;
out secname:string):TElfObjSection;
function ReadBytes(offs:longint;out buf;len:longint):boolean;
end;
TElfVersionDef = class(TFPHashObject)
@ -1474,6 +1478,13 @@ implementation
end;
function TElfObjInput.ReadBytes(offs:longint;out buf;len:longint):boolean;
begin
FReader.Seek(offs);
result:=FReader.Read(buf,len);
end;
procedure TElfObjInput.LoadSection(const shdr:TElfsechdr;index:longint;objdata:tobjdata);
var
sec: TElfObjSection;