Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add debug command #567

Closed
spoenemann opened this issue Jan 24, 2020 · 7 comments · Fixed by #590
Closed

Add debug command #567

spoenemann opened this issue Jan 24, 2020 · 7 comments · Fixed by #590
Labels
type: enhancement Proposed improvement

Comments

@spoenemann
Copy link

Feature Request

We are implementing a debugger for the Arduino Pro IDE. The debugger needs specific command line tools for the selected board. Currently we have hard-coded the paths to these tools for the Arduino Zero board, but of course we'd like to generalize this (arduino/arduino-pro-ide#185).

Could the CLI provide paths to the debugging tools when we query board details?

This is the list of required tools, along with the path we currently use for Arduino Zero:

  • gdb
    $Arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-gdb
  • objdump
    $Arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-objdump
  • openocd
    $Arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd
  • openocd scripts
    $Arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts
  • openocd configuration
    $Arduino15/packages/arduino/hardware/samd/1.8.4/variants/arduino_zero/openocd_scripts/arduino_zero.cfg
@masci masci added the type: enhancement Proposed improvement label Jan 24, 2020
@spoenemann spoenemann changed the title Provide debugging tool locations Add debug command Feb 3, 2020
@spoenemann
Copy link
Author

spoenemann commented Feb 3, 2020

An even better alternative to printing the debugging tool locations as described above would be to add a debug command that takes care of spawning gdb and openocd with the correct arguments.

The current proof-of-concept of the debugger does the following:

  • openocd is spawned with the command
~/Arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd -s ~/Arduino15/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts --file ~/Arduino15/packages/arduino/hardware/samd/1.8.4/variants/arduino_zero/openocd_scripts/arduino_zero.cfg --file /tmp/.../gdb.cfg

where gdb.cfg is a temporary file with the content

gdb_port 50000
telnet_port 4444
echo "GDB server started"
  • gdb is spawned with the command
~/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-gdb --interpreter=mi2 -q ~/Arduino/Blink/Blink.arduino.samd.arduino_zero_edbg.elf
  • Afterwards we send the following commands to the gdb process via std I/O
-gdb-set target-async on
-target-select extended-remote localhost:50000
-interpreter-exec console "monitor reset halt"

@cmaglie
Copy link
Member

cmaglie commented Feb 5, 2020

Thanks @spoenemann

We can provide:

  • a command to start a GDB server for you at a specified port and return the path to the gdb client arm-none-eabi-gdb (so you have the path to the client specific for the architecture, anyway from the IDE you still need to launch and manage the gdb client)
  • a command to stop the GDB server

Questions:

  • do you need telnet_port or is gdb_port sufficient?
  • Is the binary (.elf) already populated with debugging symbols? Do we need to re-build for debugging?

@spoenemann
Copy link
Author

That sounds good!

Regarding the second question: I have been able to debug with the default compiler settings, which use -Os to optimize for size. But it would be very good to have an option for the compile command to control the optimization level. Otherwise the compiler does stuff like eliminating local variables and inlining function calls, which makes debugging more difficult.

@csweichel
Copy link
Contributor

  • do you need telnet_port or is gdb_port sufficient?

I'd think that the GDB port is sufficient for the time being. One would need to find out what's the default behaviour for OpenOCD, i.e. does it spawn a telnet server by default. If so, this port would need to be set to some value so as not to conflict with other sessions.

@matthijskooijman
Copy link
Collaborator

Note that you can also let gdb spawn openocd and talk to it through a pair of pipes, which saves one open network port. A long time ago, I figured this out for an arduino-debugger tool that never really got finished. For another platform, I'm using this technique again, which is done using this command in the gdb init file (this uses normal gdb commands):

target extended-remote | openocd -c "gdb_port pipe" -c "telnet_port 0" --file openocd.cfg -c init -c halt

Looking back at my arduino-debugger work, which used gdb mi commands, the command I used was:

    _, err = state.gdb.CheckedSend("target-select remote | ", openocdPath, "-c", "gdb_port pipe", "--search", openocdScripts, "--file", openocdConfig, "-cinit", "-chalt")

Note that this CheckedSend command actually added quoting of arguments that contained spaces, except for the first argument which is passed unchanged. https://github.com/cyrus-and/gdb/blob/0306a029f42faa30878795ea2c66134cdecfa304/commands.go#L33-L44

The "telnet_port 0" is added to disable the unused telnet port (which is inside the openocdConfig file in the second version). -cinit -chalt was needed to sync the openocd and gdb states, but it seems you are sending a reset halt through gdb later (and I suspect openocd might be running the init automatically if not explicitly done).

Is the binary (.elf) already populated with debugging symbols? Do we need to re-build for debugging?

I guess this depends on the flags set in platform.txt. The default AVR core always builds with -g, but some cores (such as STM32) need a board option to enable -g.

do you need telnet_port or is gdb_port sufficient?

I suspect this needs only gdb_port, and telnet_port should be explicitly disabled as suggested above.

a command to start a GDB server for you at a specified port and return the path to the gdb client arm-none-eabi-gdb (so you have the path to the client specific for the architecture, anyway from the IDE you still need to launch and manage the gdb client)

@cmaglie, starting a "GDB server" in this case means just starting openocd, right, which provides a gdb server? I wonder if it would make sense to let arduino-cli start both openocd and gdb (as suggested above) and maybe even directly connect gdb (using mi2) to stdin/stdout (not needing any network ports at all)? That would also remove the need for a stop command, since the IDE could just send a term (or gdb quit command or whatever).

a command to stop the GDB server

If there would be a stop command, how will you select the instance of the server to stop? More generally, how will you select the board to debug? I guess this could be done similarly to how a board is selected for upload, but might need some platform.txt additions to know what options to pass to openocd to select the board (I guess the options are dependent on what adapter is used by openocd).

@matthijskooijman
Copy link
Collaborator

I'd think that the GDB port is sufficient for the time being. One would need to find out what's the default behaviour for OpenOCD, i.e. does it spawn a telnet server by default. If so, this port would need to be set to some value so as not to conflict with other sessions.

AFAIK, it is enabled by default, setting telnet_port 0 disables it.

@cmaglie
Copy link
Member

cmaglie commented Feb 5, 2020

Hi @matthijskooijman thank you for the hints!

I wonder if it would make sense to let arduino-cli start both openocd and gdb (as suggested above) and maybe even directly connect gdb (using mi2) to stdin/stdout (not needing any network ports at all)

that would be the ideal solution using arduino-cli as a pure command line (and therefore as a standalone process that gets cleaned up automatically by the OS at the end of the debug session).

In our case we are using arduino-cli as a daemon/grpc (for integration with IDE) and, since we don't have stdin/out, we must stream the gdb stdin/out via GRPC... it's doable but it's more work.

@rsora let's figure this out...

If there would be a stop command, how will you select the instance of the server to stop? More generally, how will you select the board to debug? I guess this could be done similarly to how a board is selected for upload, but might need some platform.txt additions to know what options to pass to openocd to select the board (I guess the options are dependent on what adapter is used by openocd).

Yes, well I've omitted the details, we could simply return a session-id when the gdb is opened, and use the same id in the close command to indentify the session to close.

@cmaglie cmaglie linked a pull request Feb 21, 2020 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement Proposed improvement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants