[lld] [LLD] Make lld define __eh_frame_* symbols (PR #162638)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 9 04:50:49 PDT 2025


https://github.com/quic-k created https://github.com/llvm/llvm-project/pull/162638

This patch makes LLD explicitly define the following symbols during linking:

- `__eh_frame_start`
- `__eh_frame_end`
- `__eh_frame_hdr_start`
- `__eh_frame_hdr_end`

These are expected by libunwind for exception handling in baremetal builds
Right now, these symbols need to be explicitly defined by the linker script.
I think its better that the linker defines them implicitly, so we don't have to create a linker script only because we needed to provide these symbols

I am interested in feedback on this change

>From cc50dc9d8432f78033dc4811c97a23452bce6f7b Mon Sep 17 00:00:00 2001
From: Kushal Pal <kushpal at qti.qualcomm.com>
Date: Thu, 9 Oct 2025 17:06:12 +0530
Subject: [PATCH] [LLD] Make lld define __eh_frame_* symbols

Libunwind needs the following symbols for exception handling

__eh_frame_start __eh_frame_end __eh_frame_hdr_start __eh_frame_hdr_end

Instead of using a linker script just to define these symbols, let the
linker define them as standard symbols.
Now we can create static executable with libunwind without a linker
script.

Signed-off-by: Kushal Pal <kushpal at qti.qualcomm.com>
---
 lld/ELF/Writer.cpp           |  6 ++++++
 lld/test/ELF/eh-frame-syms.s | 25 +++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 lld/test/ELF/eh-frame-syms.s

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 4fa80397cbfa7..145bff5007466 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2269,6 +2269,12 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
   define("__preinit_array_start", "__preinit_array_end", ctx.out.preinitArray);
   define("__init_array_start", "__init_array_end", ctx.out.initArray);
   define("__fini_array_start", "__fini_array_end", ctx.out.finiArray);
+  // Define __eh_frame_* symbols, libunwind needs these symbols.
+  // Define them only if the corresponding output section exists.
+  if (OutputSection *sec = findSection(ctx, ".eh_frame"))
+    define("__eh_frame_start", "__eh_frame_end", sec);
+  if (OutputSection *sec = findSection(ctx, ".eh_frame_hdr"))
+    define("__eh_frame_hdr_start", "__eh_frame_hdr_end", sec);
 
   // As a special case, don't unnecessarily retain .ARM.exidx, which would
   // create an empty PT_ARM_EXIDX.
diff --git a/lld/test/ELF/eh-frame-syms.s b/lld/test/ELF/eh-frame-syms.s
new file mode 100644
index 0000000000000..074221ade4fb6
--- /dev/null
+++ b/lld/test/ELF/eh-frame-syms.s
@@ -0,0 +1,25 @@
+## Verify that lld defines __eh_frame_start/end and __eh_frame_hdr_start/end symbols
+
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -eh-frame-hdr -o %t
+# RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=SYM
+
+# SYM: __eh_frame_start
+# SYM: __eh_frame_end
+# SYM: __eh_frame_hdr_start
+# SYM: __eh_frame_hdr_end
+
+.text
+.globl _start
+.type _start, @function
+_start:
+  nop
+
+# Emit references so the link will fail if these are not defined
+check_symbol:
+  .quad __eh_frame_start
+  .quad __eh_frame_end
+  .quad __eh_frame_hdr_start
+  .quad __eh_frame_hdr_end



More information about the llvm-commits mailing list