Re: [rfa] Attach vsyscall support for GNU/Linux

Daniel Jacobowitz
2004-11-07T21:18:45Z

On Sun, Nov 07, 2004 at 06:35:44PM +0100, Mark Kettenis wrote:
> Date: Fri, 5 Nov 2004 18:42:30 -0500
> From: Daniel Jacobowitz <drow@false.org>
>
> How about this, in the meantime? If you don't like the approach, I'll
> wait until we can properly decide the relationship between unwinders
> and frame types.
>
> This patch adds a new sniffer, dwarf2_signal_frame_sniffer, which will
> only accept the frame if an architecture-specific hook has claimed that
> this is a signal frame (i386 GNU/Linux provides one that works by
> name). However, we then use the CFI normally - the only difference is
> that the result has SIGTRAMP_FRAME as its type. It works beautifully!
> Tested on i386-pc-linux-gnu, with vsyscall DSO.
>
> Within the current framework this seems to be a reasonable approach.
> Actually it's a lot less invasive than I envisioned this to be. So,
> actually I like it ;-). Thanks! I'm wondering though whether we need
> the seperate dwarf2_signal_frame_sniffer. Actually I'm sure we don't.
> Targets that don't want this simply shouldn't provide the
> signal_frame_p() function. Can you fix that? Just change
> dwarf2_frame_sniffer such that it checks signal_frame_p() and returns
> &dwarf2_sigtramp_frame_unwind instead of &dwarf2_frame_unwind if it's
> true.
>
> Oh, and please check the dwarf2-frame.* changes in as a seperately
> from the vsyscall changes.

Here's this bit, as committed - let me know if I didn't get it quite
the way you wanted. Thanks for the observation about just using one
sniffer; it looks much cleaner now.

--
Daniel Jacobowitz

2004-11-07 Daniel Jacobowitz <dan@debian.org>

* dwarf2-frame.c (struct dwarf2_frame_ops): Add signal_frame_p.
(dwarf2_frame_set_signal_frame_p, dwarf2_frame_signal_frame_p)
(dwarf2_signal_frame_unwind): New.
(dwarf2_frame_sniffer): Use dwarf2_frame_signal_frame_p.
* dwarf2-frame.h (dwarf2_frame_set_signal_frame_p): New prototype.

Index: gdb/dwarf2-frame.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2-frame.c,v
retrieving revision 1.41
diff -u -p -r1.41 dwarf2-frame.c
--- gdb/dwarf2-frame.c 4 Nov 2004 21:15:15 -0000 1.41
+++ gdb/dwarf2-frame.c 7 Nov 2004 17:41:58 -0000
@@ -471,6 +471,10 @@ struct dwarf2_frame_ops
{
/* Pre-initialize the register state REG for register REGNUM. */
void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg *);
+
+ /* Check whether the frame preceding NEXT_FRAME will be a signal
+ trampoline. */
+ int (*signal_frame_p) (struct gdbarch *, struct frame_info *);
};

/* Default architecture-specific register state initialization
@@ -547,6 +551,33 @@ dwarf2_frame_init_reg (struct gdbarch *g

ops->init_reg (gdbarch, regnum, reg);
}
+
+/* Set the architecture-specific signal trampoline recognition
+ function for GDBARCH to SIGNAL_FRAME_P. */
+
+void
+dwarf2_frame_set_signal_frame_p (struct gdbarch *gdbarch,
+ int (*signal_frame_p) (struct gdbarch *,
+ struct frame_info *))
+{
+ struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
+
+ ops->signal_frame_p = signal_frame_p;
+}
+
+/* Query the architecture-specific signal frame recognizer for
+ NEXT_FRAME. */
+
+static int
+dwarf2_frame_signal_frame_p (struct gdbarch *gdbarch,
+ struct frame_info *next_frame)
+{
+ struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, dwarf2_frame_data);
+
+ if (ops->signal_frame_p == NULL)
+ return 0;
+ return ops->signal_frame_p (gdbarch, next_frame);
+}
\f

struct dwarf2_frame_cache
@@ -841,6 +872,13 @@ static const struct frame_unwind dwarf2_
dwarf2_frame_prev_register
};

+static const struct frame_unwind dwarf2_signal_frame_unwind =
+{
+ SIGTRAMP_FRAME,
+ dwarf2_frame_this_id,
+ dwarf2_frame_prev_register
+};
+
const struct frame_unwind *
dwarf2_frame_sniffer (struct frame_info *next_frame)
{
@@ -848,10 +886,18 @@ dwarf2_frame_sniffer (struct frame_info
function. frame_pc_unwind(), for a no-return next function, can
end up returning something past the end of this function's body. */
CORE_ADDR block_addr = frame_unwind_address_in_block (next_frame);
- if (dwarf2_frame_find_fde (&block_addr))
- return &dwarf2_frame_unwind;
+ if (!dwarf2_frame_find_fde (&block_addr))
+ return NULL;

- return NULL;
+ /* On some targets, signal trampolines may have unwind information.
+ We need to recognize them so that we set the frame type
+ correctly. */
+
+ if (dwarf2_frame_signal_frame_p (get_frame_arch (next_frame),
+ next_frame))
+ return &dwarf2_signal_frame_unwind;
+
+ return &dwarf2_frame_unwind;
}
\f

Index: gdb/dwarf2-frame.h
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/dwarf2-frame.h,v
retrieving revision 1.6
diff -u -p -r1.6 dwarf2-frame.h
--- gdb/dwarf2-frame.h 28 Feb 2004 16:59:32 -0000 1.6
+++ gdb/dwarf2-frame.h 7 Nov 2004 17:40:41 -0000
@@ -79,6 +79,14 @@ extern void dwarf2_frame_set_init_reg (s
void (*init_reg) (struct gdbarch *, int,
struct dwarf2_frame_state_reg *));

+/* Set the architecture-specific signal trampoline recognition
+ function for GDBARCH to SIGNAL_FRAME_P. */
+
+extern void
+ dwarf2_frame_set_signal_frame_p (struct gdbarch *gdbarch,
+ int (*signal_frame_p) (struct gdbarch *,
+ struct frame_info *));
+
/* Return the frame unwind methods for the function that contains PC,
or NULL if it can't be handled by DWARF CFI frame unwinder. */