[PATCH 1/2] jit-reader.h: describe interface implemented by the JIT readers.

Sanjoy Das sanjoy@playingwithpointers.com
Wed Jul 13 20:23:00 GMT 2011


Generating ELF files in memory is usually too much work for JIT
compilers, since they usually don't have the related routines (as
opposed to a regular static compiler). One way to simplify this is to
have the JIT vendor themselves provide a shared object which is loaded
and used to parse the debug information. This patch exposes a
simplified interface for the debug info parser.

The interface is _simplified_ in the sense that it does not expose all
of GDB's functionality. The idea is that if the user wishes to use GDB
for full-on debugging of generated code, it will probably be simpler
to generate the full DWARF info.

The interface does not expose more than the minimum amount of GDB
internals; both to prevent versioning problems, and to keep writing
the debug-info reader simple. For the same reason, GDB specific
typedefs (like CORE_ADDR) have been kept out of `jit-reader.h'.

This patch adds a header file (`jit-reader.h') which can be included
and implemented in a shared object to build a working JIT
debug-reader.

gdb/ChangeLog:

	* jit-reader.h: Add (new) JIT reader interface.
	* jit.c: Include jit-reader.h in source file
	* Makefile.in: Add jit-reader.h to HFILES_NO_SRCDIR.
---
 gdb/ChangeLog    |    6 ++
 gdb/Makefile.in  |    2 +-
 gdb/jit-reader.h |  189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/jit.c        |    4 +
 4 files changed, 200 insertions(+), 1 deletions(-)
 create mode 100644 gdb/jit-reader.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8ed7eaf..e067f04 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2011-07-13  Sanjoy Das  <sanjoy@playingwithpointers.com>
+
+	* jit-reader.h: Add (new) JIT reader interface.
+	* jit.c: Include jit-reader.h in source file
+	* Makefile.in: Add jit-reader.h to HFILES_NO_SRCDIR.
+
 2011-07-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	Code cleanup making also optimized out values lazy.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 494f24f..ca2cbcb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -816,7 +816,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \
 python/python-internal.h python/python.h ravenscar-thread.h record.h \
 solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \
 gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \
