Read the registers of a stopped thread with PTRACE_PEEKUSER, which on
alpha takes a register number rather than a struct user offset: 0-31
for the integer registers, 32-62 for $f0-$f30, 63 for the FPCR and 64
for the pc. $31 and $f31 always read as zero, so skip them.
The peeked value is the return value, so check errno instead of
treating -1 as an error.
* backends/alpha_initreg.c: New file.
* backends/Makefile.am (alpha_SRCS): Add alpha_initreg.c.
* backends/alpha_init.c (alpha_init): Hook
set_initial_registers_tid.
* NEWS: Add entry.
---
NEWS | 4 +++
backends/Makefile.am | 2 +-
backends/alpha_init.c | 1 +
backends/alpha_initreg.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/NEWS b/NEWS
index a66cbda7..be100686 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Version 0.197
+
+backends: Add unwinding support for alpha core files and processes.
+
Version 0.196 "Split Personality"
debuginfod: The $DEBUGINFOD_TIMEOUT environment variable is now enforced
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 604673b6..dac2c060 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -53,7 +53,7 @@ x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c
x86_64_cfi.c \
ia64_SRCS = ia64_init.c ia64_symbol.c ia64_regs.c ia64_retval.c
alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
- alpha_corenote.c alpha_auxv.c alpha_cfi.c
+ alpha_corenote.c alpha_auxv.c alpha_cfi.c alpha_initreg.c
arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \
arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c arm_initreg.c \
diff --git a/backends/alpha_init.c b/backends/alpha_init.c
index 229c5beb..0e46e92f 100644
--- a/backends/alpha_init.c
+++ b/backends/alpha_init.c
@@ -62,6 +62,7 @@ alpha_init (Elf *elf __attribute__ ((unused)),
DWARF_ALT_FRAME_RETURN_COLUMN and glibc's signal trampolines use
as the return address column. */
eh->frame_nregs = 65;
+ HOOK (eh, set_initial_registers_tid);
eh->sysvhash_entrysize = sizeof (Elf64_Xword);
return eh;
diff --git a/backends/alpha_initreg.c b/backends/alpha_initreg.c
new file mode 100644
index 00000000..dcf81e7a
--- /dev/null
+++ b/backends/alpha_initreg.c
@@ -0,0 +1,72 @@
+/* Fetch live process registers from TID.
+ Copyright (C) 2026 Matt Turner
+ This file is part of elfutils.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined __alpha__ && defined __linux__
+# include <errno.h>
+# include <stdint.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+bool
+alpha_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc __attribute__
((unused)),
+ void *arg __attribute__ ((unused)))
+{
+#if !defined __alpha__ || !defined __linux__
+ return false;
+#else /* __alpha__ */
+ /* PTRACE_PEEKUSER takes a register number: 0-31 for the integer
+ registers, 32-62 for $f0-$f30, 63 for the FPCR and 64 for the PC.
+ The value is the return value, so check errno rather than for -1. */
+ Dwarf_Word regs[65];
+ for (int i = 0; i < 65; i++)
+ {
+ /* $31 and $f31 always read as zero. */
+ if (i == 31 || i == 63)
+ {
+ regs[i] = 0;
+ continue;
+ }
+ errno = 0;
+ regs[i] = ptrace (PTRACE_PEEKUSER, tid, (void *) (uintptr_t) i, NULL);
+ if (errno != 0)
+ return false;
+ }
+
+ /* $0-$31 and $f0-$f31, then the PC. */
+ return setfunc (0, 64, regs, arg) && setfunc (-1, 1, ®s[64], arg);
+#endif /* __alpha__ */
+}
--
2.55.0