From: Sanjoy Das <sanjoy@playingwithpointers.com>
To: gdb-patches@sourceware.org
Cc: Sanjoy Das <sanjoy@playingwithpointers.com>
Subject: [PATCH 5/7] Add a proxy unwinder.
Date: Tue, 09 Aug 2011 15:21:00 -0000 [thread overview]
Message-ID: <1312903509-25132-6-git-send-email-sanjoy@playingwithpointers.com> (raw)
In-Reply-To: <1312903509-25132-1-git-send-email-sanjoy@playingwithpointers.com>
Have the proxy unwinder pass down all calls to the functions the JIT
reader provides.
---
gdb/ChangeLog | 9 +++
gdb/jit.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/jit.h | 6 ++
3 files changed, 206 insertions(+), 0 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index bd63356..2556be7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2011-08-09 Sanjoy Das <sdas@igalia.com>
+ * jit.c (jut_unwind_reg_set_impl, free_reg_value_impl)
+ (jit_unwind_reg_get_impl, jit_frame_sniffer)
+ (jit_frame_unwind_stop_reason, jit_frame_this_id)
+ (jit_frame_prev_register, jit_dealloc_cache)
+ (jit_prepend_unwinder): New functions
+ * jit.h (jit_prepend_unwinder): New function
+
+2011-08-09 Sanjoy Das <sdas@igalia.com>
+
* jit.c (add_objfile_entry, jit_target_read_impl)
(jit_object_open_impl, jit_symtab_open_impl, compare_block)
(jit_block_open_impl, jit_block_open_impl)
diff --git a/gdb/jit.c b/gdb/jit.c
index e81a386..58c3149 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -31,6 +31,7 @@
#include "inferior.h"
#include "observer.h"
#include "objfiles.h"
+#include "regcache.h"
#include "symfile.h"
#include "symtab.h"
#include "target.h"
@@ -843,6 +844,190 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
return 0;
}
+/* The private data passed around in the frame unwind callback
+ functions. */
+struct jit_unwind_private
+{
+ /* Cached register values. See jit_frame_sniffer to see how this
+ works. */
+ struct gdb_reg_value **registers;
+ /* The frame being unwound. */
+ struct frame_info *this_frame;
+};
+
+static void
+jit_unwind_reg_set_impl (struct gdb_unwind_callbacks *cb, int regnum,
+ struct gdb_reg_value *value)
+{
+ struct jit_unwind_private *priv = cb->priv_data;
+ int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum);
+ gdb_assert (priv->registers);
+ priv->registers[gdb_reg] = value;
+}
+
+static void
+free_reg_value_impl (struct gdb_reg_value *reg_value)
+{
+ free (reg_value);
+}
+
+static struct gdb_reg_value *
+jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
+{
+ struct jit_unwind_private *priv = cb->priv_data;
+ int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum);
+ int size = register_size (target_gdbarch, gdb_reg);
+ struct gdb_reg_value *value = malloc (sizeof (struct gdb_reg_value) +
+ size - 1);
+ value->defined = frame_register_read (priv->this_frame, gdb_reg,
+ value->value);
+ value->size = size;
+ value->free = free_reg_value_impl;
+ return value;
+}
+
+/* The frame sniffer for the pseudo unwinder.
+
+ While this is nominally a frame sniffer, in the case where the JIT
+ reader actually recognizes the frame, it does a lot more work -- it
+ unwinds the frame and saves the corresponding register values in
+ the cache. jit_frame_prev_register simply returns the saved
+ register values. */
+static int
+jit_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame, void **cache)
+{
+ struct jit_inferior_data *inf_data = get_jit_inferior_data ();
+ struct jit_unwind_private *priv_data;
+ struct jit_dbg_reader *iter;
+ struct gdb_unwind_callbacks callbacks =
+ {
+ jit_unwind_reg_get_impl,
+ jit_unwind_reg_set_impl,
+ jit_target_read_impl
+ };
+ struct gdb_reader_funcs *funcs;
+
+ if (loaded_jit_reader == NULL)
+ return 0;
+ funcs = loaded_jit_reader->functions;
+
+ if (!*cache)
+ {
+ *cache = XZALLOC (struct jit_unwind_private);
+ priv_data = *cache;
+ priv_data->registers = XCALLOC (gdbarch_num_regs (target_gdbarch),
+ struct gdb_reg_value *);
+ priv_data->this_frame = this_frame;
+ }
+ else
+ {
+ priv_data = *cache;
+ priv_data->this_frame = this_frame;
+ }
+
+ callbacks.priv_data = priv_data;
+
+ /* Try to coax the provided unwinder to unwind the stack */
+ if (funcs->unwind (funcs, &callbacks) == GDB_SUCCESS)
+ {
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog, "Successfully unwound frame using "
+ "JIT reader.\n");
+ return 1;
+ }
+ if (jit_debug)
+ fprintf_unfiltered (gdb_stdlog, "Could not unwind frame using "
+ "JIT reader.\n");
+
+ xfree (priv_data->registers);
+ xfree (priv_data);
+ *cache = NULL;
+
+ return 0;
+}
+
+static enum unwind_stop_reason
+jit_frame_unwind_stop_reason (struct frame_info *this_frame, void **cache)
+{
+ return UNWIND_NO_REASON;
+}
+
+static void
+jit_frame_this_id (struct frame_info *this_frame, void **cache,
+ struct frame_id *this_id)
+{
+ struct jit_unwind_private private =
+ {
+ NULL,
+ this_frame
+ };
+ struct gdb_frame_id frame_id;
+ struct gdb_reader_funcs *funcs;
+ struct gdb_unwind_callbacks callbacks =
+ {
+ jit_unwind_reg_get_impl,
+ NULL,
+ jit_target_read_impl,
+
+ &private
+ };
+
+ gdb_assert (loaded_jit_reader);
+ funcs = loaded_jit_reader->functions;
+
+ frame_id = funcs->get_frame_id (funcs, &callbacks);
+ *this_id = frame_id_build (frame_id.stack_address, frame_id.code_address);
+}
+
+static struct value *
+jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
+{
+ struct jit_unwind_private *priv = *cache;
+ struct gdb_reg_value *value;
+
+ if (priv == NULL)
+ return frame_unwind_got_optimized (this_frame, reg);
+
+ gdb_assert (priv->registers);
+ value = priv->registers[reg];
+ if (value && value->defined)
+ return frame_unwind_got_bytes (this_frame, reg, value->value);
+ else
+ return frame_unwind_got_optimized (this_frame, reg);
+}
+
+/* gdb_reg_value has a free function, which must be called on each
+ saved register value. */
+static void
+jit_dealloc_cache (struct frame_info *this_frame, void *cache)
+{
+ struct jit_unwind_private *priv_data = cache;
+ int i;
+
+ gdb_assert (priv_data->registers);
+
+ for (i = 0; i < gdbarch_num_regs (target_gdbarch); i++)
+ if (priv_data->registers[i] && priv_data->registers[i]->free)
+ priv_data->registers[i]->free (priv_data->registers[i]);
+
+ xfree (priv_data->registers);
+ xfree (priv_data);
+}
+
+/* Simply relays everything back to the unwinder registered by the JIT
+ debug info reader.*/
+static const struct frame_unwind jit_frame_unwind =
+{
+ NORMAL_FRAME,
+ jit_frame_unwind_stop_reason,
+ jit_frame_this_id,
+ jit_frame_prev_register,
+ NULL,
+ jit_frame_sniffer,
+ jit_dealloc_cache
+};
+
/* Register any already created translations. */
static void
@@ -1010,6 +1195,12 @@ jit_event_handler (struct gdbarch *gdbarch)
}
}
+void
+jit_prepend_unwinder (struct gdbarch *gdbarch)
+{
+ frame_unwind_prepend_unwinder (gdbarch, &jit_frame_unwind);
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
extern void _initialize_jit (void);
diff --git a/gdb/jit.h b/gdb/jit.h
index 73a1414..29cd10d 100644
--- a/gdb/jit.h
+++ b/gdb/jit.h
@@ -80,4 +80,10 @@ extern void jit_breakpoint_re_set (void);
extern void jit_event_handler (struct gdbarch *gdbarch);
+/* Prepend the JIT unwinder GDBARCH's. Prepending adds negligible
+ overhead since this unwinder quickly fails if no JIT reader is
+ loaded. This also prevents other unwinders which depend on the BFD
+ field not being NULL from tripping. */
+extern void jit_prepend_unwinder (struct gdbarch *gdbarch);
+
#endif /* JIT_H */
--
1.7.5.4
next prev parent reply other threads:[~2011-08-09 15:21 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-08-09 15:21 [PATCH] JIT debug info Reader Sanjoy Das
2011-08-09 15:21 ` [PATCH 1/7] Introduce header (jit-reader.h.in) and modify build system Sanjoy Das
2011-08-09 15:40 ` Eli Zaretskii
2011-08-09 15:43 ` Sanjoy Das
2011-08-09 15:53 ` Eli Zaretskii
2011-08-20 17:17 ` Jan Kratochvil
2011-08-20 17:31 ` Eli Zaretskii
2011-08-20 17:42 ` Jan Kratochvil
2011-08-20 17:52 ` Eli Zaretskii
2011-08-10 20:57 ` Tom Tromey
2011-08-09 15:21 ` [PATCH 4/7] Use the loaded reader Sanjoy Das
2011-08-15 20:21 ` Tom Tromey
2011-08-09 15:21 ` [PATCH 3/7] New commands for loading and unloading a reader Sanjoy Das
2011-08-12 20:58 ` Tom Tromey
2011-08-09 15:21 ` [PATCH 7/7] Add documentation Sanjoy Das
2011-08-09 15:51 ` Eli Zaretskii
2011-08-09 15:21 ` Sanjoy Das [this message]
2011-08-15 20:38 ` [PATCH 5/7] Add a proxy unwinder Tom Tromey
2011-08-20 6:26 ` Sanjoy Das
2011-08-09 15:21 ` [PATCH 2/7] Add platform agnostic dynamic loading code Sanjoy Das
2011-08-10 21:01 ` Tom Tromey
2011-08-09 15:21 ` [PATCH 6/7] Register the proxy unwinder Sanjoy Das
2011-08-12 21:07 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1312903509-25132-6-git-send-email-sanjoy@playingwithpointers.com \
--to=sanjoy@playingwithpointers.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox