nuttx-mirror/Documentation/guides/debugging_elf_loadable_modules.rst
Ludovic Vanasse c55c2511ad
Some checks failed
Build Documentation / build-html (push) Has been cancelled
Doc: improve and add documentations for the guide section of the wiki
* Add a migration warning to the update release system and the elf
programs documentation pages. This is just to add a papertrail from
where the documentation originate in case of error during the migration
process.
* Improve the building nuttx with app out of source tree
* Add new guide pages
	* Building uclibc++
	* Custom app directories
	* Debugging ELF loadable modules
	* Multiple NSH sessions
	* NSH network link management
	* RAM & ROM disks
	* Reading CAN messages
	* Remove device drivers with NSH
2024-12-30 12:32:42 +08:00

84 lines
3 KiB
ReStructuredText

==============================
Debugging ELF Loadable Modules
==============================
.. warning::
Migrated from:
https://cwiki.apache.org/confluence/display/NUTTX/Debugging+ELF+Loadable+Modules
Debugging ELF modules loaded in memory can be tricky because the load address
in memory does not match the addresses in the ELF file. This challenge has long
existed for debugging uClinux programs and Linux kernel modules; the same
solution can be used with NuttX ELF files (and probably with NxFLAT modules as
well). Below is a summary of one way to approach this:
1. Get ELF Module Load Address
==============================
Put a change in ``nuttx/binfmt`` so that you print the address where the ELF
text was loaded into memory.
Turning on BINFMT debug (``CONFIG_DEBUG_BINFMT=y``) should give you the same
information, although it may also provide more output than you really want.
Alternatively, you could place a ``printf()`` at the beginning of your ``main()``
function so that your ELF module can print its own load address. For example,
the difference between the address of ``main()`` in your object file and the
address of ``main()`` at run time reveals the actual load address.
2. Make the ELF Module Wait for You
===================================
Insert an infinite loop in the ``main()`` routine of your ELF program. For
example:
.. code-block:: c
volatile bool waitforme;
int main (int arc, char **argv)
{
while (!waitforme);
...
When you start the ELF program, you will see where it was loaded in memory, and
the ELF program will remain stuck in the infinite loop. It will continue to
wait for ``waitforme`` to become true before proceeding.
3. Start the Debugger
=====================
Start the debugger, connect to the GDB server, and halt the program. If your
debugger is well-behaved, it should stop at the infinite loop in ``main()``.
4. Load Offset Symbols
======================
Load symbols using the offset where the ELF module was loaded:
.. code-block:: shell
(gdb) add-symbol-file <myprogram> <load-address>
Here, ``<myprogram>`` is your ELF file containing symbols, and
``<load-address>`` is the address where the program text was actually loaded (as
determined above). Single-step a couple of times and confirm that you are in the
infinite loop.
5. And Debug
============
Set ``waitforme`` to a non-zero value. Execution should exit the infinite loop,
and now you can debug the ELF program loaded into RAM in the usual way.
An Easier Way?
==============
There might be an alternative that allows you to step into the ELF module
without modifying the code to include the ``waitforme`` loop. You could place a
breakpoint on the OS function ``task_start()``. That function runs before your
ELF program starts, so you should be able to single-step from the OS code
directly into your loaded ELF application—no changes to the ELF application
required.
When you step into the application's ``main()``, you have the relocated address
of ``main()`` and can use that address (see step #1) to compute the load offset.