* COFF linker: postpone import section generation until unreferenced sections (and imports) are removed, and put all remaining imports into a single section. This is much more efficient than generating multiple smart-linkable import sections and immediately discarding a good half of them.

git-svn-id: trunk@24123 -
This commit is contained in:
sergei 2013-04-02 05:46:32 +00:00
parent b9fc64f697
commit 999c3a0a02
2 changed files with 81 additions and 57 deletions

View File

@ -468,11 +468,13 @@ interface
FOrdNr : longint;
FIsVar : boolean;
FMangledName : string;
FCachedExeSymbol: TExeSymbol;
public
constructor create(AList:TFPHashObjectList;const AName,AMangledName:string;AOrdNr:longint;AIsVar:boolean);
property OrdNr: longint read FOrdNr;
property MangledName: string read FMangledName;
property IsVar: boolean read FIsVar;
property CachedExeSymbol: TExeSymbol read FCachedExeSymbol write FCachedExeSymbol;
end;
TExeWriteMode = (ewm_exefull,ewm_dbgonly,ewm_exeonly);

View File

@ -221,10 +221,18 @@ interface
TPECoffexeoutput = class(TCoffexeoutput)
private
FImports: TFPHashObjectList;
textobjsection,
idata2objsection,
idata4objsection,
idata5objsection,
idata6objsection,
idata7objsection : TObjSection;
FRelocsGenerated : boolean;
procedure GenerateRelocs;
public
constructor create;override;
procedure AfterUnusedSectionRemoval;override;
procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
procedure MemPos_Start;override;
procedure MemPos_ExeSection(const aname:string);override;
@ -1988,7 +1996,10 @@ const pemagic : array[0..3] of byte = (
internalerror(200603053);
with texesymbol(p).objsymbol do
begin
exesec:=TExeSection(objsection.exesection);
if assigned(objsection) then
exesec:=TExeSection(objsection.exesection)
else
exesec:=nil;
{ There is no exesection defined for special internal symbols
like __image_base__ }
if assigned(exesec) then
@ -2461,14 +2472,8 @@ const pemagic : array[0..3] of byte = (
end;
procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
procedure TPECoffexeoutput.AfterUnusedSectionRemoval;
var
textobjsection,
idata2objsection,
idata4objsection,
idata5objsection,
idata6objsection,
idata7objsection : TObjSection;
basedllname : string;
procedure StartImport(const dllname:string);
@ -2479,26 +2484,17 @@ const pemagic : array[0..3] of byte = (
exemap.Add('Importing from DLL '+dllname);
end;
basedllname:=ExtractFileName(dllname);
idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
{ idata2 }
idata2objsection.writereloc_internal(idata4objsection,0,sizeof(longint),RELOC_RVA);
idata2objsection.writereloc_internal(idata4objsection,idata4objsection.size,sizeof(longint),RELOC_RVA);
idata2objsection.writezeros(2*sizeof(longint));
idata2objsection.writereloc_internal(idata7objsection,0,sizeof(longint),RELOC_RVA);
idata2objsection.writereloc_internal(idata5objsection,0,sizeof(longint),RELOC_RVA);
idata2objsection.writereloc_internal(idata7objsection,idata7objsection.size,sizeof(longint),RELOC_RVA);
idata2objsection.writereloc_internal(idata5objsection,idata5objsection.size,sizeof(longint),RELOC_RVA);
{ idata7 }
idata7objsection.writestr(basedllname);
end;
procedure EndImport;
begin
{ These are referenced from idata2, oso_keep is not necessary. }
idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
idata2objsection.writereloc_internal(idata4objsection,0,0,RELOC_NONE);
idata2objsection.writereloc_internal(idata5objsection,0,0,RELOC_NONE);
{ idata4 }
idata4objsection.writezeros(sizeof(longint));
if target_info.system=system_x86_64_win64 then
@ -2525,25 +2521,13 @@ const pemagic : array[0..3] of byte = (
$90,$90
);
var
secname: string;
ordint: dword;
procedure WriteTableEntry(objsec:TObjSection);
var
ordint: dword;
begin
if AOrdNr <= 0 then
begin
{ import by name }
if idata6objsection=nil then
begin
idata6objsection:=internalobjdata.createsection(sec_idata6,secname);
ordint:=Abs(AOrdNr);
{ index hint, function name, null terminator and align }
idata6objsection.write(ordint,2);
idata6objsection.writestr(afuncname);
idata6objsection.writezeros(align(idata6objsection.size,2)-idata6objsection.size);
end;
objsec.writereloc_internal(idata6objsection,0,sizeof(longint),RELOC_RVA);
objsec.writereloc_internal(idata6objsection,idata6objsection.size,sizeof(longint),RELOC_RVA);
if target_info.system=system_x86_64_win64 then
objsec.writezeros(sizeof(longint));
end
@ -2567,8 +2551,6 @@ const pemagic : array[0..3] of byte = (
begin
result:=nil;
textobjsection:=nil;
idata6objsection:=nil;
if assigned(exemap) then
begin
if AOrdNr <= 0 then
@ -2577,35 +2559,36 @@ const pemagic : array[0..3] of byte = (
exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
end;
secname:=basedllname+'_i_'+amangledname;
idata4objsection:=internalobjdata.createsection(sec_idata4, secname);
idata5objsection:=internalobjdata.createsection(sec_idata5, secname);
{ idata4, import lookup table }
WriteTableEntry(idata4objsection);
{ idata5, import address table }
internalobjdata.SetSection(idata5objsection);
{ dummy back links }
idata5objsection.writereloc_internal(idata4objsection,0,0,RELOC_NONE);
idata5objsection.writereloc_internal(idata2objsection,0,0,RELOC_NONE);
if isvar then
result:=internalobjdata.SymbolDefine(amangledname,AB_GLOBAL,AT_DATA)
else
begin
textobjsection:=internalobjdata.createsection(internalobjdata.sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,
internalobjdata.sectiontype2options(sec_code) - [oso_keep]);
internalobjdata.SetSection(textobjsection);
textobjsection.writezeros(align_aword(textobjsection.size,16)-textobjsection.size);
result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
textobjsection.write(jmpopcode,sizeof(jmpopcode));
{$ifdef x86_64}
textobjsection.writereloc_internal(idata5objsection,0,4,RELOC_RELATIVE);
textobjsection.writereloc_internal(idata5objsection,idata5objsection.size,4,RELOC_RELATIVE);
{$else}
textobjsection.writereloc_internal(idata5objsection,0,4,RELOC_ABSOLUTE32);
textobjsection.writereloc_internal(idata5objsection,idata5objsection.size,4,RELOC_ABSOLUTE32);
{$endif x86_64}
textobjsection.write(nopopcodes,align(textobjsection.size,sizeof(nopopcodes))-textobjsection.size);
end;
{ idata5 section data }
WriteTableEntry(idata5objsection);
if (AOrdNr<=0) then
begin
{ index hint, function name, null terminator and align }
ordint:=abs(AOrdNr);
idata6objsection.write(ordint,2);
idata6objsection.writestr(afuncname);
idata6objsection.writezeros(align(idata6objsection.size,2)-idata6objsection.size);
end;
end;
var
@ -2613,15 +2596,58 @@ const pemagic : array[0..3] of byte = (
ImportLibrary : TImportLibrary;
ImportSymbol : TImportSymbol;
exesym : TExeSymbol;
newdll : boolean;
begin
for i:=0 to FImports.Count-1 do
begin
ImportLibrary:=TImportLibrary(FImports[i]);
newdll:=False;
for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
begin
ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
exesym:=ImportSymbol.CachedExeSymbol;
if assigned(exesym) and
exesym.Used then
begin
if (not newdll) then
StartImport(ImportLibrary.Name);
newdll:=True;
exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
end;
end;
if newdll then
EndImport;
end;
FixupSymbols;
end;
procedure TPECoffexeoutput.GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);
var
i,j: longint;
ImportLibrary: TImportLibrary;
ImportSymbol: TImportSymbol;
exesym: TExeSymbol;
begin
{ Here map import symbols to exe symbols and create necessary sections.
Actual import generation is done after unused sections (and symbols) are removed. }
FImports:=ImportLibraryList;
textobjsection:=internalObjData.CreateSection(sec_code);
textobjsection.SecOptions:=[oso_keep];
idata2objsection:=internalObjData.CreateSection(sec_idata2);
idata2objsection.SecOptions:=[oso_keep];
idata4objsection:=internalObjData.CreateSection(sec_idata4);
idata4objsection.SecOptions:=[oso_keep];
idata5objsection:=internalObjData.CreateSection(sec_idata5);
idata5objsection.SecOptions:=[oso_keep];
idata6objsection:=internalObjData.CreateSection(sec_idata6);
idata6objsection.SecOptions:=[oso_keep];
idata7objsection:=internalObjData.CreateSection(sec_idata7);
idata7objsection.SecOptions:=[oso_keep];
for i:=0 to ImportLibraryList.Count-1 do
begin
ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
idata2objsection:=nil;
idata4objsection:=nil;
idata5objsection:=nil;
idata6objsection:=nil;
idata7objsection:=nil;
for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
begin
ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
@ -2629,14 +2655,10 @@ const pemagic : array[0..3] of byte = (
if assigned(exesym) and
(exesym.State<>symstate_defined) then
begin
if not assigned(idata2objsection) then
StartImport(ImportLibrary.Name);
exesym.objsymbol:=AddImport(ImportSymbol.Name,ImportSymbol.MangledName,ImportSymbol.OrdNr,ImportSymbol.IsVar);
ImportSymbol.CachedExeSymbol:=exesym;
exesym.State:=symstate_defined;
end;
end;
if assigned(idata2objsection) then
EndImport;
end;
PackUnresolvedExeSymbols('after DLL imports');
end;