GDB is REALLY easy! Find Bugs in Your Code with Only A Few Commands
By Low Level
Summary
## Key takeaways - **Compile with -g for GDB Source View**: Use gcc -o main main.c -g instead of -s to add debug information, making the file bigger but allowing GDB to show human-readable source code alongside assembly for easy line-by-line debugging. [00:22], [01:17] - **Break main: gdb run Stops at Entry**: Type break main to set a breakpoint at the main function, then run to start the program—it executes until main and stops there, ready for inspection. [02:00], [02:20] - **Next for C Lines, nexti for ASM**: Use next to step to the next line of C code, which may span multiple assembly instructions; use nexti to step one assembly instruction at a time. [02:41], [03:04] - **Step vs Next: Into vs Over Functions**: Step dives into functions like puts to see their code; next skips over them, staying in main's context without inspecting internals. [03:36], [04:11] - **Segfault Reveals scanf Pointer Bug**: scanf crashed dereferencing rdx=2 (value of d) as a pointer because code passed d instead of &d; gcc warned about passing int instead of int*. [05:06], [06:42]
Topics Covered
- Compile with -g for Debug Info
- Breakpoints Halt at Main Entry
- Step vs Next Skips Functions
- Examine Registers Pinpoint Crash
Full Transcript
what is up guys in today's video we're going to be talking about gdb or the gnu debugger and we're going to use gdb to find a bug in a particularly buggy program that i wrote over here on the left for those of you that are
pretty good at c you'll probably see the bug in the program pretty quickly but we're just going to talk about gdb and how to use the various commands in gdb to debug a program and find bugs such as this one so typically when people compile their code in c
they use the following commands to do so right gcc tac o the name of the program the source code that they use to create it and then tack s to strip it right what that does
is that creates a file an elf and the file is stripped which means that it's pretty small and it has a certain size to it you know 14k not too bad and we can run the program
and get its functionality but the problem with this is that we cannot run gdb on it and see the source code it has no source code available that's because we didn't
compile our program with debug information so that gdb can show us a human readable output of our program so to get our program into that format where we can actually debug it
we're going to do an additional flag instead of attack s on our program so we're going to do gcc tac o main main.c your source code and then tack g what that tag g does
is it puts what's called debug information into our code and the debug information does make our file a little bigger notice we added about 5k of information into the program but what
that does is we can actually do lay next for layout next and eventually when we hit enter a few times we'll get to this nice view where we can see the source code in gdb
that the program was created with and the assembly and that makes it really really easy to step line by line through our code and figure out where is this crash occurring right so the way that we want to run our
program is using a series of commands that gdb has um the first one is we want gdb to stop execution at a known point and for us the known point
the only place we've written code is the function main that has to be where our program has a bug right so let's add a breakpoint
by typing break at the label main so it says that breakpoint 1 is added to this address which is where main lives in assembly which is also line 4 of our c
awesome so if we type run to start the program the program will begin to run and it gets to where main is written in code and it stops and it says hey we're at main what do we do now
so there are four instructions that allow us to step line by line through our code we can step through the c code line by line and we can step
through the assembly code line by line obviously one line of c can imply multiple lines of assembly right so if we want to jump immediately to line five in c where it says in d equals two we just
type next that gets us to several lines through the assembly where it puts two onto the stack in the place that
variable d lives we also can instead of doing next line of c we can do the next line of assembly with next i it's next instruction and you see that moved us
from this instruction and assembly to this instruction assembly so we'll do that one more time next i okay so this tells us that we are about to
run the instruction that calls puts right and puts is a simplified version of printf which prints this to the screen the question is do we want to go
into puts and see what happens when puts gets ran or do we want to ignore puts entirely that's what's called a step into versus a step over a step into is when we step into puts to
introspectively see its code in a step over is when we go over puts and completely ignore it and stay in the context of main so for example if we wanted to step
into puts we would say step the step command would call into puts and gdb would try to display the instructions of puts and the source code of puts to us for the sake of this tutorial we don't
want to go into puts because we don't really care what happens inside of puts instead we want to do next next we'll jump over the call to puts and bring us to in this case line 8 because it's a next
and not a next i in our code and then we need to do ref sometimes when programs print in gdb it messes up the layout a little bit
so we type ref for refresh and that kind of cleans up the screen a little bit so see we've jumped over the call to puts it printed that output to the screen before i refreshed and now it says that we're on line eight
of our code great so now we get to continue forward and just do another next instruction
okay so the next is hanging because the scanf function does expect input from the user so i'm going to give it some number i'm type 5 and hit enter
ah interesting so me typing 5 and hitting enter caused a sig seg v or a segmentation fault and now it tries to show us every piece of information that it can about
what caused the program to fail so we can actually read through this so something is wrong with the way that we wrote our scanf call right because we have vf scanf internal
that function call is what's failing and making the program crashed so another thing we can do is we can figure out exactly what instruction in assembly caused our program to crash doing that enables us to know what kind
of bug we have and can give us further information to debug our program and fix our code so what the way we can do that is we can do x slash that means examine right view memory
examine the instruction so x slash i at pc so here we see that the instruction is move into eax the thing pointed to
by rdx okay that's an intel instruction that says dereference rdx put it into eax so then we can do info registers to figure out what is the registered state of the program
that's causing this to happen during this instruction so we can see that rax is five and rdx is two
well if we go back to our instruction we see that it's trying to de-reference rdx and put it into eax well the number two isn't a valid instruction so what's going on here
the answer to the question is that scanf takes a pointer to an integer when you're getting user input so it's actually instead of giving you a pointer to d in this code it's giving you the value of d and
treating that as a pointer gcc warned us about this uh and it said hey bud um this is indicative of an int star you gave it an n this is going to cause
issues so instead if we make this ampersand d which is the address of d and c and we fix our code we get no warnings we can run it and it says you gave me four
i hope you learned something about gdb in this i'm gonna go a little deeper into gdb using core files in the next video but if you like this or learn something do me a favor hit like hit subscribe and i'll see you guys
next time have a good one bye
Loading video analysis...