Walking through your program's code is a good way to compare your expectations against the reality of the code execution. Finding where the two diverge from each other can provide the scope in which a bug in your code or a conceptual misunderstanding may exist. Here are some things to keep in mind:
Debugging is especially difficult when you do not know where the bug is in your code! Most of the labs in 351 are comprised of multiple functions or parts that should be tackled one-by-one:
We encourage collaboration in this course! Oftentimes, bugs can be easily overlooked individually, so collaboration allows more perspectives, ideas, and just another pair of eyes when writing code or trying to understand the problem! Here are some ideas to consider:
printf
debuggingDebugging with printf can be a good starting point for better understanding the state and execution of your program. Here are some places where it might be useful:
GDB is an immensely useful tool to help you debug your C and assembly programs.
printf
).The time you spend getting familiar with GDB will be an excellent investment for this and future courses.
Here are some code samples for playing with GDB along with some example commands you can try:
GDB also has a text user interface which is optional, but you may find useful.
In 351, we will deal with binary files, where the stored data uses the full range of possible character values. This is in contrast to text files, where the stored data are mostly restricted to the values that correspond to printable (e.g., ASCII or Unicode) characters. Different types of binary files serve different purposes, but the one thing they have in common is that they will look like garbage when opened in a text editor because non-printable characters will be represented in ways you wouldn't expect.
objdump
The primary types of binary files that we will examine are object files and executables. Both of these types of files are primarily used to hold machine code, so we can use the utility objdump
to interpret their contents in a textual format.
Knowing the ins and outs of objdump
isn't a high priority in 351, so, when applicable, you will generally be given the exact commands to run in the assignments.
xxd
xxd
will print out the bytes of a file in hex format. You don't need to know much about this utility and it is primarily useful for Lab 3.
Here is an example usage. The first command creates a file called test.bin
whose contents are the ASCII characters hello world
followed by the bytes CA
, FE
, F0
, and 0D
(the \x
you see means that the byte is specified in hex). The second command invokes xxd
on the binary file that we just created.
[attu]$ echo -ne "hello world\xca\xfe\xf0\x0d" > test.bin
[attu]$ xxd test.bin
00000000: 6865 6c6c 6f20 776f 726c 64ca fef0 0d hello world....
There are three blocks/columns of information in the single line of output shown above:
00000000:
) represents the byte address/index of the left-most byte of the line (in hex). This can be helpful for finding your place in a longer file.68
through 0d
) shows the values (in hex) of the bytes themselves. Recall that one byte = two hex digits. The bytes have increasing address/index from left-to-right.0x68
, is the ASCII character 'h'
. The last four bytes show up as .
, which is how xxd
chooses to show non-printable ASCII characters. This can be a little bit confusing as there is a valid '.'
character (0x2e
) and these non-printable characters might display differently in a text editor.Text User Interface (TUI) mode of GDB can nicely show your code and the value of registers as you debug! Its use is entirely optional for 351, but we wanted you to be aware of it as it may help some of you.
Most TUI commands will automatically start TUI mode, but you can also explicitly open GDB in TUI mode using:
[attu]$ gdb -tui <filename>
Of particular interest, you can bring up the disassembly and registers view using:
(gdb) layout asm (gdb) layout regs
Note that you want to do them in that order so that the registers window is on top. Then as you execute instructions (stepi
or si
for assembly instructions), the assembly view will highlight the next instruction (not executed yet) and the registers view will highlight any changed registers.
Unfortunately, there are some annoying formatting issues that sometimes pop up while using TUI mode. If things start to look weird, run the following command (or press Ctrl+L) to set things straight:
(gdb) refresh