[RFC v3] RISC-V: Fix SIGSEGV of --static-pie binaries on riscv64 [BZ #33911]
daichengrong
daichengrong@iscas.ac.cn
Sun Mar 8 06:21:54 GMT 2026
This patch fixes a SIGSEGV observed in --static-pie binaries on riscv64,
as reported in BZ #33911.
The first issue occurs when compiler optimizations are enabled: memory
initialization via `memset` may generate early libcalls before static PIE
relocation, leading to incorrect symbol resolution.
The second issue occurs when compiler optimizations are not enabled:
`memcpy` may be emitted as a direct libc call instead of an inlined
instruction sequence, which can also trigger relocation problems.
This patch addresses both issues by providing safe early implementations
that avoid generating libcalls before static PIE relocation, ensuring
memory operations are performed correctly.
Signed-off-by: daichengrong <daichengrong@iscas.ac.cn>
---
elf/dynamic-link.h | 67 ++++++++++++++++++++++++++------------
sysdeps/riscv/dl-machine.h | 15 ++++++---
2 files changed, 57 insertions(+), 25 deletions(-)
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index a46f36b8d4..8c12812b63 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -18,7 +18,14 @@
#include <dl-machine.h>
#include <elf.h>
+// #include <sys/cdefs.h>
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
#ifdef RESOLVE_MAP
/* We pass reloc_addr as a pointer to void, as opposed to a pointer to
ElfW(Addr), because not all architectures can assume that the
@@ -82,11 +89,11 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
do { \
struct { ElfW(Addr) start, size; \
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
- ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \
+ ranges[2]; \
\
/* With DT_RELR, DT_RELA/DT_REL can have zero value. */ \
- if ((map)->l_info[DT_##RELOC] != NULL \
- && (map)->l_info[DT_##RELOC]->d_un.d_ptr != 0) \
+ if (likely((map)->l_info[DT_##RELOC] != NULL \
+ && (map)->l_info[DT_##RELOC]->d_un.d_ptr != 0)) \
{ \
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
@@ -94,28 +101,46 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ranges[0].nrelative \
= map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val; \
} \
- if ((map)->l_info[DT_PLTREL] \
- && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
+ else \
+ { \
+ ranges[0].size = 0; \
+ ranges[0].nrelative = 0; \
+ } \
+ if (likely((map)->l_info[DT_PLTREL] \
+ && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC))) \
{ \
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
\
- if (ranges[0].start == 0) \
- ranges[0].start = start; \
- if (ranges[0].start + ranges[0].size == (start + size)) \
- ranges[0].size -= size; \
- if (!(do_lazy) \
- && (ranges[0].start + ranges[0].size) == start) \
- { \
- /* Combine processing the sections. */ \
- ranges[0].size += size; \
- } \
- else \
- { \
- ranges[1].start = start; \
- ranges[1].size = size; \
- ranges[1].lazy = (do_lazy); \
- } \
+ if (ranges[0].size == 0) \
+ { \
+ ranges[0].lazy = (do_lazy); \
+ ranges[0].start = start; \
+ ranges[0].size = size; \
+ ranges[1].size = 0; \
+ } \
+ else \
+ { \
+ ranges[1].start = start; \
+ ranges[1].size = size; \
+ ranges[1].lazy = (do_lazy); \
+ if (likely(do_lazy)) \
+ { \
+ /* Combine processing the sections. */ \
+ if (unlikely(ranges[0].start + ranges[0].size == (start + size))) \
+ { \
+ ranges[1].size = 0; \
+ ranges[0].start = ranges[0].start; \
+ ranges[1].lazy = 0; \
+ ranges[0].size = ranges[0].size + size; \
+ ranges[0].lazy = (do_lazy); \
+ } \
+ } \
+ } \
+ } \
+ else \
+ { \
+ ranges[1].size = 0; \
} \
\
for (int ranges_index = 0; ranges_index < 2; ++ranges_index) \
diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
index 8c7312ad98..0c6b55c3f3 100644
--- a/sysdeps/riscv/dl-machine.h
+++ b/sysdeps/riscv/dl-machine.h
@@ -157,10 +157,17 @@ __attribute__ ((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr)
{
- /* R_RISCV_RELATIVE might located in debug info section which might not
- aligned to XLEN bytes. Also support relocations on unaligned offsets. */
- ElfW(Addr) value = l_addr + reloc->r_addend;
- memcpy (reloc_addr, &value, sizeof value);
+#if __riscv_xlen == 64
+ uint64_t value = l_addr + reloc->r_addend;
+
+ uint32_t lo = (uint32_t)value;
+ uint32_t hi = (uint32_t)(value >> 32);
+
+ ((uint32_t*)reloc_addr)[0] = lo;
+ ((uint32_t*)reloc_addr)[1] = hi;
+#else
+ *reloc_addr = l_addr + reloc->r_addend;
+#endif
}
/* Perform a relocation described by R_INFO at the location pointed to
--
2.25.1
More information about the Libc-alpha
mailing list