Sfoglia il codice sorgente

* Factored code for allocating GOT slots into TElfExeOutput.AllocGOTSlot.
* Changed signature of GOTRelocPass1 to pass relocation index instead of relocation itself, because sometimes (e.g. when doing TLS relaxation) we need to process several subsequent relocations at once.

git-svn-id: trunk@23077 -

sergei 12 anni fa
parent
commit
a730830c19
3 ha cambiato i file con 64 aggiunte e 62 eliminazioni
  1. 11 25
      compiler/i386/cpuelf.pas
  2. 36 3
      compiler/ogelf.pas
  3. 17 34
      compiler/x86_64/cpuelf.pas

+ 11 - 25
compiler/i386/cpuelf.pas

@@ -45,7 +45,7 @@ implementation
       procedure WriteFirstPLTEntry;override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WriteIndirectPLTEntry(exesym:TExeSymbol);override;
-      procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);override;
+      procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);override;
       procedure DoRelocationFixup(objsec:TObjSection);override;
     end;
 
@@ -191,12 +191,13 @@ implementation
     end;
 
 
-  procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);
+  procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;var idx:longint);
     var
       objsym:TObjSymbol;
-      sym:TExeSymbol;
+      objreloc:TObjRelocation;
       reltyp:byte;
     begin
+      objreloc:=TObjRelocation(objsec.ObjRelocations[idx]);
       if (ObjReloc.flags and rf_raw)=0 then
         reltyp:=ElfTarget.encodereloc(ObjReloc)
       else
@@ -209,30 +210,15 @@ implementation
             objsym.refs:=objsym.refs or symref_plt;
           end;
 
-        R_386_TLS_IE,
-        R_386_GOT32:
+        R_386_TLS_IE:
           begin
-            sym:=ObjReloc.symbol.exesymbol;
 
-            { Although local symbols should not be accessed through GOT,
-              this isn't strictly forbidden. In this case we need to fake up
-              the exesym to store the GOT offset in it.
-              TODO: name collision; maybe use a different symbol list object? }
-            if sym=nil then
-              begin
-                sym:=TExeSymbol.Create(ExeSymbolList,objreloc.symbol.name+'*local*');
-                sym.objsymbol:=objreloc.symbol;
-                objreloc.symbol.exesymbol:=sym;
-              end;
-            if sym.GotOffset>0 then
-              exit;
-            gotobjsec.alloc(sizeof(pint));
-            sym.GotOffset:=gotobjsec.size;
-            { In shared library, every GOT entry needs a RELATIVE dynamic reloc,
-              imported/exported symbols need GLOB_DAT instead. For executables,
-              only the latter applies. }
-            if IsSharedLibrary or (sym.dynindex>0) then
-              dynrelocsec.alloc(dynrelocsec.shentsize);
+            AllocGOTSlot(objreloc.symbol);
+          end;
+
+        R_386_GOT32:
+          begin
+            AllocGOTSlot(objreloc.symbol);
           end;
 
         R_386_32:

+ 36 - 3
compiler/ogelf.pas

@@ -222,11 +222,12 @@ interface
          dynreloclist: TFPObjectList;
          tlsseg: TElfSegment;
          relative_reloc_count: longint;
+         procedure AllocGOTSlot(objsym: TObjSymbol);
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
          procedure WriteIndirectPLTEntry(exesym:TExeSymbol);virtual;
-         procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);virtual;abstract;
+         procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);virtual;abstract;
        public
          constructor Create;override;
          destructor Destroy;override;
@@ -2316,6 +2317,34 @@ implementation
       end;
 
 
+    procedure TElfExeOutput.AllocGOTSlot(objsym:TObjSymbol);
+      var
+        exesym: TExeSymbol;
+      begin
+        exesym:=objsym.exesymbol;
+
+        { Although local symbols should not be accessed through GOT,
+          this isn't strictly forbidden. In this case we need to fake up
+          the exesym to store the GOT offset in it.
+          TODO: name collision; maybe use a different symbol list object? }
+        if exesym=nil then
+          begin
+            exesym:=TExeSymbol.Create(ExeSymbolList,objsym.name+'*local*');
+            exesym.objsymbol:=objsym;
+            objsym.exesymbol:=exesym;
+          end;
+        if exesym.GotOffset>0 then
+          exit;
+        gotobjsec.alloc(sizeof(pint));
+        exesym.GotOffset:=gotobjsec.size;
+        { In shared library, every GOT entry needs a RELATIVE dynamic reloc,
+          imported/exported symbols need GLOB_DAT instead. For executables,
+          only the latter applies. }
+        if IsSharedLibrary or (exesym.dynindex>0) then
+          dynrelocsec.alloc(dynrelocsec.shentsize);
+      end;
+
+
     procedure TElfExeOutput.PrepareGOT;
       var
         i,j,k: longint;
