]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools GenFw: Add support for RISCV GOT/PLT relocations
authorSunil V L <sunilvl@ventanamicro.com>
Thu, 24 Jun 2021 13:25:31 +0000 (21:25 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Tue, 29 Jun 2021 02:47:44 +0000 (02:47 +0000)
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3096

This patch adds support for R_RISCV_CALL_PLT and R_RISCV_GOT_HI20
relocations generated by PIE enabled compiler. This also needed
changes to R_RISCV_32 and R_RISCV_64 relocations as explained in
https://github.com/riscv/riscv-gnu-toolchain/issues/905#issuecomment-846682710

Testing:
1) Debian GCC 8.3.0 and booted sifive_u and QMEU virt models.
2) Debian 10.2.0 and booted QEMU virt model.
3) riscv-gnu-tool chain 9.2 and booted QEMU virt model.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Acked-by: Abner Chang <abner.chang@hpe.com>
Reviewed-by: Daniel Schaefer <daniel.schaefer@hpe.com>
Tested-by: Daniel Schaefer <daniel.schaefer@hpe.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
BaseTools/Source/C/GenFw/Elf64Convert.c

index 33031ec8f6e7f63a64f07a5cb96db8a50b6a9c55..3d7e20aaff30ba41447643cda46f6bf59acf5ebf 100644 (file)
@@ -129,6 +129,8 @@ STATIC UINT32 mDebugOffset;
 STATIC UINT8       *mRiscVPass1Targ = NULL;\r
 STATIC Elf_Shdr    *mRiscVPass1Sym = NULL;\r
 STATIC Elf64_Half  mRiscVPass1SymSecIndex = 0;\r
+STATIC INT32       mRiscVPass1Offset;\r
+STATIC INT32       mRiscVPass1GotFixup;\r
 \r
 //\r
 // Initialization Function\r
@@ -474,17 +476,18 @@ WriteSectionRiscV64 (
 {\r
   UINT32      Value;\r
   UINT32      Value2;\r
+  Elf64_Addr  GOTEntryRva;\r
 \r
   switch (ELF_R_TYPE(Rel->r_info)) {\r
   case R_RISCV_NONE:\r
     break;\r
 \r
   case R_RISCV_32:\r
-    *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
+    *(UINT64 *)Targ = Sym->st_value + Rel->r_addend;\r
     break;\r
 \r
   case R_RISCV_64:\r
-    *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
+    *(UINT64 *)Targ = Sym->st_value + Rel->r_addend;\r
     break;\r
 \r
   case R_RISCV_HI20:\r
@@ -534,6 +537,18 @@ WriteSectionRiscV64 (
     mRiscVPass1SymSecIndex = 0;\r
     break;\r
 \r
+  case R_RISCV_GOT_HI20:\r
+    GOTEntryRva = (Sym->st_value - Rel->r_offset);\r
+    mRiscVPass1Offset = RV_X(GOTEntryRva, 0, 12);\r
+    Value = (UINT32)RV_X(GOTEntryRva, 12, 20);\r
+    *(UINT32 *)Targ = (Value << 12) | (RV_X(*(UINT32*)Targ, 0, 12));\r
+\r
+    mRiscVPass1Targ = Targ;\r
+    mRiscVPass1Sym = SymShdr;\r
+    mRiscVPass1SymSecIndex = Sym->st_shndx;\r
+    mRiscVPass1GotFixup = 1;\r
+    break;\r
+\r
   case R_RISCV_PCREL_HI20:\r
     mRiscVPass1Targ = Targ;\r
     mRiscVPass1Sym = SymShdr;\r
@@ -546,11 +561,17 @@ WriteSectionRiscV64 (
     if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && mRiscVPass1SymSecIndex != 0) {\r
       int i;\r
       Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20));\r
-      Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));\r
-      if(Value & (RISCV_IMM_REACH/2)) {\r
-        Value |= ~(RISCV_IMM_REACH-1);\r
+\r
+      if(mRiscVPass1GotFixup) {\r
+        Value = (UINT32)(mRiscVPass1Offset);\r
+      } else {\r
+        Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));\r
+        if(Value & (RISCV_IMM_REACH/2)) {\r
+          Value |= ~(RISCV_IMM_REACH-1);\r
+        }\r
       }\r
       Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + mCoffSectionsOffset[mRiscVPass1SymSecIndex];\r
+\r
       if(-2048 > (INT32)Value) {\r
         i = (((INT32)Value * -1) / 4096);\r
         Value2 -= i;\r
@@ -570,12 +591,35 @@ WriteSectionRiscV64 (
         }\r
       }\r
 \r
-      *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20));\r
+      if(mRiscVPass1GotFixup) {\r
+        *(UINT32 *)Targ = (RV_X((UINT32)Value, 0, 12) << 20)\r
+                            | (RV_X(*(UINT32*)Targ, 0, 20));\r
+        // Convert LD instruction to ADDI\r
+        //\r
+        // |31      20|19  15|14  12|11   7|6       0|\r
+        // |-----------------------------------------|\r
+        // |imm[11:0] | rs1  | 011  |  rd  | 0000011 | LD\r
+        //  -----------------------------------------\r
+\r
+        // |-----------------------------------------|\r
+        // |imm[11:0] | rs1  | 000  |  rd  | 0010011 | ADDI\r
+        //  -----------------------------------------\r
+\r
+        // To convert, let's first reset bits 12-14 and 0-6 using ~0x707f\r
+        // Then modify the opcode to ADDI (0010011)\r
+        // All other fields will remain same.\r
+\r
+        *(UINT32 *)Targ = ((*(UINT32 *)Targ & ~0x707f) | 0x13);\r
+      } else {\r
+        *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20));\r
+      }\r
       *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 *)mRiscVPass1Targ, 0, 12));\r
     }\r
     mRiscVPass1Sym = NULL;\r
     mRiscVPass1Targ = NULL;\r
     mRiscVPass1SymSecIndex = 0;\r
+    mRiscVPass1Offset = 0;\r
+    mRiscVPass1GotFixup = 0;\r
     break;\r
 \r
   case R_RISCV_ADD64:\r
@@ -587,6 +631,7 @@ WriteSectionRiscV64 (
   case R_RISCV_GPREL_I:\r
   case R_RISCV_GPREL_S:\r
   case R_RISCV_CALL:\r
+  case R_RISCV_CALL_PLT:\r
   case R_RISCV_RVC_BRANCH:\r
   case R_RISCV_RVC_JUMP:\r
   case R_RISCV_RELAX:\r
@@ -1530,6 +1575,7 @@ WriteRelocations64 (
             case R_RISCV_GPREL_I:\r
             case R_RISCV_GPREL_S:\r
             case R_RISCV_CALL:\r
+            case R_RISCV_CALL_PLT:\r
             case R_RISCV_RVC_BRANCH:\r
             case R_RISCV_RVC_JUMP:\r
             case R_RISCV_RELAX:\r
@@ -1539,6 +1585,7 @@ WriteRelocations64 (
             case R_RISCV_SET16:\r
             case R_RISCV_SET32:\r
             case R_RISCV_PCREL_HI20:\r
+            case R_RISCV_GOT_HI20:\r
             case R_RISCV_PCREL_LO12_I:\r
               break;\r
 \r