Remote Debugging of Raspberry Pi Applications From Eclipse

In this entry I will outline how one can utilize remote debugging tools available in Eclipse to debug applications from a linux PC/VM,  on the raspberry Pi. This tutorial assumes that you have already setup your Raspberry Pi cross compiling toolchain and Eclipse and that you are able to  build your applications in Eclipse (using the cross-compiling toolchain) as well as transfer the binary executables to the RaspberryPi via the RSE plugin. If you have not done so I urge you to look at the “Development Environment for the Raspberry Pi using a Cross Compiling Toolchain and Eclipse” since this tutorial is really a continuation of the tutorial in that blog entry.

To make things easy I will use the same project created in that previous entry and modify the code slightly to the following:

#include <iostream>
#include <unistd.h>

using namespace std;

int main (void)
{
	int i = 0;
	cout << "Hello RPi Development World !"<< endl;

	cout << "Hello RPI Development World Again !" << endl;

	while(1)
	{
		cout << "I'm in the While loop and the value of variable i is: " << i << endl;
		i++;
		usleep(1000000); //wait for 1 seconds
	}

	return 0;

}

This gives us a slightly longer program that makes demoing the debug process easier. Before moving onto the debugging, make sure you clean the project and rebuild it. Then transfer the binary file to the raspberry Pi via the RSE plugin  as instructed in the previous blog entry. In the SSH terminal (on the Raspberry Pi) modify the binary “HelloWorld” file permissions to include “execute” with the command “chmod +x HelloWorld” then run the binary with “./HelloWorld” as shown in figure 1.

Figure 1. Make sure Binary executable file runs properly

Figure 1. Make sure Binary executable file runs properly

If you are able to get to this point then you are ready to debug!!! Two debug approaches will be covered; automatic remote debugging and manual remote debugging.

Automatic Remote Debugging

This is the easiest approach to remote debugging applications in Eclipse. It basically logs into the Raspberry Pi, downloads the binary file from the Linux PC/VM to the RaspberryPi, invokes the gdbserver on the RaspberryPi and then invokes the GDB client on the Linux PC and allows it to connect to GDB server!

Figure 2. Automatic remote debug configuration

Figure 2. Automatic remote debug configuration

 

  • Go To “Debug Configurations” window and create a new remote debug configuration by double clicking on the “C/C++ Remote Application” option in the left frame.
  • Create a distinctive name for this debug configuration. I chose to call it “Automatic Debug”.
Figure 3. Ensure that the "GDB (DSF) Automatic Remote Debugging Launcher" option is selected

Figure 3. Ensure that the “GDB (DSF) Automatic Remote Debugging Launcher” option is selected

  • Make sure that on the bottom of the Debug configuration Window it says “Using GDB (DSF) Automatic Remote Debugging Launcher”. If it does not, then click on “Select Other”. This will open the “Select Preferred Launcher Window”. Then click on the change workplace settings” link and this will open the “Preferences (Filtered)” window. In this window highlight the word “[Debug]” under “C++ Remote Application” in the left frame(Launch Type/Mode), Finally in the right frame (Preferred Launcher) select the “GDB (DSF) Automatic Remote Debugging Launcher” option as shown in Figure 3. Click the “Apply” button in the “Preferences (Filtered)” window and “OK” in the “Select Preferred Launcher” window. You should be back at the “Debug configurations” window with “Using GDB (DSF) Automatic Remote Debugging Launcher” visible in the bottom of that window.
  • In the ”Debug configurations” window, under the “Main” tab (Figure 2), make sure that you have the location of the binary file “HelloWorld” on the Linux PC/VM, relative to the projects work directory, listed in the “C/C++ Application” field. In this particular case that field ought to contain “Debug/HelloWorld” because that is the path of the the binary on my Kubuntu VM relative to the project directory. The absolute path of the binary on the Linux PC/VM should also work.
  • In the “Project” field (Figure 2) make sure you choose the correct project. In this case that would be “HelloWorld”.
  • Under “Build configuration”(Figure 2), enable on the “Select configuration using ‘C/C++ Application’ check-box and select the ‘Enable auto build’ radio button.
  • For the “Connection” field (Figure 2) select the “RaspberryPi” connection. This is basically the name of the SSH connection to the RaspberryPi. Take a look at the previous tutorial if you don’t know what this is or how to create it.
  • In the “Remote Absolute File Path for C/C++ Application” field (Figure 2) specify where you would like the binary to be placed in the RaspberryPi’s filesystem. Make sure that the directory path already exists, since Eclipse’s automatic remote debugging launcher is incapable of creating directories in the remote system(RPi). If you specify a directory that doesn’t exist, the remote debugging attempt will fail. I opted for the home directory of the user ‘pi’ i.e. “/home/pi/HelloWorld”.
  • In the “Commands to Execute Before application” field (Figure 2) add two commands. First add the “sudo -i” command that switches RaspberryPi user from ‘pi’ to ‘root’. This is necessary if your application uses resources that require root access such as GPIO. Then press “Enter” to create a second line in the field and add the second command “chmod +x HelloWorld“. This will ensure that the HelloWorld binary is made executable before the GDB server is run on the Raspberry Pi.
  • DO NOT  check the “Skip download to target path” check-box.
  • Now go to the “Debugger” tab in the “Debugger Configurations” window. In the “GDB debugger” field type “arm-linux-gnueabihf-gdb”. This ensures that the ARM toolchain’s GDB client  connects to the GDB server on the RaspberryPi (ARM GDB Server).
