diff mbox series

hurd: libgcc unwinding support over signal trampolines

Message ID 20200529114650.tent6dxgq4bzbkdz@function
State New
Headers show
Series hurd: libgcc unwinding support over signal trampolines | expand

Commit Message

Samuel Thibault May 29, 2020, 11:46 a.m. UTC
Hello,

libgcc is currently missing the support for unwinding over signal
trampolines on GNU/Hurd. The attached patch implements it.

Samuel
hurd: libgcc unwinding support over signal trampolines

* libgcc/config.host (md_unwind_header): Set to i386/gnu-unwind.h on
i[34567]86-*-gnu*.
* src/libgcc/config/i386/gnu-unwind.h: New file.

Comments

Samuel Thibault June 6, 2020, 9:42 p.m. UTC | #1
Hello,

Any news on this?

Samuel

Samuel Thibault, le ven. 29 mai 2020 13:46:50 +0200, a ecrit:
> Hello,
> 
> libgcc is currently missing the support for unwinding over signal
> trampolines on GNU/Hurd. The attached patch implements it.
> 
> Samuel

> hurd: libgcc unwinding support over signal trampolines
> 
> * libgcc/config.host (md_unwind_header): Set to i386/gnu-unwind.h on
> i[34567]86-*-gnu*.
> * src/libgcc/config/i386/gnu-unwind.h: New file.
> 
> diff --git a/libgcc/config.host b/libgcc/config.host
> index 2cd42097167..044b34d53cc 100644
> --- a/libgcc/config.host
> +++ b/libgcc/config.host
> @@ -734,11 +734,17 @@ i[34567]86-*-linux*)
>  	tm_file="${tm_file} i386/elf-lib.h"
>  	md_unwind_header=i386/linux-unwind.h
>  	;;
> -i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
> +i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-kopensolaris*-gnu)
>  	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
>  	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
>  	tm_file="${tm_file} i386/elf-lib.h"
>  	;;
> +i[34567]86-*-gnu*)
> +	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
> +	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
> +	tm_file="${tm_file} i386/elf-lib.h"
> +	md_unwind_header=i386/gnu-unwind.h
> +	;;
>  x86_64-*-linux*)
>  	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
>  	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
> diff --git a/src/libgcc/config/i386/gnu-unwind.h b/src/libgcc/config/i386/gnu-unwind.h
> new file mode 100644
> index 00000000000..db47f0ac1d4
> --- /dev/null
> +++ b/src/libgcc/config/i386/gnu-unwind.h
> @@ -0,0 +1,107 @@
> +/* DWARF2 EH unwinding support for GNU Hurd: x86.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   Contributed by Samuel Thibault <samuel.thibault@gnu.org>
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 3, or (at your option)
> +any later version.
> +
> +GCC 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.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +/* Do code reading to identify a signal frame, and set the frame
> +   state data appropriately.  See unwind-dw2.c for the structs. */
> +
> +#ifndef inhibit_libc
> +
> +#include <signal.h>
> +
> +#define MD_FALLBACK_FRAME_STATE_FOR x86_gnu_fallback_frame_state
> +
> +static _Unwind_Reason_Code
> +x86_gnu_fallback_frame_state
> +(struct _Unwind_Context *context, _Unwind_FrameState *fs)
> +{
> +  struct handler_args {
> +    int signo;
> +    int sigcode;
> +    struct sigcontext *scp;
> +  } *handler_args;
> +  struct sigcontext *scp;
> +  unsigned long usp;
> +
> +/*
> + * i386 sigtramp frame we are looking for follows.
> + * (see glibc/sysdeps/mach/hurd/i386/trampoline.c assembly)
> + *
> + * rpc_wait_trampoline:
> + *   0:	b8 e7 ff ff ff       	mov    $-25,%eax       mach_msg_trap
> + *   5:	9a 00 00 00 00 07 00 	lcall  $7,$0
> + *  12:	89 01                	movl   %eax, (%ecx)
> + *  14:	89 dc                	movl   %ebx, %esp      switch to signal stack
> + *
> + * trampoline:
> + *  16:	ff d2                	call   *%edx           call the handler function
> + * RA HERE
> + *  18:	83 c4 0c             	addl   $12, %esp       pop its args
> + *  21:	c3                   	ret                    return to sigreturn
> + *
> + * firewall:
> + *  22:	f4                   	hlt
> + */
> +
> +  if (!(   *(unsigned int   *)(context->ra     ) == 0xc30cc483
> +        && *(unsigned char  *)(context->ra +  4) ==       0xf4
> +
> +        && *(unsigned int   *)(context->ra -  4) == 0xd2ffdc89
> +        && *(unsigned int   *)(context->ra -  8) == 0x01890007
> +        && *(unsigned int   *)(context->ra - 12) == 0x00000000
> +        && *(unsigned int   *)(context->ra - 16) == 0x9affffff
> +        && *(unsigned short *)(context->ra - 18) ==     0xe7b8))
> +    return _URC_END_OF_STACK;
> +
> +  handler_args = context->cfa;
> +  scp = handler_args->scp;
> +  usp = scp->sc_uesp;
> +
> +  fs->regs.cfa_how = CFA_REG_OFFSET;
> +  fs->regs.cfa_reg = 4;
> +  fs->regs.cfa_offset = usp - (unsigned long) context->cfa;
> +
> +  fs->regs.reg[0].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[0].loc.offset = (unsigned long)&scp->sc_eax - usp;
> +  fs->regs.reg[1].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[1].loc.offset = (unsigned long)&scp->sc_ecx - usp;
> +  fs->regs.reg[2].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[2].loc.offset = (unsigned long)&scp->sc_edx - usp;
> +  fs->regs.reg[3].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[3].loc.offset = (unsigned long)&scp->sc_ebx - usp;
> +  fs->regs.reg[5].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[5].loc.offset = (unsigned long)&scp->sc_ebp - usp;
> +  fs->regs.reg[6].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[6].loc.offset = (unsigned long)&scp->sc_esi - usp;
> +  fs->regs.reg[7].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[7].loc.offset = (unsigned long)&scp->sc_edi - usp;
> +  fs->regs.reg[8].how = REG_SAVED_OFFSET;
> +  fs->regs.reg[8].loc.offset = (unsigned long)&scp->sc_eip - usp;
> +  fs->retaddr_column = 8;
> +  fs->signal_frame = 1;
> +
> +  return _URC_NO_REASON;
> +}
> +
> +#endif /* ifndef inhibit_libc */
Thomas Schwinge June 8, 2020, 10:15 a.m. UTC | #2
Hi Samuel!

