Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Debugging Multiple Binaries With GDB/Eclipse

DZone's Guide to

Debugging Multiple Binaries With GDB/Eclipse

Ever need to debug multiple binaries? Say, a library and your app? Not fun. Fortunately, you can use GDB commands, Eclipse, and symbols to make the process easier.

· IoT Zone
Free Resource

When working and debugging a bootloader, debugging can be a challenge: While debugging the bootloader, a new binary gets loaded into the microcontroller address space, which is unknown to the debugger. As soon as I step into the newly loaded binary, I only see assembly code — with that ugly “No source available” in Eclipse:

No Source Available, debugging in assembly

No source available, debugging in assembly

But wait: GDB is able to do pretty much everything you can imagine, so here is how to debug multiple binaries with GDB and Eclipse and turn the above into something which is easy to debug:

Debugging with Symbolics

Debugging with Symbolics

Outline

In many use cases, it is necessary to debug multiple binaries. One use case is with a bootloader (see Serial Bootloader for the Freedom Board with Processor Expert) or with using libraries (see Creating and using Libraries with ARM GCC and Eclipse). What is common in these cases is that the debugger might not have the necessary debug information (or ‘symbolics’) to display the source files and the variable information.

Code and Debug Information

‘Debug information’ is embedded and part of the .elf (ELF), which usually has DWARF debug information. When debugging an .elf file, that combined information is passed to the debugger, as shown below in the Eclipse launch configuration for GDB:

  • Symbols file: This specifies which file is used for the debug information. The debug information is kept on the host and not downloaded to the target.
  • Executable file: This file is used to download the code to the target. Only the code will be stored on the target.

symbols and executable information

Symbols and executable information

As above, usually, the symbols and executable file are the same, as the .elf file can contain both the code (ELF) and the debug (DWARF) information. Unless debug information is removed, of course (see Debug vs. Release?).

Adding Symbols

In the above setting, I have specified an executable and a symbols file. But how can I add more symbols for debugging? For example, a bootloader loads another executable or library. Or my microcontroller has a built-in library I need to debug.

What I need is the symbols or symbolic information. The easiest way is if I have that library (archive) or executable (.elf) with debug information. Then, I need to tell the debugger (GDB) that extra information needs to be added.

 It is possible to generate files with symbolic information only (without the code) using the GNU tools.

The GNU debugger has the command:

add-symbol-file 


(See GDB File Handling for a full description and other options.)

That adds extra debugging information the current debugging session.

For example, I use the following command to add symbolic information in the Eclipse (or GDB) console:

add-symbol-file "c://tmp//FRDM-K64F_Bootloader_test.elf" 0x8200

Adding Symbols in GDB Command Line Session

Adding symbols in GDB command line session

This adds that set of other debug information to the information already present, allowing me to debug that code:

Debugging with Symbolics

Debugging with Symbolics

Offset for the Symbols

You might wonder about that offset of 0x8200 in the command at the end:

add-symbol-file "c://tmp//FRDM-K64F_Bootloader_test.elf" 0x8200


That’s the offset of the .text section of the code I have loaded. In my bootloader example, I load an executable with the vector table at 0x8000 and the code starting at 0x8200. The approach I’m using to determine that offset is to use the readelf program which is part of the GNU compiler suite. For example, it is part of the Kinetis Design Studio, too:

c:\nxp\KDS_3.2.0\Toolchain\bin\arm-none-eabi-readelf.exe -WS c:\tmp\FRDM-K64F_Bootloader_Test.elf


The -WS option dumps the symbolics (-S) in wide (-W) format: For the above case it produces the following:

There are 23 section headers, starting at offset 0x1354e8:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interrupts       PROGBITS        00008000 008000 000198 00   A  0   0  4
  [ 2] .text             PROGBITS        00008200 008200 000da0 00  AX  0   0  4
  [ 3] .ARM              ARM_EXIDX       00008fa0 008fa0 000008 00  AL  2   0  4
  [ 4] .init_array       INIT_ARRAY      00008fa8 008fa8 000004 00  WA  0   0  4
  [ 5] .fini_array       FINI_ARRAY      00008fac 008fac 000004 00  WA  0   0  4
  [ 6] .data             PROGBITS        20000000 010000 000060 00  WA  0   0  4
  [ 7] .bss              NOBITS          20000060 010060 000034 00  WA  0   0  4
  [ 8] .romp             PROGBITS        20000094 010094 000024 00  WA  0   0  1
  [ 9] ._user_heap_stack NOBITS          200000b8 0100b8 000400 00  WA  0   0  1
  [10] .ARM.attributes   ARM_ATTRIBUTES  00000000 0100b8 000030 00      0   0  1
  [11] .debug_info       PROGBITS        00000000 0100e8 002cbc 00      0   0  1
  [12] .debug_abbrev     PROGBITS        00000000 012da4 000c85 00      0   0  1
  [13] .debug_aranges    PROGBITS        00000000 013a29 0005c0 00      0   0  1
  [14] .debug_ranges     PROGBITS        00000000 013fe9 0004f0 00      0   0  1
  [15] .debug_macro      PROGBITS        00000000 0144d9 02f96a 00      0   0  1
  [16] .debug_line       PROGBITS        00000000 043e43 005026 00      0   0  1
  [17] .debug_str        PROGBITS        00000000 048e69 0eb25b 01  MS  0   0  1
  [18] .comment          PROGBITS        00000000 1340c4 000070 01  MS  0   0  1
  [19] .debug_frame      PROGBITS        00000000 134134 0012c4 00      0   0  4
  [20] .shstrtab         STRTAB          00000000 1353f8 0000ee 00      0   0  1
  [21] .symtab           SYMTAB          00000000 135880 000f90 10     22 182  4
  [22] .strtab           STRTAB          00000000 136810 000803 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)


For the add-symbol-file GDB command, the offset of the .text section is relevant:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 2] .text             PROGBITS        00008200 008200 000da0 00  AX  0   0  4


With this, I have the offset I can use with the command:

add-symbol-file c://tmp//FRDM-K64F_Bootloader_test.elf 0x8200
add symbol table from file "c://tmp//FRDM-K64F_Bootloader_test.elf" at
    .text_addr = 0x8200
(y or n) [answered Y; input not from terminal]
Reading symbols from c:\tmp\FRDM-K64F_Bootloader_test.elf...done.


With this, I’m able to debug the loaded code because I have told GDB that the debug information (line and debug information) is loaded at 0x8200.

Finding and Checking Symbol Information

With the symbol information loaded, I should be able to debug that newly loaded code like normal code. I can use the GDB ‘info symbol’ command with an address to check which function is located at address 0x8254:

info symbol 0x8254
_start in section .text of c:\tmp\FRDM-K64F_Bootloader_test.elf


So gdb tells me that at the address 0x8254 the function _start() is loaded (based on the symbols I have provided).

Automating Adding Symbols

Instead of adding symbols interactively during the debug session, I can pass that information at debugger startup. Most Eclipse-based GDB debuggers (including the NXP Kinetis Design Studio) have a setting in the launch configuration to pass commands and scripting to the GDB. Below, you can see an example with the GNU ARM Eclipse plugins:

Running GDB Command to load Symbols

Running the GDB command to load symbols

There, I can add any kind of GDB commands I like.

Summary

Typically, all the debug information needed is in the binary under debug. But often, the debugger doesn't have all the information needed. In that case, I can use GDB commands to add the necessary debug information and symbolics information. I can add this information during debug, or I can automate things using the Eclipse launch configuration.

Topics:
debugging ,eclipse ,gdb ,iot ,tutorial

Published at DZone with permission of Erich Styger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}