mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-02 23:50:24 +02:00
* 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:
parent
b9fc64f697
commit
999c3a0a02
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user