Browse Source

+ Added method TObjSection.writeReloc_internal to write relocations to given section+offset without need to have a symbol at target location.
* Optimized COFF importing code using the new method.
- Don't create .text sections for imported variables.
- Don't create .idata$6 sections for imports by ordinal.

git-svn-id: trunk@22086 -

sergei 13 years ago
parent
commit
ec56677927
2 changed files with 63 additions and 92 deletions
  1. 9 0
      compiler/ogbase.pas
  2. 54 92
      compiler/ogcoff.pas

+ 9 - 0
compiler/ogbase.pas

@@ -209,6 +209,7 @@ interface
        function  write(const d;l:aword):aword;
        function  writestr(const s:string):aword;
        function  WriteZeros(l:longword):aword;
+       procedure writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);virtual;
        function  setmempos(mpos:qword):qword;
        procedure setDatapos(var dpos:aword);
        procedure alloc(l:aword);
@@ -712,6 +713,14 @@ implementation
       end;
 
 
+    { Writes relocation to (section+offset) without need to have a symbol at that location.
+      Not an abstract method because not every backend needs this functionality. }
+    procedure TObjSection.writeReloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
+      begin
+        InternalError(2012081501);
+      end;
+
+
     procedure TObjSection.setDatapos(var dpos:aword);
       begin
         if oso_Data in secoptions then

+ 54 - 92
compiler/ogcoff.pas

@@ -109,6 +109,7 @@ interface
        public
          constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);override;
          procedure addsymsizereloc(ofs:aword;p:TObjSymbol;symsize:aword;reloctype:TObjRelocationType);
+         procedure writereloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);override;
        end;
 
        TCoffObjData = class(TObjData)
@@ -220,7 +221,6 @@ interface
 
        TPECoffexeoutput = class(TCoffexeoutput)
        private
-         idatalabnr : longword;
          FRelocsGenerated : boolean;
          procedure GenerateRelocs;
        public
