5.7. GDB#

Until now, many of you have been able to get by debugging your programs using print statements. Don’t even try to that with this course; you will not be successful. In the container image available with this course, we provide you with the very powerful GNU Debugger gdb, with documentation available here. As discussed previously, you should always run it from emacs, but if you want to run gdb from the command line, type gdb <program> to debug the executable program, and then run to run it. Some of the key features you will find critical in this course are:

  • Setting breakpoints at specific lines in your source code where you want to see the state. For example:

    • break <function>: sets a breakpoint at the beginning of function.

    • break <filename>:<linenumber>: sets the breakpoint to the given line number in the source file.

    • to delete a breakpoint, type delete # where to find out what number each breakpoint is, type info breakpoints

    • you can then type c to continue, n to go to the next line (stepping over functions), s to step into a function, or si to step by a single machine instructions (critical with some of the programs you will write here).

  • Displaying the state of your program, e.g.:

    • print <variable> will print the value of a variable, or `display will print each every time you step ahead.

    • info registers will show you the state in all the registers of the computer; and info regis XXX will show you the state of a particular register, e.g., rsp for the stack pointer

    • x/FMT will examine the state of memory, e.g., x/10gx <address> will show you 10 values of giant (64 bit) values in hexidecimal

    • info threads will tell you about all the threads in your program.

  • Debugging multiple processes; something you will need for implementing a shell

    • set follow-fork-mode <option>: e.g., set follow-fork-mode child to debug child instead of parent

    • detach-on-fork <option>: e.g. set detach-on-fork off to debug all the processes (you are debugging one at a time, and child is blocked right after fork)

    • info inferiors: list all inferiors being managed

    • inferior <inferior_id>: selects which inferior to switch to

  • Debugging threads of execution in your program

    • info threads: lists all existing threads.

    • thread <thread_id>: selects which thread to switch to.

    • set scheduler-locking mode: if set to on will debug one thread at a time

  • Debugging signals

    • info signals or info signals <signal>: lists all signals (or one signal) and shows how gdb responds to it.

    • handle <signal> <keyword>: changes how gdb responds to that signal based on the keyword.

      • nostop: gdb should not stop your program when this signal happens.

      • stop: gdb should stop your program when this signal happens.

      • print: gdb should print a message when this signal happens.

      • noprint: gdb should not mention the occurrence of the signal at all.

      • ignore: gdb should not allow your program to see this signal.

      • noignore: gdb should allow your program to see this signal.

Note, all of the above functionality can be done from within emacs. Occassionally it is valuable to run gdb on the command line using the text user interface. When you run gdb, type Xa to go into tui mode, and then X2 to switch between displays, e.g., to see assembly, all the registers…