-gnulib/stddef.in.h inline-frame.h
+gnulib/stddef.in.h inline-frame.h jit-reader.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
diff --git a/gdb/jit-reader.h b/gdb/jit-reader.h
new file mode 100644
index 0000000..15980bd
--- /dev/null
+++ b/gdb/jit-reader.h
@@ -0,0 +1,189 @@
+/* Interface for JIT debug-info readers.
+
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_JIT_READER_H
+#define GDB_JIT_READER_H
+
+/* Versioning: for the SO to be correctly recognized and loaded, put the macro
+   GDB_JIT_DECLARE_API_VERSION in a source file. */
+
+#define GDB_JIT_INTERFACE_VERSION  1
+#define GDB_JIT_DECLARE_API_VERSION             \
+  extern int __gdbjit_so_api_version (void)     \
+  {                                             \
+    return GDB_JIT_INTERFACE_VERSION;           \
+  }
+
+#define GDB_JIT_SUCCESS          1
+#define GDB_JIT_FAIL             0
+#define GDBJIT_MAX_REGISTER_SIZE 64 /* Mirrors the internal GDB definition. */
+
+struct gdbjit_symtab;
+struct gdbjit_block;
+struct gdbjit_symbol;
+struct gdbjit_symtab_callbacks;
+
+#ifndef __GDB__INTERNAL /* Only defined when being compiled in GDB. */
+typedef long long CORE_ADDR;
+#endif
+
+struct gdbjit_line_mapping
+{
+  int line;
+  CORE_ADDR pc;
+};
+
+typedef struct gdbjit_symtab *(gdbjit_symtab_open)
+  (struct gdbjit_symtab_callbacks *callbacks,
+   const char *file_name);
+
+typedef struct gdbjit_block *(gdbjit_new_block)
+  (struct gdbjit_symtab_callbacks *callbacks, struct gdbjit_symtab *symtab,
+   struct gdbjit_block *parent, CORE_ADDR begin_addr, CORE_ADDR end_addr,
+   const char *name);
+
+typedef void (gdbjit_symtab_close) (struct gdbjit_symtab_callbacks *callbacks,
+                                    struct gdbjit_symtab *symtab);
+
+typedef void (gdbjit_symtab_add_line_mapping)
+(struct gdbjit_symtab_callbacks * callbacks, struct gdbjit_symtab *symtab,
+ int nlines, struct gdbjit_line_mapping *lines);
+
+typedef int (gdbjit_target_read) (CORE_ADDR target_mem, void *gdb_buf, int len);
+
+struct gdbjit_symtab_callbacks {
+  /* Create a new symbol table. A symbol table consists of a forest of block
+     hierachies. Blocks are added by a call to new_block. This needs to be
+     paired with a call to symtab_close.
+
+     An optional FILE_NAME can be passed, which will be associated with the
+     symbol table as the source file from which this code was compiled.
+
+     Returns a new struct gdbjit_symtab which can be further passed to
+     new_block and symtab_close. */
+  gdbjit_symtab_open *symtab_open;
+
+  /* Creates a new block. A block is an optionally named contiguous block of
+     code in memory. Creating a new block automatically adds it to the symbol
+     table in which it is created.
+
+     SYMTAB is the symbol table this block is added to. Each block may have an
+     optionally non-NULL PARENT. BEGIN_ADDR and END_ADDR are the first and last
+     addresses spanned by this piece of compiled code. This block may have an
+     optional NAME, in case it corresponds to a function.
+
+     Returns a gdbjit_block instance, which, at this point, is useless. */
+  gdbjit_new_block *new_block;
+
+  /* Adds PC <-> line number mapping for the symbol table SYMTAB. Pass an array
+     of NLINES gdbjit_line_mapping s in LINES. */
+  gdbjit_symtab_add_line_mapping *add_line_mapping;
+
+  /* Reads LEN bytes of memory from the target's address space, beginning from
+     TARGET_MEM into the buffer GDB_BUF points to. */
+  gdbjit_target_read *target_read;
+
+  /* Closes the symbol table SYMTAB, and add it to the internal GDB list. */
+  gdbjit_symtab_close *symtab_close;
+
+  /* For internal use. */
+  void *private;
+};
+
+/* Denotes a register value. */
+struct gdbjit_reg_value
+{
+  /* Set to non-zero if this register has a valid value. Otherwise 0. */
+  int defined;
+  /* The actual value of the register (this is considered valid only if defined
+     is non-zero). */
+  unsigned char value[GDBJIT_MAX_REGISTER_SIZE];
+};
+
+/* Unique frame identifier. This should remain constant throughout the lifetime
+   of the frame concerned. */
+struct gdbjit_frame_id
+{
+  CORE_ADDR code_address;
+  CORE_ADDR stack_address;
+};
+
+struct gdbjit_unwind_callbacks;
+
+typedef struct gdbjit_reg_value (gdbjit_unwind_reg_get)
+  (struct gdbjit_unwind_callbacks *callback, int regnum);
+
+typedef void (gdbjit_unwind_reg_set) (struct gdbjit_unwind_callbacks *callback,
+                                      int regnum, struct gdbjit_reg_value val);
+
+struct gdbjit_unwind_callbacks
+{
+  /* Gets the current value for the register REGNUM (DWARF numbering). */
+  gdbjit_unwind_reg_get *reg_get;
+
+  /* Sets the previous value of the REGNUM register (i.e. its value in the
+     previous frame) to VAL. */
+  gdbjit_unwind_reg_set *reg_set;
+
+  /* Function to read memory off the inferior process being debugged, as
+     documented in gdbjit_symtab_callbacks. */
+  gdbjit_target_read *target_read;
+
+  /* For internal use. */
+  void *private;
+};
+
+/* Called once for each new inferior program. It should also initialize the
+   private pointer (to which a pointer is passed here) if the it needs one.
+
+   return: GDB_SUCCESS on success, or GDB_JIT_FAIL on error,
+   in which this plugin will be discarded (gdbjit_destroy_reader will not be
+   called in such a case). */
+extern int gdbjit_init_reader (void **private);
+
+/* Called to have the reader try to read a block of memory. PRIVATE is the
+   private pointer, (possibly) initialized by gdbjit_init_reader.
+
+   The function is expected to use CALLBACKS (documented above) to build a
+   symbol table for this particular block of memory (pointed to by MEMORY,
+   already copied from the target address space to GDB's address space).
+   MEMORY_SZ is the size of the block of memory.
+
+   Should return GDB_JIT_SUCESS on success and GDB_JIT_FAIL on error. */
+extern int gdbjit_read_debug_info (void *private,
+                                   struct gdbjit_symtab_callbacks *callbacks,
+                                   CORE_ADDR memory, long memory_sz);
+
+/* Called to unwind one frame. PRIVATE is the private pointer. Expected to use
+   CALLBACKS to unwind the registers to the older frame.
+
+   Should return GDB_JIT_SUCESS for success, GDB_JIT_FAIL for fail. */
+extern int gdbjit_unwind_frame (void *private,
+                                struct gdbjit_unwind_callbacks *callbacks);
+
+/* Called to get a unique identifier for the current stack frame (as reported by
+   callbacks). */
+struct gdbjit_frame_id gdbjit_get_frame_id (void *private, struct
+                                            gdbjit_unwind_callbacks *callbacks);
+
+/* Called once the inferior process exits. */
+extern void gdbjit_destroy_reader (void *private);
+
+#endif
diff --git a/gdb/jit.c b/gdb/jit.c
index eb1bcc7..6c07a57 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -19,7 +19,11 @@
 
 #include "defs.h"
 
+/* To stop jit-reader.h from re-defining CORE_ADDR */
+#define __GDB__INTERNAL
+
 #include "jit.h"
+#include "jit-reader.h"
 #include "breakpoint.h"
 #include "command.h"
 #include "gdbcmd.h"
-- 
1.7.5.4



More information about the Gdb-patches mailing list