Figure 4. Select GDB client that will connect to GDB server. The client must be associated with the ARM toolchain i.e. arm-linux-gnueabihf-gdb.

Figure 4. Select GDB client that will connect to GDB server. The client must be associated with the ARM toolchain i.e. arm-linux-gnueabihf-gdb.

  •  Now go to the “Common” Tab in the “Debugger Configurations” window (Figure 5) and check the “Debug” check-box under “Display in Favourites Menu”. This will make the “Automatic Debug” Debug configuration accessible from the “green bug” icon in the Eclipse toolbar.
Figure 5. "Add Automatic Debug" configuration to toolbar.

Figure 5. “Add Automatic Debug” configuration to toolbar.

  • At this point you can click on the “Apply” button to apply all changes to the “Automatic Debug” debug configuration. To start this debug configuration, you can either click the “Debug” button in the ”Debugger Configurations” window. You can also click the “Close” button in the ”Debugger Configurations” window. Then click on the arrow sign to the right of the green bug icon in the Eclipse toolbar (Figure 6). This will open a small menu containing the “Automatic Debug” debug configuration. You can then click on that to start the Debug session.
Figure 6 Accessing the "Automatic Debug" debug configuration from the Eclipse toolbar

Figure 6 Accessing the “Automatic Debug” debug configuration from the Eclipse toolbar

  • If everything goes OK, just before  the debug session starts, you will get a “Confirm Perspective Switch” window (Figure 7). This basically informs the user that the Eclipse perspective will be switched from the C/C++ perspective to the Debug Perspective. Click on the “Yes” button in this pop-up window and the Debug session will commence!
Figure 7. "Confirm Perspective Switch" Window

Figure 7. “Confirm Perspective Switch” Window

 

 

Manual Remote Debugging

Remote Debugging can also be performed manually. This requires that the user manually transfers the binary file onto the RaspberryPi (via the RSE plugin) and that the user manually starts the GDB server on the RaspberryPI.

  • First transfer the “HelloWorld” binary file onto the RaspberryPi via the RSE plugin.
  • Then make the “HelloWorld” binary file executable with the “chmod +x HelloWorld” command.
  • Then start the GDB server on the RaspberryPi with the following command: “sudo gdbserver 192.168.0.112:12345 HelloWorld“. First we need to start the GDB server with root privileges using sudo. This is required in case the program requires user-restricted resources such as GPIO. We then specify the IP address of the Linux PC/VM  where Eclipse and the cross-compiling toolchain is running from along with the port number that the GDB server will be listening to. This number can be changed from “12345″. But make sure that you do not choose a port number assigned to another application such as “80 (HTTP)” or “22 (SSH)”. Finally you need to specify the name of the binary file that will be debugged.  The GDB server needs to be started on the Raspberry Pi. This can done via the SSH terminal in Eclipse (RSE Plugin) as shown in Figure 8.
Figure 8.  Starting the GDB server on the RaspberryPi

Figure 8. Starting the GDB server on the RaspberryPi

  • Go To “Debug Configurations” window and create a new remote debug configuration by double clicking on the “C/C++ Remote Application” option in the left frame.
  • Create a distinctive name for this debug configuration. I chose to call it “Manual Debug”.
Figure 9. Debug Configuration Window. Manual Debug

Figure 9. Debug Configuration Window. Manual Debug

  • Make sure that on the bottom of the Debug configuration Window it says “Using GDB (DSF) Manual Remote Debugging Launcher”. If it does not, then click on the “Select Other” link. This will open the “Select Preferred Launcher Window”. Then click on the change workplace settings” link and this will open the “Preferences (Filtered)” window. In this window highlight the word “[Debug]” under “C++ Remote Application” in the left frame(Launch Type/Mode). Finally in the right frame (Preferred Launcher), select the “GDB (DSF) Manual Remote Debugging Launcher” option as shown in Figure 10. Click the “Apply” button in the “Preferences (Filtered)” window and “OK” in the “Select Preferred Launcher” window. You should be back at the “Debug configurations” window with “GDB (DSF) Manual Remote Debugging Launcher” shown at the bottom of the window.
Figure 10. Selecting GDB (DSF) Automatic Remote Debugging Launcher

Figure 10. Selecting GDB (DSF) Automatic Remote Debugging Launcher

  • In the ”Debug configurations” window, under the “Main” tab, make sure that all entries look identical to those in Figure 9.
Figure 11. Specify ARM specific GDB client from cross compiling toolchain

Figure 11. Specify ARM specific GDB client from cross compiling toolchain

  • In the ”Debug configurations” window, under the “Debug” tab and then “Main” sub-tab (Figure 11) , select the ARM specific GDB client “arm-linux-gnueabihf-gdb” from the cross compiling toolchain.
Figure 12. Specify RaspberryPi IP address and the port number that the GDB server is listening to.

Figure 12. Specify RaspberryPi IP address and the port number that the GDB server is listening to.

  • In the ”Debug configurations” window, under the “Debug” tab and then “connection” sub-tab (Figure 12) , specify the RaspberryPi’s IP address  in the “Host name or IP address” field and the port number that the GDB server is listening to in the “Port number” field. In my case, the IP address of the Raspberry Pi is 192.168.0.102  and the GDB server is listening to port 12345 as specified earlier (see Figure 8).
Figure 13. "Add Manual Debug" configuration to toolbar.

Figure 13. “Add Manual Debug” configuration to toolbar.

  • In the ”Debug configurations” window, under the “common” tab (Figure 13), check the “Debug” check-box under “Display in Favourites menu”. This will make the “Manual Debug” Debug configuration accessible from the “green bug” icon in the Eclipse toolbar.
Figure 14 Accessing the "Manual Debug" debug configuration from the Eclipse toolbar

Figure 14 Accessing the “Manual Debug” debug configuration from the Eclipse toolbar

  • At this point you can click on the “Apply” button to apply all changes to the “Manual Debug” debug configuration.
  • To start this debug configuration, you can either click the “Debug” button in the ”Debugger Configurations” window. You can also click the “Close” button in the ”Debugger Configurations” window. Then click on the arrow sign to the right of the green bug icon in the Eclipse toolbar (Figure 14). This will open a small menu containing the “Manual Debug” debug configuration. You can then click on that to start the Debug session.
  • If everything goes OK, just before  the debug session starts, you will get a “Confirm Perspective Switch” window (Figure 7). This basically informs the user that the Eclipse perspective will be switched from the C/C++ perspective to the Debug Perspective. Click on the “Yes” button in this pop-up window and the Debug session will commence!

A Brief Introduction to Debugging in Eclipse

Regardless of whether you decide to use automatic or manual debugging, the debug session in both cases will start in the Debug Perspective. In the top right you’ll find several tabbed windows showing you program outline, Make Targets e.t.c.  You can also add local variables, current breakpoints, CPU registers, modules, disassembly and/or memory windows by  clicking on the “show view” option under the “Window” menu and then selecting an item under the “Debug folder”.

Additionally There is a “Debug” toolbar that contains useful icons. The icons are numbered in Figure 15.

Figure 15. Debug Perspective

Figure 15. Debug Perspective

  1. This is the continue or Resume icon and will cause code to be run.
  2. This icon halts execution and is selectable only while the program is running
  3. The red square button terminates debug mode and kills the GDB server and client applications.
  4. This icon disconnects the GDB client from the GDB Server.
  5. This is the “step into” icon allowing you to step into functions or to the next instruction
  6. This is the “step over” icon allowing you to step over functions or to the next instruction
  7. This is the “step out of” icon allowing you to step out of a function or the current scope.
  • To add a breakpoint just right click in the blue margin of the source code window and choose the “toggle breakpoint” option. Repeat the process to remove break points. So let’s add a break point at each “cout“  statement as shown in Figure 15. Now click continue.
  • After hitting the continue icon once, code execution will halt at the first breakpoint. Hitting the continue icon again repeatedly will cause code to halt at the next breakpoint an so forth. Congratulations! you just remotely debugged your first RaspberryPi application!
  • Once you are done debugging, you can always stop debugging by pressing on the red square termination icon (icon 3) or icon 4 and switching the perspective back to C/C++.
This entry was posted in Uncategorized. Bookmark the permalink.

9 Responses to Remote Debugging of Raspberry Pi Applications From Eclipse

  1. Neil says:

    I had tried automatic debugging before and could not get it work. Manual Debugging works for me, i.e. manual download to RPi and start gdbserver, then debug from eclipse.

    I carefully followed the tutorial in the hope that my own approach had missed something crucial. However I get similar problem to my own method.

    The problem seems to be when you start the debug session in Eclipse and it tries to download the binary. I get the following dialog popup message.
    “Problem Occured
    ‘Launching DebugTut Debug’ has encountered a problem.

    Error during file upload.
    Missing element for :”
    Missing element for :”
    Missing element for :”

    Any ideas where to look ?

  2. Neil says:

    I have discovered why it did not download the binary file. It seems I had a remote path that did not exist ! Opps.

    However having fixed that it downloaded the binary prompted me to switch to the debug perspective.

    When it starts debugging the console tab reports “Cannot access memory at address 0×0″.
    Not sure what this is trying to tell me. However single stepping does work, although can take 30 seconds or more for everything to update which seems very slow.

    • halherta says:

      Neil, Yes the remote path has to exist…I will amend to tutorial & explicitly make note of this. As for the “Cannot access memory at address 0×0″ warning, I also get it (see Fig15). I have no problems however with stepping and using breakpoints. I do not have any serious speed issues when simulating a simple program similar to the one in the Tutorial. I also had no problems when debugging the GPIO examples posted on this site. Having said that I didn’t simulate a program that calls external libraries such as libjpeg. Perhaps that is why debugging is slow in your case ?

  3. wr says:

    when follwing the Automatic Debug way, I get the error:

    Error during file upload.
    Operation failed. File system input or output error
    Operation failed. File system input or output error
    Operation failed. File system input or output error

    looking on my rasPi on an independent console, it has downloaded the binary, but not chmod’ed it. I added an explicit “cd” to the “Commands to execute before application”, which looks now like this:

    sudo -i
    chmod +x /home/pi/test/crosscompile/HelloWorld
    cd /home/pi/test/crosscompile/

    When I paste this lines to a ssh console, they work.
    There is no gdbserver process running on the rasPi.

    When working with the previous HelloWorld tutorial, I had the impression that there is a lazy resynchronisation of the sftp-connection.
    Maybe these issues are related?
    The Debugger successfully downloads the file, but fail to realize its success due to lazy synchronisation? Is there any config on that?

    • halherta says:

      wr, I’ve not encountered this error before. You do not need to add the “cd /home/pi/test/crosscompile/” in the “commands to execute before application” box. Simply ensure that in the “Remote Absolute File Path for C/C++ Application” field (in figure 2) you put “/home/pi/test/crosscompile/HelloWorld”.

      • Charlie says:

        I had the same… or at least somewhat similar problem as wr.

        Turned out I ran the program once as instructed by the tut earlier, but didn’t exit from it cleanly, so it was still loaded in memory, and thus the file couldn’t be written to, so it obviously wouldn’t transfer over.

        Don’t use Ctrl+Z or other odd methods to kill the process. Only ever use Ctrl+C. You can check if you have a process stuck in limbo like I did by SSHing into the pi or using the console window in eclipse and typing the command “jobs”. If you do have some, you can stop them cleanly by using the command “kill %n”, where “n” is the jobs number. Restarting the pi is probably a blanket fix for such things too.

        If that’s not your problem, sorry, but it sounded quite similar to me.

  4. Koen says:

    I also had the error “Operation failed. File system input or output error”. I fixed this by adding the filename to the “Remote Absolute Path for C/C++ Application”. It seems that this must contain the path + filename to work.

    PS: Regarding Eclipse: I run this in VMWare. I have installed MobaXterm (X-Windows server) on my windows machine, and now Eclipse runs almost as a native windows app :-)

    Thx Halherta !

  5. spium says:

    Very useful tutorial!
    I found a little “bug” in the automatic debug one though: when you set “sudo -i” as pre-execute command, it logs into the superuser. After you’re done debugging Eclipse automatically executes “logout” to disconnect from the shell, but it actually just logs out of the superuser, so the shell stays open.
    You can verify this in the Debug perspective where you see the currently running processes: when you stop debugging the shell process is still running and doesn’t shut off.
    If you forget to close it manually, every time you debug you end up with one more running process.

    I solved this simply by setting up a new connection to the Pi as root user, instead of the pi user, and deleted the “sudo -i” command from the post-exec script.
    This way Eclipse shuts off all processes cleanly after it’s done debugging.

    Hope this was useful :D

  6. Cristian Prado says:

    Thanks !!!!!!!!!!!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>