This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [RFC][PATCH] Allow JIT unwinder provide symbol information
- From: Alexander Smundak <asmundak at google dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 18 Feb 2014 19:30:43 -0800
- Subject: Re: [RFC][PATCH] Allow JIT unwinder provide symbol information
- Authentication-results: sourceware.org; auth=none
- References: <20131226183618 dot D264CA18A0 at sasha2 dot mtv dot corp dot google dot com> <21204 dot 13416 dot 607204 dot 485255 at ruffy dot mtv dot corp dot google dot com> <CAHQ51u6Hd3+B78RUK5rTh49nqvFgt_o1x6f=sePPZVDEo1ueTA at mail dot gmail dot com> <CADPb22Qithfi41fs1Ax5tz_g-zf8pzPRWKbnBrJZCiSqrO=KuA at mail dot gmail dot com> <CADPb22Rf5jpi_YCF5UE13=CUmUV-FNZHPSpfbmpO3KNQq1sKfQ at mail dot gmail dot com>
> On a separate note,
> IIRC we still have to decide how to handle version 1 jit-reader-load
> shared libs.The revised patch addressing the reviewer's comments is below.
Is it known if anybody is using this version?
The patch addressing review comments is below.
2013-12-19 Sasha Smundak <asmundak@google.com>
* gdb/NEWS: Announcement.
* gdb/frame-unwind.h (frame_symbol_type): New function type.
(struct frame_unwind): Add the pointer to the frame_symbol_type.
* gdb/frame.c (get_frame_symbol_info): New function.
* gdb/frame.h (struct frame_symbol_info): Declare the struct
containing symbol information returned by the unwinder.
(get_frame_symbol_info): Declare it.
* gdb/jit-reader.in (GDB_READER_INTERFACE_VERSION): New version.
(gdb_unwind_stash): New function type.
(gdb_find_symbol): Ditto.
(gdb_get_jtid): Ditto.
(gdb_enumerate_shared): Ditto.
(gdb_unwind_debug_flag): Ditto.
(gdb_architecture_name): Ditto.
(gdb_pointer_size): Ditto.
(struct gdb_unwind_callbacks): Add members pointing to
gdb_unwind_stash, unwind_reg_get, gdb_find_symbol, gdb_get_jtid,
gdb_enumerate_shared, gdb_unwind_debug_flag,
gdb_architecture_name and gdb_pointer_size functions.
(enum jit_frame_symbol_attr): New enum.
(enum jit_frame_language): Ditto.
(gdb_get_symbol_attr): New function type.
(struct gdb_reader_funcs): Add member pointing to
gdb_get_symbol_attr function.
* gdb/jit.c: Include arch-utils.h.
Include solist.h.
Include ptid.h.
(jit_prepend_unwinder): Declare.
(jit_find_symbol_address): Declare.
(jit_get_current_jtid): Declare.
(jit_enumerate_shared): Declare.
(jit_unwind_debug_flag): Declare.
(jit_unwind_architecture_name): Declare.
(jit_unwind_pointer_size): Declare.
(jit_unwind_debug): Declare.
(show_jit_unwind_debug): New function.
(jit_breakpoint_re_set_internal): Add the call to
jit_prepend_unwinder.
(struct jit_unwind_private): Add a member containing the
pointer to JIT reader's private area.
(jit_get_register_from_frame): New function returning a
register from the given frame (refactored from
jit_unwind_reg_get_impl).
(jit_unwind_reg_get_impl): Now a wrapper around
jit_get_register_from_frame.
(jit_unwind_get_cpu_register_value): New function to get
"live" registers.
(jit_stash_impl): Allocate private data area for the JIT reader.
(jit_dealloc_cache): Free JIT reader private area.
(jit_set_unwind_callbacks_vtable): New function, refactored
from two different places where callbacks were set up.
(jit_frame_sniffer): Use jit_set_unwind_callbacks_vtable.
(jit_frame_language_to_language): New function converting
JIT reader's language type to the GDB internal language type.
(jit_symbol): New function returning symbol information supplied
by the JIT reader.
(jit_frame_unwind): Add the pointer to jit_symbol.
(jit_find_symbol_address): New GDB callback for the JIT reader
returning symbols's address.
(jit_get_current_jtid): New GDB callback for the JIT reader
returning the current thread ID.
(jit_enumerate_shared): New GDB callback for the JIT reader to
traverse inferior's shared objects.
(jit_unwind_debug_flag): New GDB callback returning JIT unwind
debugging flags.
(jit_unwind_architecture_name): New GDB callback returning
inferior's architecture name.
(jit_unwind_pointer_size): New GDB callback returning inferior's
pointer size.
(_initialize_jit): Register 'show/set debug jitunwind'
subcommand.
* gdb/stack.c (find_frame_funname): If symbol information from
the unwindeer if available.
(find_frame_source_location): New function to return symbol
source location from the unwinder if available.
(print_frame): Use arguments information and source location
from the unwinder if available.
diff --git a/gdb/NEWS b/gdb/NEWS
index b54a414..34b7dc6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,9 @@
*** Changes since GDB 7.7
+* Revised JIT interface allows creating plugins that display
+ JIT_specific symbol information.
+
* Guile scripting
GDB now has support for scripting using Guile. Whether this is
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
index 9507be2..407b882 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -140,6 +140,12 @@ typedef void (frame_dealloc_cache_ftype) (struct
frame_info *self,
typedef struct gdbarch *(frame_prev_arch_ftype) (struct frame_info *this_frame,
void **this_prologue_cache);
+/* Return unwinder-specific symbol info or NULL. */
+
+typedef const struct frame_symbol_info* (frame_symbol_ftype)
+ (struct frame_info *this_frame,
+ void **this_prologue_cache);
+
struct frame_unwind
{
/* The frame's type. Should this instead be a collection of
@@ -154,6 +160,9 @@ struct frame_unwind
frame_sniffer_ftype *sniffer;
frame_dealloc_cache_ftype *dealloc_cache;
frame_prev_arch_ftype *prev_arch;
+ /* For the JIT interface to give external code a chance to supply
+ symbol information describing the frame. */
+ frame_symbol_ftype *symbol_info;
};
/* Register a frame unwinder, _prepending_ it to the front of the
diff --git a/gdb/frame.c b/gdb/frame.c
index 8cd607b..72331ac 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2307,6 +2307,16 @@ find_frame_sal (struct frame_info *frame,
struct symtab_and_line *sal)
(*sal) = find_pc_line (pc, notcurrent);
}
+/* If frame-specific unwinder has symbol info, return it. */
+
+const struct frame_symbol_info *
+get_frame_symbol_info (struct frame_info *fi)
+{
+ return ((fi->unwind->symbol_info == NULL)
+ ? NULL
+ : fi->unwind->symbol_info (fi, &fi->prologue_cache));
+}
+
/* Per "frame.h", return the ``address'' of the frame. Code should
really be using get_frame_id(). */
CORE_ADDR
diff --git a/gdb/frame.h b/gdb/frame.h
index e451a93..c7365c7 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -491,6 +491,23 @@ enum unwind_stop_reason
#undef FIRST_ERROR
};
+/* Unwinder-specific symbol information. */
+
+struct frame_symbol_info
+{
+ const char *function;
+ const char *source_file;
+ const char *arguments;
+ enum language language;
+ int source_line;
+};
+
+/* Return symbol information supplied by the unwinder. If this frame's
+ unwinder implements frame_unwind.symbol_info method, calls it and
+ returns the result, otherwise returns NULL. */
+
+const struct frame_symbol_info *get_frame_symbol_info (struct frame_info *);
+
/* Return the reason why we can't unwind past this frame. */
enum unwind_stop_reason get_frame_unwind_stop_reason (struct frame_info *);
diff --git a/gdb/jit-reader.in b/gdb/jit-reader.in
index 6e2ee64..a6a0ab1 100644
--- a/gdb/jit-reader.in
+++ b/gdb/jit-reader.in
@@ -26,7 +26,7 @@ extern "C" {
/* Versioning information. See gdb_reader_funcs. */
-#define GDB_READER_INTERFACE_VERSION 1
+#define GDB_READER_INTERFACE_VERSION 2
/* Readers must be released under a GPL compatible license. To
declare that the reader is indeed released under a GPL compatible
@@ -260,6 +260,43 @@ typedef struct gdb_reg_value *(gdb_unwind_reg_get)
typedef void (gdb_unwind_reg_set) (struct gdb_unwind_callbacks *cb, int regnum,
struct gdb_reg_value *val);
+/* Provides access to the stashed data associated with the current frame.
+ On first call, allocates the memory and zeroes it. On subsequent calls
+ returns the pointer to the allocated memory. */
+
+typedef void * (gdb_unwind_stash) (struct gdb_unwind_callbacks *cb,
+ size_t size);
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches SYMBOL_NAME. Return symbol's
+ address, 0 if symbol is unknown.
+ If it is a C++ symbol, SYMBOL_NAME is in a mangled form. */
+
+typedef GDB_CORE_ADDR (gdb_find_symbol) (const char *symbol_name);
+
+/* Returns thread ID of the current thread or 0. */
+
+typedef long (gdb_get_jtid) (void);
+
+/* Iterate over shared objects present in the inferior, calling given
+ callback function for each shared object. The callback is passed
+ the shared object file name, expanded to something GDB can open,
+ and data pointer. Once the callback function returns non-zero,
+ stop iteration and return shared object file name. */
+
+typedef const char * (gdb_enumerate_shared) (int (*) (const char *so_name,
+ void *data),
+ void *data);
+
+/* Returns debug flags setting for the unwinding. */
+typedef unsigned int (gdb_unwind_debug_flag) (void);
+
+/* Returns inferior's architecture name. */
+typedef const char * (gdb_architecture_name) (void);
+
+/* Returns inferior's pointer size in bytes. */
+typedef size_t (gdb_pointer_size)(void);
+
/* This struct is passed to unwind in gdb_reader_funcs, and is to be
used to unwind the current frame (current being the frame whose
registers can be read using reg_get) into the earlier frame. The
@@ -270,7 +307,14 @@ struct gdb_unwind_callbacks
gdb_unwind_reg_get *reg_get;
gdb_unwind_reg_set *reg_set;
gdb_target_read *target_read;
-
+ gdb_unwind_stash *stash;
+ gdb_unwind_reg_get *cpu_reg_get;
+ gdb_find_symbol *find_symbol;
+ gdb_get_jtid *get_jtid;
+ gdb_enumerate_shared *enumerate_shared;
+ gdb_unwind_debug_flag *debug_flag;
+ gdb_architecture_name *architecture_name;
+ gdb_pointer_size *pointer_size;
/* For internal use by GDB. */
void *priv_data;
};
@@ -306,6 +350,39 @@ typedef enum gdb_status (gdb_unwind_frame)
(struct gdb_reader_funcs *self,
typedef struct gdb_frame_id (gdb_get_frame_id) (struct gdb_reader_funcs *self,
struct
gdb_unwind_callbacks *c);
+enum jit_frame_symbol_attr {
+ JIT_FRAME_SYMBOL_ATTR_FUNCTION_NAME,
+ JIT_FRAME_SYMBOL_ATTR_LANGUAGE,
+ JIT_FRAME_SYMBOL_ATTR_SOURCE_FILE,
+ JIT_FRAME_SYMBOL_ATTR_SOURCE_LINE,
+ JIT_FRAME_SYMBOL_ATTR_FUNCTION_ARGS,
+};
+
+enum jit_frame_language {
+ frame_language_unknown, /* Language not known */
+ frame_language_auto, /* Placeholder for automatic setting */
+ frame_language_c, /* C */
+ frame_language_cplus, /* C++ */
+ frame_language_d, /* D */
+ frame_language_go, /* Go */
+ frame_language_objc, /* Objective-C */
+ frame_language_java, /* Java */
+ frame_language_fortran, /* Fortran */
+ frame_language_m2, /* Modula-2 */
+ frame_language_asm, /* Assembly language */
+ frame_language_pascal, /* Pascal */
+ frame_language_ada, /* Ada */
+ frame_language_opencl, /* OpenCL */
+ frame_language_minimal, /* All other languages, minimal
support only */
+ frame_nr_languages
+};
+
+/* Return given attribute of a symbol associated with the current frame. */
+
+typedef void * (gdb_get_symbol_attr) (struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *c,
+ enum jit_frame_symbol_attr attr);
+
/* Called when a reader is being unloaded. This function should also
free SELF, if required. */
@@ -336,6 +413,7 @@ struct gdb_reader_funcs
gdb_read_debug_info *read;
gdb_unwind_frame *unwind;
gdb_get_frame_id *get_frame_id;
+ gdb_get_symbol_attr *get_symbol_attr;
gdb_destroy_reader *destroy;
};
diff --git a/gdb/jit.c b/gdb/jit.c
index 546b3b6..147ab52 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -21,6 +21,7 @@
#include "jit.h"
#include "jit-reader.h"
+#include "arch-utils.h"
#include "block.h"
#include "breakpoint.h"
#include "command.h"
@@ -33,6 +34,7 @@
#include "observer.h"
#include "objfiles.h"
#include "regcache.h"
+#include "solist.h"
#include "symfile.h"
#include "symtab.h"
#include "target.h"
@@ -40,6 +42,7 @@
#include <sys/stat.h>
#include "exceptions.h"
#include "gdb_bfd.h"
+#include "ptid.h"
static const char *jit_reader_dir = NULL;
@@ -53,6 +56,22 @@ static const struct program_space_data
*jit_program_space_data = NULL;
static void jit_inferior_init (struct gdbarch *gdbarch);
+static void jit_prepend_unwinder (struct gdbarch *gdbarch);
+
+static CORE_ADDR jit_unwind_find_symbol_address (const char *);
+
+static long jit_unwind_get_current_jtid (void);
+
+static const char *jit_unwind_enumerate_shared (int (*callback) (const char *,
+ void *),
+ void *);
+
+static unsigned int jit_unwind_debug_flag (void);
+
+static const char *jit_unwind_architecture_name (void);
+
+static size_t jit_unwind_pointer_size (void);
+
/* An unwinder is registered for every gdbarch. This key is used to
remember if the unwinder has been registered for a particular
gdbarch. */
@@ -70,6 +89,15 @@ show_jit_debug (struct ui_file *file, int from_tty,
fprintf_filtered (file, _("JIT debugging is %s.\n"), value);
}
+static unsigned jit_unwind_debug;
+
+static void
+show_jit_unwind_debug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("JIT unwinder debugging is %s.\n"), value);
+}
+
struct target_buffer
{
CORE_ADDR base;
@@ -1020,6 +1048,8 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
struct jit_objfile_data *objf_data;
CORE_ADDR addr;
+ jit_prepend_unwinder (gdbarch);
+
if (ps_data->objfile == NULL)
{
/* Lookup the registration symbol. If it is missing, then we
@@ -1076,6 +1106,12 @@ struct jit_unwind_private
/* The frame being unwound. */
struct frame_info *this_frame;
+
+ /* Symbol associated with this frame. */
+ struct frame_symbol_info symbol_info;
+
+ /* Memory allocated on behalf of JIT handler. */
+ void *stash;
};
/* Sets the value of a particular register in this frame. */
@@ -1110,29 +1146,65 @@ reg_value_free_impl (struct gdb_reg_value *value)
xfree (value);
}
-/* Get the value of register REGNUM in the previous frame. */
+/* Get the value of register REGNUM in the given frame. */
static struct gdb_reg_value *
-jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
+jit_get_register_from_frame (struct frame_info *this_frame, int regnum)
{
- struct jit_unwind_private *priv;
struct gdb_reg_value *value;
int gdb_reg, size;
struct gdbarch *frame_arch;
- priv = cb->priv_data;
- frame_arch = get_frame_arch (priv->this_frame);
+ frame_arch = get_frame_arch (this_frame);
gdb_reg = gdbarch_dwarf2_reg_to_regnum (frame_arch, regnum);
size = register_size (frame_arch, gdb_reg);
value = xmalloc (sizeof (struct gdb_reg_value) + size - 1);
- value->defined = deprecated_frame_register_read (priv->this_frame, gdb_reg,
+ value->defined = deprecated_frame_register_read (this_frame, gdb_reg,
value->value);
value->size = size;
value->free = reg_value_free_impl;
return value;
}
+/* Get the value of register REGNUM in the previous frame. */
+
+static struct gdb_reg_value *
+jit_unwind_reg_get_impl (struct gdb_unwind_callbacks *cb, int regnum)
+{
+ return jit_get_register_from_frame (
+ ((struct jit_unwind_private *) cb->priv_data)->this_frame, regnum);
+}
+
+/* Get the value of the register REGNUM in the innermost frame. */
+
+static struct gdb_reg_value *
+jit_unwind_get_cpu_register_value (struct gdb_unwind_callbacks *cb, int regnum)
+{
+ struct frame_info *frame
+ = ((struct jit_unwind_private *) cb->priv_data)->this_frame;
+ struct frame_info *next_frame;
+
+ while ((next_frame = get_next_frame (frame)) != NULL)
+ frame = next_frame;
+ return jit_get_register_from_frame (frame, regnum);
+}
+
+/* Return memory area allocated for the JIT reader. The area is allocated on
+ demand (the first time this function is called with non-zero size).
+ Calling this function with size == 0 will not allocate memory but will
+ return its address if it has been already allocated. */
+
+static void *
+jit_unwind_stash_impl (struct gdb_unwind_callbacks *cb, size_t size)
+{
+ struct jit_unwind_private *priv_data = cb->priv_data;
+
+ if (!priv_data->stash && size)
+ priv_data->stash = xcalloc (size, 1);
+ return priv_data->stash;
+}
+
/* gdb_reg_value has a free function, which must be called on each
saved register value. */
@@ -1151,9 +1223,27 @@ jit_dealloc_cache (struct frame_info
*this_frame, void *cache)
priv_data->registers[i]->free (priv_data->registers[i]);
xfree (priv_data->registers);
+ xfree (priv_data->stash);
xfree (priv_data);
}
+static void
+jit_set_unwind_callbacks_vtable (struct gdb_unwind_callbacks *callbacks,
+ int allow_reg_set)
+{
+ callbacks->reg_get = jit_unwind_reg_get_impl;
+ callbacks->reg_set = allow_reg_set ? jit_unwind_reg_set_impl : NULL;
+ callbacks->target_read = jit_target_read_impl;
+ callbacks->stash = jit_unwind_stash_impl;
+ callbacks->cpu_reg_get = jit_unwind_get_cpu_register_value;
+ callbacks->find_symbol = jit_unwind_find_symbol_address;
+ callbacks->get_jtid = jit_unwind_get_current_jtid;
+ callbacks->enumerate_shared = jit_unwind_enumerate_shared;
+ callbacks->debug_flag = jit_unwind_debug_flag;
+ callbacks->architecture_name = jit_unwind_architecture_name;
+ callbacks->pointer_size = jit_unwind_pointer_size;
+}
+
/* The frame sniffer for the pseudo unwinder.
While this is nominally a frame sniffer, in the case where the JIT
@@ -1170,9 +1260,7 @@ jit_frame_sniffer (const struct frame_unwind *self,
struct gdb_unwind_callbacks callbacks;
struct gdb_reader_funcs *funcs;
- callbacks.reg_get = jit_unwind_reg_get_impl;
- callbacks.reg_set = jit_unwind_reg_set_impl;
- callbacks.target_read = jit_target_read_impl;
+ jit_set_unwind_callbacks_vtable (&callbacks, 1);
if (loaded_jit_reader == NULL)
return 0;
@@ -1226,9 +1314,7 @@ jit_frame_this_id (struct frame_info
*this_frame, void **cache,
/* We don't expect the frame_id function to set any registers, so we
set reg_set to NULL. */
- callbacks.reg_get = jit_unwind_reg_get_impl;
- callbacks.reg_set = NULL;
- callbacks.target_read = jit_target_read_impl;
+ jit_set_unwind_callbacks_vtable (&callbacks, 0);
callbacks.priv_data = &private;
gdb_assert (loaded_jit_reader);
@@ -1258,6 +1344,73 @@ jit_frame_prev_register (struct frame_info
*this_frame, void **cache, int reg)
return frame_unwind_got_optimized (this_frame, reg);
}
+/* Convert jit_frame_language enum to GDB's internal language enum. */
+
+static enum language
+jit_frame_language_to_language (enum jit_frame_language frame_language)
+{
+#define LANG_CASE(x) frame_language_##x: return language_##x
+ switch (frame_language)
+ {
+ LANG_CASE (auto);
+ LANG_CASE (c);
+ LANG_CASE (cplus);
+ LANG_CASE (d);
+ LANG_CASE (go);
+ LANG_CASE (objc);
+ LANG_CASE (java);
+ LANG_CASE (fortran);
+ LANG_CASE (m2);
+ LANG_CASE (asm);
+ LANG_CASE (pascal);
+ LANG_CASE (ada);
+ LANG_CASE (opencl);
+ LANG_CASE (minimal);
+ default:
+ return language_unknown;
+ }
+#undef LANG_CASE
+}
+
+/* Returns unwinder-specific symbol info. */
+
+static const struct frame_symbol_info *
+jit_symbol (struct frame_info *this_frame, void **cache)
+{
+ struct gdb_reader_funcs *funcs;
+ struct gdb_unwind_callbacks callbacks;
+ struct jit_unwind_private *priv_data;
+
+ if (*cache == NULL)
+ return NULL;
+
+ jit_set_unwind_callbacks_vtable (&callbacks, 0);
+ priv_data = *cache;
+ callbacks.priv_data = priv_data;
+
+ gdb_assert (loaded_jit_reader);
+
+ funcs = loaded_jit_reader->functions;
+ priv_data->symbol_info.function
+ = funcs->get_symbol_attr (funcs, &callbacks,
+ JIT_FRAME_SYMBOL_ATTR_FUNCTION_NAME);
+ priv_data->symbol_info.language
+ = jit_frame_language_to_language (
+ (enum jit_frame_language)
+ (funcs->get_symbol_attr (funcs, &callbacks,
+ JIT_FRAME_SYMBOL_ATTR_LANGUAGE)));
+ priv_data->symbol_info.source_file
+ = funcs->get_symbol_attr (funcs, &callbacks,
+ JIT_FRAME_SYMBOL_ATTR_SOURCE_FILE);
+ priv_data->symbol_info.source_line = (int)(uintptr_t)
+ funcs->get_symbol_attr (funcs, &callbacks,
+ JIT_FRAME_SYMBOL_ATTR_SOURCE_LINE);
+ priv_data->symbol_info.arguments
+ = funcs->get_symbol_attr (funcs, &callbacks,
+ JIT_FRAME_SYMBOL_ATTR_FUNCTION_ARGS);
+ return &priv_data->symbol_info;
+}
+
/* Relay everything back to the unwinder registered by the JIT debug
info reader.*/
@@ -1267,9 +1420,11 @@ static const struct frame_unwind jit_frame_unwind =
default_frame_unwind_stop_reason,
jit_frame_this_id,
jit_frame_prev_register,
- NULL,
+ NULL, /* frame_data */
jit_frame_sniffer,
- jit_dealloc_cache
+ jit_dealloc_cache,
+ NULL, /* prev_arch */
+ jit_symbol,
};
@@ -1310,8 +1465,6 @@ jit_inferior_init (struct gdbarch *gdbarch)
if (jit_debug)
fprintf_unfiltered (gdb_stdlog, "jit_inferior_init\n");
- jit_prepend_unwinder (gdbarch);
-
ps_data = get_jit_program_space_data ();
if (jit_breakpoint_re_set_internal (gdbarch, ps_data) != 0)
return;
@@ -1443,6 +1596,67 @@ free_objfile_data (struct objfile *objfile, void *data)
xfree (data);
}
+/* Locates exported symbol in the target and returns its address. */
+
+CORE_ADDR
+jit_unwind_find_symbol_address (const char *symbol_name)
+{
+ struct minimal_symbol *min_symbol
+ = lookup_minimal_symbol (symbol_name, NULL, NULL);
+
+ return (min_symbol == NULL) ? 0 : SYMBOL_VALUE_ADDRESS (min_symbol);
+}
+
+/* Returns thread ID of the inferior's current thread. */
+
+long
+jit_unwind_get_current_jtid (void)
+{
+ long jtid = ptid_get_lwp (inferior_ptid);
+
+ /* ptid_get_lwp returns 0 if inferior is run via gdbserver.
+ However, ptid_get_tid returns 0 for the local inferior. Ugly. */
+ return jtid ? jtid : ptid_get_tid (inferior_ptid);
+}
+
+/* Calls provided function for every shared object currently loaded into
+ the inferior until the function returns non zero. */
+
+const char *
+jit_unwind_enumerate_shared (int (*callback) (const char *so_name,
+ void *data),
+ void *data)
+{
+ struct so_list *so;
+
+ for (so = master_so_list (); so; so = so->next)
+ {
+ if (callback (so->so_name, data))
+ return so->so_name;
+ }
+ return NULL;
+}
+
+static unsigned int
+jit_unwind_debug_flag (void)
+{
+ return jit_unwind_debug;
+}
+
+
+/* Return current architecture's string name. */
+static const char *
+jit_unwind_architecture_name (void)
+{
+ return gdbarch_bfd_arch_info (target_gdbarch ())->printable_name;
+}
+
+static size_t
+jit_unwind_pointer_size (void)
+{
+ return gdbarch_ptr_bit (target_gdbarch()) / 8;
+}
+
/* Initialize the jit_gdbarch_data slot with an instance of struct
jit_gdbarch_data_type */
@@ -1472,6 +1686,13 @@ _initialize_jit (void)
NULL,
show_jit_debug,
&setdebuglist, &showdebuglist);
+ add_setshow_zuinteger_cmd ("jitunwind", class_maintenance, &jit_unwind_debug,
+ _("Set JIT frame unwinder debug."),
+ _("Show JIT frame unwinder debug."),
+ _("A collection of bit flags for debugging."),
+ NULL,
+ show_jit_unwind_debug,
+ &setdebuglist, &showdebuglist);
observer_attach_inferior_exit (jit_inferior_exit_hook);
observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
diff --git a/gdb/stack.c b/gdb/stack.c
index 54553bc..3bcc54e 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1038,6 +1038,15 @@ find_frame_funname (struct frame_info *frame,
char **funname,
enum language *funlang, struct symbol **funcp)
{
struct symbol *func;
+ const struct frame_symbol_info *frame_symbol = get_frame_symbol_info (frame);
+
+ if (frame_symbol != NULL)
+ {
+ *funname = xstrdup (frame_symbol->function);
+ *funlang = frame_symbol->language;
+ *funcp = NULL;
+ return;
+ }
*funname = NULL;
*funlang = language_unknown;
@@ -1125,6 +1134,23 @@ find_frame_funname (struct frame_info *frame,
char **funname,
}
}
+/* Fill unwinder-specific source location for the frame if available and
+ return 1. Otherwise return 0. */
+
+static int
+find_frame_source_location (struct frame_info *fi, const char **file,
+ int *line)
+{
+ const struct frame_symbol_info *frame_symbol = get_frame_symbol_info (fi);
+
+ if (frame_symbol == NULL || frame_symbol->source_file == NULL)
+ return 0;
+
+ *file = frame_symbol->source_file;
+ *line = frame_symbol->source_line;
+ return 1;
+}
+
static void
print_frame (struct frame_info *frame, int print_level,
enum print_what print_what, int print_args,
@@ -1140,6 +1166,8 @@ print_frame (struct frame_info *frame, int print_level,
struct symbol *func;
CORE_ADDR pc = 0;
int pc_p;
+ const char *file;
+ int line;
pc_p = get_frame_pc_if_available (frame, &pc);
@@ -1200,7 +1228,16 @@ print_frame (struct frame_info *frame, int print_level,
args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args");
TRY_CATCH (e, RETURN_MASK_ERROR)
{
- print_frame_args (func, frame, numargs, gdb_stdout);
+ const struct frame_symbol_info *frame_symbol;
+ frame_symbol = get_frame_symbol_info (frame);
+
+ if (frame_symbol != NULL)
+ {
+ if (frame_symbol->arguments != NULL)
+ ui_out_text (uiout, frame_symbol->arguments);
+ }
+ else
+ print_frame_args (func, frame, numargs, gdb_stdout);
}
/* FIXME: ARGS must be a list. If one argument is a string it
will have " that will not be properly escaped. */
@@ -1209,7 +1246,21 @@ print_frame (struct frame_info *frame, int print_level,
QUIT;
}
ui_out_text (uiout, ")");
- if (sal.symtab)
+
+ if (find_frame_source_location (frame, &file, &line))
+ {
+ annotate_frame_source_begin ();
+ ui_out_wrap_hint (uiout, " ");
+ ui_out_text (uiout, " at ");
+ annotate_frame_source_file ();
+ ui_out_field_string (uiout, "file", file);
+ annotate_frame_source_file_end ();
+ ui_out_text (uiout, ":");
+ annotate_frame_source_line ();
+ ui_out_field_int (uiout, "line", line);
+ annotate_frame_source_end ();
+ }
+ else if (sal.symtab)
{
const char *filename_display;
On Tue, Feb 11, 2014 at 11:50 PM, Doug Evans <dje@google.com> wrote:
> On Tue, Feb 11, 2014 at 2:25 PM, Doug Evans <dje@google.com> wrote:
>> On Tue, Jan 14, 2014 at 4:39 PM, Alexander Smundak <asmundak@google.com> wrote:
>>> I fixed the patch based on your comments, except for the one
>>> about using LWP for thread identification.
>>> Waiting for the opinions about the approach used in this RFC patch.
>>>
>>>> > +/* Returns LWP ID of the current thread or 0. */
>>>> > +
>>>> > +typedef long (gdb_get_lwp) (void);
>
> Another issue that occurs to me is what if the loaded jit shared
> library on some platform (not necessarily linux) wants to use
> ptid.tid, even if both ptid.lwp and ptid.tid are available?
>
> Does it make sense to provide routines that access each?
>
> Pedro, the issue is what handle on a thread to export to the
> jit-reader-load shared library.
> Java for linux wants the lwp, and currently the patch will return
> ptid.tid instead of ptid.lwp if lwp == 0 to shield the shared lib
> from gdb vs gdbserver thread ptid usage differences, on the assumption
> that if lwp == 0 then tid is actually lwp.
>
> On a separate note,
> IIRC we still have to decide how to handle version 1 jit-reader-load
> shared libs.