From aea762b9ce0660ce8117490c9c3f91de4e8578a3 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Thu, 30 Jun 2011 15:30:06 +0530 Subject: [PATCH 1/3] Adds a jit-reader interface. Adds a jit-reader.h, which JIT debug info readers can include and implement. --- gdb/Makefile.in | 2 +- gdb/jit-reader.h | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/jit.c | 1 + 3 files changed, 170 insertions(+), 1 deletions(-) create mode 100644 gdb/jit-reader.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9b6e913..7bdec38 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -817,7 +817,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..0380234 --- /dev/null +++ b/gdb/jit-reader.h @@ -0,0 +1,168 @@ +/* Defines the interface for JIT debug-info readers. This file needs to be + self-sufficient since it will be included in the JIT debug-info readers + directly. + + This is a minimum-functionality version - the JIT reader can only read in + enough debug information to allow GDB to display a meaningful stack trace. */ + +#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; + +struct gdbjit_line_mapping { + int line; + void *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, void *begin_addr, void *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) (void *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 { + void *code_address; + void *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, + void *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 be123a5..4ce5814 100644 --- a/gdb/jit.c +++ b/gdb/jit.c @@ -20,6 +20,7 @@ #include "defs.h" #include "jit.h" +#include "jit-reader.h" #include "breakpoint.h" #include "command.h" #include "gdbcmd.h" -- 1.7.5.3