Skip to content

[llvm-objdump][RISCV] Display `@plt' symbols when disassembling .plt section #147933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mylai-mtk
Copy link
Contributor

This patch adds dummy symbols for PLT entries for RISC-V 32-bit and 64-bit targets so llvm-objdump can show the function symbol that corresponds to each PLT entry.

…section

This patch adds dummy symbols for PLT entries for RISC-V 32-bit and 64-bit
targets so llvm-objdump can show the function symbol that corresponds to each
PLT entry.
@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Ming-Yi Lai (mylai-mtk)

Changes

This patch adds dummy symbols for PLT entries for RISC-V 32-bit and 64-bit targets so llvm-objdump can show the function symbol that corresponds to each PLT entry.


Full diff: https://github.com/llvm/llvm-project/pull/147933.diff

4 Files Affected:

  • (modified) llvm/lib/Object/ELFObjectFile.cpp (+4)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp (+42)
  • (added) llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test (+44)
  • (added) llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test (+44)
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index 0e13d32bbe522..5597d7db6426d 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -810,6 +810,10 @@ ELFObjectFileBase::getPltEntries(const MCSubtargetInfo &STI) const {
       JumpSlotReloc = ELF::R_HEX_JMP_SLOT;
       GlobDatReloc = ELF::R_HEX_GLOB_DAT;
       break;
+    case Triple::riscv32:
+    case Triple::riscv64:
+      JumpSlotReloc = ELF::R_RISCV_JUMP_SLOT;
+      break;
     default:
       return {};
   }
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
index f66c2d5f99cb3..61ecfb278a7d3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -30,6 +30,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
 #include <bitset>
 
 #define GET_INSTRINFO_MC_DESC
@@ -305,6 +306,47 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
     }
   }
 
+  /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries.
+  std::vector<std::pair<uint64_t, uint64_t>>
+  findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
+                 const MCSubtargetInfo &STI) const override {
+    uint32_t LoadInsnOpCode;
+    if (const Triple &T = STI.getTargetTriple(); T.isRISCV64())
+      LoadInsnOpCode = 0x3003; // ld
+    else if (T.isRISCV32())
+      LoadInsnOpCode = 0x2003; // lw
+    else
+      return {};
+
+    constexpr uint64_t FirstEntryAt = 32, EntrySize = 16;
+    if (PltContents.size() < FirstEntryAt + EntrySize)
+      return {};
+
+    std::vector<std::pair<uint64_t, uint64_t>> Results;
+    for (uint64_t EntryStart = FirstEntryAt,
+                  EntryStartEnd = PltContents.size() - EntrySize;
+         EntryStart <= EntryStartEnd; EntryStart += EntrySize) {
+      const uint32_t AuipcInsn =
+          support::endian::read32le(PltContents.data() + EntryStart);
+      const bool IsAuipc = (AuipcInsn & 0x7F) == 0x17;
+      if (!IsAuipc)
+        continue;
+
+      const uint32_t LoadInsn =
+          support::endian::read32le(PltContents.data() + EntryStart + 4);
+      const bool IsLoad = (LoadInsn & 0x707F) == LoadInsnOpCode;
+      if (!IsLoad)
+        continue;
+
+      const uint64_t GotPltSlotVA = PltSectionVA + EntryStart +
+                                    (AuipcInsn & 0xFFFFF000) +
+                                    SignExtend64<12>(LoadInsn >> 20);
+      Results.emplace_back(PltSectionVA + EntryStart, GotPltSlotVA);
+    }
+
+    return Results;
+  }
+
 private:
   static bool maybeReturnAddress(MCRegister Reg) {
     // X1 is used for normal returns, X5 for returns from outlined functions.
diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test
new file mode 100644
index 0000000000000..2160dc77fdc09
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test
@@ -0,0 +1,44 @@
+# RUN: yaml2obj %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
+
+# CHECK:      00001470 <strcmp@plt>:
+# CHECK-NEXT:     1470:       auipc   t3, 0x2
+# CHECK-NEXT:     1474:       lw      t3, 0xfc(t3)
+# CHECK-NEXT:     1478:       jalr    t1, t3
+# CHECK-NEXT:     147c:       nop
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
+Sections:
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x290
+    Link:            .dynsym
+    AddressAlign:    0x4
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x356C
+        Symbol:          strcmp
+        Type:            R_RISCV_JUMP_SLOT
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1450
+    AddressAlign:    0x10
+    Content:         972300003303C34103AE4311130343FD938243111353230083A2420067000E00172E0000032ECE0F67030E0013000000
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x3564
+    AddressAlign:    0x4
+    Content:         '000000000000000050140000'
+DynamicSymbols:
+  - Name:            strcmp
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+...
diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test
new file mode 100644
index 0000000000000..a6ecbf4a0a33f
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test
@@ -0,0 +1,44 @@
+# RUN: yaml2obj %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
+
+# CHECK:      0000000000001630 <strcmp@plt>:
+# CHECK-NEXT:     1630:       auipc   t3, 0x2
+# CHECK-NEXT:     1634:       ld      t3, 0x1b8(t3)
+# CHECK-NEXT:     1638:       jalr    t1, t3
+# CHECK-NEXT:     163c:       nop
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
+Sections:
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x408
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x37E8
+        Symbol:          strcmp
+        Type:            R_RISCV_JUMP_SLOT
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1610
+    AddressAlign:    0x10
+    Content:         972300003303C34103BE831C130343FD9382831C1353130083B2820067000E00172E0000033E8E1B67030E0013000000
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x37D8
+    AddressAlign:    0x8
+    Content:         '000000000000000000000000000000001016000000000000'
+DynamicSymbols:
+  - Name:            strcmp
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+...

@llvmbot
Copy link
Member

llvmbot commented Jul 10, 2025

@llvm/pr-subscribers-llvm-binary-utilities

Author: Ming-Yi Lai (mylai-mtk)

Changes

This patch adds dummy symbols for PLT entries for RISC-V 32-bit and 64-bit targets so llvm-objdump can show the function symbol that corresponds to each PLT entry.


Full diff: https://github.com/llvm/llvm-project/pull/147933.diff

4 Files Affected:

  • (modified) llvm/lib/Object/ELFObjectFile.cpp (+4)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp (+42)
  • (added) llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test (+44)
  • (added) llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test (+44)
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index 0e13d32bbe522..5597d7db6426d 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -810,6 +810,10 @@ ELFObjectFileBase::getPltEntries(const MCSubtargetInfo &STI) const {
       JumpSlotReloc = ELF::R_HEX_JMP_SLOT;
       GlobDatReloc = ELF::R_HEX_GLOB_DAT;
       break;
+    case Triple::riscv32:
+    case Triple::riscv64:
+      JumpSlotReloc = ELF::R_RISCV_JUMP_SLOT;
+      break;
     default:
       return {};
   }
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
index f66c2d5f99cb3..61ecfb278a7d3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -30,6 +30,7 @@
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
 #include <bitset>
 
 #define GET_INSTRINFO_MC_DESC
@@ -305,6 +306,47 @@ class RISCVMCInstrAnalysis : public MCInstrAnalysis {
     }
   }
 
+  /// Returns (PLT virtual address, GOT virtual address) pairs for PLT entries.
+  std::vector<std::pair<uint64_t, uint64_t>>
+  findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
+                 const MCSubtargetInfo &STI) const override {
+    uint32_t LoadInsnOpCode;
+    if (const Triple &T = STI.getTargetTriple(); T.isRISCV64())
+      LoadInsnOpCode = 0x3003; // ld
+    else if (T.isRISCV32())
+      LoadInsnOpCode = 0x2003; // lw
+    else
+      return {};
+
+    constexpr uint64_t FirstEntryAt = 32, EntrySize = 16;
+    if (PltContents.size() < FirstEntryAt + EntrySize)
+      return {};
+
+    std::vector<std::pair<uint64_t, uint64_t>> Results;
+    for (uint64_t EntryStart = FirstEntryAt,
+                  EntryStartEnd = PltContents.size() - EntrySize;
+         EntryStart <= EntryStartEnd; EntryStart += EntrySize) {
+      const uint32_t AuipcInsn =
+          support::endian::read32le(PltContents.data() + EntryStart);
+      const bool IsAuipc = (AuipcInsn & 0x7F) == 0x17;
+      if (!IsAuipc)
+        continue;
+
+      const uint32_t LoadInsn =
+          support::endian::read32le(PltContents.data() + EntryStart + 4);
+      const bool IsLoad = (LoadInsn & 0x707F) == LoadInsnOpCode;
+      if (!IsLoad)
+        continue;
+
+      const uint64_t GotPltSlotVA = PltSectionVA + EntryStart +
+                                    (AuipcInsn & 0xFFFFF000) +
+                                    SignExtend64<12>(LoadInsn >> 20);
+      Results.emplace_back(PltSectionVA + EntryStart, GotPltSlotVA);
+    }
+
+    return Results;
+  }
+
 private:
   static bool maybeReturnAddress(MCRegister Reg) {
     // X1 is used for normal returns, X5 for returns from outlined functions.
diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test
new file mode 100644
index 0000000000000..2160dc77fdc09
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test
@@ -0,0 +1,44 @@
+# RUN: yaml2obj %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
+
+# CHECK:      00001470 <strcmp@plt>:
+# CHECK-NEXT:     1470:       auipc   t3, 0x2
+# CHECK-NEXT:     1474:       lw      t3, 0xfc(t3)
+# CHECK-NEXT:     1478:       jalr    t1, t3
+# CHECK-NEXT:     147c:       nop
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
+Sections:
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x290
+    Link:            .dynsym
+    AddressAlign:    0x4
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x356C
+        Symbol:          strcmp
+        Type:            R_RISCV_JUMP_SLOT
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1450
+    AddressAlign:    0x10
+    Content:         972300003303C34103AE4311130343FD938243111353230083A2420067000E00172E0000032ECE0F67030E0013000000
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x3564
+    AddressAlign:    0x4
+    Content:         '000000000000000050140000'
+DynamicSymbols:
+  - Name:            strcmp
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+...
diff --git a/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test
new file mode 100644
index 0000000000000..a6ecbf4a0a33f
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test
@@ -0,0 +1,44 @@
+# RUN: yaml2obj %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
+
+# CHECK:      0000000000001630 <strcmp@plt>:
+# CHECK-NEXT:     1630:       auipc   t3, 0x2
+# CHECK-NEXT:     1634:       ld      t3, 0x1b8(t3)
+# CHECK-NEXT:     1638:       jalr    t1, t3
+# CHECK-NEXT:     163c:       nop
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_DYN
+  Machine:         EM_RISCV
+  Flags:           [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_DOUBLE ]
+Sections:
+  - Name:            .rela.plt
+    Type:            SHT_RELA
+    Flags:           [ SHF_ALLOC, SHF_INFO_LINK ]
+    Address:         0x408
+    Link:            .dynsym
+    AddressAlign:    0x8
+    Info:            .got.plt
+    Relocations:
+      - Offset:          0x37E8
+        Symbol:          strcmp
+        Type:            R_RISCV_JUMP_SLOT
+  - Name:            .plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1610
+    AddressAlign:    0x10
+    Content:         972300003303C34103BE831C130343FD9382831C1353130083B2820067000E00172E0000033E8E1B67030E0013000000
+  - Name:            .got.plt
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x37D8
+    AddressAlign:    0x8
+    Content:         '000000000000000000000000000000001016000000000000'
+DynamicSymbols:
+  - Name:            strcmp
+    Type:            STT_FUNC
+    Binding:         STB_GLOBAL
+...

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants