Since I was also impacted by this in the RISC-V NTFS driver, and I can vouch that this patch does produce a functional executable when tested with QEMU, I'll add my T-b as well.

On 2021.06.24 14:25, Sunil V L wrote:
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

Changes in v4:
   - Fixed the typecast issue found by VS2019.

Changes in v3:
   - Added the comments to address Liming's feedback.

Changes in v2:
   - Addressed Daniel's comment on formatting

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 <suni...@ventanamicro.com>

Acked-by: Abner Chang <abner.ch...@hpe.com>
Reviewed-by: Daniel Schaefer <daniel.schae...@hpe.com>
Tested-by: Daniel Schaefer <daniel.schae...@hpe.com>

Cc: Bob Feng <bob.c.f...@intel.com>
Cc: Liming Gao <gaolim...@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.c...@intel.com>
Cc: Heinrich Schuchardt <xypron.g...@gmx.de>
---
  BaseTools/Source/C/GenFw/Elf64Convert.c | 59 ++++++++++++++++++++++---
  1 file changed, 53 insertions(+), 6 deletions(-)

diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c 
b/BaseTools/Source/C/GenFw/Elf64Convert.c
index d097db8632..f86be95fbb 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -129,6 +129,8 @@ STATIC UINT32 mDebugOffset;
  STATIC UINT8       *mRiscVPass1Targ = NULL;

  STATIC Elf_Shdr    *mRiscVPass1Sym = NULL;

  STATIC Elf64_Half  mRiscVPass1SymSecIndex = 0;

+STATIC INT32       mRiscVPass1Offset;

+STATIC INT32       mRiscVPass1GotFixup;

  //

  // Initialization Function

@@ -473,17 +475,18 @@ WriteSectionRiscV64 (
  {

    UINT32      Value;

    UINT32      Value2;

+  Elf64_Addr  GOTEntryRva;

    switch (ELF_R_TYPE(Rel->r_info)) {

    case R_RISCV_NONE:

      break;

    case R_RISCV_32:

-    *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + 
mCoffSectionsOffset[Sym->st_shndx]);

+    *(UINT64 *)Targ = Sym->st_value + Rel->r_addend;

      break;

    case R_RISCV_64:

-    *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + 
mCoffSectionsOffset[Sym->st_shndx];

+    *(UINT64 *)Targ = Sym->st_value + Rel->r_addend;

      break;

    case R_RISCV_HI20:

@@ -533,6 +536,18 @@ WriteSectionRiscV64 (
      mRiscVPass1SymSecIndex = 0;

      break;

+  case R_RISCV_GOT_HI20:

+    GOTEntryRva = (Sym->st_value - Rel->r_offset);

+    mRiscVPass1Offset = RV_X(GOTEntryRva, 0, 12);

+    Value = (UINT32)RV_X(GOTEntryRva, 12, 20);

+    *(UINT32 *)Targ = (Value << 12) | (RV_X(*(UINT32*)Targ, 0, 12));

+

+    mRiscVPass1Targ = Targ;

+    mRiscVPass1Sym = SymShdr;

+    mRiscVPass1SymSecIndex = Sym->st_shndx;

+    mRiscVPass1GotFixup = 1;

+    break;

+

    case R_RISCV_PCREL_HI20:

      mRiscVPass1Targ = Targ;

      mRiscVPass1Sym = SymShdr;

@@ -545,11 +560,17 @@ WriteSectionRiscV64 (
      if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && 
mRiscVPass1SymSecIndex != 0) {

        int i;

        Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20));

-      Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));

-      if(Value & (RISCV_IMM_REACH/2)) {

-        Value |= ~(RISCV_IMM_REACH-1);

+

+      if(mRiscVPass1GotFixup) {

+        Value = (UINT32)(mRiscVPass1Offset);

+      } else {

+        Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));

+        if(Value & (RISCV_IMM_REACH/2)) {

+          Value |= ~(RISCV_IMM_REACH-1);

+        }

        }

        Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + 
mCoffSectionsOffset[mRiscVPass1SymSecIndex];

+

        if(-2048 > (INT32)Value) {

          i = (((INT32)Value * -1) / 4096);

          Value2 -= i;

@@ -569,12 +590,35 @@ WriteSectionRiscV64 (
          }

        }

-      *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 
20));

+      if(mRiscVPass1GotFixup) {

+        *(UINT32 *)Targ = (RV_X((UINT32)Value, 0, 12) << 20)

+                            | (RV_X(*(UINT32*)Targ, 0, 20));

+        // Convert LD instruction to ADDI

+        //

+        // |31      20|19  15|14  12|11   7|6       0|

+        // |-----------------------------------------|

+        // |imm[11:0] | rs1  | 011  |  rd  | 0000011 | LD

+        //  -----------------------------------------

+

+        // |-----------------------------------------|

+        // |imm[11:0] | rs1  | 000  |  rd  | 0010011 | ADDI

+        //  -----------------------------------------

+

+        // To convert, let's first reset bits 12-14 and 0-6 using ~0x707f

+        // Then modify the opcode to ADDI (0010011)

+        // All other fields will remain same.

+

+        *(UINT32 *)Targ = ((*(UINT32 *)Targ & ~0x707f) | 0x13);

+      } else {

+        *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 
0, 20));

+      }

        *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 
*)mRiscVPass1Targ, 0, 12));

      }

      mRiscVPass1Sym = NULL;

      mRiscVPass1Targ = NULL;

      mRiscVPass1SymSecIndex = 0;

+    mRiscVPass1Offset = 0;

+    mRiscVPass1GotFixup = 0;

      break;

    case R_RISCV_ADD64:

@@ -586,6 +630,7 @@ WriteSectionRiscV64 (
    case R_RISCV_GPREL_I:

    case R_RISCV_GPREL_S:

    case R_RISCV_CALL:

+  case R_RISCV_CALL_PLT:

    case R_RISCV_RVC_BRANCH:

    case R_RISCV_RVC_JUMP:

    case R_RISCV_RELAX:

@@ -1528,6 +1573,7 @@ WriteRelocations64 (
              case R_RISCV_GPREL_I:

              case R_RISCV_GPREL_S:

              case R_RISCV_CALL:

+            case R_RISCV_CALL_PLT:

              case R_RISCV_RVC_BRANCH:

              case R_RISCV_RVC_JUMP:

              case R_RISCV_RELAX:

@@ -1537,6 +1583,7 @@ WriteRelocations64 (
              case R_RISCV_SET16:

              case R_RISCV_SET32:

              case R_RISCV_PCREL_HI20:

+            case R_RISCV_GOT_HI20:

              case R_RISCV_PCREL_LO12_I:

                break;


Tested-by: Pete Batard <p...@akeo.ie>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#77696): https://edk2.groups.io/g/devel/message/77696
Mute This Topic: https://groups.io/mt/83760258/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to