============================== 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 Here, ```` is your ELF file containing symbols, and ```` 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.