This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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: [PATCH] Unwinding CFI for x86_64 signal frame (__restore_rt)


On Sat, Nov 25, 2006 at 07:06:16PM +0100, Jan Kratochvil wrote:

> +/* Define if CFI x86_64 rflags is available.  */
> +#undef	HAVE_ASM_CFI_RFLAGS

I don't think this conditional is needed, we can use numbers instead
of register names and they will work with any unwinder.  The CFI_IF_RFLAGS
macros are just too ugly and e.g. cs etc. regnames have been added
together with rflags to gas.

> --- glibc-20061120T1000-orig/sysdeps/unix/sysv/linux/x86_64/sigaction.c	2006-10-28 08:44:03.000000000 +0200
> +++ glibc-20061120T1000/sysdeps/unix/sysv/linux/x86_64/sigaction.c	2006-11-25 16:59:17.000000000 +0100
> @@ -92,16 +92,49 @@ weak_alias (__libc_sigaction, sigaction)
>     If you ever feel the need to make any changes, please notify the
>     appropriate GDB maintainer.  */
>  
> +/* sizeof (struct rt_sigframe)  */
> +#define FRAME_SIZE 0x238
> +/* offsetof (struct rt_sigframe, uc.uc_mcontext)  */
> +#define SIGCONTEXT_BASE (-FRAME_SIZE + 0x28)

I think you should use here (and in the offsets of the various registers)
a *.sym file to precompute macros and use them.  There is already
sysdeps/unix/sysv/linux/x86_64/ucontext_i.sym, with oR* macros for the
registers, where oR8 is 0x28.

Another, more important thing, you are assuming the size of signal
frame is always 0x238 bytes.  But what guarantees that?  That's something
that can be hardcoded e.g. in vDSO signal description, because if you change
the kernel, you just adjust the CFI as well.  But not in glibc.  Say if
2.6.35 kernel needs to save some new fancy register in new hardware,
it will need extra space.  MD_FALLBACK_FRAME_STATE_FOR in gcc handles
this portably:
  new_cfa = sc->rsp;
  fs->regs.cfa_how = CFA_REG_OFFSET;
  /* Register 7 is rsp  */
  fs->regs.cfa_reg = 7;
  fs->regs.cfa_offset = new_cfa - (long) context->cfa;

  fs->regs.reg[0].how = REG_SAVED_OFFSET;
  fs->regs.reg[0].loc.offset = (long)&sc->rax - new_cfa;
...
So, new CFA is read from uc_mcontext.gregs[REG_RSP] and
all offsets adjusted.

This can be represented in DWARF3 with DW_CFA_def_cfa_expression
to define new CFA and DW_CFA_expression for all the registers
(where e.g. r8 could have DW_CFA_expression
.byte DW_OP_breg7; .sleb128 oR8), but current .cfi_escape
can't deal with that, because some of the constants are > 128
and you'd need to translate them to SLEB128 manually (well,
#if (oRDX >= 128 && oRDX < 256)
.cfi_escape oRDX, 1
#elif (oRDX < 128)
.cfi_escape oRDX
#else
#error ...
#endif
is possible, but way too unreadable).  I plan to change fix
that on the gas side soon, but for the time being I'd say
you'd have much more readable unwind info if you just coded
by hand a (commented) .eh_frame section, after all, .cfi_*
directives don't help you much here, because all you want
is cover the 2 instructions including 1 byte before them.
With an open coded .eh_frame for the sigreturn pad, you don't
need configure checks for .cfi_signal_frame, you just use
S at the end of the augmentation.

	Jakub


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