On 2020-05-29T13:46:50+0200, Samuel Thibault <samuel.thibault@gnu.org> wrote:
> libgcc is currently missing the support for unwinding over signal
> trampolines on GNU/Hurd.

ACK.  Has been on my long TODO list for a long time.  ;-)

> The attached patch implements it.

Thanks!

I'm not intimately familiar with the unwinding implementation, but your
changes look quite what I'd have guessed they'd look like, and also
somewhat similar to 'libgcc/config/i386/linux-unwind.h'.  (I'll get
there, eventually, again..., but) I'm not currently set up to test this,
but I'll assume you have.

Which GCC branches would you like this on?

> --- /dev/null
> +++ b/src/libgcc/config/i386/gnu-unwind.h
> @@ -0,0 +1,107 @@

> + * i386 sigtramp frame we are looking for follows.
> + * (see glibc/sysdeps/mach/hurd/i386/trampoline.c assembly)
> + *
> + * rpc_wait_trampoline:
> + *   0:      b8 e7 ff ff ff          mov    $-25,%eax       mach_msg_trap
> + *   5:      9a 00 00 00 00 07 00    lcall  $7,$0
> + *  12:      89 01                   movl   %eax, (%ecx)
> + *  14:      89 dc                   movl   %ebx, %esp      switch to signal stack
> + *
> + * trampoline:
> + *  16:      ff d2                   call   *%edx           call the handler function
> + * RA HERE
> + *  18:      83 c4 0c                addl   $12, %esp       pop its args
> + *  21:      c3                      ret                    return to sigreturn
> + *
> + * firewall:
> + *  22:      f4                      hlt
> + */
> +
> +  if (!(   *(unsigned int   *)(context->ra     ) == 0xc30cc483
> +        && *(unsigned char  *)(context->ra +  4) ==       0xf4
> +
> +        && *(unsigned int   *)(context->ra -  4) == 0xd2ffdc89
> +        && *(unsigned int   *)(context->ra -  8) == 0x01890007
> +        && *(unsigned int   *)(context->ra - 12) == 0x00000000
> +        && *(unsigned int   *)(context->ra - 16) == 0x9affffff
> +        && *(unsigned short *)(context->ra - 18) ==     0xe7b8))
> +    return _URC_END_OF_STACK;

