summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2023-05-09 00:31:15 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-05-10 02:35:50 +0200
commit4c37060484c17619699ad67cd4d716c59bceef85 (patch)
treecb83c5c6a38967d31d9faf7ca84717e9f890e9a3
parent6e5ad3f307307b87f87d1cc662ec1ea13ad4ade4 (diff)
elfcore: Add support for saving x86_64 registers
Message-Id: <20230508213136.608575-21-bugaevc@gmail.com>
-rw-r--r--exec/elfcore.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/exec/elfcore.c b/exec/elfcore.c
index ab6dc2ba..c6aa2bc8 100644
--- a/exec/elfcore.c
+++ b/exec/elfcore.c
@@ -23,6 +23,7 @@
#include <link.h>
#include <string.h>
#include <argz.h>
+#include <error.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include <sys/procfs.h>
@@ -44,7 +45,76 @@
#include <mach/vm_param.h>
#include <assert-backtrace.h>
-#ifdef i386_THREAD_STATE
+#ifdef __x86_64__
+# define ELF_MACHINE EM_X86_64
+
+static inline void
+fetch_thread_regset (thread_t thread, prgregset_t *gregs)
+{
+ error_t err;
+ struct i386_thread_state state;
+ mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
+
+ memset (gregs, 0, sizeof (*gregs));
+
+ err = thread_get_state (thread, i386_THREAD_STATE,
+ (thread_state_t) &state, &count);
+ if (err)
+ {
+ error (0, err, "Failed to fetch thread state");
+ return;
+ }
+
+ assert_backtrace (count == i386_THREAD_STATE_COUNT);
+
+ (*gregs)[REG_RAX] = state.rax;
+ (*gregs)[REG_RBX] = state.rbx;
+ (*gregs)[REG_RCX] = state.rcx;
+ (*gregs)[REG_RDX] = state.rdx;
+
+ (*gregs)[REG_RDI] = state.rdi;
+ (*gregs)[REG_RSI] = state.rsi;
+
+ (*gregs)[REG_RBP] = state.rbp;
+ (*gregs)[REG_RSP] = state.ursp;
+ (*gregs)[REG_RIP] = state.rip;
+ (*gregs)[REG_RFL] = state.rfl;
+
+ (*gregs)[REG_R8] = state.r8;
+ (*gregs)[REG_R9] = state.r9;
+ (*gregs)[REG_R10] = state.r10;
+ (*gregs)[REG_R11] = state.r11;
+ (*gregs)[REG_R12] = state.r12;
+ (*gregs)[REG_R13] = state.r13;
+ (*gregs)[REG_R14] = state.r14;
+ (*gregs)[REG_R15] = state.r15;
+}
+
+static inline void
+fetch_thread_fpregset (thread_t thread, prfpregset_t *fpregs)
+{
+ error_t err;
+ struct i386_float_state st;
+ mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT;
+
+ memset (*fpregs, 0, sizeof (**fpregs));
+
+ err = thread_get_state (thread, i386_FLOAT_STATE,
+ (thread_state_t) &st, &count);
+ if (err)
+ {
+ error (0, err, "Failed to fetch thread state");
+ return;
+ }
+ if (st.initialized)
+ {
+ _Static_assert (sizeof (**fpregs) >= sizeof (st.hw_state),
+ "Expected prfpregset_t to contain hw_state");
+ memcpy (*fpregs, &st.hw_state, sizeof (st.hw_state));
+ }
+}
+
+#elif defined (i386_THREAD_STATE)
# define ELF_MACHINE EM_386
/* The gregset_t format (compatible with Linux/x86) almost fits