Forráskód Böngészése

* 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 -
sergei 12 éve
szülő
commit
999c3a0a02
2 módosított fájl, 81 hozzáadás és 57 törlés
  1. 2 0
      compiler/ogbase.pas
  2. 79 57
      compiler/ogcoff.pas

+ 2 - 0
compiler/ogbase.pas

@@ -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);

+ 79 - 57
compiler/ogcoff.pas

@@ -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;