Răsfoiți Sursa

+ MIPS internal linker: support TLS IE/LE and GPREL32 relocations, is now able to link tw14265.

git-svn-id: trunk@25181 -
sergei 12 ani în urmă
părinte
comite
e7f6b06969
2 a modificat fișierele cu 77 adăugiri și 0 ștergeri
  1. 66 0
      compiler/mips/cpuelf.pas
  2. 11 0
      compiler/ogelf.pas

+ 66 - 0
compiler/mips/cpuelf.pas

@@ -49,6 +49,7 @@ implementation
       stubcount: longint;
       stubcount: longint;
       trampolinesection: TObjSection;
       trampolinesection: TObjSection;
       procedure MaybeWriteGOTEntry(relocval:aint;objsym:TObjSymbol);
       procedure MaybeWriteGOTEntry(relocval:aint;objsym:TObjSymbol);
+      procedure MaybeWriteTLSIEGotEntry(relocval:aint;objsym:TObjSymbol);
       procedure CreatePICStub(objsym:TObjSymbol);
       procedure CreatePICStub(objsym:TObjSymbol);
     protected
     protected
       procedure PrepareGOT;override;
       procedure PrepareGOT;override;
@@ -225,9 +226,18 @@ implementation
 
 
 
 
   function elf_mips_loadsection(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
   function elf_mips_loadsection(objinput:TElfObjInput;objdata:TObjData;const shdr:TElfsechdr;shindex:longint):boolean;
+    var
+      ri: TElfReginfo;
     begin
     begin
       case shdr.sh_type of
       case shdr.sh_type of
         SHT_MIPS_REGINFO:
         SHT_MIPS_REGINFO:
+          begin
+            objinput.ReadBytes(shdr.sh_offset,ri,sizeof(ri));
+            MaybeSwapElfReginfo(ri);
+            TElfObjData(objdata).gp_value:=ri.ri_gp_value;
+            result:=true;
+          end;
+        SHT_MIPS_DWARF:
           result:=true;
           result:=true;
       else
       else
         writeln('elf_mips_loadsection: ',hexstr(shdr.sh_type,8),' ',objdata.name);
         writeln('elf_mips_loadsection: ',hexstr(shdr.sh_type,8),' ',objdata.name);
@@ -555,6 +565,31 @@ implementation
         end;
         end;
     end;
     end;
 
 
+  procedure TElfExeOutputMIPS.MaybeWriteTLSIEGotEntry(relocval:aint;objsym:TObjSymbol);
+    var
+      gotoff,tmp:aword;
+    begin
+      gotoff:=objsym.exesymbol.gotoffset;
+      if gotoff=0 then
+        InternalError(2012060903);
+
+      if gotoff=gotobjsec.Data.size+sizeof(pint) then
+        begin
+          tmp:=gotobjsec.mempos+gotoff-sizeof(pint);
+          if (objsym.exesymbol.dynindex>0) then
+            begin
+              gotobjsec.writezeros(sizeof(pint));
+              dynreloclist.Add(TObjRelocation.CreateRaw(tmp,objsym,R_MIPS_TLS_TPREL32));
+            end
+          else
+            begin
+              putword(gotobjsec,relocval);
+              if IsSharedLibrary then
+                dynreloclist.Add(TObjRelocation.CreateRaw(tmp,nil,R_MIPS_TLS_TPREL32));
+            end;
+        end;
+    end;
+
   procedure TElfExeOutputMIPS.CreatePICStub(objsym:TObjSymbol);
   procedure TElfExeOutputMIPS.CreatePICStub(objsym:TObjSymbol);
     var
     var
       textsec,newsec:TObjSection;
       textsec,newsec:TObjSection;
@@ -722,6 +757,9 @@ implementation
                 local_got_relocs.add(objreloc);
                 local_got_relocs.add(objreloc);
               end;
               end;
           end;
           end;
+
+        R_MIPS_TLS_GOTTPREL:
+          inherited AllocGOTSlot(objreloc.symbol);
       end;
       end;
     end;
     end;
 
 
@@ -918,6 +956,34 @@ implementation
               //TODO: check overflow
               //TODO: check overflow
               address:=(address and $FFFF0000) or ((((SmallInt(address) shl 2)+relocval-curloc) shr 2) and $FFFF);
               address:=(address and $FFFF0000) or ((((SmallInt(address) shl 2)+relocval-curloc) shr 2) and $FFFF);
 
 
+            R_MIPS_GPREL32:
+              address:=address+relocval+TElfObjData(objsec.objdata).gp_value-gotsymbol.address;
+
+            R_MIPS_TLS_GOTTPREL:
+              begin
+                if IsSharedLibrary then
+                  relocval:=relocval-tlsseg.MemPos
+                else
+                  relocval:=relocval-(tlsseg.MemPos+TP_OFFSET);
+                MaybeWriteTLSIEGotEntry(relocval,objreloc.symbol);
+                relocval:=-(gotsymbol.offset-(objreloc.symbol.exesymbol.gotoffset-sizeof(pint)));
+                // TODO: check overflow
+                address:=(address and $FFFF0000) or (relocval and $FFFF);
+              end;
+
+            R_MIPS_TLS_TPREL_HI16:
+              begin
+                tmp:=SmallInt(address)+relocval-(tlsseg.MemPos+TP_OFFSET);
+                tmp:=(tmp+$8000) shr 16;
+                address:=(address and $FFFF0000) or (tmp and $FFFF);
+              end;
+
+            R_MIPS_TLS_TPREL_LO16:
+              begin
+                tmp:=SmallInt(address)+relocval-(tlsseg.MemPos+TP_OFFSET);
+                address:=(address and $FFFF0000) or (tmp and $FFFF);
+              end;
+
             R_MIPS_JALR: {optimization hint, ignore for now }
             R_MIPS_JALR: {optimization hint, ignore for now }
               ;
               ;
           else
           else

+ 11 - 0
compiler/ogelf.pas

@@ -76,6 +76,9 @@ interface
        public
        public
          ident: TElfIdent;
          ident: TElfIdent;
          flags: longword;
          flags: longword;
+{$ifdef mips}
+         gp_value: longword;
+{$endif mips}
          constructor create(const n:string);override;
          constructor create(const n:string);override;
          function  sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
          function  sectionname(atype:TAsmSectiontype;const aname:string;aorder:TAsmSectionOrder):string;override;
          procedure CreateDebugSections;override;
          procedure CreateDebugSections;override;
@@ -148,6 +151,7 @@ interface
          class function CanReadObjData(AReader:TObjectreader):boolean;override;
          class function CanReadObjData(AReader:TObjectreader):boolean;override;
          function CreateSection(const shdr:TElfsechdr;index:longint;objdata:TObjData;
          function CreateSection(const shdr:TElfsechdr;index:longint;objdata:TObjData;
            out secname:string):TElfObjSection;
            out secname:string):TElfObjSection;
+         function ReadBytes(offs:longint;out buf;len:longint):boolean;
        end;
        end;
 
 
        TElfVersionDef = class(TFPHashObject)
        TElfVersionDef = class(TFPHashObject)
@@ -1474,6 +1478,13 @@ implementation
       end;
       end;
 
 
 
 
+    function TElfObjInput.ReadBytes(offs:longint;out buf;len:longint):boolean;
+      begin
+        FReader.Seek(offs);
+        result:=FReader.Read(buf,len);
+      end;
+
+
     procedure TElfObjInput.LoadSection(const shdr:TElfsechdr;index:longint;objdata:tobjdata);
     procedure TElfObjInput.LoadSection(const shdr:TElfsechdr;index:longint;objdata:tobjdata);
       var
       var
         sec: TElfObjSection;
         sec: TElfObjSection;