This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Notes on a frame_unwind_address_in_block problem


On Tue, Jul 18, 2006 at 09:24:39AM +0200, Andreas Jaeger wrote:
> > Andreas, looking at the i386 version, I guess that using SA_RESTORER
> > this way is not necessary.  Simply a performance optimization because
> > the old trampolines (written to the stack) were so slow, or maybe
> > because they required an executable stack.  i386 has
> > "if (GLRO(dl_sysinfo_dso) == NULL)" around it.  Can x86_64 do the same
> > thing?
> 
> i386 is the only platform doing it.  I don't know the history of the
> change and whether this is the right thing to do.  Is somebody willing
> to test this?

Well, I tried.  But it looks like I was just wrong about the situation.
i386 has a vDSO and uses it for signal return trampolines, but x86_64
doesn't have a vDSO and in fact requires the use of SA_RESTORER.  All
x86_64 has is the vsyscall page, which is older.

(There's something claiming to be [vdso] mapped in, but I think it's
just the vsyscalls.)

So I came up with this alternative patch.  Glibc tests fine, and GDB
(combined with a patch for the function-address-in-block issue mentioned
upthread) improves quite a lot.

The only caveat is that it is in glibc, but knows about the kernel
layout of struct rt_sigframe - specifically that a struct ucontext
lives just above the SA_RESTORER return address.  Andi, what do you
think of that?  If it's a bad idea, we may need a different approach
(i.e. a vdso).

-- 
Daniel Jacobowitz
CodeSourcery

2006-07-18  Daniel Jacobowitz  <dan@codesourcery.com>

	* sysdeps/unix/sysv/linux/x86_64/sigaction.c (restore_rt): Add correct
	unwind information.

Index: sysdeps/unix/sysv/linux/x86_64/sigaction.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/x86_64/sigaction.c,v
retrieving revision 1.9
diff -u -p -r1.9 sigaction.c
--- sysdeps/unix/sysv/linux/x86_64/sigaction.c	29 Dec 2005 16:32:17 -0000	1.9
+++ sysdeps/unix/sysv/linux/x86_64/sigaction.c	18 Jul 2006 17:52:21 -0000
@@ -95,18 +95,94 @@ weak_alias (__libc_sigaction, sigaction)
    signal handlers work right.  Important are both the names
    (__restore_rt) and the exact instruction sequence.
    If you ever feel the need to make any changes, please notify the
-   appropriate GDB maintainer.  */
+   appropriate GDB maintainer.
+
+   The unwind information starts a byte before __restore_rt, so that
+   it is found when unwinding, to get an address the unwinder assumes
+   will be in the middle of a call instruction.  See the Linux kernel
+   (the i386 vsyscall, in particular) for an explanation of the complex
+   unwind information used here in order to get the traditional CFA.
+   We do not restore cs - it's only stored as two bytes here so that's
+   a bit tricky.  We don't use the gas cfi directives, so that we can
+   reliably add .cfi_signal_frame.  */
+
+#define do_cfa_expr \
+  ".byte 0x0f\n"	/* DW_CFA_def_cfa_expression */	\
+  ".byte 0x04\n"	/* length */		\
+  ".byte 0x77\n"   	/* DW_OP_breg8 */	\
+  ".byte 0xa0\n"				\
+  ".byte 0x01\n"	/* 160 */		\
+  ".byte 0x06\n"	/* DW_OP_deref */
+
+#define do_expr_1(regno, offset) \
+  ".byte 0x10\n"	/* DW_CFA_expression */	\
+  ".byte " CFI_STRINGIFY(regno) "\n"		\
+  ".byte 0x02\n"	/* length */		\
+  ".byte 0x77\n"   	/* DW_OP_breg8 */	\
+  ".byte " CFI_STRINGIFY(offset) "\n"		\
+
+#define do_expr_2(regno, offset1, offset2) \
+  ".byte 0x10\n"	/* DW_CFA_expression */	\
+  ".byte " CFI_STRINGIFY(regno) "\n"		\
+  ".byte 0x03\n"	/* length */		\
+  ".byte 0x77\n"   	/* DW_OP_breg8 */	\
+  ".byte " CFI_STRINGIFY(offset1) "\n"		\
+  ".byte " CFI_STRINGIFY(offset2) "\n"		\
 
 #define RESTORE(name, syscall) RESTORE2 (name, syscall)
 # define RESTORE2(name, syscall) \
 asm						\
   (						\
    ".align 16\n"				\
-   CFI_STARTPROC "\n"				\
+   ".LSTART_" #name ":\n"			\
+   "	nop\n"					\
    "__" #name ":\n"				\
    "	movq $" #syscall ", %rax\n"		\
    "	syscall\n"				\
-   CFI_ENDPROC "\n"				\
+   ".LEND_" #name ":\n"				\
+   ".section .eh_frame,\"a\",@progbits\n"				\
+   ".LSTARTFRAME_" #name ":\n"						\
+   "	.long .LENDCIE_" #name "-.LSTARTCIE_" #name "\n"		\
+   ".LSTARTCIE_" #name ":\n"						\
+   "	.long 0\n"	/* CIE ID */					\
+   "	.byte 1\n"	/* Version number */				\
+   "	.string \"zRS\"\n" /* NUL-terminated augmentation string */	\
+   "	.uleb128 1\n"	/* Code alignment factor */			\
+   "	.sleb128 -8\n"	/* Data alignment factor */			\
+   "	.byte 0x10\n"	/* Return address register column */		\
+   "	.uleb128 1\n"	/* Augmentation value length */			\
+   "	.byte 0x1b\n"	/* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */		\
+   "	.byte 0\n"	/* DW_CFA_nop */				\
+   "	.align 8\n"							\
+   ".LENDCIE_" #name ":\n"						\
+   "	.long .LENDFDE_" #name "-.LSTARTFDE_" #name "\n" /* FDE len */	\
+   ".LSTARTFDE_" #name ":\n"						\
+   "	.long .LSTARTFDE_" #name "-.LSTARTFRAME_" #name "\n" /* CIE */	\
+   "	.long .LSTART_" #name "-.\n"	/* PC-relative start address */	\
+   "	.long .LEND_" #name "-.LSTART_" #name "\n"			\
+   "	.uleb128 0\n"			/* Augmentation */		\
+   do_cfa_expr					\
+   do_expr_1 (8, 0x28)				\
+   do_expr_1 (9, 0x30)				\
+   do_expr_1 (10, 0x38)				\
+   do_expr_2 (11, 0xc0, 0x00)			\
+   do_expr_2 (12, 0xc8, 0x00)			\
+   do_expr_2 (13, 0xd0, 0x00)			\
+   do_expr_2 (14, 0xd8, 0x00)			\
+   do_expr_2 (15, 0xe0, 0x00)			\
+   do_expr_2 (5, 0xe8, 0x00)			\
+   do_expr_2 (4, 0xf0, 0x00)			\
+   do_expr_2 (6, 0xf8, 0x00)			\
+   do_expr_2 (3, 0x80, 0x01)			\
+   do_expr_2 (1, 0x88, 0x01)			\
+   do_expr_2 (0, 0x90, 0x01)			\
+   do_expr_2 (2, 0x98, 0x01)			\
+   do_expr_2 (7, 0xa0, 0x01)			\
+   do_expr_2 (16, 0xa8, 0x01)			\
+   do_expr_2 (41, 0xb0, 0x01)			\
+   ".align 4\n"					\
+   ".LENDFDE_" #name ":\n"			\
+   ".previous\n"				\
    );
 /* The return code for realtime-signals.  */
 RESTORE (restore_rt, __NR_rt_sigreturn)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]