From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26449 invoked by alias); 13 Jul 2011 20:23:54 -0000 Received: (qmail 26131 invoked by uid 22791); 13 Jul 2011 20:23:51 -0000 X-SWARE-Spam-Status: No, hits=-0.6 required=5.0 tests=AWL,BAYES_50,RCVD_IN_DNSWL_LOW,SPF_SOFTFAIL,TW_DB X-Spam-Check-By: sourceware.org Received: from mail-pz0-f41.google.com (HELO mail-pz0-f41.google.com) (209.85.210.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 13 Jul 2011 20:23:28 +0000 Received: by pzk4 with SMTP id 4so6044346pzk.0 for ; Wed, 13 Jul 2011 13:23:28 -0700 (PDT) Received: by 10.68.58.162 with SMTP id s2mr2007057pbq.155.1310588607985; Wed, 13 Jul 2011 13:23:27 -0700 (PDT) Received: from localhost.localdomain ([203.110.240.178]) by mx.google.com with ESMTPS id e6sm9387727pbm.39.2011.07.13.13.23.26 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 13 Jul 2011 13:23:27 -0700 (PDT) From: Sanjoy Das To: gdb-patches@sourceware.org Cc: Sanjoy Das Subject: [PATCH 3/4] Add an unwinder for JIT compiled code. Date: Thu, 14 Jul 2011 01:39:00 -0000 Message-Id: <1310588850-10967-3-git-send-email-sanjoy@playingwithpointers.com> In-Reply-To: <1310588850-10967-1-git-send-email-sanjoy@playingwithpointers.com> References: <1310588850-10967-1-git-send-email-sanjoy@playingwithpointers.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-07/txt/msg00360.txt.bz2 Add a (pseudo) unwinder which proxies back everything to the unwinder registered by the JIT debug info reader. gdb/ChangeLog: * jit.c: Add JIT frame unwinding code. * jit-reader.h: Added jit_prepend_unwinder. --- gdb/ChangeLog | 5 ++ gdb/jit.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/jit.h | 2 + 3 files changed, 157 insertions(+), 0 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ac207d1..8485b05 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ 2011-07-13 Sanjoy Das + * jit.c: Add JIT frame unwinding code. + * jit-reader.h: Added jit_prepend_unwinder. + +2011-07-13 Sanjoy Das + * jit.c: Add symbol handling callbacks for the JIT reader interface. 2011-07-13 Sanjoy Das diff --git a/gdb/jit.c b/gdb/jit.c index 2899469..03a3d0b 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -28,6 +28,7 @@ #include "breakpoint.h" #include "command.h" #include "dictionary.h" +#include "frame-unwind.h" #include "gdbcmd.h" #include "gdbcore.h" #include "inferior.h" @@ -781,6 +782,149 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch, return 0; } +struct jit_unwind_private { + struct gdbjit_reg_value *registers; + struct frame_info *this_frame; +}; + +static void +jit_unwind_reg_set_impl (struct gdbjit_unwind_callbacks *cb, int regnum, + struct gdbjit_reg_value value) +{ + struct jit_unwind_private *priv = cb->private; + int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum); + priv->registers[gdb_reg] = value; +} + +static struct gdbjit_reg_value +jit_unwind_reg_get_impl (struct gdbjit_unwind_callbacks *cb, int regnum) +{ + struct jit_unwind_private *priv = cb->private; + struct gdbjit_reg_value val; + int gdb_reg = gdbarch_dwarf2_reg_to_regnum (target_gdbarch, regnum); + val.defined = frame_register_read (priv->this_frame, gdb_reg, val.value); + return val; +} + +static int +jit_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, void **cache) +{ + /* First look up the PC, and check if the code address has been registered or + not. */ + CORE_ADDR pc = get_frame_pc (this_frame); + struct jit_inferior_data *inf_data = get_jit_inferior_data (); + struct jit_unwind_private *priv_data; + struct jit_dbg_reader *iter; + struct gdbjit_unwind_callbacks callbacks = + { + jit_unwind_reg_get_impl, + jit_unwind_reg_set_impl, + jit_target_read_impl + }; + + if (inf_data->reader == NULL) + return 0; + + /* All the unwinding happens here, and the unwound registers are written to + this block of memory, which we then sneakily read back in + jit_frame_prev_register. */ + if (!*cache) + { + *cache = XZALLOC (struct jit_unwind_private); + priv_data = *cache; + priv_data->registers = XCALLOC (gdbarch_num_regs (target_gdbarch), + struct gdbjit_reg_value); + priv_data->this_frame = this_frame; + } + else + { + priv_data = *cache; + priv_data->this_frame = this_frame; + } + + callbacks.private = priv_data; + + /* Try to coax the provided unwinder to unwind the stack, and hope it + succeeds. */ + if (inf_data->reader->unwind (inf_data->reader->private_data, &callbacks) + == GDB_JIT_SUCCESS) + return 1; + 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_inferior_data *inf_data = get_jit_inferior_data (); + struct jit_unwind_private private = + { + NULL, + this_frame + }; + struct gdbjit_frame_id frame_id; + struct gdbjit_unwind_callbacks callbacks = + { + jit_unwind_reg_get_impl, + NULL, + jit_target_read_impl, + + &private + }; + + frame_id = inf_data->reader->get_frame_id (inf_data->reader->private_data, + &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 gdbjit_reg_value value; + + if (priv == NULL) + return frame_unwind_got_optimized (this_frame, reg); + + value = priv->registers[reg]; + if (value.defined) + return frame_unwind_got_bytes (this_frame, reg, value.value); + else + return frame_unwind_got_optimized (this_frame, reg); +} + +static void +jit_dealloc_cache (struct frame_info *this_frame, void *cache) +{ + (void) this_frame; + + xfree (cache); +} + +/* 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 @@ -960,6 +1104,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..9dd8f5a 100644 --- a/gdb/jit.h +++ b/gdb/jit.h @@ -80,4 +80,6 @@ extern void jit_breakpoint_re_set (void); extern void jit_event_handler (struct gdbarch *gdbarch); +extern void jit_prepend_unwinder (struct gdbarch *gdbarch); + #endif /* JIT_H */ -- 1.7.5.4