@@ -2333,8 +2362,12 @@ implementation
                   continue;
                 if not objsec.Used then
                   internalerror(2012060901);
-                for k:=0 to objsec.ObjRelocations.Count-1 do
-                  GOTRelocPass1(objsec,TObjRelocation(objsec.ObjRelocations[k]));
+                k:=0;
+                while k<objsec.ObjRelocations.Count do
+                  begin
+                    GOTRelocPass1(objsec,k);
+                    inc(k);
+                  end;
               end;
           end;
         { remember sizes for sanity checking }

+ 17 - 34
compiler/x86_64/cpuelf.pas

@@ -48,7 +48,7 @@ implementation
       procedure WriteFirstPLTEntry;override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WriteIndirectPLTEntry(exesym:TExeSymbol);override;
-      procedure GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);override;
+      procedure GOTRelocPass1(objsec:TObjSection;var idx:longint);override;
       procedure DoRelocationFixup(objsec:TObjSection);override;
     end;
 
@@ -217,12 +217,13 @@ implementation
     end;
 
 
-  procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);
+  procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;var idx:longint);
     var
       objsym:TObjSymbol;
-      sym:TExeSymbol;
+      objreloc:TObjRelocation;
       reltyp:byte;
     begin
+      objreloc:=TObjRelocation(objsec.ObjRelocations[idx]);
       if (ObjReloc.flags and rf_raw)=0 then
         reltyp:=ElfTarget.encodereloc(ObjReloc)
       else
@@ -239,20 +240,14 @@ implementation
       end;
 
       case reltyp of
-        R_X86_64_GOT32,
-        R_X86_64_GOT64,
-        R_X86_64_GOTTPOFF,
-        R_X86_64_GOTPCREL,
-        R_X86_64_GOTPCREL64:
+        R_X86_64_GOTTPOFF:
           begin
-            sym:=ObjReloc.symbol.exesymbol;
             { TLS IE to locally defined symbol, convert into LE so GOT entry isn't needed
               (Is TLS IE allowed in shared libs at all? Yes it is, when lib is accessing
                a threadvar in main program or in other *statically* loaded lib; TLS IE access to
                own threadvars may render library not loadable dynamically) }
 (*
-            if (reltyp=R_X86_64_GOTTPOFF) and not
-              (IsSharedLibrary or (sym.dynindex>0)) then
+            if not (IsSharedLibrary or (sym.dynindex>0)) then
               begin
                 if not IsValidIEtoLE(objsec,ObjReloc) then
                   Comment(v_error,'Cannot transform TLS IE to LE');
@@ -261,29 +256,17 @@ implementation
                 exit;
               end;
 *)
-            { Although local symbols should not be accessed through GOT,
-              this isn't strictly forbidden. In this case we need to fake up
-              the exesym to store the GOT offset in it.
-              TODO: name collision; maybe use a different symbol list object? }
-            if sym=nil then
-              begin
-                sym:=TExeSymbol.Create(ExeSymbolList,objreloc.symbol.name+'*local*');
-                sym.objsymbol:=objreloc.symbol;
-                objreloc.symbol.exesymbol:=sym;
-              end;
-            if sym.GotOffset>0 then
-              exit;
-            gotobjsec.alloc(sizeof(pint));
-            sym.GotOffset:=gotobjsec.size;
-            { In shared library, every GOT entry needs a RELATIVE dynamic reloc,
-              imported/exported symbols need GLOB_DAT instead. For executables,
-              only the latter applies. }
-            if IsSharedLibrary or (sym.dynindex>0) then
-              begin
-                dynrelocsec.alloc(dynrelocsec.shentsize);
-                if (sym.dynindex=0) and (reltyp<>R_X86_64_GOTTPOFF) then
-                  Inc(relative_reloc_count);
-              end;
+            AllocGOTSlot(objreloc.symbol);
+          end;
+
+        R_X86_64_GOT32,
+        R_X86_64_GOT64,
+        R_X86_64_GOTPCREL,
+        R_X86_64_GOTPCREL64:
+          begin
+            AllocGOTSlot(objreloc.symbol);
+            if IsSharedLibrary and (objreloc.symbol.exesymbol.dynindex=0) then
+              Inc(relative_reloc_count);
           end;
 
         //R_X86_64_TLSGD,