* Changed TElfTarget from class to record, so it can contain data members while remaining statically allocated.

* Moved target-dependent constants into ElfTarget records, eliminates a lot of $ifdef's in ogelf.pas.
+ Added TElfTarget.loadsection hook and pass unknown sections to it.

git-svn-id: trunk@23090 -
This commit is contained in:
sergei 2012-12-02 11:15:35 +00:00
parent 66553a253e
commit d79761c607
4 changed files with 90 additions and 105 deletions

View File

@ -29,15 +29,10 @@ implementation
uses
globtype,cclasses,
verbose,
systems,ogbase,ogelf,assemble;
verbose,elfbase,
systems,aasmbase,ogbase,ogelf,assemble;
type
TElfTarget386=class(TElfTarget)
class function encodereloc(objrel:TObjRelocation):byte;override;
class procedure loadreloc(objrel:TObjRelocation);override;
end;
TElfExeOutput386=class(TElfExeOutput)
private
procedure MaybeWriteGOTEntry(reltyp:byte;relocval:aint;objsym:TObjSymbol);
@ -97,10 +92,10 @@ implementation
{****************************************************************************
TElfTarget386
ELF Target methods
****************************************************************************}
class function TElfTarget386.encodereloc(objrel:TObjRelocation):byte;
function elf_i386_encodereloc(objrel:TObjRelocation):byte;
begin
case objrel.typ of
RELOC_NONE :
@ -122,7 +117,7 @@ implementation
end;
class procedure TElfTarget386.loadreloc(objrel:TObjRelocation);
procedure elf_i386_loadreloc(objrel:TObjRelocation);
begin
end;
@ -179,7 +174,7 @@ implementation
pltrelocsec.writeReloc_internal(gotpltobjsec,got_offset,sizeof(pint),RELOC_ABSOLUTE);
got_offset:=(exesym.dynindex shl 8) or R_386_JUMP_SLOT;
pltrelocsec.write(got_offset,sizeof(pint));
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
pltrelocsec.writezeros(sizeof(pint));
end;
@ -325,7 +320,7 @@ implementation
else
reltyp:=objreloc.ftype;
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
address:=objreloc.orgsize
else
begin
@ -463,6 +458,17 @@ implementation
*****************************************************************************}
const
elf_target_i386 : TElfTarget =
(
max_page_size: $1000;
exe_image_base: $8048000;
machine_code: EM_386;
relocs_use_addend: false;
encodereloc: @elf_i386_encodeReloc;
loadreloc: @elf_i386_loadReloc;
loadsection: nil;
);
as_i386_elf32_info : tasminfo =
(
id : as_i386_elf32;
@ -483,7 +489,7 @@ implementation
initialization
RegisterAssembler(as_i386_elf32_info,TElfAssembler);
ElfExeOutputClass:=TElfExeOutput386;
ElfTarget:=TElfTarget386;
ElfTarget:=elf_target_i386;
end.

View File

@ -102,14 +102,6 @@ interface
constructor create(smart:boolean);override;
end;
TElfTarget=class(TObject)
public
class function encodereloc(objrel:TObjRelocation):byte;virtual;abstract;
class procedure loadreloc(objrel:TObjRelocation);virtual;abstract;
end;
TElfTargetClass=class of TElfTarget;
PSectionRec=^TSectionRec;
TSectionRec=record
sec: TObjSection;
@ -152,6 +144,21 @@ interface
class function CanReadObjData(AReader:TObjectreader):boolean;override;
end;
TEncodeRelocProc=function(objrel:TObjRelocation):byte;
TLoadRelocProc=procedure(objrel:TObjRelocation);
TLoadSectionProc=function(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
TElfTarget=record
max_page_size: longword;
exe_image_base: longword;
machine_code: word;
relocs_use_addend: boolean;
encodereloc: TEncodeRelocProc;
loadreloc: TLoadRelocProc;
loadsection: TLoadSectionProc;
end;
TElfExeSection=class(TExeSection)
public
secshidx : longword; { index of the section header }
@ -258,20 +265,12 @@ interface
var
ElfExeOutputClass: TExeOutputClass;
ElfTarget: TElfTargetClass;
ElfTarget: TElfTarget;
const
{ Bits of TObjSymbol.refs field }
symref_plt = 1;
{TODO: should become property of back-end }
{$ifdef x86_64}
const
relocs_use_addend:Boolean=True;
{$else x86_64}
const
relocs_use_addend:Boolean=False;
{$endif x86_64}
implementation
@ -285,31 +284,6 @@ implementation
const
symbolresize = 200*18;
{$ifdef sparc}
ELFMACHINE = EM_SPARC;
{$endif sparc}
{$ifdef i386}
ELFMACHINE = EM_386;
{$endif i386}
{$ifdef m68k}
ELFMACHINE = EM_M68K;
{$endif m68k}
{$ifdef powerpc}
ELFMACHINE = EM_PPC;
{$endif powerpc}
{$ifdef powerpc64}
ELFMACHINE = EM_PPC; // TODO
{$endif}
{$ifdef mips}
ELFMACHINE = EM_MIPS;
{$endif}
{$ifdef arm}
ELFMACHINE = EM_ARM;
{$endif arm}
{$ifdef x86_64}
ELFMACHINE = EM_X86_64;
{$endif x86_64}
{$ifdef cpu64bitaddr}
const
ELFCLASS = ELFCLASS64;
@ -341,16 +315,6 @@ implementation
end;
{$endif cpu64bitaddr}
{$ifdef x86_64}
const
ELF_MAXPAGESIZE:longint=$200000;
TEXT_SEGMENT_START:longint=$400000;
{$else x86_64}
const
ELF_MAXPAGESIZE:longint=$1000;
TEXT_SEGMENT_START:longint=$8048000;
{$endif x86_64}
procedure MayBeSwapHeader(var h : telf32header);
begin
if source_info.endian<>target_info.endian then
@ -619,11 +583,11 @@ implementation
constructor TElfObjSection.create_reloc(aobjdata:TObjData;const Aname:string;allocflag:boolean);
begin
create_ext(aobjdata,
relsec_prefix[relocs_use_addend]+aname,
relsec_shtype[relocs_use_addend],
relsec_prefix[ElfTarget.relocs_use_addend]+aname,
relsec_shtype[ElfTarget.relocs_use_addend],
SHF_ALLOC*ord(allocflag),
sizeof(pint),
(2+ord(relocs_use_addend))*sizeof(pint));
(2+ord(ElfTarget.relocs_use_addend))*sizeof(pint));
end;
@ -638,7 +602,7 @@ implementation
dec(offset,len)
else if reltype<>RELOC_ABSOLUTE then
InternalError(2012062401);
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
begin
reloc.orgsize:=offset;
offset:=0;
@ -799,7 +763,7 @@ implementation
objreloc.size:=len;
if reltype in [RELOC_RELATIVE{$ifdef x86},RELOC_PLT32{$endif}{$ifdef x86_64},RELOC_GOTPCREL{$endif}] then
dec(data,len);
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
begin
objreloc.orgsize:=data;
data:=0;
@ -1029,13 +993,13 @@ implementation
objsec,target:TElfObjSection;
begin
shstrtabsect.writezeros(1);
prefixlen:=length('.rel')+ord(relocs_use_addend);
prefixlen:=length('.rel')+ord(ElfTarget.relocs_use_addend);
for i:=0 to data.ObjSectionList.Count-1 do
begin
objsec:=TElfObjSection(data.ObjSectionList[i]);
{ Alias section names into names of corresponding reloc sections,
this is allowed by ELF specs and saves good half of .shstrtab space. }
if objsec.shtype=relsec_shtype[relocs_use_addend] then
if objsec.shtype=relsec_shtype[ElfTarget.relocs_use_addend] then
begin
target:=TElfObjSection(data.ObjSectionList[objsec.shinfo-1]);
if (target.ObjRelocations.Count=0) or
@ -1148,7 +1112,7 @@ implementation
header.e_ident[EI_VERSION]:=1;
header.e_type:=ET_REL;
header.e_machine:=ELFMACHINE;
header.e_machine:=ElfTarget.machine_code;
header.e_version:=1;
header.e_shoff:=shoffset;
header.e_shstrndx:=shstrtabsect.index;
@ -1239,7 +1203,8 @@ implementation
if (secrec.relentsize=3*sizeof(pint)) then
objrel.orgsize:=rel.addend;
{ perform target-specific actions }
ElfTarget.loadreloc(objrel);
if Assigned(ElfTarget.loadreloc) then
ElfTarget.loadreloc(objrel);
secrec.sec.ObjRelocations.add(objrel);
end
else
@ -1453,7 +1418,9 @@ implementation
else
InternalError(2012110706);
else
InternalError(2012072603);
if not (assigned(ElfTarget.loadsection) and
ElfTarget.loadsection(self,objdata,shdr,index)) then
InternalError(2012072603);
end;
FLoaded[index]:=True;
end;
@ -1496,7 +1463,7 @@ implementation
InputError('Unknown ELF data version');
exit;
end;
if (header.e_machine<>ELFMACHINE) then
if (header.e_machine<>ElfTarget.machine_code) then
begin
InputError('ELF file is for different CPU');
exit;
@ -1850,7 +1817,7 @@ implementation
header.e_type:=ET_DYN
else
header.e_type:=ET_EXEC;
header.e_machine:=ELFMACHINE;
header.e_machine:=ElfTarget.machine_code;
header.e_version:=1;
header.e_phoff:=sizeof(TElfHeader);
header.e_shoff:=shoffset;
@ -1966,8 +1933,8 @@ implementation
seg.Add(interpobjsec.ExeSection);
end;
textseg:=CreateSegment(PT_LOAD,PF_X or PF_R,ELF_MAXPAGESIZE);
dataseg:=CreateSegment(PT_LOAD,PF_R or PF_W,ELF_MAXPAGESIZE);
textseg:=CreateSegment(PT_LOAD,PF_X or PF_R,ElfTarget.max_page_size);
dataseg:=CreateSegment(PT_LOAD,PF_R or PF_W,ElfTarget.max_page_size);
for i:=0 to ExeSectionList.Count-1 do
begin
exesec:=TExeSection(ExeSectionList[i]);
@ -2347,7 +2314,7 @@ implementation
if IsSharedLibrary then
CurrMemPos:=0
else
CurrMemPos:=TEXT_SEGMENT_START;
CurrMemPos:=ElfTarget.exe_image_base;
textseg.MemPos:=CurrMemPos;
if assigned(phdrseg) then
begin
@ -2357,7 +2324,7 @@ implementation
CurrMemPos:=CurrMemPos+sizeof(TElfHeader)+segmentlist.count*sizeof(TElfproghdr);
MemPos_Segment(textseg);
CurrMemPos:=Align(CurrMemPos,SectionDataAlign); {! Data,not MemAlign}
CurrMemPos:=CurrMemPos+ELF_MAXPAGESIZE;
CurrMemPos:=CurrMemPos+ElfTarget.max_page_size;
dataseg.MemPos:=CurrMemPos;
MemPos_Segment(dataseg);
{ Mempos of unmapped sections is forced to zero, but we have to set positions

View File

@ -28,15 +28,9 @@ interface
implementation
uses
verbose,
verbose,elfbase,
systems,ogbase,ogelf,assemble;
type
TElfTargetSparc=class(TElfTarget)
class function encodereloc(objrel:TObjRelocation):byte;override;
class procedure loadreloc(objrel:TObjRelocation);override;
end;
const
{ Relocation types }
R_SPARC_NONE = 0;
@ -68,10 +62,10 @@ implementation
{****************************************************************************
TElfTargetSparc
ELF Target methods
****************************************************************************}
class function TElfTargetSparc.encodereloc(objrel:TObjRelocation):byte;
function elf_sparc_encodereloc(objrel:TObjRelocation):byte;
begin
case objrel.typ of
RELOC_NONE :
@ -86,7 +80,7 @@ implementation
end;
class procedure TElfTargetSparc.loadreloc(objrel:TObjRelocation);
procedure elf_sparc.loadreloc(objrel:TObjRelocation);
begin
end;
@ -97,6 +91,17 @@ implementation
*****************************************************************************}
const
elf_target_sparc: TElfTarget =
(
max_page_size: $8000; // fixme
exe_image_base: $8000; // fixme
machine_code: EM_SPARC;
relocs_use_addend: false;
encodereloc: @elf_sparc_encodeReloc;
loadreloc: @elf_sparc_loadReloc;
loadsection: nil;
);
as_sparc_elf32_info : tasminfo =
(
id : as_sparc_elf32;
@ -114,7 +119,7 @@ implementation
initialization
RegisterAssembler(as_sparc_elf32_info,TElfAssembler);
ElfTarget:=TElfTargetSparc;
ElfTarget:=elf_target_sparc;
end.

View File

@ -29,15 +29,10 @@ implementation
uses
globtype,cutils,cclasses,
verbose,
verbose,elfbase,
systems,aasmbase,ogbase,ogelf,assemble;
type
TElfTargetx86_64=class(TElfTarget)
class function encodereloc(objrel:TObjRelocation):byte;override;
class procedure loadreloc(objrel:TObjRelocation);override;
end;
TElfExeOutputx86_64=class(TElfExeOutput)
private
function RelocName(reltyp:byte):string;
@ -148,10 +143,10 @@ implementation
{****************************************************************************
TELFTargetx86_64
ELF Target methods
****************************************************************************}
class function TElfTargetx86_64.encodereloc(objrel:TObjRelocation):byte;
function elf_x86_64_encodereloc(objrel:TObjRelocation):byte;
begin
case objrel.typ of
RELOC_NONE :
@ -185,7 +180,7 @@ implementation
end;
class procedure TElfTargetx86_64.loadreloc(objrel:TObjRelocation);
procedure elf_x86_64_loadreloc(objrel:TObjRelocation);
begin
end;
@ -381,7 +376,7 @@ implementation
else
InternalError(2012092103);
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
address:=objreloc.orgsize
else
begin
@ -547,7 +542,7 @@ implementation
pltrelocsec.writeReloc_internal(gotpltobjsec,gotpltobjsec.size-sizeof(pint),sizeof(pint),RELOC_ABSOLUTE);
got_offset:=(qword(exesym.dynindex) shl 32) or R_X86_64_JUMP_SLOT;
pltrelocsec.write(got_offset,sizeof(pint));
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
pltrelocsec.writezeros(sizeof(pint));
end;
@ -585,7 +580,7 @@ implementation
ipltrelocsec.writeReloc_internal(gotpltobjsec,gotpltobjsec.size-sizeof(pint),sizeof(pint),RELOC_ABSOLUTE);
tmp:=R_X86_64_IRELATIVE;
ipltrelocsec.write(tmp,sizeof(pint));
if relocs_use_addend then
if ElfTarget.relocs_use_addend then
ipltrelocsec.writeReloc_internal(targetsym.objsection,targetsym.offset,sizeof(pint),RELOC_ABSOLUTE);
end;
@ -594,6 +589,18 @@ implementation
*****************************************************************************}
const
elf_target_x86_64: TElfTarget =
(
max_page_size: $200000;
exe_image_base: $400000;
machine_code: EM_X86_64;
relocs_use_addend: true;
encodereloc: @elf_x86_64_encodeReloc;
loadreloc: @elf_x86_64_loadReloc;
loadsection: nil;
);
as_x86_64_elf64_info : tasminfo =
(
id : as_x86_64_elf64;
@ -610,7 +617,7 @@ implementation
initialization
RegisterAssembler(as_x86_64_elf64_info,TElfAssembler);
ElfTarget:=TElfTargetx86_64;
ElfTarget:=elf_target_x86_64;
ElfExeOutputClass:=TElfExeOutputx86_64;
end.