summaryrefslogtreecommitdiffstats
path: root/doc/rgdb_specs/gdbinternals.t
diff options
context:
space:
mode:
Diffstat (limited to 'doc/rgdb_specs/gdbinternals.t')
-rw-r--r--doc/rgdb_specs/gdbinternals.t214
1 files changed, 214 insertions, 0 deletions
diff --git a/doc/rgdb_specs/gdbinternals.t b/doc/rgdb_specs/gdbinternals.t
new file mode 100644
index 0000000000..caef8928bc
--- /dev/null
+++ b/doc/rgdb_specs/gdbinternals.t
@@ -0,0 +1,214 @@
+@c
+@c RTEMS Remote Debugger Server Specifications
+@c
+@c Written by: Eric Valette <valette@crf.canon.fr>
+@c Emmanuel Raguet <raguet@crf.canon.fr>
+@c
+@c
+@c $Id$
+@c
+
+@chapter A Rapid Tour of GDB Internals
+
+To help the reader to understand what needs to be implemented, we
+will present briefly how GDB works regardless if the target is local or remote.
+A debugger is a tool which enables control of the execution of software on a
+target system. In most of cases, the debugger connects to a target system, attaches
+a process, inserts breakpoints and resumes execution. Then the normal execution
+is completely events driven (process execution stopped due to a breakpoint,
+process fault, single-step,...) coming from the debuggee. It can also directly
+access some parts of the target processor context (registers, data memory, code
+memory,...) and change their content. Native GDB debugger can just be seen as
+special cases where the host and the target are on the same machine and GDB
+can directly access the target system debug API.
+
+
+In our case, the host and the target are not on the same machine and
+an Ethernet link is used to communicate between the different machines. Because
+GDB needs to be able to support various targets (including Unix core file, ...),
+each action that needs to be performed on the debuggee is materialized by a
+field of the following @emph{targets_op}s structure :
+
+@example
+struct target_ops
+@{
+ char *to_shortname; /* Name this target type */
+ char *to_longname; /* Name for printing */
+ char *to_doc; /* Documentation. Does not include trailing
+ newline, and starts with a one-line descrip-
+ tion (probably similar to to_longname). */
+ void (*to_open) PARAMS ((char *, int));
+ void (*to_close) PARAMS ((int));
+ void (*to_attach) PARAMS ((char *, int));
+ void (*to_detach) PARAMS ((char *, int));
+ void (*to_resume) PARAMS ((int, int, enum target_signal));
+ int (*to_wait) PARAMS ((int, struct target_waitstatus *));
+ void (*to_fetch_registers) PARAMS ((int));
+ void (*to_store_registers) PARAMS ((int));
+ void (*to_prepare_to_store) PARAMS ((void));
+
+ /* Transfer LEN bytes of memory between GDB address MYADDR and
+ target address MEMADDR. If WRITE, transfer them to the target, else
+ transfer them from the target. TARGET is the target from which we
+ get this function.
+
+ Return value, N, is one of the following:
+
+ 0 means that we can't handle this. If errno has been set, it is the
+ error which prevented us from doing it (FIXME: What about bfd_error?).
+
+ positive (call it N) means that we have transferred N bytes
+ starting at MEMADDR. We might be able to handle more bytes
+ beyond this length, but no promises.
+
+ negative (call its absolute value N) means that we cannot
+ transfer right at MEMADDR, but we could transfer at least
+ something at MEMADDR + N. */
+
+ int (*to_xfer_memory) PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int write,
+ struct target_ops * target));
+
+ void (*to_files_info) PARAMS ((struct target_ops *));
+ int (*to_insert_breakpoint) PARAMS ((CORE_ADDR, char *));
+ int (*to_remove_breakpoint) PARAMS ((CORE_ADDR, char *));
+ void (*to_terminal_init) PARAMS ((void));
+ void (*to_terminal_inferior) PARAMS ((void));
+ void (*to_terminal_ours_for_output) PARAMS ((void));
+ void (*to_terminal_ours) PARAMS ((void));
+ void (*to_terminal_info) PARAMS ((char *, int));
+ void (*to_kill) PARAMS ((void));
+ void (*to_load) PARAMS ((char *, int));
+ int (*to_lookup_symbol) PARAMS ((char *, CORE_ADDR *));
+ void (*to_create_inferior) PARAMS ((char *, char *, char **));
+ void (*to_mourn_inferior) PARAMS ((void));
+ int (*to_can_run) PARAMS ((void));
+ void (*to_notice_signals) PARAMS ((int pid));
+ int (*to_thread_alive) PARAMS ((int pid));
+ void (*to_stop) PARAMS ((void));
+ enum strata to_stratum;
+ struct target_ops
+ *DONT_USE; /* formerly to_next */
+ int to_has_all_memory;
+ int to_has_memory;
+ int to_has_stack;
+ int to_has_registers;
+ int to_has_execution;
+ struct section_table
+ *to_sections;
+ struct section_table
+ *to_sections_end;
+ int to_magic;
+ /* Need sub-structure for target machine related rather than comm related? */
+@};
+@end example
+
+This structure contains pointers to functions (in C++, this would
+be called a virtual class). Each different target supported by GDB has its own
+structure with the relevant implementation of the functions (some functions
+may be not implemented). When a user connects GDB to a target via the ``target''
+command, GDB points to the structure corresponding to this target. Then the
+user can attache GDB to a specific task via the ``attach'' command. We have
+therefore identified two steps to begin a remote debug session :
+
+@enumerate
+@item the choice of the target type (in our case RTEMS),
+@item the choice of what to debug (entire system, specific task,...),
+@end enumerate
+Note that in the case of natives debugger, the choice of the target is implicitly
+performed by commands like @b{run}, @b{attach}, @b{detach}. Several
+figures will now be described showing the main steps of a debug session.
+
+@C XXX figure reference
+Figure @b{Debug session initialization} explains how the debugger connects to the target
+:
+
+@enumerate
+@item The debugger opens a connection to the target. The word ``connection''
+doesn't only mean Ethernet or serial link connection but all the ways by which
+a process can communicate with another one (direct function call, messages mailbox,
+...),
+@item The targets checks if it can accept or reject this connection,
+@item If the connection is accepted, the host ``attaches'' the process,
+@item the target stops the process, notifies a child's stop to the host
+and waits for command,
+@item the host can ask information about the debugged process (name, registers,...)
+or perform some action like setting breakpoints, ...
+@end enumerate
+
+@C XXX figure reference
+Figure @b{Breakpoint and process execution} explains how the debugger manages the
+breakpoints and controls the execution of a process :
+
+@enumerate
+@item The host asks the debuggee what is the opcode at the concerned address
+in order for GDB to memorize this instruction,
+@item the host sends a CONTINUE command : it asks the target to write the
+``DEBUG'' opcode (for example, the INTEL ``DEBUG'' opcode is INT3 which
+generate a breakpoint trap) instead of the debugged opcode.
+@item then the host waits for events,
+@item after the change of instruction, the target resumes the execution
+of the debuggee,
+@item when the ``DEBUG'' opcode is executed, the breakpoint exception
+handler is executed and it notifies the host that the process is stopped. Then
+it waits for commands (if no command is sent after a certain amount of time,
+the connection will be closed by the target).
+@item the host asks the target to re-write the right opcode instead of the
+''DEBUG'' opcode and then can ask information
+@end enumerate
+
+@C XXX figure reference
+Figure @b{Breakpoint and process execution} also shows the case of other ``CONTINUE''
+commands (remember that the ``DEBUG'' opcode has been replaced by the right
+instruction):
+
+@enumerate
+@item Host sends first a ``single step'' command to execute the debugged
+instruction,
+@item It then waits for ``single step`` exception event,
+@item the target, once the single step executed, calls the debug exception
+handler. It notifies the host that execution is suspended and wait for commands.
+@item the host asks the target to re-write the ``DEBUG'' opcode (breakpoint
+trap) instead of the debugged one.
+@item then the host sends a ``CONTINUE'' command in order the target to
+resume the process execution to the next breakpoint.
+@end enumerate
+
+@C XXX figure reference
+Figure @b{Detach a process and close a connection} explains how the debugger disconnects from
+a target :
+
+@enumerate
+@item the host sends a detach command to the target.
+@item the target detaches the concerned process, notifies the detachment
+and resumes the process execution.
+@item once notified, the host sends a close connection command.
+@item the target closes the connection.
+@end enumerate
+These 3 examples show that the mains actions that are performed by
+the host debugger on the target are only simple actions which look like :
+
+@itemize @b
+@item read/write code,
+@item read/write data,
+@item read/write registers,
+@item manage exceptions,
+@item send/receive messages to/from the host.
+@end itemize
+
+
+@example
+XXX Figure seg_init.eps
+XXX Debug session initialization
+@end example
+
+@example
+XXX Figure seq_break.eps
+XXX Breakpoint and process execution
+@end example
+
+@example
+XXX Figure seq_detach.eps
+XXX Detach a process and close a connection
+@end example
+