Improve your productivity by using the debugger in Rational Developer for Power Systems Software
IBM® Rational® Developer for Power Systems Software™ provides integrated development and debugging tools for IBM® AIX®, IBM® PowerLinux™, or IBM i. It helps developers create and maintain applications on IBM Power Systems™ with rich source-editing features, visual design and analysis tools, integrated search and compile error feedback, and remote debugging based on Eclipse.
The integrated debugger is an interactive, source-level graphical debugger. It works on Microsoft Windows and Linux-based workstations connected remotely to a debugger engine running on either AIX or PowerLinux.
The integrated debugger enables you to debug programs written in C, C++, and COBOL. Using the integrated debugger, you can diagnose problems quicker as you deepen your understanding of your own program.
We use C/C++ on AIX to describe the features of the integrated debugger in this article.
Starting a debug session
This section describes how to prepare your program for debugging and how to launch a debug session by using the Remote System Explorer. We also introduce the basic debug features, such as setting breakpoints, stepping through your program, displaying variables, and monitoring expressions.
Compile the program with debug information
To debug your program at source code level, you need to compile your program with certain compiler options that instruct the compiler to generate debug information in the object files. For the IBM XL C/C++ compiler Enterprise Edition for AIX, compile with the -g option.
Set up the Remote System Explorer
To debug a remote application on AIX or Power Linux, set up a remote system connection first. You can do this through the Remote System Explorer perspective. As an example, we will describe how to set up a remote connection to an AIX host.
- From the Remote Systems navigator, double click New Connection > AIX, to open a New Connection dialog window.
- Enter the AIX host name. You can also modify the connection configuration at the Next page.
- A new node is created in the navigator after you click the OK button.
Figure 1. Creating a connection to a remote AIX system
You can expand the Files > My Home tree to browse the files under your home directory or the Files > Root tree to browse from the root directory. It might prompt you for the user ID and password when making the remote connection. When you enter the password, you can check the Save Password check box so that you do not have to enter the password again.
Launch a debug session
After creating a remote connection from the Remote Systems Explorer, you can start to debug a remote application from the Remote Systems navigator.
- Expand the remote file system tree to expose the remote executable file that you compiled with debug information.
- Right-click the remote file, and select Debug > Remote Application.
This will start a debug session on the remote executable. If you want to configure the launching parameters, you can select the Debug > Remote Application... action to open the launch configuration dialog window. You can modify the following debug startup parameters in that view:
- If the Automatically stop at the first executable line of main method option is selected, the debugger will automatically stop at the first line of the main method.
- You can enter the program arguments from the Arguments tab
- You can enable the Production Debug feature from the Advanced tab.
You can also attach to a running process using the debugger. To do this, expand the Processes > My Processes tree from the Remote Systems navigator, right-click the process that you want to attach, and select Attach > Process.
Using the IBM debugger
After launching a debug session, you would normally debug it from the Debug perspective. The following screen capture shows the UI for a debug session in the Debug perspective.
Figure 2. The Debug perspective
The debugger displays a lot of information, and it is grouped into different sections called views. The sections that follow describe those that are most relevant to various debugging-related tasks.
The view that you will probably use the most is the Debug view, which is the main control center for your debug session. In addition to the Debug view, the UI contains several other views for displaying special information, including the Breakpoints, Variables, and Monitors views and, for advanced debugging, Modules, Memory, and Registers views. The icons in each view's toolbar provide additional useful actions, and you can hover your mouse cursor over each of them to display a tool tip that describes the action. To learn more, experiment with each of them.
The Debug view is the starting point for any debug session. For each process under Debug, the view displays all of the running threads. In turn, for each suspended thread, a list of stack frames is visible, representing the call hierarchy. Also, the source file currently being debugged is displayed in the Source editor. When a debug session is selected, it is considered the active debug context. Other debug views show content based on the current active debug context. Selecting a debug session automatically updates other debug views to show the matching content.
The Breakpoints view is the central location for controlling breakpoints. You can always see a list of breakpoints that you have set in the Breakpoints view, and you can add a new breakpoint by right-clicking in the view and selecting one of the entries from the Add Breakpoint submenu. You can also set a source line breakpoint from the annotation column of the editor. In the Breakpoints view, enabled breakpoints have a check mark beside them. You can enable and disable breakpoints by checking or clearing that box.
Step through your program
You can step through your program by using the Step Into, Step Over, and Step Return toolbar buttons. These commands are also available from the Run menu or by using the keyboard shortcuts: F5, F6, and F7, respectively. If you direct the program to run (F8), execution will resume until it hits a breakpoint, the program terminates, or an exception occurs.
You can use the Animated Step Into action to perform repeated step into your program. The animation pace can be set directly on the animated step icon or from the Preferences page. The default pace is 2 seconds.
The Variables view lists in-scope variables each time a thread or program stops.
After every program stop, changes to in-scope variables will be highlighted in the Variables view. There are several actions available, which you can see by right-clicking anywhere inside this view to bring up the context menu.
You can change variable values here. If you edit a variable from the Variables view, the new value becomes effective immediately. You can also change the representation of a variable. For example, to display an integer in binary format instead of the default decimal, use the Change representation context menu of a selected variable.
You can use the Monitors view to monitor a collection of variables and expressions of interest, for easy access and modification. The values of the monitored variables or expressions are updated each time the program stops. If a variable is out of scope, its value will not be displayed until it comes back into scope. This is especially useful for observing global variables as they change throughout your debug session. You can monitor any valid expression, such as a simple local variable, to a particular index in an array.
You can use one of the following ways to monitor a new expression:
- Right-click inside the Monitors view, and select Monitor Expression. Enter the expression that you want to monitor in the dialog window that opens.
- Select an expression from the source editor, and then select the Monitor Expression action from the context menu.
- Right-click a variable from the Variables view, and select Monitor Local Variable.
Using advanced debugging techniques
Sometimes a piece of code is called many times, even from different threads, but you want to stop in that code only if a particular condition is met. This is where the Optional parameters page of the breakpoint wizard is very useful.
- Right-click a breakpoint in the Breakpoints view, and choose Edit to invoke the Edit Breakpoint wizard.
- Then click the Next button to go to the "Optional parameters" page, where you can specify how you want to handle these situations.
You can select the thread on which you wish to stop, the frequency of suspension, and even define a Boolean expression that must be true before suspending. You may also have multiple conditional breakpoints at the same location, and they can be easily enabled and disabled from the Breakpoints view.
Figure 3. The breakpoint conditions page
The Modules view displays all of the loaded modules for the debugged program. By default, only modules with debug information are displayed. You can clear the Show Modules with Debug Information toolbar button to also show the modules without debug information.
You can expand each module to show the compilation units, source files, and functions that it contains. You can double-click a source file or function to open it in the source code editor. You can also set an entry breakpoint on a function from the context menu.
Figure 4. The Modules view
The Memory view enables you to examine and modify the contents of memory at a specific address, usually that of a variable. You can also choose which format the memory will be displayed in, such as hex, ASCII, EBCDIC, signed integer, or unsigned integer. The address of the expression used as the base memory is called a memory monitor, and you can use the Monitors pane in the Memory view to add and remove memory monitors.
Memory monitors are different from the monitors used in the Monitors view described in the preceding section.
Figure 5. The Memory view
You can display and modify the contents of various registers by using the Registers view. The registers are logically grouped in the view. The Registers view is similar to the Variables view in that it indicates register changes by highlighting the changed items. You can add registers to the Monitors view and monitor them for changes. In addition, if a register's value is a memory address, you can monitor it by using the Memory view.
Figure 6. The Registers view
You can use the debug console to send debug commands to the debug engine. You can issue commands directly to the debug engine and view the resulting output in the debug console, which helps enable a fairly interactive debug. The commands supported are debug engine-dependent, and you can display them by typing
help in the debug console.
In Figure 7, the commands list pane is on the right. It lists all of the commands that have been entered. The commands history pane on the left displays the output from entered commands. You can use the toolbar buttons to clear the commands history and list panes, import, export, and run lists of commands.
Figure 7. The debug console
Debug a client/server application
You can use the Rational Developer for Power Systems Software debugger to debug your client/server application. For example, if the client side of your application is written in Java and running on Windows or Linux, and the server side of your application is written in C/C++ and running on an AIX system, you can use the Java debugger to debug the Java front end and use the complied language debugger to debug the C/C++ back end. You can step through both programs to see how they interact with each other.
The debugger provides three different source visualization options:
- Source view, which shows the default application's source code
- Disassembly view, which displays the instruction codes
- Mixed view, which includes both source and instruction codes
You can choose the views by right-clicking in the editor view and choosing Switch View.
Figure 8. Different source visualization views
Debugging a core dump
The integrated debugger for IBM Power provides a post-mortem debugging feature that allows the user to debug a core file generated by a running executable file. An executable can generate a core dump when it runs into a segmentation fault, which can be caused by a null pointer reference.
To debug a core dump, just select the core file from the Remote Systems navigator, right-click, and select Debug Post-Mortem > Core File. The debug session started from the core dump will automatically stop at the stack frames where the core dump happens. You can examine the variables from the Variables view to find out what triggers the core dump.
The integrated debugger for Power provides a Production Debug feature that you can use to debug a production binary file, using the debug information from another binary. Under this scenario, you would create a binary with debug information by using the -g compilation flag and then create a production binary by stripping away the debug information from the debuggable binary. The production binary is the one that you send to your customer.
There are cases where you will need to diagnose a problem on the customer's machine. When this happens, you can copy the debuggable binary to the customer's machine. Using the Production Debug feature, you can start a debug session on the production binary but use the debug information from the debuggable binary:
- From the Advanced tab of the launch configuration dialog window, select Enable production debug.
- Add the directory that contains the corresponding debuggable binary to the Debuggable binaries path list. In a production debug scenario, the production binary is still the one running on the machine, but the debug information is retrieved from the debuggable binary, instead.
Production debug can also be enabled by associating a debuggable binary with a loaded module. One use case for production debugging is that the customer ran into a core dump when using the production binary and calls you, the developer, in for assistance. You can debug the core dump by following the procedures in Debugging a core dump. However, because the core dump is produced by the production binary, which does not contain any debug information, the developer cannot debug it at source level. The developer can clear the Show modules with debug information toggle toolbar button to expose the main executable module. Then you can associate a debuggable binary with the main module from the context menu and diagnose the problem at source level.
Team Debug is a feature that allows the transfer of debug sessions between IBM® Rational Team Concert™ team members. Transferring a debug session is useful in team environments where different team members are experts or owners of different components of an application. Sharing debug sessions enables faster problem resolution by allowing the transfer of existing debug sessions without the receiver having to establish the correct environment and start the debug session over again.
During a debug session, a team member can transfer the debug session and its current state to another team member. The transfer includes the current thread states, breakpoints, and monitors. The receiving team member can continue to debug the application after accepting the notification that someone has transferred a debug session. A team member can also park the debug session on the Rational Team Concert server, where the debug session remains in its current state until someone retrieves it from the team repository to continue debugging it.
Rational Developer for Power Systems provides a cross-platform, cross-language code coverage capability. You can use it to see how well your test cases are exercising your compiled language applications by generating statistics that show the percentage of lines in your code that have been run by a test case. The code coverage features are implemented using debug technology.
Using the code coverage tools, you can launch a code coverage session by following steps similar to those for launching a regular debug session. You can see the coverage statistics of all compiled elements in a tree structure from the Code Coverage Report view. Use the Compiled Code Coverage Launch History view to manage all previous launches.
Figure 9. The Code Coverage Report view
The integrated debugger in Rational Developer for Power Systems Software provides rich debugging capabilities with support for different compiled languages and different platforms. In addition to the basic debug functionality, such as stepping and setting line breakpoints, the tool offers numerous advanced features, including Memory view, multiple breakpoint types, core dump debugging, Production Debug, Team Debug, and code coverage. See the documentation link in Related topics for an in-depth explanation of each topic.
- IBM Rational Developer for Power Systems Software provides integrated development environments for the major development workloads on IBM i, IBM AIX, and Linux, including Java, C/C++ on AIX and Linux, COBOL on AIX, and RPG, COBOL, C, and C++ on IBM i. To learn more, start with the developerWorks page, and then review the Rational Developer for Power Systems Software product information, features and benefits page, as well as the product line overview. For support or documentation, see the Rational Developer for Power Systems Software information center.
- Stay current with developerWorks technical events and webcasts focused on a variety of IBM products and IT industry topics.
- Improve your skills. Check the Rational training and certification catalog, which includes many types of courses on a wide range of topics. You can take some of them anywhere, any time, and many of the Getting Started ones are free.
- Download the free trial so you can evaluate Rational Developer for Power Systems Software, or try the Power Systems software in the online sandbox.
- Download a free trial version of other Rational software.
- Evaluate other IBM software in the way that suits you best: Download it for a trial, try it online, use it in a cloud environment, or spend a few hours in the SOA Sandbox learning how to implement service-oriented architecture efficiently.