Browse Source

* 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 years ago
parent
commit
a730830c19
3 changed files with 64 additions and 62 deletions
  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 WriteFirstPLTEntry;override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WriteIndirectPLTEntry(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;
       procedure DoRelocationFixup(objsec:TObjSection);override;
     end;
     end;
 
 
@@ -191,12 +191,13 @@ implementation
     end;
     end;
 
 
 
 
-  procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);
+  procedure TElfExeOutput386.GOTRelocPass1(objsec:TObjSection;var idx:longint);
     var
     var
       objsym:TObjSymbol;
       objsym:TObjSymbol;
-      sym:TExeSymbol;
+      objreloc:TObjRelocation;
       reltyp:byte;
       reltyp:byte;
     begin
     begin
+      objreloc:=TObjRelocation(objsec.ObjRelocations[idx]);
       if (ObjReloc.flags and rf_raw)=0 then
       if (ObjReloc.flags and rf_raw)=0 then
         reltyp:=ElfTarget.encodereloc(ObjReloc)
         reltyp:=ElfTarget.encodereloc(ObjReloc)
       else
       else
@@ -209,30 +210,15 @@ implementation
             objsym.refs:=objsym.refs or symref_plt;
             objsym.refs:=objsym.refs or symref_plt;
           end;
           end;
 
 
-        R_386_TLS_IE,
-        R_386_GOT32:
+        R_386_TLS_IE:
           begin
           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;
           end;
 
 
         R_386_32:
         R_386_32:

+ 36 - 3
compiler/ogelf.pas

@@ -222,11 +222,12 @@ interface
          dynreloclist: TFPObjectList;
          dynreloclist: TFPObjectList;
          tlsseg: TElfSegment;
          tlsseg: TElfSegment;
          relative_reloc_count: longint;
          relative_reloc_count: longint;
+         procedure AllocGOTSlot(objsym: TObjSymbol);
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
          procedure WriteIndirectPLTEntry(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
        public
          constructor Create;override;
          constructor Create;override;
          destructor Destroy;override;
          destructor Destroy;override;
@@ -2316,6 +2317,34 @@ implementation
       end;
       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;
     procedure TElfExeOutput.PrepareGOT;
       var
       var
         i,j,k: longint;
         i,j,k: longint;
@@ -2333,8 +2362,12 @@ implementation
                   continue;
                   continue;
                 if not objsec.Used then
                 if not objsec.Used then
                   internalerror(2012060901);
                   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;
           end;
           end;
         { remember sizes for sanity checking }
         { remember sizes for sanity checking }

+ 17 - 34
compiler/x86_64/cpuelf.pas

@@ -48,7 +48,7 @@ implementation
       procedure WriteFirstPLTEntry;override;
       procedure WriteFirstPLTEntry;override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WritePLTEntry(exesym:TExeSymbol);override;
       procedure WriteIndirectPLTEntry(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;
       procedure DoRelocationFixup(objsec:TObjSection);override;
     end;
     end;
 
 
@@ -217,12 +217,13 @@ implementation
     end;
     end;
 
 
 
 
-  procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;ObjReloc:TObjRelocation);
+  procedure TElfExeOutputx86_64.GOTRelocPass1(objsec:TObjSection;var idx:longint);
     var
     var
       objsym:TObjSymbol;
       objsym:TObjSymbol;
-      sym:TExeSymbol;
+      objreloc:TObjRelocation;
       reltyp:byte;
       reltyp:byte;
     begin
     begin
+      objreloc:=TObjRelocation(objsec.ObjRelocations[idx]);
       if (ObjReloc.flags and rf_raw)=0 then
       if (ObjReloc.flags and rf_raw)=0 then
         reltyp:=ElfTarget.encodereloc(ObjReloc)
         reltyp:=ElfTarget.encodereloc(ObjReloc)
       else
       else
@@ -239,20 +240,14 @@ implementation
       end;
       end;
 
 
       case reltyp of
       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
           begin
-            sym:=ObjReloc.symbol.exesymbol;
             { TLS IE to locally defined symbol, convert into LE so GOT entry isn't needed
             { 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
               (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
                a threadvar in main program or in other *statically* loaded lib; TLS IE access to
                own threadvars may render library not loadable dynamically) }
                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
               begin
                 if not IsValidIEtoLE(objsec,ObjReloc) then
                 if not IsValidIEtoLE(objsec,ObjReloc) then
                   Comment(v_error,'Cannot transform TLS IE to LE');
                   Comment(v_error,'Cannot transform TLS IE to LE');
@@ -261,29 +256,17 @@ implementation
                 exit;
                 exit;
               end;
               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;
           end;
 
 
         //R_X86_64_TLSGD,
         //R_X86_64_TLSGD,