Debugging Microwindows code with GDB This is a short walk-through of a GDB session with an Xlib program using the libNX11 and libnano-X libraries. It explains the most often used GDB commands. This GDB session uses our xhello.c example in the nxlib/test directory. To add debugging information for GDB we have to compile the example with the -g flag and without the -s flag. If we set the DEBUG macro to "Y" in the config file, Microwindows will compile with these switches. If
you compiled shared libraries, which is the default
setting in the config file, you have to execute the nano-X& nanowm& This is not required if you selected „LINK_APP_INTO_SERVER“ in the config file Then we get into the nxlib/test directory and load xhello into GDB by entering: "gdb xhello". Then the (gdb) prompt will appear. If we would enter "q" now, we would exit GDB again. Entering
"l 1" (list from line 1) will display the first 10 lines
of our xhello example. Pressing enter will display the next lines.
Entering "l 50" will display ten lines with line 50 in
the middle. The command If there are several source files linked together, you have to preceed the line number with the name of that file and a colon. So you can e.g. enter "l foo.c:10" to list line 10 and the following ones in source file "foo.c". Before you run the program, you usually set some breakpoints first. The most common command now is "break main" which will stop the program execution at the first command in the main function. Then you can single step through the program from there. Here, we will now set a breakpoint if one clicks into the window. This is handled in "case ButtonPress:". Since the code below that is commented out, we set the breakpoint on the "break" statement in line 109. Entering "b 109" sets a breakpoint at statement 109. "clear 109" would remove that breakpoint again. We can also enter a function name here, so "b terminate" will break when this function is called. An alternative is "advance 109", this will continue execution up to line number 109. You can also add a condition to the breakpoint. If you enter "b 109 blackColor = 0" the breakpoint will only be triggered if the variable blackColor has the value zero. Now we start our the program by entering "r" at the (gdb) prompt. GDB will report that the breakpoint has been reached and display its (gdb) prompt which allows you to enter further commands. To inspect the value of a variable you can use the "p" command. So "p text" will display "Hello world" while "p whiteColor" (capital C!) will display the numeric value of that color. Local variables within functions can only be displayed while you are within that function. To see the color value in hex you can enter: "p /x whiteColor". These format specifiers are similiar to the ones used by the printf statement in C. In fact you can also enter statements like that: "printf "Colorvalue: %X",whiteColor". Do not use parentheses here. If you enter "display whiteColor" this variable will be displayed automatically whenever the program is interrupted. "undisplay" will terminate this display command again, but you have to specify the number for this command. "info display" will output the numbers for the display commands specified so far. You can also change variables with GDB. If you enter "set blackColor = 10000" the updated part of the window background will turn dark green. If you enter "c" the program will continue. We can also interrupt it entering CTRL-C and return to GDB. Sometimes you have to enter CTRL-C several times till it is accepted. Then the (gdb) prompt will appear and you can enter commands again. You could now search for an expression: "search dpy" will display the next line containing "dpy" while "reverse-search Hello" will move up the code to "Hello World". Here you could enter "s" to single-step through the code. "s 10" will make ten steps. If you do not want to step into a function, you can step over that by entering "n" for "next" to step to the line following that function call. Now enter "c" to make the program continue again to trigger our breakpoint. Using the "call" statement we can call functions from the (gdb) prompt. If we enter "call terminate(dpy)" now, the program will exit. However, if we enter "call terminate(1)" instead we will get an error. Now we can use the "bt" or backtrace command will allow to display the lines of code executed before the error occured. If you want to determine the reason for a program crash, you can just enter "r" after loading the program and enter "bt" after the program crash occured. If you want to trace into the Nano-X or NX11 libraries, you have to compile these with the -g switch too. If you set "DEBUG=Y" in the "config" file, the "Makefile.rules" file will add the "-g" switch when compiling the libraries. Commands covered in this walk-through: q - quit r - run program c - continue program advance - continue program execution up to the line number specified s - single step through program code n - step through program code, skipping current function CTRL-C - interrupt program and return to GDB b - set breakpoint call - call function bt - backtrace p - display value of variable display - set variable to display on each breakpoint set - change value of variable l - list lines of code search - search expression in code A manual for GDB can be found here: http://sourceware.org/gdb/onlinedocs/gdb/index.html#Top October 2018 Georg Potthast
|