From 5805151cffccc087942b9dd8d7ac10ca5f4f80a8 Mon Sep 17 00:00:00 2001
From: lapla <me@lapla.dev>
Date: Tue, 20 Jan 2026 18:47:13 +0900
Subject: [PATCH] fix: Resolve weak undefined symbols to zero in read-only
 sections (#1474)

#1472

When a weak undefined symbol is referenced from a read-only section via
an absolute relocation, the resolved value should be 0, not the PLT
entry address.
---
 libwild/src/elf_writer.rs               |  6 ++++++
 wild/tests/integration_tests.rs         |  3 ++-
 wild/tests/sources/undefined-weak-sym.c | 25 +++++++++++++++++++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 wild/tests/sources/undefined-weak-sym.c

diff --git a/libwild/src/elf_writer.rs b/libwild/src/elf_writer.rs
index 2923bc9e9..026636f0d 100644
--- a/libwild/src/elf_writer.rs
+++ b/libwild/src/elf_writer.rs
@@ -2574,6 +2574,12 @@ fn write_absolute_relocation<A: Arch>(
             &layout.merged_strings,
             &layout.merged_string_start_addresses,
         )
+    } else if resolution.flags.is_dynamic()
+        && resolution.flags.is_absolute()
+        && !section_info.is_writable
+    {
+        // Weak undefined symbol referenced from a read-only section. Fill in as zero.
+        Ok(0)
     } else if resolution.flags.is_interposable() && section_info.is_writable {
         table_writer.write_dynamic_symbol_relocation::<A>(
             place,
diff --git a/wild/tests/integration_tests.rs b/wild/tests/integration_tests.rs
index bc4730412..9dd611ba7 100644
--- a/wild/tests/integration_tests.rs
+++ b/wild/tests/integration_tests.rs
@@ -3320,7 +3320,8 @@ fn integration_test(
         "wrap-real-only.c",
         "ifunc-alias.c",
         "ifunc-address-equality.c",
-        "stack-size.c"
+        "stack-size.c",
+        "undefined-weak-sym.c"
     )]
     program_name: &'static str,
     #[allow(unused_variables)] setup_symlink: (),
diff --git a/wild/tests/sources/undefined-weak-sym.c b/wild/tests/sources/undefined-weak-sym.c
new file mode 100644
index 000000000..b029ca7e2
--- /dev/null
+++ b/wild/tests/sources/undefined-weak-sym.c
@@ -0,0 +1,25 @@
+// A test for #1472.
+
+//#Object:runtime.c
+//#CompArgs:-fno-PIC
+//#Mode:dynamic
+//#Shared:force-dynamic-linking.c
+//#DiffIgnore:section.got
+//#DiffIgnore:.dynamic.DT_NEEDED
+//#DiffIgnore:.dynamic.DT_RELA
+//#DiffIgnore:.dynamic.DT_RELAENT
+//#DiffIgnore:rel.undefined-weak.dynamic.R_X86_64_GLOB_DAT
+
+#include "runtime.h"
+
+#define WEAK __attribute__((weak))
+
+int WEAK foo(void);
+
+void _start(void) {
+  runtime_init();
+  if (foo) {
+    exit_syscall(foo());
+  }
+  exit_syscall(42);
+}
