From f3059fb80504e1f4e1e4c34562508f404ce7b0f7 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 15 May 2023 18:33:47 +0200 Subject: sigsegv: Add tentative support for Hurd/x86_64. Based on explanations by Sergey Bugaev . * lib/sigsegv.c: Update from libsigsegv/src/fault-hurd-i386-old.h. --- ChangeLog | 6 ++++++ lib/sigsegv.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index ade908c972..b894505c2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2023-05-15 Bruno Haible + + sigsegv: Add tentative support for Hurd/x86_64. + Based on explanations by Sergey Bugaev . + * lib/sigsegv.c: Update from libsigsegv/src/fault-hurd-i386-old.h. + 2023-05-15 Paul Eggert file-has-acl: improve port to Fedora 39 diff --git a/lib/sigsegv.c b/lib/sigsegv.c index aadba4e060..8263d9b7bd 100644 --- a/lib/sigsegv.c +++ b/lib/sigsegv.c @@ -361,7 +361,7 @@ int libsigsegv_version = LIBSIGSEGV_VERSION; #if defined __GNU__ /* Hurd */ -# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, int code, struct sigcontext *scp +# define SIGSEGV_FAULT_HANDLER_ARGLIST int sig, long code, struct sigcontext *scp # define SIGSEGV_FAULT_ADDRESS (unsigned long) code # define SIGSEGV_FAULT_CONTEXT scp @@ -370,11 +370,29 @@ int libsigsegv_version = LIBSIGSEGV_VERSION; /* scp points to a 'struct sigcontext' (defined in glibc/sysdeps/mach/hurd/x86_64/bits/sigcontext.h). - The registers, at the moment the signal occurred, get pushed on the stack - through gnumach/x86_64/locore.S:alltraps and then copied into the struct - through glibc/sysdeps/mach/hurd/x86/trampoline.c. */ -/* sc_rsp is unused (not set by gnumach/x86_64/locore.S:alltraps). We need - to use sc_ursp. */ + The registers, at the moment the signal occurred, get pushed on the kernel + stack through gnumach/x86_64/locore.S:alltraps. They are denoted by a + 'struct i386_saved_state' (defined in gnumach/i386/i386/thread.h). + Upon invocation of the Mach interface function thread_get_state + + (= __thread_get_state in glibc), defined in gnumach/kern/thread.c, + the function thread_getstatus, defined in gnumach/i386/i386/pcb.c, copies the + register values in a different arrangement into a 'struct i386_thread_state', + defined in gnumach/i386/include/mach/i386/thread_status.h. (Different + arrangement: trapno, err get dropped; different order of r8...r15; also rsp + gets set to 0.) + This 'struct i386_thread_state' is actually the 'basic' part of a + 'struct machine_thread_all_state', defined in + glibc/sysdeps/mach/x86/thread_state.h. + From there, the function _hurd_setup_sighandler, defined in + glibc/sysdeps/mach/hurd/x86/trampoline.c, + 1. sets rsp to the same value as ursp, + 2. copies the 'struct i386_thread_state' into the appropriate part of a + 'struct sigcontext', defined in + glibc/sysdeps/mach/hurd/x86_64/bits/sigcontext.h. */ +/* Both sc_rsp and sc_ursp have the same value. + It appears more reliable to use sc_ursp because sc_rsp is marked as + "not used". */ # define SIGSEGV_FAULT_STACKPOINTER scp->sc_ursp # elif defined __i386__ @@ -382,12 +400,28 @@ int libsigsegv_version = LIBSIGSEGV_VERSION; /* scp points to a 'struct sigcontext' (defined in glibc/sysdeps/mach/hurd/i386/bits/sigcontext.h). - The registers, at the moment the signal occurred, get pushed on the stack - through gnumach/i386/i386/locore.S:alltraps and then copied into the struct - through glibc/sysdeps/mach/hurd/x86/trampoline.c. */ -/* Both sc_esp and sc_uesp appear to have the same value. - It appears more reliable to use sc_uesp because it is labelled as - "old esp, if trapped from user". */ + The registers, at the moment the signal occurred, get pushed on the kernel + stack through gnumach/i386/i386/locore.S:alltraps. They are denoted by a + 'struct i386_saved_state' (defined in gnumach/i386/i386/thread.h). + Upon invocation of the Mach interface function thread_get_state + + (= __thread_get_state in glibc), defined in gnumach/kern/thread.c, + the function thread_getstatus, defined in gnumach/i386/i386/pcb.c, copies the + register values in a different arrangement into a 'struct i386_thread_state', + defined in gnumach/i386/include/mach/i386/thread_status.h. (Different + arrangement: trapno, err get dropped; also esp gets set to 0.) + This 'struct i386_thread_state' is actually the 'basic' part of a + 'struct machine_thread_all_state', defined in + glibc/sysdeps/mach/x86/thread_state.h. + From there, the function _hurd_setup_sighandler, defined in + glibc/sysdeps/mach/hurd/x86/trampoline.c, + 1. sets esp to the same value as uesp, + 2. copies the 'struct i386_thread_state' into the appropriate part of a + 'struct sigcontext', defined in + glibc/sysdeps/mach/hurd/i386/bits/sigcontext.h. */ +/* Both sc_esp and sc_uesp have the same value. + It appears more reliable to use sc_uesp because sc_esp is marked as + "not used". */ # define SIGSEGV_FAULT_STACKPOINTER scp->sc_uesp # endif -- cgit v1.2.1