Browse Source

* MIPS: some progress with linker:
* Fixed values of R_MIPS_GOT_HI16/LO16.
+ Implemented elf_mips_relocname
+ Check R_MIPS_PC16 relocations for overflows
+ Handle R_MIPS_JALR optimization hint.

git-svn-id: trunk@33240 -

sergei 9 years ago
parent
commit
578348817b
1 changed files with 83 additions and 7 deletions
  1. 83 7
      compiler/mips/cpuelf.pas

+ 83 - 7
compiler/mips/cpuelf.pas

@@ -117,8 +117,8 @@ implementation
     R_MIPS_PC16    = 10;
     R_MIPS_PC16    = 10;
     R_MIPS_CALL16  = 11;
     R_MIPS_CALL16  = 11;
     R_MIPS_GPREL32 = 12;
     R_MIPS_GPREL32 = 12;
-    R_MIPS_GOT_HI16 = 21;
-    R_MIPS_GOT_LO16 = 22;
+    R_MIPS_GOT_HI16 = 22;
+    R_MIPS_GOT_LO16 = 23;
     R_MIPS_CALL_HI16 = 30;
     R_MIPS_CALL_HI16 = 30;
     R_MIPS_CALL_LO16 = 31;
     R_MIPS_CALL_LO16 = 31;
     R_MIPS_JALR    = 37;
     R_MIPS_JALR    = 37;
@@ -175,6 +175,62 @@ implementation
       offset:aword;
       offset:aword;
     end;
     end;
 
 
+
+  const
+    relocnames: array[0..50] of PChar = (
+      'R_MIPS_NONE',
+      'R_MIPS_16',
+      'R_MIPS_32',
+      'R_MIPS_REL32',
+      'R_MIPS_26',
+      'R_MIPS_HI16',
+      'R_MIPS_LO16',
+      'R_MIPS_GPREL16',
+      'R_MIPS_LITERAL',
+      'R_MIPS_GOT16',
+      'R_MIPS_PC16',
+      'R_MIPS_CALL16',
+      'R_MIPS_GPREL32',
+      nil,  {13}
+      nil,  {14}
+      nil,  {15}
+      nil,  {16}
+      nil,  {17}
+      nil,  {18}
+      nil,  {19}
+      nil,  {20}
+      nil,  {21}
+      'R_MIPS_GOT_HI16',
+      'R_MIPS_GOT_LO16',
+      nil,  {24}
+      nil,  {25}
+      nil,  {26}
+      nil,  {27}
+      nil,  {28}
+      nil,  {29}
+      'R_MIPS_CALL_HI16',
+      'R_MIPS_CALL_LO16',
+      nil,  {32}
+      nil,  {33}
+      nil,  {34}
+      nil,  {35}
+      nil,  {36}
+      'R_MIPS_JALR',
+      'R_MIPS_TLS_DTPMOD32',
+      'R_MIPS_TLS_DTPREL32',
+      'R_MIPS_TLS_DTPMOD64',
+      'R_MIPS_TLS_DTPREL64',
+      'R_MIPS_TLS_GD',
+      'R_MIPS_TLS_LDM',
+      'R_MIPS_TLS_DTPREL_HI16',
+      'R_MIPS_TLS_DTPREL_LO16',
+      'R_MIPS_TLS_GOTTPREL',
+      'R_MIPS_TLS_TPREL32',
+      'R_MIPS_TLS_TPREL64',
+      'R_MIPS_TLS_TPREL_HI16',
+      'R_MIPS_TLS_TPREL_LO16'
+    );
+
   procedure MaybeSwapElfReginfo(var h:TElfReginfo);
   procedure MaybeSwapElfReginfo(var h:TElfReginfo);
     var
     var
       i: longint;
       i: longint;
@@ -218,7 +274,11 @@ implementation
 
 
   function elf_mips_relocname(reltyp:byte):string;
   function elf_mips_relocname(reltyp:byte):string;
     begin
     begin
-      result:='TODO';
+      if (reltyp<=high(relocnames)) and
+        (relocnames[reltyp]<>nil) then
+        result:=relocnames[reltyp]
+      else
+        result:='unknown ('+tostr(reltyp)+')';
     end;
     end;
 
 
 
 
@@ -863,6 +923,8 @@ implementation
               begin
               begin
                 tmp:=(address and $03FFFFFF) shl 2;
                 tmp:=(address and $03FFFFFF) shl 2;
                 tmp:=((tmp or (curloc and $F0000000))+relocval) shr 2;
                 tmp:=((tmp or (curloc and $F0000000))+relocval) shr 2;
+                { TODO: Report overflow if upper 4 bits change
+                        However JAL to undefined weak symbol is not treated as an overflow }
                 address:=(address and $FC000000) or (tmp and $3FFFFFF);
                 address:=(address and $FC000000) or (tmp and $3FFFFFF);
               end;
               end;
 
 
@@ -955,8 +1017,12 @@ implementation
               end;
               end;
 
 
             R_MIPS_PC16:
             R_MIPS_PC16:
-              //TODO: check overflow
-              address:=(address and $FFFF0000) or ((((SmallInt(address) shl 2)+relocval-curloc) shr 2) and $FFFF);
+              begin
+                tmp:=((SmallInt(address) shl 2)+relocval-curloc) shr 2;
+                if (tmp<>SmallInt(tmp)) then
+                  ReportRelocOverflow(reltyp,objsec,objreloc);
+                address:=(address and $FFFF0000) or (tmp and $FFFF);
+              end;
 
 
             R_MIPS_GPREL32:
             R_MIPS_GPREL32:
               address:=address+relocval+TElfObjData(objsec.objdata).gp_value-gotsymbol.address;
               address:=address+relocval+TElfObjData(objsec.objdata).gp_value-gotsymbol.address;
@@ -986,8 +1052,18 @@ implementation
                 address:=(address and $FFFF0000) or (tmp and $FFFF);
                 address:=(address and $FFFF0000) or (tmp and $FFFF);
               end;
               end;
 
 
-            R_MIPS_JALR: {optimization hint, ignore for now }
-              ;
+            R_MIPS_JALR: {optimization hint}
+              begin
+                { 4 is subtracted because branch is relative to delay slot, not instruction itself }
+                tmp:=(relocval-curloc-4) shr 2;
+                if (tmp=SmallInt(tmp)) then
+                  begin
+                    if (address=$0320f809) then        { JALR $t9 -> BAL addr }
+                      address:=$04110000 or (tmp and $FFFF)
+                    else if (address=$03200008) then   { JR $t9   -> B addr }
+                      address:=$10000000 or (tmp and $FFFF);
+                  end;
+              end;
           else
           else
             begin
             begin
               writeln(objsec.fullname,'+',objreloc.dataoffset,' ',objreloc.ftype);
               writeln(objsec.fullname,'+',objreloc.dataoffset,' ',objreloc.ftype);