[Lldb-commits] [lld] [lldb] [llvm] [X86] Add dynamic section support per psABI (PR #206002)
Phoebe Wang via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 26 01:35:25 PDT 2026
https://github.com/phoebewang updated https://github.com/llvm/llvm-project/pull/206002
>From 0892425b2582788a8937655cfa739863034b978b Mon Sep 17 00:00:00 2001
From: Phoebe Wang <phoebe.wang at intel.com>
Date: Fri, 26 Jun 2026 15:45:06 +0800
Subject: [PATCH 1/2] [X86] Add dynamic section support per psABI
Add option [no]mark-plt to enable it. Dynamic linker can change PLT
entries with JMPABS instruction on supported targets.
---
lld/ELF/Config.h | 1 +
lld/ELF/Driver.cpp | 1 +
lld/ELF/Relocations.cpp | 10 ++++-
lld/ELF/SyntheticSections.cpp | 7 ++++
lld/test/ELF/x86-64-mark-plt.s | 37 +++++++++++++++++++
.../include/llvm/BinaryFormat/DynamicTags.def | 19 ++++++++++
llvm/lib/Object/ELF.cpp | 22 +++++++++++
7 files changed, 96 insertions(+), 1 deletion(-)
create mode 100644 lld/test/ELF/x86-64-mark-plt.s
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 12b16ded61fca..d6590ab284e5b 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -439,6 +439,7 @@ struct Config {
bool zKeepDataSectionPrefix;
bool zKeepTextSectionPrefix;
bool zLrodataAfterBss;
+ bool zMarkPlt;
bool zNoBtCfi;
bool zNodefaultlib;
bool zNodelete;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7ec7dfcae6bca..c41991e377832 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1657,6 +1657,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
ctx.arg.zLrodataAfterBss =
getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false);
+ ctx.arg.zMarkPlt = getZFlag(args, "mark-plt", "nomark-plt", false);
ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi");
ctx.arg.zNodefaultlib = hasZOption(args, "nodefaultlib");
ctx.arg.zNodelete = hasZOption(args, "nodelete");
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 0d45236e6d11e..b8aac5b5b63f4 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -749,9 +749,17 @@ static void addPltEntry(Ctx &ctx, PltSection &plt, GotPltSection &gotPlt,
RelocationBaseSection &rel, RelType type, Symbol &sym) {
plt.addEntry(sym);
gotPlt.addEntry(sym);
+ // The x86-64 psABI requires the r_addend of R_X86_64_JUMP_SLOT to hold the
+ // link-time VA of the PLT entry so that the dynamic linker can locate the
+ // indirect branch (l->l_addr + r_addend) and rewrite it to a direct branch
+ // when -z mark-plt is active.
+ RelExpr addendExpr = R_ADDEND;
+ if (ctx.arg.emachine == EM_X86_64 && ctx.arg.zMarkPlt &&
+ type == ctx.target->pltRel)
+ addendExpr = R_PLT;
if (sym.isPreemptible)
rel.addReloc(
- {type, &gotPlt, sym.getGotPltOffset(ctx), true, sym, 0, R_ADDEND});
+ {type, &gotPlt, sym.getGotPltOffset(ctx), true, sym, 0, addendExpr});
else
rel.addReloc(
{type, &gotPlt, sym.getGotPltOffset(ctx), false, sym, 0, R_ABS});
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b9a42590dc8e7..ac417e160f31d 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1318,6 +1318,13 @@ DynamicSection<ELFT>::computeContents() {
addInt(DT_PLTREL, ctx.arg.isRela ? DT_RELA : DT_REL);
}
+ if (ctx.arg.emachine == EM_X86_64 && ctx.arg.zMarkPlt &&
+ ctx.in.plt->isNeeded()) {
+ addInSec(DT_X86_64_PLT, *ctx.in.plt);
+ addInt(DT_X86_64_PLTSZ, ctx.in.plt->getSize());
+ addInt(DT_X86_64_PLTENT, ctx.target->pltEntrySize);
+ }
+
if (ctx.arg.emachine == EM_AARCH64) {
if (ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
addInt(DT_AARCH64_BTI_PLT, 0);
diff --git a/lld/test/ELF/x86-64-mark-plt.s b/lld/test/ELF/x86-64-mark-plt.s
new file mode 100644
index 0000000000000..e177c64ee418f
--- /dev/null
+++ b/lld/test/ELF/x86-64-mark-plt.s
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/shared.s -o %t2.o
+# RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so
+
+## -z mark-plt emits DT_X86_64_PLT, DT_X86_64_PLTSZ, DT_X86_64_PLTENT.
+## PLT layout: 16-byte header + 1 entry * 16 bytes = 0x20 bytes total.
+# RUN: ld.lld %t.o %t2.so -z mark-plt -z now -o %t
+# RUN: llvm-readelf --dynamic-table %t | FileCheck %s --check-prefix=MARK
+# RUN: llvm-readelf --relocs %t | FileCheck %s --check-prefix=RELA
+
+## Without -z mark-plt: no tags and zero addend on JUMP_SLOT.
+# RUN: ld.lld %t.o %t2.so -z now -o %t.nomark
+# RUN: llvm-readelf --dynamic-table %t.nomark | FileCheck %s --check-prefix=NOMARK
+# RUN: llvm-readelf --relocs %t.nomark | FileCheck %s --check-prefix=NORELA
+
+## -z mark-plt also works for shared libraries.
+# RUN: ld.lld -shared %t.o %t2.so -z mark-plt -z now -o %t.so
+# RUN: llvm-readelf --dynamic-table %t.so | FileCheck %s --check-prefix=MARK
+
+# MARK: 0x0000000070000000 (X86_64_PLT) {{0x[0-9a-f]+}}
+# MARK: 0x0000000070000001 (X86_64_PLTSZ) 0x20
+# MARK: 0x0000000070000003 (X86_64_PLTENT) 0x10
+
+# NOMARK-NOT: (X86_64_PLT)
+# NOMARK-NOT: (X86_64_PLTSZ)
+# NOMARK-NOT: (X86_64_PLTENT)
+
+## With -z mark-plt, R_X86_64_JUMP_SLOT addend is the PLT entry VA (non-zero).
+# RELA: R_X86_64_JUMP_SLOT {{.*}} bar + {{[1-9a-f][0-9a-f]+}}
+
+## Without -z mark-plt, R_X86_64_JUMP_SLOT addend is 0.
+# NORELA: R_X86_64_JUMP_SLOT {{.*}} bar + 0
+
+.globl _start
+_start:
+ call bar at plt
diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def
index 1e9b87e1e58a7..c700044920575 100644
--- a/llvm/include/llvm/BinaryFormat/DynamicTags.def
+++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def
@@ -41,6 +41,11 @@
#define SPARC_DYNAMIC_TAG_DEFINED
#endif
+#ifndef X86_64_DYNAMIC_TAG
+#define X86_64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value)
+#define X86_64_DYNAMIC_TAG_DEFINED
+#endif
+
#ifndef DYNAMIC_TAG_MARKER
#define DYNAMIC_TAG_MARKER(name, value) DYNAMIC_TAG(name, value)
#define DYNAMIC_TAG_MARKER_DEFINED
@@ -248,6 +253,12 @@ RISCV_DYNAMIC_TAG(RISCV_VARIANT_CC, 0x70000001)
SPARC_DYNAMIC_TAG(SPARC_REGISTER, 0x70000001)
+// x86-64 specific dynamic table entry tags.
+
+X86_64_DYNAMIC_TAG(X86_64_PLT, 0x70000000) // Address of PLT table.
+X86_64_DYNAMIC_TAG(X86_64_PLTSZ, 0x70000001) // Size of PLT table in bytes.
+X86_64_DYNAMIC_TAG(X86_64_PLTENT, 0x70000003) // Size of a PLT entry in bytes.
+
// Sun machine-independent extensions.
DYNAMIC_TAG(AUXILIARY, 0x7FFFFFFD) // Shared object to load before self
DYNAMIC_TAG(USED, 0x7FFFFFFE) // Same as DT_NEEDED
@@ -282,3 +293,11 @@ DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from
#undef RISCV_DYNAMIC_TAG
#undef RISCV_DYNAMIC_TAG_DEFINED
#endif
+#ifdef SPARC_DYNAMIC_TAG_DEFINED
+#undef SPARC_DYNAMIC_TAG
+#undef SPARC_DYNAMIC_TAG_DEFINED
+#endif
+#ifdef X86_64_DYNAMIC_TAG_DEFINED
+#undef X86_64_DYNAMIC_TAG
+#undef X86_64_DYNAMIC_TAG_DEFINED
+#endif
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index f159fd82e7117..48dd225932ba8 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -588,6 +588,24 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#undef RISCV_DYNAMIC_TAG
}
break;
+
+ case ELF::EM_SPARC:
+ case ELF::EM_SPARC32PLUS:
+ case ELF::EM_SPARCV9:
+ switch (Type) {
+#define SPARC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef SPARC_DYNAMIC_TAG
+ }
+ break;
+
+ case ELF::EM_X86_64:
+ switch (Type) {
+#define X86_64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef X86_64_DYNAMIC_TAG
+ }
+ break;
}
#undef DYNAMIC_TAG
switch (Type) {
@@ -598,6 +616,8 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#define PPC_DYNAMIC_TAG(name, value)
#define PPC64_DYNAMIC_TAG(name, value)
#define RISCV_DYNAMIC_TAG(name, value)
+#define SPARC_DYNAMIC_TAG(name, value)
+#define X86_64_DYNAMIC_TAG(name, value)
// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
#define DYNAMIC_TAG_MARKER(name, value)
#define DYNAMIC_TAG(name, value) case value: return #name;
@@ -609,6 +629,8 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch,
#undef PPC_DYNAMIC_TAG
#undef PPC64_DYNAMIC_TAG
#undef RISCV_DYNAMIC_TAG
+#undef SPARC_DYNAMIC_TAG
+#undef X86_64_DYNAMIC_TAG
#undef DYNAMIC_TAG_MARKER
#undef DYNAMIC_STRINGIFY_ENUM
default:
>From d16048a10dbca3492448bff3052734ae2f9bfe1e Mon Sep 17 00:00:00 2001
From: Phoebe Wang <phoebe.wang at intel.com>
Date: Fri, 26 Jun 2026 16:35:01 +0800
Subject: [PATCH 2/2] Fix lldb failure
---
.../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 16dd2fc122906..f343939ad115f 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -3800,6 +3800,24 @@ std::string static getDynamicTagAsString(uint16_t Arch, uint64_t Type) {
#undef RISCV_DYNAMIC_TAG
}
break;
+
+ case llvm::ELF::EM_SPARC:
+ case llvm::ELF::EM_SPARC32PLUS:
+ case llvm::ELF::EM_SPARCV9:
+ switch (Type) {
+#define SPARC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef SPARC_DYNAMIC_TAG
+ }
+ break;
+
+ case llvm::ELF::EM_X86_64:
+ switch (Type) {
+#define X86_64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value)
+#include "llvm/BinaryFormat/DynamicTags.def"
+#undef X86_64_DYNAMIC_TAG
+ }
+ break;
}
#undef DYNAMIC_TAG
switch (Type) {
@@ -3810,6 +3828,8 @@ std::string static getDynamicTagAsString(uint16_t Arch, uint64_t Type) {
#define PPC_DYNAMIC_TAG(name, value)
#define PPC64_DYNAMIC_TAG(name, value)
#define RISCV_DYNAMIC_TAG(name, value)
+#define SPARC_DYNAMIC_TAG(name, value)
+#define X86_64_DYNAMIC_TAG(name, value)
// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc.
#define DYNAMIC_TAG_MARKER(name, value)
#define DYNAMIC_TAG(name, value) \
@@ -3823,6 +3843,8 @@ std::string static getDynamicTagAsString(uint16_t Arch, uint64_t Type) {
#undef PPC_DYNAMIC_TAG
#undef PPC64_DYNAMIC_TAG
#undef RISCV_DYNAMIC_TAG
+#undef SPARC_DYNAMIC_TAG
+#undef X86_64_DYNAMIC_TAG
#undef DYNAMIC_TAG_MARKER
#undef DYNAMIC_STRINGIFY_ENUM
default:
More information about the lldb-commits
mailing list