Once we've got this in GCC, please then also cross-reference GCC's
'libgcc/config/i386/gnu-unwind.h' file in glibc's
'sysdeps/mach/hurd/i386/trampoline.c' file.


Grüße
 Thomas
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
Samuel Thibault June 8, 2020, 11:36 a.m. UTC | #3
Thomas Schwinge, le lun. 08 juin 2020 12:15:12 +0200, a ecrit:
> I'm not currently set up to test this, but I'll assume you have.

Sure :)

> Which GCC branches would you like this on?

Ideally it's be backported to gcc 9 and 10, so that it lands naturally
in the Debian packages without having to bother doko.

> Once we've got this in GCC, please then also cross-reference GCC's
> 'libgcc/config/i386/gnu-unwind.h' file in glibc's
> 'sysdeps/mach/hurd/i386/trampoline.c' file.

Ah, yes, I thought about it and forgot, will do.

Samuel
Samuel Thibault June 8, 2020, 11:49 a.m. UTC | #4
Samuel Thibault, le lun. 08 juin 2020 13:36:55 +0200, a ecrit:
> Thomas Schwinge, le lun. 08 juin 2020 12:15:12 +0200, a ecrit:
> > Which GCC branches would you like this on?
> 
> Ideally it's be backported to gcc 9 and 10, so that it lands naturally
> in the Debian packages without having to bother doko.

Actually only gcc 10 would be needed.

Samuel
Thomas Schwinge June 17, 2020, 10:10 p.m. UTC | #5
Hi!

On 2020-06-08T13:49:55+0200, Samuel Thibault <samuel.thibault@gnu.org> wrote:
> Samuel Thibault, le lun. 08 juin 2020 13:36:55 +0200, a ecrit:
>> Thomas Schwinge, le lun. 08 juin 2020 12:15:12 +0200, a ecrit:
>> > Which GCC branches would you like this on?
>>
>> Ideally it's be backported to gcc 9 and 10, so that it lands naturally
>> in the Debian packages without having to bother doko.
>
> Actually only gcc 10 would be needed.

Well, it was easy enough to just put it onto all active branches, so I've
now pushed "hurd: libgcc unwinding support over signal trampolines" to
master branch in commit 5e2eebc80d6eeca24745c27a925afdb64292ed22,
releases/gcc-10 branch in commit
a2b187c13919987ca0444ab7c701f9f93ee536c2, releases/gcc-9 branch in commit
cd32b2c51b913eed517e9503009fb3f0822d9cab, releases/gcc-8 branch in commit
9c5787ea072e16f26c9950139c00ae28fddadd72, see attached.


Grüße
 Thomas


-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
diff mbox series

Patch

diff --git a/libgcc/config.host b/libgcc/config.host
index 2cd42097167..044b34d53cc 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -734,11 +734,17 @@  i[34567]86-*-linux*)
 	tm_file="${tm_file} i386/elf-lib.h"
 	md_unwind_header=i386/linux-unwind.h
 	;;
-i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
+i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-kopensolaris*-gnu)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
 	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
 	tm_file="${tm_file} i386/elf-lib.h"
 	;;
+i[34567]86-*-gnu*)
+	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
+	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
+	tm_file="${tm_file} i386/elf-lib.h"
+	md_unwind_header=i386/gnu-unwind.h
+	;;
 x86_64-*-linux*)
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
 	tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules"
