From 09e057539a861f021b03c23fa826c6788e002e8a Mon Sep 17 00:00:00 2001 From: Ming-Yi Lai Date: Tue, 20 Aug 2024 15:17:04 +0800 Subject: [PATCH] [llvm-objdump][RISCV] Display `@plt' symbols when disassembling .plt 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. --- llvm/lib/Object/ELFObjectFile.cpp | 4 ++ .../RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp | 42 ++++++++++++++++++ .../llvm-objdump/ELF/RISCV/rv32-plt.test | 44 +++++++++++++++++++ .../llvm-objdump/ELF/RISCV/rv64-plt.test | 44 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 llvm/test/tools/llvm-objdump/ELF/RISCV/rv32-plt.test create mode 100644 llvm/test/tools/llvm-objdump/ELF/RISCV/rv64-plt.test 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 #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> + findPltEntries(uint64_t PltSectionVA, ArrayRef 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> 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 : +# 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 : +# 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 +...