@@ -812,6 +812,13 @@ const pemagic : array[0..3] of byte = (
       end;
 
 
+    procedure TCoffObjSection.writereloc_internal(aTarget:TObjSection;offset:aword;len:byte;reltype:TObjRelocationType);
+      begin
+        AddSectionReloc(size,aTarget,reltype);
+        write(offset,len);
+      end;
+
+
     procedure TCoffExeOutput.DoRelocationFixup(objsec:TObjSection);
       var
         i,zero,address_size : longint;
@@ -2400,77 +2407,49 @@ const pemagic : array[0..3] of byte = (
         idata5objsection,
         idata6objsection,
         idata7objsection : TObjSection;
-        idata2label : TObjSymbol;
         basedllname : string;
 
         procedure StartImport(const dllname:string);
-        var
-          idata4label,
-          idata5label,
-          idata7label : TObjSymbol;
-          emptyint    : longint;
         begin
           if assigned(exemap) then
             begin
               exemap.Add('');
               exemap.Add('Importing from DLL '+dllname);
             end;
-          emptyint:=0;
           basedllname:=ExtractFileName(dllname);
           idata2objsection:=internalobjdata.createsection(sec_idata2,basedllname);
-          idata2label:=internalobjdata.SymbolDefine('__imp_dir_'+basedllname,AB_LOCAL,AT_DATA);
           idata4objsection:=internalobjdata.createsection(sec_idata4,basedllname);
-          idata4label:=internalobjdata.SymbolDefine('__imp_names_'+basedllname,AB_LOCAL,AT_DATA);
           idata5objsection:=internalobjdata.createsection(sec_idata5,basedllname);
-          idata5label:=internalobjdata.SymbolDefine('__imp_fixup_'+basedllname,AB_LOCAL,AT_DATA);
           idata7objsection:=internalobjdata.createsection(sec_idata7,basedllname);
-          idata7label:=internalobjdata.SymbolDefine('__imp_dll_'+basedllname,AB_LOCAL,AT_DATA);
           { idata2 }
-          internalobjdata.SetSection(idata2objsection);
-          { dummy links to imports finalization }
-          internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_names_end_'+basedllname),RELOC_NONE);
-          internalobjdata.writereloc(0,0,internalobjdata.SymbolRef('__imp_fixup_end_'+basedllname),RELOC_NONE);
-          { section data }
-          internalobjdata.writereloc(0,sizeof(longint),idata4label,RELOC_RVA);
-          internalobjdata.writebytes(emptyint,sizeof(emptyint));
-          internalobjdata.writebytes(emptyint,sizeof(emptyint));
-          internalobjdata.writereloc(0,sizeof(longint),idata7label,RELOC_RVA);
-          internalobjdata.writereloc(0,sizeof(longint),idata5label,RELOC_RVA);
+          idata2objsection.writereloc_internal(idata4objsection,0,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);
           { idata7 }
-          internalobjdata.SetSection(idata7objsection);
-          internalobjdata.writebytes(basedllname[1],length(basedllname));
-          internalobjdata.writebytes(emptyint,1);
+          idata7objsection.writestr(basedllname);
+          idata7objsection.writezeros(1);
         end;
 
         procedure EndImport;
-        var
-          emptyint : longint;
         begin
-          emptyint:=0;
           { These are referenced from idata2, oso_keep is not necessary. }
           idata4objsection:=internalobjdata.createsection(sec_idata4, basedllname+'_z_');
-          internalobjdata.SymbolDefine('__imp_names_end_'+basedllname,AB_LOCAL,AT_DATA);
           idata5objsection:=internalobjdata.createsection(sec_idata5, basedllname+'_z_');
-          internalobjdata.SymbolDefine('__imp_fixup_end_'+basedllname,AB_LOCAL,AT_DATA);
+          idata2objsection.writereloc_internal(idata4objsection,0,0,RELOC_NONE);
+          idata2objsection.writereloc_internal(idata5objsection,0,0,RELOC_NONE);
           { idata4 }
-          internalobjdata.SetSection(idata4objsection);
-          internalobjdata.writebytes(emptyint,sizeof(emptyint));
+          idata4objsection.writezeros(sizeof(longint));
           if target_info.system=system_x86_64_win64 then
-            internalobjdata.writebytes(emptyint,sizeof(emptyint));
+            idata4objsection.writezeros(sizeof(longint));
           { idata5 }
-          internalobjdata.SetSection(idata5objsection);
-          internalobjdata.writebytes(emptyint,sizeof(emptyint));
+          idata5objsection.writezeros(sizeof(longint));
           if target_info.system=system_x86_64_win64 then
-            internalobjdata.writebytes(emptyint,sizeof(emptyint));
+            idata5objsection.writezeros(sizeof(longint));
         end;
 
         function AddImport(const afuncname,amangledname:string; AOrdNr:longint;isvar:boolean):TObjSymbol;
         const
-{$ifdef x86_64}
-          jmpopcode : array[0..1] of byte = (
-            $ff,$25             // jmp qword [rip + offset32]
-          );
-{$else x86_64}
   {$ifdef arm}
           jmpopcode : array[0..7] of byte = (
             $00,$c0,$9f,$e5,    // ldr ip, [pc, #0]
@@ -2481,29 +2460,32 @@ const pemagic : array[0..3] of byte = (
             $ff,$25
           );
   {$endif arm}
-{$endif x86_64}
           nopopcodes : array[0..1] of byte = (
             $90,$90
           );
         var
-          idata4label,
-          idata5label,
-          idata6label : TObjSymbol;
-          emptyint : longint;
-          secname,
-          num : string;
-          absordnr: word;
-
-          procedure WriteTableEntry;
+          secname: string;
+
+          procedure WriteTableEntry(objsec:TObjSection);
           var
             ordint: dword;
           begin
             if AOrdNr <= 0 then
               begin
                 { import by name }
-                internalobjdata.writereloc(0,sizeof(longint),idata6label,RELOC_RVA);
+                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(1);
+                    idata6objsection.writezeros(align(idata6objsection.size,2)-idata6objsection.size);
+                  end;
+                objsec.writereloc_internal(idata6objsection,0,sizeof(longint),RELOC_RVA);
                 if target_info.system=system_x86_64_win64 then
-                  internalobjdata.writebytes(emptyint,sizeof(emptyint));
+                  objsec.writezeros(sizeof(longint));
               end
             else
               begin
@@ -2511,21 +2493,22 @@ const pemagic : array[0..3] of byte = (
                 ordint:=AOrdNr;
                 if target_info.system=system_x86_64_win64 then
                   begin
-                    internalobjdata.writebytes(ordint,sizeof(ordint));
+                    objsec.write(ordint,sizeof(ordint));
                     ordint:=$80000000;
-                    internalobjdata.writebytes(ordint,sizeof(ordint));
+                    objsec.write(ordint,sizeof(ordint));
                   end
                 else
                   begin
                     ordint:=ordint or $80000000;
-                    internalobjdata.writebytes(ordint,sizeof(ordint));
+                    objsec.write(ordint,sizeof(ordint));
                   end;
               end;
           end;
 
         begin
           result:=nil;
-          emptyint:=0;
+          textobjsection:=nil;
+          idata6objsection:=nil;
           if assigned(exemap) then
             begin
               if AOrdNr <= 0 then
@@ -2534,56 +2517,35 @@ const pemagic : array[0..3] of byte = (
                 exemap.Add(' Importing Function '+afuncname+' (OrdNr='+tostr(AOrdNr)+')');
             end;
 
-          with internalobjdata do
-            begin
-              secname:=basedllname+'_i_'+amangledname;
-              textobjsection:=createsection(sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,sectiontype2options(sec_code) - [oso_keep]);
-              idata4objsection:=createsection(sec_idata4, secname);
-              idata5objsection:=createsection(sec_idata5, secname);
-              idata6objsection:=createsection(sec_idata6, secname);
-            end;
+          secname:=basedllname+'_i_'+amangledname;
+          idata4objsection:=internalobjdata.createsection(sec_idata4, secname);
+          idata5objsection:=internalobjdata.createsection(sec_idata5, secname);
 
-          { idata6, import data (ordnr+name) }
-          internalobjdata.SetSection(idata6objsection);
-          inc(idatalabnr);
-          num:=tostr(idatalabnr);
-          idata6label:=internalobjdata.SymbolDefine('__imp_'+num,AB_LOCAL,AT_DATA);
-          absordnr:=Abs(AOrdNr);
-          { write index hint }
-          internalobjdata.writebytes(absordnr,2);
-          if AOrdNr <= 0 then
-            internalobjdata.writebytes(afuncname[1],length(afuncname));
-          internalobjdata.writebytes(emptyint,1);
-          internalobjdata.writebytes(emptyint,align(internalobjdata.CurrObjSec.size,2)-internalobjdata.CurrObjSec.size);
           { idata4, import lookup table }
-          internalobjdata.SetSection(idata4objsection);
-          idata4label:=internalobjdata.SymbolDefine('__imp_lookup_'+num,AB_LOCAL,AT_DATA);
-          WriteTableEntry;
+          WriteTableEntry(idata4objsection);
           { idata5, import address table }
           internalobjdata.SetSection(idata5objsection);
           { dummy back links }
-          internalobjdata.writereloc(0,0,idata4label,RELOC_NONE);
-          internalobjdata.writereloc(0,0,idata2label,RELOC_NONE);
-          { section data }
+          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
-            idata5label:=internalobjdata.SymbolDefine('__imp_'+amangledname,AB_LOCAL,AT_DATA);
-          WriteTableEntry;
-          { text, jmp }
-          if not isvar then
             begin
-              internalobjdata.SetSection(textobjsection);
+              textobjsection:=internalobjdata.createsection(internalobjdata.sectionname(sec_code,secname,secorder_default),current_settings.alignment.procalign,
+                internalobjdata.sectiontype2options(sec_code) - [oso_keep]);
               result:=internalobjdata.SymbolDefine('_'+amangledname,AB_GLOBAL,AT_FUNCTION);
-              internalobjdata.writebytes(jmpopcode,sizeof(jmpopcode));
+              textobjsection.write(jmpopcode,sizeof(jmpopcode));
 {$ifdef x86_64}
-              internalobjdata.writereloc(0,4,idata5label,RELOC_RELATIVE);
+              textobjsection.writereloc_internal(idata5objsection,0,4,RELOC_RELATIVE);
 {$else}
-              internalobjdata.writereloc(0,4,idata5label,RELOC_ABSOLUTE32);
+              textobjsection.writereloc_internal(idata5objsection,0,4,RELOC_ABSOLUTE32);
 {$endif x86_64}
 
-              internalobjdata.writebytes(nopopcodes,align(internalobjdata.CurrObjSec.size,sizeof(nopopcodes))-internalobjdata.CurrObjSec.size);
+              textobjsection.write(nopopcodes,align(textobjsection.size,sizeof(nopopcodes))-textobjsection.size);
             end;
+          { idata5 section data }
+          WriteTableEntry(idata5objsection);
         end;
 
       var