diff --git a/src/libgcc/config/i386/gnu-unwind.h b/src/libgcc/config/i386/gnu-unwind.h
new file mode 100644
index 00000000000..db47f0ac1d4
--- /dev/null
+++ b/src/libgcc/config/i386/gnu-unwind.h
@@ -0,0 +1,107 @@ 
+/* DWARF2 EH unwinding support for GNU Hurd: x86.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Contributed by Samuel Thibault <samuel.thibault@gnu.org>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* Do code reading to identify a signal frame, and set the frame
+   state data appropriately.  See unwind-dw2.c for the structs. */
+
+#ifndef inhibit_libc
+
+#include <signal.h>
+
+#define MD_FALLBACK_FRAME_STATE_FOR x86_gnu_fallback_frame_state
+
+static _Unwind_Reason_Code
+x86_gnu_fallback_frame_state
+(struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct handler_args {
+    int signo;
+    int sigcode;
+    struct sigcontext *scp;
+  } *handler_args;
+  struct sigcontext *scp;
+  unsigned long usp;
+
+/*
+ * i386 sigtramp frame we are looking for follows.
+ * (see glibc/sysdeps/mach/hurd/i386/trampoline.c assembly)
+ *
+ * rpc_wait_trampoline:
+ *   0:	b8 e7 ff ff ff       	mov    $-25,%eax       mach_msg_trap
+ *   5:	9a 00 00 00 00 07 00 	lcall  $7,$0
+ *  12:	89 01                	movl   %eax, (%ecx)
+ *  14:	89 dc                	movl   %ebx, %esp      switch to signal stack
+ *
+ * trampoline:
+ *  16:	ff d2                	call   *%edx           call the handler function
+ * RA HERE
+ *  18:	83 c4 0c             	addl   $12, %esp       pop its args
+ *  21:	c3                   	ret                    return to sigreturn
+ *
+ * firewall:
+ *  22:	f4                   	hlt
+ */
+
+  if (!(   *(unsigned int   *)(context->ra     ) == 0xc30cc483
+        && *(unsigned char  *)(context->ra +  4) ==       0xf4
+
+        && *(unsigned int   *)(context->ra -  4) == 0xd2ffdc89
+        && *(unsigned int   *)(context->ra -  8) == 0x01890007
+        && *(unsigned int   *)(context->ra - 12) == 0x00000000
+        && *(unsigned int   *)(context->ra - 16) == 0x9affffff
+        && *(unsigned short *)(context->ra - 18) ==     0xe7b8))
+    return _URC_END_OF_STACK;
+
+  handler_args = context->cfa;
+  scp = handler_args->scp;
+  usp = scp->sc_uesp;
+
+  fs->regs.cfa_how = CFA_REG_OFFSET;
+  fs->regs.cfa_reg = 4;
+  fs->regs.cfa_offset = usp - (unsigned long) context->cfa;
+
+  fs->regs.reg[0].how = REG_SAVED_OFFSET;
+  fs->regs.reg[0].loc.offset = (unsigned long)&scp->sc_eax - usp;
+  fs->regs.reg[1].how = REG_SAVED_OFFSET;
+  fs->regs.reg[1].loc.offset = (unsigned long)&scp->sc_ecx - usp;
+  fs->regs.reg[2].how = REG_SAVED_OFFSET;
+  fs->regs.reg[2].loc.offset = (unsigned long)&scp->sc_edx - usp;
+  fs->regs.reg[3].how = REG_SAVED_OFFSET;
+  fs->regs.reg[3].loc.offset = (unsigned long)&scp->sc_ebx - usp;
+  fs->regs.reg[5].how = REG_SAVED_OFFSET;
+  fs->regs.reg[5].loc.offset = (unsigned long)&scp->sc_ebp - usp;
+  fs->regs.reg[6].how = REG_SAVED_OFFSET;
+  fs->regs.reg[6].loc.offset = (unsigned long)&scp->sc_esi - usp;
+  fs->regs.reg[7].how = REG_SAVED_OFFSET;
+  fs->regs.reg[7].loc.offset = (unsigned long)&scp->sc_edi - usp;
+  fs->regs.reg[8].how = REG_SAVED_OFFSET;
+  fs->regs.reg[8].loc.offset = (unsigned long)&scp->sc_eip - usp;
+  fs->retaddr_column = 8;
+  fs->signal_frame = 1;
+
+  return _URC_NO_REASON;
+}
+
+#endif /* ifndef inhibit_libc */