doc: debug: expand documentation on gdbstub
This expands the documentation on GDB stub, and adding hints on porting to new architectures. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
5d19da4507
commit
bdc812c15a
|
@ -1,4 +1,4 @@
|
|||
.. _gdbgstub:
|
||||
.. _gdbstub:
|
||||
|
||||
GDB stub
|
||||
########
|
||||
|
@ -15,13 +15,11 @@ TCP/IP. Zephyr currently supports only serial device communication.
|
|||
|
||||
The GDB program acts as the client while Zephyr acts as the
|
||||
server. When this feature is enabled, Zephyr stops its execution after
|
||||
``gdb_init()`` starts gdbstub service and waits for a GDB
|
||||
:c:func:`gdb_init` starts gdbstub service and waits for a GDB
|
||||
connection. Once a connection is established it is possible to
|
||||
synchronously interact with Zephyr. Note that currently it is not
|
||||
possible to asynchronously send commands to the target.
|
||||
|
||||
Enable this feature with the :kconfig:`CONFIG_GDBSTUB` option.
|
||||
|
||||
Features
|
||||
********
|
||||
|
||||
|
@ -32,3 +30,53 @@ The following features are supported:
|
|||
* Print backtrace
|
||||
* Read or write general registers
|
||||
* Read or write the memory
|
||||
|
||||
Enabling GDB Stub
|
||||
*****************
|
||||
|
||||
GDB stub can be enabled with the :kconfig:`CONFIG_GDBSTUB` option.
|
||||
|
||||
Using Serial Backend
|
||||
====================
|
||||
|
||||
The serial backend for GDB stub can be enabled with
|
||||
the :kconfig:`CONFIG_GDBSTUB_SERIAL_BACKEND` option.
|
||||
|
||||
Since serial backend utilizes UART devices to send and receive GDB commands,
|
||||
|
||||
* If there are spare UART devices on the board, set
|
||||
:kconfig:`CONFIG_GDBSTUB_SERIAL_BACKEND_NAME` to the spare UART device
|
||||
so that :c:func:`printk` and log messages are not being printed to
|
||||
the same UART device used for GDB.
|
||||
|
||||
* For boards with only one UART device, :c:func:`printk` and logging
|
||||
must be disabled if they are also using the same UART device for output.
|
||||
GDB related messages may interleave with log messages which may have
|
||||
unintended consequences. Usually this can be done by disabling
|
||||
:kconfig:`CONFIG_PRINTK` and :kconfig:`CONFIG_LOG`.
|
||||
|
||||
Debugging
|
||||
*********
|
||||
|
||||
Using Serial Backend
|
||||
====================
|
||||
|
||||
#. Build with GDB stub and serial backend enabled.
|
||||
|
||||
#. Flash built image onto board and reset the board.
|
||||
|
||||
* Execution should now be paused at :c:func:`gdb_init`.
|
||||
|
||||
#. Execute GDB on development machine and connect to the GDB stub.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
target remote <serial device>
|
||||
|
||||
For example,
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
target remote /dev/ttyUSB1
|
||||
|
||||
#. GDB commands can be used to start debugging.
|
||||
|
|
|
@ -835,6 +835,141 @@ In addition to implementing these APIs, there are some other tasks as well:
|
|||
:c:enum:`K_SYSCALL_BAD` handler. Upon completion of the system call, care
|
||||
must be taken not to leak any register state back to user mode.
|
||||
|
||||
GDB Stub
|
||||
********
|
||||
|
||||
To enable GDB stub for remote debugging on a new architecture:
|
||||
|
||||
#. Create a new ``gdbstub.h`` header file under appropriate architecture
|
||||
include directory (``include/arch/<arch>/gdbstub.h``).
|
||||
|
||||
* Create a new struct ``struct gdb_ctx`` as the GDB context.
|
||||
|
||||
* Must define a member named ``exception`` of type ``unsigned int`` to
|
||||
store the GDB exception reason. This value needs to be set before
|
||||
entering :c:func:`z_gdb_main_loop`.
|
||||
|
||||
* Architecture can define as many members as needed for GDB stub to
|
||||
function.
|
||||
|
||||
* Pointer to this struct needs to be passed to :c:func:`z_gdb_main_loop`,
|
||||
where this pointer will be passed to other GDB stub functions.
|
||||
|
||||
#. Functions for entering and exiting GDB stub main loop.
|
||||
|
||||
* If the architecture relies on interrupts to service breakpoints,
|
||||
interrupt service routines (ISR) need to be implemented, which
|
||||
will serve as the entry point to GDB stub main loop.
|
||||
|
||||
* These functions need to save and restore context so code execution
|
||||
can continue as if no breakpoints have been encountered.
|
||||
|
||||
* These functions need to call :c:func:`z_gdb_main_loop` after saving
|
||||
execution context to go into the GDB stub main loop to receive commands
|
||||
from GDB.
|
||||
|
||||
* Before calling :c:func:`z_gdb_main_loop`, :c:member:`gdb_ctx.exception`
|
||||
must be set to specify the exception reason.
|
||||
|
||||
#. Implementat necessary functions to support GDB stub functionality:
|
||||
|
||||
* :c:func:`arch_gdb_init`
|
||||
|
||||
* This needs to initialize necessary bits to support GDB stub functionality,
|
||||
for example, setting up the GDB context and connecting debug interrupts.
|
||||
|
||||
* This must stop code execution via architecture specific method (e.g.
|
||||
raising debug interrupts). This allows GDB to connect during boot.
|
||||
|
||||
* :c:func:`arch_gdb_continue`
|
||||
|
||||
* This function is called when GDB sends a ``c`` or ``continue`` command
|
||||
to continue code execution.
|
||||
|
||||
* :c:func:`arch_gdb_step`
|
||||
|
||||
* This function is called when GDB sends a ``si`` or ``stepi`` command
|
||||
to execute one machine instruction, before returning to GDB prompt.
|
||||
|
||||
* Hardware register read/write functions:
|
||||
|
||||
* Since the GDB stub is running on the target, manipulation of hardware
|
||||
registers need to cached to avoid affecting the execution of GDB stub.
|
||||
Think of it as context switching, where the execution context is
|
||||
changed to the GDB stub. So that the register values of the running
|
||||
thread before context switch need to be stored. Manipulation of
|
||||
register values must only be done to this cached copy. The updated
|
||||
values will then be written to hardware registers before switching
|
||||
back to the previous running thread.
|
||||
|
||||
* :c:func:`arch_gdb_reg_readall`
|
||||
|
||||
* This collects all hardware register values that would appear in
|
||||
a ``g``/``G`` packets which will be sent back to GDB. The format of
|
||||
the G-packet is architecture specific. Consult GDB on what is
|
||||
expected.
|
||||
|
||||
* Note that, for most architectures, a valid G-packet must be returned
|
||||
and sent to GDB. If a packet without incorrect length is sent to
|
||||
GDB, GDB will abort the debugging session.
|
||||
|
||||
* :c:func:`arch_gdb_reg_writeall`
|
||||
|
||||
* This takes a G-packet sent by GDB and populates the hardware
|
||||
registers with values from the G-packet.
|
||||
|
||||
* :c:func:`arch_gdb_reg_readone`
|
||||
|
||||
* This reads the value of one hardware register and sends
|
||||
the result to GDB.
|
||||
|
||||
* :c:func:`arch_gdb_reg_writeone`
|
||||
|
||||
* This writes the value of one hardware register received from GDB.
|
||||
|
||||
* Breakpoints:
|
||||
|
||||
* :c:func:`arch_gdb_add_breakpoint` and
|
||||
:c:func:`arch_gdb_remove_breakpoint`
|
||||
|
||||
* GDB may decide to use software breakpoints which modifies
|
||||
the memory at the breakpoint locations to replace the instruction
|
||||
with software breakpoint or trap instructions. GDB will then
|
||||
restore the memory content once execution reaches the breakpoints.
|
||||
GDB supports this by default and there is usually no need to
|
||||
handle software breakpoints in the architecture code (where
|
||||
breakpoint type is ``0``).
|
||||
|
||||
* Hardware breakpoints (type ``1``) are required if the code is
|
||||
in ROM or flash that cannot be modified at runtime. Consult
|
||||
the architecture datasheet on how to enable hardware breakpoints.
|
||||
|
||||
* If hardware breakpoints are not supported by the architecture,
|
||||
there is no need to implement these in architecture code.
|
||||
GDB will then rely on software breakpoints.
|
||||
|
||||
#. For architecture where certain memory regions are not accessible,
|
||||
an array named :c:var:`gdb_mem_region_array` of type
|
||||
:c:struct:`gdb_mem_region` needs to be defined to specify regions
|
||||
that are accessible. For each array item:
|
||||
|
||||
* :c:member:`gdb_mem_region.start` specifies the start of a memory
|
||||
region.
|
||||
|
||||
* :c:member:`gdb_mem_region.end` specifies the end of a memory
|
||||
region.
|
||||
|
||||
* :c:member:`gdb_mem_region.attribites` specifies the permission
|
||||
of a memory region.
|
||||
|
||||
* :c:macro:`GDB_MEM_REGION_RO`: region is read-only.
|
||||
|
||||
* :c:macro:`GDB_MEM_REGION_RW`: region is read-write.
|
||||
|
||||
* :c:member:`gdb_mem_region.alignment` specifies read/write alignment
|
||||
of a memory region. Use ``0`` if there is no alignment requirement
|
||||
and read/write can be done byte-by-byte.
|
||||
|
||||
API Reference
|
||||
*************
|
||||
|
||||
|
@ -879,3 +1014,8 @@ Miscellaneous Architecture APIs
|
|||
===============================
|
||||
|
||||
.. doxygengroup:: arch-misc
|
||||
|
||||
GDB Stub APIs
|
||||
=============
|
||||
|
||||
.. doxygengroup:: arch-gdbstub
|
||||
|
|
|
@ -2268,6 +2268,7 @@ PREDEFINED = __DOXYGEN__ \
|
|||
CONFIG_FLASH_PAGE_LAYOUT \
|
||||
CONFIG_FPU \
|
||||
CONFIG_FPU_SHARING \
|
||||
CONFIG_GDBSTUB \
|
||||
CONFIG_HEAP_MEM_POOL_SIZE \
|
||||
CONFIG_MMU \
|
||||
CONFIG_NET_L2_ETHERNET_MGMT \
|
||||
|
|
Loading…
Reference in a new issue