As mentioned, a reader is essentially a shared object conforming to a certain ABI. This ABI is described in jit-reader.h.
jit-reader.h defines the structures, macros and functions required to write a reader. It is installed (along with gdb), in includedir/gdb where includedir is the system include directory.
Readers need to be released under a GPL compatible license. A reader
can be declared as released under such a license by placing the macro
GDB_DECLARE_GPL_COMPATIBLE_READER
in a source file.
The entry point for readers is the symbol gdb_init_reader
,
which is expected to be a function with the prototype
extern struct gdb_reader_funcs *gdb_init_reader (void);
struct gdb_reader_funcs
contains a set of pointers to callback
functions. These functions are executed to read the debug info
generated by the JIT compiler (read
), to unwind stack frames
(unwind
) and to create canonical frame IDs
(get_Frame_id
). It also has a callback that is called when the
reader is being unloaded (destroy
). The struct looks like this
struct gdb_reader_funcs { /* Must be set to GDB_READER_INTERFACE_VERSION. */ int reader_version; /* For use by the reader. */ void *priv_data; gdb_read_debug_info *read; gdb_unwind_frame *unwind; gdb_get_frame_id *get_frame_id; gdb_destroy_reader *destroy; };
The callbacks are provided with another set of callbacks by
gdb to do their job. For read
, these callbacks are
passed in a struct gdb_symbol_callbacks
and for unwind
and get_frame_id
, in a struct gdb_unwind_callbacks
.
struct gdb_symbol_callbacks
has callbacks to create new object
files and new symbol tables inside those object files. struct
gdb_unwind_callbacks
has callbacks to read registers off the current
frame and to write out the values of the registers in the previous
frame. Both have a callback (target_read
) to read bytes off the
target's address space.