This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/4] Adds documentation.


Adds some basic documentation to gdb.texinfo about the new JIT reader functionality. This should be a good entry point for developers writing parsers for the debug info their JIT compiler generates.

gdb/ChangeLog
	* gdb.texinfo: Some documentation about the new JIT debug info reader functionality.
---
 gdb/ChangeLog       |    4 +++
 gdb/doc/gdb.texinfo |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 25281f4..656a42d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,4 +1,8 @@
 2011-07-24  Sanjoy Das  <sdas@igalia.com>
+
+	* gdb.texinfo: Some documentation about the new JIT debug info reader functionality.
+
+2011-07-24  Sanjoy Das  <sdas@igalia.com>
 	* jit-reader.h.in: Add API and interface.
 	* jit.c: Include jit-reader.h.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 16bb6bc..3968861 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -30870,6 +30870,72 @@ Set @code{action_flag} to @code{JIT_UNREGISTER} and call
 If the JIT frees or recompiles code without unregistering it, then @value{GDBN}
 and the JIT will leak the memory used for the associated symbol files.
 
+@node Custom Object File Format
+@section Custom Object File Format
+
+Generating debug information in native file formats (like ELF or COFF) can become an overkill for JIT compilers; especially if all the debug info is used for displaying a meaningful backtrace. The issue can be resolved by having the JIT writers decide on a debug info format and provide a third-party reader that parses the debug info generated by the JIT compiler. This section gives an overview on writing such a parser. More details can be found in the file @code{gdb/jit-reader.h.in}.
+
+The reader is implemented as a shared object. GDB, when trying to read the debug information generated by a JIT compiler, looks for such shared objects in a special, pre-configured, directory. If such a (conforming) shared object is found, it is dynamically loaded and used to parse the debug info.
+
+@node Writing A Parser
+@subsection Writing A Parser
+
+The parser needs to include @code{jit-reader.h}, which defines the required structures, macros and functions.
+
+@node Elements Of @code{jit-reader.h}
+@subsubsection Elements Of @code{jit-reader.h}
+
+The two macros declared in @code{jit-reader.h} are @code{GDB_DECLARE_READER_INTERFACE_VERSION} and @code{GDB_DECLARE_GPL_COMPATIBLE_READER}. Both of them need to be placed in a source file that will eventually be compiled and linked into the shared object.
+
+@code{GDB_DECLARE_READER_INTERFACE_VERSION} adds code that allows GDB to verify the version of the plugin. @code{GDB_DECLARE_GPL_COMPATIBLE_READER} declares the plugin to be released under a GPL compatible license.
+
+After the plugin is loaded, GDB looks for the function @code{gdb_init_reader}. The prototype of the function (also included in @code{jit-reader.h}) is:
+
+@smallexample
+extern struct gdb_reader_funcs *gdb_init_reader (void);
+@end smallexample
+
+As evident, the function is supposed to return a @code{struct gdb_reader_funcs *} (or @code{NULL}, in case of an error), which contains a set of functions later used to parse the debug info. It is declared thus:
+
+@smallexample
+struct gdb_reader_funcs
+@{
+  gdb_read_debug_info *read;
+  gdb_unwind_frame *unwind;
+  gdb_get_frame_id *get_frame_id;
+  gdb_destroy_reader *destroy;
+
+  void *private;
+@};
+@end smallexample
+
+@code{read} is called to read the debug info, @code{unwind} is called to unwind a frame corresponding to a JITted function, @code{get_frame_id} is supposed to return an unique frame id for a frame and @code{destroy} is called when the plugin is unloaded.
+
+@node The API
+@subsubsection The API
+
+The plugin provides an API for creating symbol files (which GDB will use to, for instance, display function names in the backtrace) and implementing a frame unwinder.
+
+@strong{Symbol Reading}
+
+The @code{read} function in @code{struct gdb_reader_funcs} is called to read in the debug info emitted by the JIT compiler and create the appropriate symbol tables. To keep the API clean and stable, GDB's internal structures are not exposed. Instead, a @code{struct} full of function pointers are passed to @code{read} which it is supposed to use to construct the symbol table.
+
+@strong{Frame Unwinding}
+
+@code{unwind} is called to unwind the current frame into the previous (earlier, outer) frame. The prototype for the @code{unwind} function is:
+
+@smallexample
+int unwind (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cb);
+@end smallexample
+
+The first argument is the same @code{struct} that was returned by @code{gdb_init_reader} (so that the reader can persist some data). The second argument, @code{cb} is used to unwind the frame.
+
+Unwinding a frame involves computing the values of the registers in the earlier frame given the values in the current frame. @code{struct gdb_unwind_callbacks} provides the function @code{reg_get} which returns the value of a particular register in the @emph{current} frame. So the @emph{current} frame is, in a way, the frame defined by the register values returned by @code{reg_get}.
+
+The plugin is to use @code{reg_set} to save the predicted values of registers in the outer (earlier) frame. @code{struct gdb_unwind_callbacks} also provides a third function, @code{target_read}, which reads a block of memory from the target's virtual memory.
+
+An example can be made of a JIT compiler whose code maintains the frame pointers: assuming the program counter, the previous frame pointer and the previous stack pointer are all saved at known constant offsets from the frame pointer, we can have a simple unwinder which reads the value of the frame pointer using @code{reg_get}, reads the memory at the known offsets using @code{target_read} and then calls @code{reg_set} on the program counter, frame pointer and stack pointer with the new (now discovered) values. This is usually enough for GDB to generate a meaningful stacktrace.
+
 @node GDB Bugs
 @chapter Reporting Bugs in @value{GDBN}
 @cindex bugs in @value{GDBN}
-- 
1.7.5.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]