This page is designed to provide some tips and tools for debugging your lab assignments in CSE 351. As this course is more about concepts than programming, it is always recommended to first verify your understanding of the material being assessed first. However, since we are examining many concepts beneath the software layer (and therefore abstracted away from the programmer), it is very important to make use the debugging tools to examine what's actually going on in your program.
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 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
Debugging
Debugging 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:
printf
.
Parts of 351 can only be done through GDB.
GDB (Gnu DeBugger) is an immensely useful tool to help you debug your C and assembly programs:
printf
statements.Here are some code samples for playing with GDB along with some example commands you can try:
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. Here is the link for the full documentation of .
[attu]$ gdb -tui <filename>
(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.
Ctrl+L
) to set things straight:
(gdb) refresh
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
'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.