On 6/3/26 09:18, Matt Turner wrote:
@@ -502,6 +502,14 @@ void target_to_host_siginfo(siginfo_t *info, const
target_siginfo_t *tinfo)
info->si_value.sival_ptr = (void *)(long)sival_ptr;
}
+/*
+ * Weak arch hook: flush all register windows to the guest stack before
+ * writing a core dump. Required on SPARC where the register file holds
+ * multiple call-frames that have not been spilled to memory yet.
+ * Architectures without register windows leave this as a no-op.
+ */
+void __attribute__((weak)) target_flush_windows(CPUArchState *env) {}
+
/* returns 1 if given signal should dump core if not handled */
static int core_dump_signal(int sig)
{
@@ -828,6 +836,7 @@ void dump_core_and_abort(CPUArchState *env, int target_sig)
/* dump core if supported by target binary format */
if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
+ target_flush_windows(env);
stop_all_tasks();
core_dumped =
((*ts->bprm->core_dump)(target_sig, env) == 0);
Not a fan of the weak symbol.
I'm pretty sure you need this flush for all threads, so probably has to happen after
stop_all_tasks. Probably via one of the CPU_FOREACH in elf_core_dump.
We're not quite to the state where there are no TARGET_FOO ifdefs in elfload.c.
I think we can stand a TARGET_SPARC ifdef in elf_core_dump.
+/* Override the weak hook in linux-user/signal.c to flush all SPARC register
+ * windows to the guest stack before a core dump is written. Without this,
+ * only the active window (captured in NT_PRSTATUS) ends up in memory; all
+ * deeper call frames remain in the register file and are absent from the
+ * core's memory segments, breaking stack unwind beyond one frame. */
+void target_flush_windows(CPUArchState *env)
+{
+ flush_windows((CPUSPARCState *)env);
+}
Cast not required -- the two names are typedefs of each other.
r~