[lld] [LLD][RISCV][Zicfilp] Generate unlabeled landing pad-style PLT (PR #145461)
Piyou Chen via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 20:51:35 PDT 2026
https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/145461
>From 5dd098753d19b1f3abeced6cf59b72da0b710482 Mon Sep 17 00:00:00 2001
From: Ming-Yi Lai <ming-yi.lai at mediatek.com>
Date: Fri, 15 Mar 2024 17:13:26 +0800
Subject: [PATCH 1/5] [LLD][RISCV][Zicfilp] Generate unlabeled landing
pad-style PLT
To support dynamic linking when Zicfilp is enabled, lpad insns are inserted into
PLTs. This patch generates the unlabeled landing pad-style PLT, in which all the
lpads have label "0", when ZICFILP-unlabeled is enabled:
--- PLT Header:
```
lpad 0
1: auipc t2, %pcrel_hi(.got.plt)
sub t1, t1, t3 # shifted .got.plt offset + hdr size + 16
l[w|d] t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
addi t1, t1, -(hdr size + 16) # shifted .got.plt offset
addi t0, t2, %pcrel_lo(1b) # &.got.plt
srli t1, t1, log2(16/PTRSIZE) # .got.plt offset
l[w|d] t0, PTRSIZE(t0) # link map
jr t3
nop
nop
nop
```
--- PLT Entry:
```
lpad 0
1: auipc t3, %pcrel_hi(function at .got.plt)
l[w|d] t3, %pcrel_lo(1b)(t3)
jalr t1, t3
```
---
lld/ELF/Arch/RISCV.cpp | 72 +++++++++++-
lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s | 135 ++++++++++++++++++++++
2 files changed, 205 insertions(+), 2 deletions(-)
create mode 100644 lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 72d83159ad8ac..33d3fdcc60ff8 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -27,7 +27,7 @@ using namespace lld::elf;
namespace {
-class RISCV final : public TargetInfo {
+class RISCV : public TargetInfo {
public:
RISCV(Ctx &);
uint32_t calcEFlags() const override;
@@ -1065,6 +1065,66 @@ void RISCV::finalizeRelax(int passes) const {
}
}
+namespace {
+
+class RISCVCfiLpUnlabeledPLT final : public RISCV {
+public:
+ RISCVCfiLpUnlabeledPLT(Ctx &ctx);
+ void writePltHeader(uint8_t *buf) const override;
+ void writePlt(uint8_t *buf, const Symbol &sym,
+ uint64_t pltEntryAddr) const override;
+};
+
+} // namespace
+
+RISCVCfiLpUnlabeledPLT::RISCVCfiLpUnlabeledPLT(Ctx &ctx) : RISCV(ctx) {
+ pltHeaderSize = 48;
+}
+
+void RISCVCfiLpUnlabeledPLT::writePltHeader(uint8_t *buf) const {
+ // lpad 0
+ // 1: auipc t2, %pcrel_hi(.got.plt)
+ // sub t1, t1, t3
+ // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
+ // addi t1, t1, -pltHeaderSize-16; t1 = &.plt[i] - &.plt[0]
+ // addi t0, t2, %pcrel_lo(1b)
+ // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
+ // l[wd] t0, Wordsize(t0); t0 = link_map
+ // jr t3
+ // nop
+ // nop
+ // nop
+ const uint32_t offset =
+ ctx.in.gotPlt->getVA() - (ctx.in.plt->getVA() + 4 /* offset for lpad */);
+ const uint32_t load = ctx.arg.is64 ? LD : LW;
+ write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
+ write32le(buf + 4, utype(AUIPC, X_T2, hi20(offset)));
+ write32le(buf + 8, rtype(SUB, X_T1, X_T1, X_T3));
+ write32le(buf + 12, itype(load, X_T3, X_T2, lo12(offset)));
+ write32le(buf + 16, itype(ADDI, X_T1, X_T1, -ctx.target->pltHeaderSize - 16));
+ write32le(buf + 20, itype(ADDI, X_T0, X_T2, lo12(offset)));
+ write32le(buf + 24, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
+ write32le(buf + 28, itype(load, X_T0, X_T0, ctx.arg.wordsize));
+ write32le(buf + 32, itype(JALR, 0, X_T3, 0));
+ write32le(buf + 36, itype(ADDI, 0, 0, 0)); // nop
+ write32le(buf + 40, itype(ADDI, 0, 0, 0)); // nop
+ write32le(buf + 44, itype(ADDI, 0, 0, 0)); // nop
+}
+
+void RISCVCfiLpUnlabeledPLT::writePlt(uint8_t *buf, const Symbol &sym,
+ uint64_t pltEntryAddr) const {
+ // lpad 0
+ // 1: auipc t3, %pcrel_hi(f at .got.plt)
+ // l[wd] t3, %pcrel_lo(1b)(t3)
+ // jalr t1, t3
+ const uint32_t offset =
+ sym.getGotPltVA(ctx) - (pltEntryAddr + 4 /* offset for lpad */);
+ write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
+ write32le(buf + 4, utype(AUIPC, X_T3, hi20(offset)));
+ write32le(buf + 8, itype(ctx.arg.is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
+ write32le(buf + 12, itype(JALR, X_T1, X_T3, 0));
+}
+
namespace {
// Representation of the merged .riscv.attributes input sections. The psABI
// specifies merge policy for attributes. E.g. if we link an object without an
@@ -1357,4 +1417,12 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) {
mergeAttributesSection(ctx, sections));
}
-void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); }
+void elf::setRISCVTargetInfo(Ctx &ctx) {
+ RISCV *target;
+ if (ctx.arg.andFeatures & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED)
+ target = new RISCVCfiLpUnlabeledPLT(ctx);
+ else
+ target = new RISCV(ctx);
+
+ ctx.target.reset(target);
+}
diff --git a/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
new file mode 100644
index 0000000000000..4a80081ecc258
--- /dev/null
+++ b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
@@ -0,0 +1,135 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 rv32-foo.s -o foo32.o
+# RUN: ld.lld -shared foo32.o -soname=libfoo32.so -z zicfilp-unlabeled-report=error --fatal-warnings -o libfoo32.so
+# RUN: llvm-mc -filetype=obj -triple=riscv32 rv32-start.s -o start32.o
+# RUN: ld.lld start32.o libfoo32.so -z zicfilp-unlabeled-report=error --fatal-warnings -o out32
+# RUN: llvm-readelf -S out32 | FileCheck --check-prefix=SEC32 %s
+# RUN: llvm-objdump -d --no-show-raw-insn --mattr=+experimental-zicfilp out32 | FileCheck --check-prefixes=DIS,DIS32 %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 rv64-foo.s -o foo64.o
+# RUN: ld.lld -shared foo64.o -soname=libfoo64.so -z zicfilp-unlabeled-report=error --fatal-warnings -o libfoo64.so
+# RUN: llvm-mc -filetype=obj -triple=riscv64 rv64-start.s -o start64.o
+# RUN: ld.lld start64.o libfoo64.so -z zicfilp-unlabeled-report=error --fatal-warnings -o out64
+# RUN: llvm-readelf -S out64 | FileCheck --check-prefix=SEC64 %s
+# RUN: llvm-objdump -d --no-show-raw-insn --mattr=+experimental-zicfilp out64 | FileCheck --check-prefixes=DIS,DIS64 %s
+
+# SEC32: .plt PROGBITS {{0*}}00011210
+# SEC32: .got.plt PROGBITS {{0*}}000132b8
+
+# SEC64: .plt PROGBITS {{0*}}00011330
+# SEC64: .got.plt PROGBITS {{0*}}00013440
+
+# DIS: Disassembly of section .plt:
+# DIS: <.plt>:
+# DIS-NEXT: lpad 0x0
+# DIS-NEXT: auipc t2, 0x2
+# DIS-NEXT: sub t1, t1, t3
+# DIS32-NEXT: lw t3, 0xa4(t2)
+# DIS64-NEXT: ld t3, 0x10c(t2)
+# DIS-NEXT: addi t1, t1, -0x40
+# DIS32-NEXT: addi t0, t2, 0xa4
+# DIS64-NEXT: addi t0, t2, 0x10c
+# DIS32-NEXT: srli t1, t1, 0x2
+# DIS64-NEXT: srli t1, t1, 0x1
+# DIS32-NEXT: lw t0, 0x4(t0)
+# DIS64-NEXT: ld t0, 0x8(t0)
+# DIS-NEXT: jr t3
+# DIS-NEXT: nop
+# DIS-NEXT: nop
+# DIS-NEXT: nop
+
+# DIS: lpad 0x0
+# DIS-NEXT: auipc t3, 0x2
+# DIS32-NEXT: lw t3, 0x7c(t3)
+# DIS64-NEXT: ld t3, 0xec(t3)
+# DIS-NEXT: jalr t1, t3
+
+#--- rv32-start.s
+
+.section ".note.gnu.property", "a"
+.balign 4
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 4
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
+.balign 4
+ndesc_end:
+
+.text
+.global _start, foo
+
+_start:
+ call foo at plt
+
+#--- rv32-foo.s
+
+.section ".note.gnu.property", "a"
+.balign 4
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 4
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
+.balign 4
+ndesc_end:
+
+.text
+.global foo
+.type foo, @function
+foo:
+ ret
+
+#--- rv64-start.s
+
+.section ".note.gnu.property", "a"
+.balign 8
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 8
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
+.balign 8
+ndesc_end:
+
+.text
+.global _start, foo
+
+_start:
+ call foo at plt
+
+#--- rv64-foo.s
+
+.section ".note.gnu.property", "a"
+.balign 8
+.4byte 4
+.4byte (ndesc_end - ndesc_begin)
+.4byte 0x5 // NT_GNU_PROPERTY_TYPE_0
+.asciz "GNU"
+ndesc_begin:
+.balign 8
+.4byte 0xc0000000 // GNU_PROPERTY_RISCV_FEATURE_1_AND
+.4byte 4
+.4byte 1 // GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
+.balign 8
+ndesc_end:
+
+.text
+.global foo
+.type foo, @function
+foo:
+ ret
>From 063757cd81d62f43833974bac31fb982e47c17bf Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Wed, 3 Jun 2026 02:19:42 -0700
Subject: [PATCH 2/5] Align with latest PLT format
---
lld/ELF/Arch/RISCV.cpp | 54 ++++++++++-------------
lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s | 26 +++++------
2 files changed, 34 insertions(+), 46 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 33d3fdcc60ff8..883b3f4f39c1d 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1082,47 +1082,39 @@ RISCVCfiLpUnlabeledPLT::RISCVCfiLpUnlabeledPLT(Ctx &ctx) : RISCV(ctx) {
}
void RISCVCfiLpUnlabeledPLT::writePltHeader(uint8_t *buf) const {
- // lpad 0
- // 1: auipc t2, %pcrel_hi(.got.plt)
- // sub t1, t1, t3
- // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
- // addi t1, t1, -pltHeaderSize-16; t1 = &.plt[i] - &.plt[0]
- // addi t0, t2, %pcrel_lo(1b)
- // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
- // l[wd] t0, Wordsize(t0); t0 = link_map
- // jr t3
- // nop
- // nop
- // nop
+ // 1: auipc t3, %pcrel_hi(.got.plt)
+ // sub t1, t1, t2
+ // l[w|d] t2, %pcrel_lo(1b)(t3)
+ // addi t1, t1, -(hdr size + 16)
+ // addi t0, t3, %pcrel_lo(1b)
+ // srli t1, t1, log2(16/PTRSIZE)
+ // l[w|d] t0, PTRSIZE(t0)
+ // jr t2
const uint32_t offset =
ctx.in.gotPlt->getVA() - (ctx.in.plt->getVA() + 4 /* offset for lpad */);
const uint32_t load = ctx.arg.is64 ? LD : LW;
- write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
- write32le(buf + 4, utype(AUIPC, X_T2, hi20(offset)));
- write32le(buf + 8, rtype(SUB, X_T1, X_T1, X_T3));
- write32le(buf + 12, itype(load, X_T3, X_T2, lo12(offset)));
- write32le(buf + 16, itype(ADDI, X_T1, X_T1, -ctx.target->pltHeaderSize - 16));
- write32le(buf + 20, itype(ADDI, X_T0, X_T2, lo12(offset)));
- write32le(buf + 24, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
- write32le(buf + 28, itype(load, X_T0, X_T0, ctx.arg.wordsize));
- write32le(buf + 32, itype(JALR, 0, X_T3, 0));
- write32le(buf + 36, itype(ADDI, 0, 0, 0)); // nop
- write32le(buf + 40, itype(ADDI, 0, 0, 0)); // nop
- write32le(buf + 44, itype(ADDI, 0, 0, 0)); // nop
+ write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
+ write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T2));
+ write32le(buf + 8, itype(load, X_T2, X_T3, lo12(offset)));
+ write32le(buf + 12, itype(ADDI, X_T1, X_T1, -ctx.target->pltHeaderSize - 16));
+ write32le(buf + 16, itype(ADDI, X_T0, X_T3, lo12(offset)));
+ write32le(buf + 20, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
+ write32le(buf + 24, itype(load, X_T0, X_T0, ctx.arg.is64 ? 8 : 4));
+ write32le(buf + 28, itype(JALR, 0, X_T2, 0));
}
void RISCVCfiLpUnlabeledPLT::writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const {
- // lpad 0
- // 1: auipc t3, %pcrel_hi(f at .got.plt)
- // l[wd] t3, %pcrel_lo(1b)(t3)
- // jalr t1, t3
+ // lpad 0
+ // 1: auipc t2, %pcrel_hi(function at .got.plt)
+ // l[w|d] t2, %pcrel_lo(1b)(t2)
+ // jalr t1, t2
const uint32_t offset =
sym.getGotPltVA(ctx) - (pltEntryAddr + 4 /* offset for lpad */);
write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
- write32le(buf + 4, utype(AUIPC, X_T3, hi20(offset)));
- write32le(buf + 8, itype(ctx.arg.is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
- write32le(buf + 12, itype(JALR, X_T1, X_T3, 0));
+ write32le(buf + 4, utype(AUIPC, X_T2, hi20(offset)));
+ write32le(buf + 8, itype(ctx.arg.is64 ? LD : LW, X_T2, X_T2, lo12(offset)));
+ write32le(buf + 12, itype(JALR, X_T1, X_T2, 0));
}
namespace {
diff --git a/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
index 4a80081ecc258..87317eddf48b0 100644
--- a/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
+++ b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
@@ -23,28 +23,24 @@
# DIS: Disassembly of section .plt:
# DIS: <.plt>:
-# DIS-NEXT: lpad 0x0
-# DIS-NEXT: auipc t2, 0x2
-# DIS-NEXT: sub t1, t1, t3
-# DIS32-NEXT: lw t3, 0xa4(t2)
-# DIS64-NEXT: ld t3, 0x10c(t2)
+# DIS-NEXT: auipc t3, 0x2
+# DIS-NEXT: sub t1, t1, t2
+# DIS32-NEXT: lw t2, 0xa4(t3)
+# DIS64-NEXT: ld t2, 0x10c(t3)
# DIS-NEXT: addi t1, t1, -0x40
-# DIS32-NEXT: addi t0, t2, 0xa4
-# DIS64-NEXT: addi t0, t2, 0x10c
+# DIS32-NEXT: addi t0, t3, 0xa4
+# DIS64-NEXT: addi t0, t3, 0x10c
# DIS32-NEXT: srli t1, t1, 0x2
# DIS64-NEXT: srli t1, t1, 0x1
# DIS32-NEXT: lw t0, 0x4(t0)
# DIS64-NEXT: ld t0, 0x8(t0)
-# DIS-NEXT: jr t3
-# DIS-NEXT: nop
-# DIS-NEXT: nop
-# DIS-NEXT: nop
+# DIS-NEXT: jr t2
# DIS: lpad 0x0
-# DIS-NEXT: auipc t3, 0x2
-# DIS32-NEXT: lw t3, 0x7c(t3)
-# DIS64-NEXT: ld t3, 0xec(t3)
-# DIS-NEXT: jalr t1, t3
+# DIS-NEXT: auipc t2, 0x2
+# DIS32-NEXT: lw t2, 0x7c(t2)
+# DIS64-NEXT: ld t2, 0xec(t2)
+# DIS-NEXT: jalr t1, t2
#--- rv32-start.s
>From b0b466e2b2959e750543d0ba07dd6ac21c123424 Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Wed, 3 Jun 2026 02:39:50 -0700
Subject: [PATCH 3/5] !fixup drop the new class
---
lld/ELF/Arch/RISCV.cpp | 102 +++++++++-------------
lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s | 14 +--
2 files changed, 48 insertions(+), 68 deletions(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 883b3f4f39c1d..1b1c7cd0e3c31 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -222,6 +222,31 @@ void RISCV::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
}
void RISCV::writePltHeader(uint8_t *buf) const {
+
+ if (ctx.arg.andFeatures & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) {
+ // 1: auipc t3, %pcrel_hi(.got.plt)
+ // sub t1, t1, t2
+ // l[w|d] t2, %pcrel_lo(1b)(t3)
+ // addi t1, t1, -(hdr size + 16)
+ // addi t0, t3, %pcrel_lo(1b)
+ // srli t1, t1, log2(16/PTRSIZE)
+ // l[w|d] t0, PTRSIZE(t0)
+ // jr t2
+ const uint32_t offset = ctx.in.gotPlt->getVA() -
+ (ctx.in.plt->getVA() + 4 /* offset for lpad */);
+ const uint32_t load = ctx.arg.is64 ? LD : LW;
+ write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
+ write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T2));
+ write32le(buf + 8, itype(load, X_T2, X_T3, lo12(offset)));
+ write32le(buf + 12,
+ itype(ADDI, X_T1, X_T1, -ctx.target->pltHeaderSize - 16));
+ write32le(buf + 16, itype(ADDI, X_T0, X_T3, lo12(offset)));
+ write32le(buf + 20, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
+ write32le(buf + 24, itype(load, X_T0, X_T0, ctx.arg.is64 ? 8 : 4));
+ write32le(buf + 28, itype(JALR, 0, X_T2, 0));
+ return;
+ }
+
// 1: auipc t2, %pcrel_hi(.got.plt)
// sub t1, t1, t3
// l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
@@ -244,6 +269,21 @@ void RISCV::writePltHeader(uint8_t *buf) const {
void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const {
+
+ if (ctx.arg.andFeatures & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) {
+ // lpad 0
+ // 1: auipc t2, %pcrel_hi(function at .got.plt)
+ // l[w|d] t2, %pcrel_lo(1b)(t2)
+ // jalr t1, t2
+ const uint32_t offset =
+ sym.getGotPltVA(ctx) - (pltEntryAddr + 4 /* offset for lpad */);
+ write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
+ write32le(buf + 4, utype(AUIPC, X_T2, hi20(offset)));
+ write32le(buf + 8, itype(ctx.arg.is64 ? LD : LW, X_T2, X_T2, lo12(offset)));
+ write32le(buf + 12, itype(JALR, X_T1, X_T2, 0));
+ return;
+ }
+
// 1: auipc t3, %pcrel_hi(f at .got.plt)
// l[wd] t3, %pcrel_lo(1b)(t3)
// jalr t1, t3
@@ -1065,58 +1105,6 @@ void RISCV::finalizeRelax(int passes) const {
}
}
-namespace {
-
-class RISCVCfiLpUnlabeledPLT final : public RISCV {
-public:
- RISCVCfiLpUnlabeledPLT(Ctx &ctx);
- void writePltHeader(uint8_t *buf) const override;
- void writePlt(uint8_t *buf, const Symbol &sym,
- uint64_t pltEntryAddr) const override;
-};
-
-} // namespace
-
-RISCVCfiLpUnlabeledPLT::RISCVCfiLpUnlabeledPLT(Ctx &ctx) : RISCV(ctx) {
- pltHeaderSize = 48;
-}
-
-void RISCVCfiLpUnlabeledPLT::writePltHeader(uint8_t *buf) const {
- // 1: auipc t3, %pcrel_hi(.got.plt)
- // sub t1, t1, t2
- // l[w|d] t2, %pcrel_lo(1b)(t3)
- // addi t1, t1, -(hdr size + 16)
- // addi t0, t3, %pcrel_lo(1b)
- // srli t1, t1, log2(16/PTRSIZE)
- // l[w|d] t0, PTRSIZE(t0)
- // jr t2
- const uint32_t offset =
- ctx.in.gotPlt->getVA() - (ctx.in.plt->getVA() + 4 /* offset for lpad */);
- const uint32_t load = ctx.arg.is64 ? LD : LW;
- write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
- write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T2));
- write32le(buf + 8, itype(load, X_T2, X_T3, lo12(offset)));
- write32le(buf + 12, itype(ADDI, X_T1, X_T1, -ctx.target->pltHeaderSize - 16));
- write32le(buf + 16, itype(ADDI, X_T0, X_T3, lo12(offset)));
- write32le(buf + 20, itype(SRLI, X_T1, X_T1, ctx.arg.is64 ? 1 : 2));
- write32le(buf + 24, itype(load, X_T0, X_T0, ctx.arg.is64 ? 8 : 4));
- write32le(buf + 28, itype(JALR, 0, X_T2, 0));
-}
-
-void RISCVCfiLpUnlabeledPLT::writePlt(uint8_t *buf, const Symbol &sym,
- uint64_t pltEntryAddr) const {
- // lpad 0
- // 1: auipc t2, %pcrel_hi(function at .got.plt)
- // l[w|d] t2, %pcrel_lo(1b)(t2)
- // jalr t1, t2
- const uint32_t offset =
- sym.getGotPltVA(ctx) - (pltEntryAddr + 4 /* offset for lpad */);
- write32le(buf + 0, utype(AUIPC, 0, 0)); // lpad 0
- write32le(buf + 4, utype(AUIPC, X_T2, hi20(offset)));
- write32le(buf + 8, itype(ctx.arg.is64 ? LD : LW, X_T2, X_T2, lo12(offset)));
- write32le(buf + 12, itype(JALR, X_T1, X_T2, 0));
-}
-
namespace {
// Representation of the merged .riscv.attributes input sections. The psABI
// specifies merge policy for attributes. E.g. if we link an object without an
@@ -1409,12 +1397,4 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) {
mergeAttributesSection(ctx, sections));
}
-void elf::setRISCVTargetInfo(Ctx &ctx) {
- RISCV *target;
- if (ctx.arg.andFeatures & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED)
- target = new RISCVCfiLpUnlabeledPLT(ctx);
- else
- target = new RISCV(ctx);
-
- ctx.target.reset(target);
-}
+void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); }
diff --git a/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
index 87317eddf48b0..347975c81b2a2 100644
--- a/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
+++ b/lld/test/ELF/riscv-plt-cfi-lp-unlabeled.s
@@ -16,20 +16,20 @@
# RUN: llvm-objdump -d --no-show-raw-insn --mattr=+experimental-zicfilp out64 | FileCheck --check-prefixes=DIS,DIS64 %s
# SEC32: .plt PROGBITS {{0*}}00011210
-# SEC32: .got.plt PROGBITS {{0*}}000132b8
+# SEC32: .got.plt PROGBITS {{0*}}000132a8
# SEC64: .plt PROGBITS {{0*}}00011330
-# SEC64: .got.plt PROGBITS {{0*}}00013440
+# SEC64: .got.plt PROGBITS {{0*}}00013430
# DIS: Disassembly of section .plt:
# DIS: <.plt>:
# DIS-NEXT: auipc t3, 0x2
# DIS-NEXT: sub t1, t1, t2
-# DIS32-NEXT: lw t2, 0xa4(t3)
-# DIS64-NEXT: ld t2, 0x10c(t3)
-# DIS-NEXT: addi t1, t1, -0x40
-# DIS32-NEXT: addi t0, t3, 0xa4
-# DIS64-NEXT: addi t0, t3, 0x10c
+# DIS32-NEXT: lw t2, 0x94(t3)
+# DIS64-NEXT: ld t2, 0xfc(t3)
+# DIS-NEXT: addi t1, t1, -0x30
+# DIS32-NEXT: addi t0, t3, 0x94
+# DIS64-NEXT: addi t0, t3, 0xfc
# DIS32-NEXT: srli t1, t1, 0x2
# DIS64-NEXT: srli t1, t1, 0x1
# DIS32-NEXT: lw t0, 0x4(t0)
>From e80ea64cf51b565d68df33cb32e4a556fac3a82f Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Wed, 3 Jun 2026 18:46:51 -0700
Subject: [PATCH 4/5] !fixup restore final
---
lld/ELF/Arch/RISCV.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 1b1c7cd0e3c31..c6443b68b318a 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -27,7 +27,7 @@ using namespace lld::elf;
namespace {
-class RISCV : public TargetInfo {
+class RISCV final : public TargetInfo {
public:
RISCV(Ctx &);
uint32_t calcEFlags() const override;
>From 958a7b5290e58a13e9c1c76a8f34423432a1e2f6 Mon Sep 17 00:00:00 2001
From: Piyou Chen <gccbg04538 at gmail.com>
Date: Thu, 4 Jun 2026 11:51:25 +0800
Subject: [PATCH 5/5] Apply suggestion from @kito-cheng
Co-authored-by: Kito Cheng <npickito at gmail.com>
---
lld/ELF/Arch/RISCV.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index c6443b68b318a..9f5af38a9a46c 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -233,7 +233,8 @@ void RISCV::writePltHeader(uint8_t *buf) const {
// l[w|d] t0, PTRSIZE(t0)
// jr t2
const uint32_t offset = ctx.in.gotPlt->getVA() -
- (ctx.in.plt->getVA() + 4 /* offset for lpad */);
+ const uint32_t offset = ctx.in.gotPlt->getVA() -
+ ctx.in.plt->getVA();
const uint32_t load = ctx.arg.is64 ? LD : LW;
write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T2));
More information about the llvm-commits
mailing list