Hey everybody! Ready to crush those pesky bugs in your C++ and assembly programs? In this video, we’re diving deep into the GNU Debugger (GDB) – the ultimate tool for tracking down crashes, inspecting variables, and mastering your code. From setting up debug symbols to navigating call stacks, setting breakpoints, and even debugging assembly registers, this fun and relatable guide has you covered. Whether you’re a beginner coder or a seasoned dev, you’ll learn practical tips to level up your debugging game. We’ll also tackle null pointers, create GDB scripts, and explore why your program might be misbehaving. Stick around for a few laughs and some serious skills! Don’t forget to subscribe, hit that like button, and check out my website for more coding tutorials. Let’s debug like pros together!
Introduction to GNU Debugger 00:00:00
What is a Debugger 00:00:20
Debug Symbols Explanation 00:02:08
Compiling with Debug Symbols 00:03:13
File Size Comparison 00:05:30
Installing and Launching GDB 00:06:21
GDB Console Basics 00:06:55
Attaching GDB to Program 00:08:12
Running Program in GDB 00:09:09
Handling Program Crash 00:13:02
Understanding Call Stack 00:14:05
Navigating Call Stack 00:18:13
Inspecting Variables 00:19:08
Null Pointer Issues 00:21:25
Using GDB Script 00:25:10
Setting Breakpoints 00:27:04
Managing Breakpoints 00:28:37
Continuing Execution 00:30:41
Debugging Assembly 00:33:24
Global Variables in Assembly 00:35:43
Advanced GDB Commands 00:38:31
Conclusion and Call to Action 00:40:22
Thanks for watching!
Find us on other social media here:
- https://www.NeuralLantern.com/social
Please help support us!
- Subscribing + Sharing on Social Media
- Leaving a comment or suggestion
- Subscribing to our Blog
- Watching the main “pinned” video of this channel for offers and extras
Hey everybody! In this video I’m going to show you how to use the GNU Debugger to
debug your C++ and assembly programs.
You can also use it for C and some other stuff but we’re just going to focus on
C++ and assembly. What is the GNU Debugger and what is a debugger in the
first place? So for starters the GNU Debugger it’s like it’s called GDB and
the db you can imagine that stands for debugger something like that and the g stands for gnu i
personally don’t know how to uh pronounce gnu so i just say gnu because it it feels more fun to do
it that way it’s more interesting i think probably some people just say new but i don’t like that
because the gdb debugger is really old and robust and powerful it’s not a new tool it’s it’s an old
new debugger someone’s always going to ask what was the old debugger and then I say this is the
old debugger the new debugger is the old debugger anyway so we’re going to use the GNU debugger
if you haven’t yet watched my video on caveman debugging you probably want to watch that first
just for like some basics of you know why you might want to look at information in your program
but for now we’ll just assume that you already know what’s going on with just like why you would
know how to make make files see my other videos but here i just have a basic make file all it’s
really going to do is just sort of compile a very simple program and add debug symbols into it so
let’s double check that i’m actually doing that here yeah there we go okay so the first thing
that i should probably show you is uh we are compiling a c plus plus source module so i’ve
actually using c but i i have that left over in there anyway and then we’re assembling something
in yasm we’re linking with g plus plus because we want to have a hybrid program and we’ve got
all these flags here those are just variables and so uh so now before i can debug with gdb
i’ve got to talk about something called debug symbols what are debug symbols imagine just a
bunch of extra information explaining all of the design and variables and everything inside of your
about your code stuffed directly into the executable.
So imagine, you know, when we compile a C++ source module
into an object file, usually that’s just, you know,
assembly at that point.
But when we add debug symbols, we’ll have a bunch of information
that can help the debugger figure out where we are in the program,
what the variables look like, you know,
a bunch of extra information to help the debugger pretty much.
The assembler will put debug symbols into the object code
symbols into the object code that you generate the compilers will do that the linker will do that
and so it’s important to understand if you don’t generate debug symbols when you’re compiling and
linking your code then your debugger won’t actually be able to do anything it won’t understand what’s
going on you can debug it but like you’re not going to see anything that’s very uh that’s useful
so let me show you real fast i’m going to do make clean and then i’m going to say make build
that I do not have debug symbols.
All right, okay, if you don’t know how to compile and link from the command line, see
my other videos, but for now it looks like we’re not generating debug symbols.
So if I list the contents of my directory here, just note the size is real fast.
I have an assembly module here that I’m calling ASI.asm, ASI for assembly, and then we’re
assembling it down to an object file.
Notice how it’s just 656 bytes, very small.
plus plus module that I’m creating here is compiling to an object file that is
about four and a half kilobytes so you know not too big the final executable is
called main and it’s about 17 kilobytes so this is without debug symbols when
you’re compiling something on your own you need to add extra switches to enable
debug symbols so you can see here in this make file that I’ve made and again if
you don’t know how to make a make file or compile or link or anything see my
But for now, I’m just going to assume you kind of know your way around to makefile,
or at least you can kind of infer what’s going on.
So I’ve commented out a different version of this variable for the flags of my C++ compiler.
If I uncomment this and then comment out the other one,
you’ll notice the only real difference is this part right here, dash G dwarf 2.
Usually in C++ compilation, it’ll just be dash G to generate debug symbols,
and then the symbol format will default to a format called dwarf2 so I don’t know for these
tutorials I like to just specify the full format but you can just say dash g in your c++ compiler
and linker we do the same thing for the linker down here so I’m going to uncomment this
and comment that and the only difference is just g dwarf2 so I’m just telling my linker that I also
want debug symbols in there too then we do the same thing for the assembler so I’m going to
So I’m going to uncomment that and comment this other one.
And the only difference is that in the assembler,
we kind of have to specify it a little bit differently.
Instead of G dwarf dash two,
it’s just G dwarf two as just one string.
And I think with Yasm, you have to specify the debug symbol format.
So just keep that in mind.
So now I’ve turned on all the debug symbols.
I’m going to do real fast, make clean and make build one more time.
And then if I list everything,
list everything let me just double check that it’s building the symbols now right okay good
notice that the files are bigger so this asio um file is now 1.8 kilobytes instead of you know
half a kilobyte the main.o object file is now 36 kilobytes instead of only 4.5 and the executable
main is 36 kilobytes instead of just 17. so you can feel it already right like there’s a bunch
extra information sitting inside the object files and the binary which allows us to debug our program
okay so now that we’ve generated debug symbols in our program we can actually think about starting
to use gdb so gdb is a program just gdb by the command line if you don’t have it in your system
already you can go sudo apt install gdb or depending on what system you’re on maybe a or
or whatever your package management program is,
but we just need to install GDB.
On Ubuntu and Debian, I think,
there is a meta package called build essential,
which will give you a bunch of compilation tools
and make file stuff and whatever.
So I’m just going to assume at this point
you already have GDB on your system.
To launch GDB and go into its console,
just type GDB by itself.
So now we’re inside of the GDB console or terminal.
console or terminal. We’re no longer inside of a bash terminal. We can’t type normal commands.
Let me show you real fast. Here’s the first command you want to learn on GDB. It’s called
quit. Never quit. Never surrender. So, you know, normally if you’re at the command line,
you can do something like cat, etc. OS release just to see what operating system you’re using.
So you can see for this virtual machine that I’m using right now, I’ve got like Ubuntu 22 on there.
If we go inside of GDB, we can’t use regular bash commands anymore or regular operating
system commands.
We can’t say cat, et cetera, OS release because we can now only use GDB commands.
We’re inside of GDB already.
Notice how it says undefined catch command.
I don’t know what you’re talking about, dude.
Okay.
So remember we do a Q or quit to get out.
You can actually just type Q.
A lot of commands that I’m going to be talking about.
going to be talking about you can abbreviate them with one or two or three letters and it totally
works just for speed so now that we know how to enter gdb and now that we also know that we have
already compiled our program with debug symbols we can attach gdb to our program i mean what’s the
whole point of a debugger we most of the time we will just have our debugger attached to our program
and launch it or i guess launch it while it’s attached you can also attach to a running program
but we’re going to launch a program and stay attached to it.
And then we can sort of catch crashes and see what’s going on.
Or we could also tell the debugger to stop the program at certain points in time,
like when we hit a certain line number or when a variable changes or something like that.
And then we can look around.
We can look at all the variables, look at the state of the program,
even change things if we wanted to.
We can look at all the registers if you’re coding in assembly.
So it’s pretty useful.
Anyway, I’m going to go gdb and the next command we’re going to learn is file, which just tells
gdb to attach to a program so that we can run it.
So, you know, the name of our program here that we compiled is just called main.
And so if I type file main, then gdb should load up that file and try to parse its debug
symbols so it can begin debugging for you.
Notice how it says reading symbols from main.
you know if we did a typo or we had something with no debug symbols it will give us some sort
of an error message so for now i’m just going to quit and then go back in just to make sure that
it’s all clean and we’re going to do file main now it attaches once it’s attached that’s not i guess
it’s not technically attached because the program’s not running but once it has loaded the debug
symbols for that program we can run the program with the run command in gdb also kind of interesting
If you have debug symbols that are generated separately from your executable,
you could tell GDB to load the symbols file and then run your program.
That happens a lot in Linux where people release the non-debug friendly version of a program
and then they’ll release the debug symbols separately if you’re interested.
Anyway, so I’m going to type run and it’ll run the program.
Notice how GDB kind of tells us that it’s starting up now.
here’s like a thread debugger that’s being enabled and it says we’re using this library to do it and
then it says hello you know here’s the hello message so the program is actually running that’s
not my name i wish it was and then it prints the final result and then gdb says your program exited
normally on newer versions of gdb there’s a setting i think by default where it’ll ask you
if you want to start a debug daemon a debug info daemon or something yes or no you can usually just
without actually having to type n.
It’s a little bit faster.
So the whole program ran and finished.
If I type run again, it does the same thing.
In GDB, if you hit enter without typing anything,
it ends up repeating the previous command.
So I’m not going to type run.
If I just hit enter, are you serious?
GDB made me into a liar.
Well, most of the commands will repeat if you hit enter.
I guess not the run command.
So I’ll type run again.
And okay, I mean, the program is pretty good, right?
So if you watched my…
It’s not pretty good.
watched my it’s not pretty good it’s a nonsense program I mean it it doesn’t crash is what I’m
saying if you watched my previous video which you should on caveman debugging I had this uh you know
nonsense portion of code that just sort of updated a variable and we pretended that we were confused
and we didn’t understand what was happening and uh we used gdb to debug it so what I’m going to do
either let’s say we’ll start off with throwing an exception and then we’ll try to use a no pointer
and then we’ll see a crash and then after that I’m going to start using breakpoints where we can stop
automatically inside of our program to print the state of the program print the variables
and then I’m going to do that first in C++ and then hopefully I’ll remember to do that in
assembly right after it’s basically the same thing only with assembly you don’t really have
you know a bunch of variables everywhere you just kind of have registers and maybe some globals
globals but it’s going to be the same deal okay so let’s pretend that uh we are gonna have a crash
okay so this program just kind of runs later on we’ll figure out why the result is wrong we’ll
just pretend that it’s wrong but for now we’ll just say how about we uncomment this line right
here and what will happen is when we’re running the main loop at some point in the loop we get
When F gets called, the input will be looked at here.
And if the input is more than one,
which is definitely gonna happen like right away,
then we’ll call on the G function.
Then the G function will just throw an exception.
We’ll just pretend that something really bad happened.
You crashed or you actually did throw
and you didn’t catch your throw,
or maybe the system threw something at you
or another library threw something at you
and you didn’t catch it.
So just basically a program crash.
Let me run this real fast.
So make run just to show you that the program crashes.
Make run at this point is the same thing as just kind of executing the program.
But you can see that it says terminate called after throwing an instance of runtime error.
And then there’s the message, oh my gosh, and then aborted core dumped.
That’s not good.
So now let’s try to understand why.
Why did that crash?
Pretend you don’t know that it happened in G. You know, you’re trying to investigate.
So we could type GDB and then we could type a file to load the debug symbols, but it’s a little bit faster just to type GDB main and just sort of name the file that you want to load right away.
So if I do that, notice how it automatically tries to load the debug symbols from main.
Then I can just type run and then the program tries to run and notice how it actually catches the crash.
If you look down here, terminate called after throwing an instance of runtime error.
throwing an instance of runtime error so that’s what the program thinks is going on but then the
program is trying to terminate but then down here gdb is like wait wait wait i just caught you know
a termination uh getting invoked here and you can see this is sort of system code like we did not
create this source file p thread kill we didn’t write that that’s the standard library and there’s
a function here called p thread kill implementation with those you know fun c underscore prefixes
prefixes everywhere and so this is like some sort of a c source file and we don’t have that file on
the system so we can’t really debug that file lucky for you most of these standard libraries
work all the time so you don’t really need to debug them you need to debug your code instead
of the standard library code so the question really is how did i get here how did i get to
this crash so the next command we’ll learn in gdb is just the where command the where command will
I’m going to release a video in the future that kind of explains call stacks, but basically
imagine a abstract data type, a data structure called a stack. And every time you want to add
data to the stack, it just sort of stacks up on top of the last piece of data. So like if I add
something, let’s say I want to add the number five, then I would just add the number five on top of
the stack, right? If I wanted to add the number 11, then I would just add the number 11 onto the
off of the stack and the stack is a really good data structure to uh sort of give you a trail of
breadcrumbs to know where you got where did you come from so we call this the call stack because
what’s happening is every single time you call a function then the new scope and then you know the
new function that you’re invoking um it has something called a call frame full of information
current address is and all that stuff.
And we’ll just call that chunk of data that belongs to one instance of a function call.
We’ll just call that a call frame.
And so if you’re stacking call frames one on top of the other,
then we call that whole entire thing the call stack.
And this is what allows us to use recursion and all these complicated call graphs and everything.
It’s really simple, but it’s really powerful.
So you’re looking at the call stack.
Each one of these lines is the call frame or is a call frame.
And so for example, if you just look at number zero here, you’re looking at call frame zero,
which is the closest frame to wherever the crash occurred, which is if you look at it,
that’s exactly what we were looking at when we saw that original message, right? Call frame zero.
So that’s not really useful. You want to go down to higher numbered call frames or I guess
physically lowered number call frames and just kind of scan it until you find some code that
raise no abort no none of this stuff is ours live standard c plus plus no the first frame that
contains code that is ours is call frame number nine or i guess like nine away from our current
position so i guess find the physically highest call frame that is your code or the lowest numbered
call frame that is your code and it’s telling us right here all right we uh we actually seem to
So if I go to 65, right there, it tells you exactly where the crash happened.
If you’re still trying to figure out, well, how did I get to that crash?
I don’t know how that actually happened.
Just keep looking down further in the call frames.
The next one, call frame 10, says, well, we were inside of function f with input equals
three at main.cpb line 46.
So if I just go to 46, I can get another clue.
I can go, all right, so for some reason we called g.
Imagine again, this program is much more complicated.
And then if we’re still confused, we just look down at another one and it’s like, well, this all this whole mess started at CPP main dot CPP line 28.
So if we look at line 28, it’s like, well, we were inside of this loop and we we called the F function and then the F function called the G function.
And then G just kind of did a throw. So that gives us a lot of information.
All right. Next thing we can do is we can sort of move up and down the call stack, because right now we’re sitting at call frame zero, which is just the system code.
which is just the system code, but maybe we don’t understand why the throw actually happened at,
let’s say, line 65, right? So we can use up to go up in the call stack to a different call frame.
So if I hit up, notice how it mentions that we’re now in frame number one instead of zero.
And if I do up again, we’re now in frame two, which is a little bit closer. We can use the
trick finally where we hit the enter key instead of repeating the command. So I’m just going to
and hit enter a couple times until we eventually get to our code,
which I think was supposed to be at frame nine.
So I’m just going to hit it a bunch of times until we get to frame nine.
Now we’re looking sort of back in time at that point
because all these other frames actually did get invoked,
but we don’t really care about what was going on inside of them
because they probably did their job correctly.
We’re looking at our code, so we’re going back in time
right when we were doing this throw.
Oh no, we threw. Why did we throw?
well there’s another command in gdb called info locals
okay the info locals uh there’s there’s really not much to this maybe maybe let me do this again
a equals five and uh then i’ll just say a plus plus just so that we have a local variable
i forgot that gdb doesn’t consider the incoming arguments as locals so there was nothing there
real fast uh gdp oh let’s do make build and then gdp main and then run and then we have a throw
and then i say where and then i go up up up up to a frame you can also use the keyword down if you
go too far if you want to go you know back down in the call stack but i’m just going to use up
okay so now we have it here now finally i think i can do info locals just to see the local variables
notice how the a variable is there now because I just added a local variable a a moment ago
you can also print things directly you can say print the input incoming variable if you’re in
assembly you can also print registers you can say info registers like that and you’ll get a nice
print out of all the registers you could print individual registers you can say let’s print
register r12 you can print register r12 as binary by saying I think it’s p slash t
or print slash t yeah we can probably just do print slash t also
t stands for two because they’re it’s a base two number system
does that mean there’s a p slash h or a p slash f for 15 or 16 s for 16 i don’t know i haven’t
tried that is it going to work hang on p slash s bar 12 it’s not going to work nope didn’t work
i think it thinks it’s a character point or something but anyway so we can print a lot of
So we can print a lot of stuff.
And like I said before, we can go up and down the call stack.
So I can go down a couple times and then go back up again.
And now we can assume that we’ve kind of debugged, you know, where the source of the error was.
So I’m going to comment that call out to G and run the program again one more time with a different error.
So I’ve commented this code out from before, but just imagine now that we’re going to use some pointers.
We’re going to start off with a pointer called P.
a pointer called p we’re going to set it to null at the beginning and then we’re going to just
kind of allocate it and then we’re going to set you know a value and then we’re going to dereference
it and dereferencing a pointer just kind of sets the first value in an array you can do that and
then we’re going to deallocate the pointer and then how about right after that we do something
really really naughty we say p at some index is equal to a five this should be this should be a
a program crash because we deallocated p already at that point we would be dealing with junk data
if we tried to dereference p but to make it even more clear that it’s naughty we’ll set it to a no
pointer and then we’ll try to actually use it so let me let me just restart the program real fast
i’m gonna do quit yes and then we’ll do make a debug just so you know my make debug is just a
Let’s see, where’s that? Where’s that? Where’s that? Do I not have a debug shortcut yet?
Oh dear. I need to add that before this video is over. You know what? I’ll add it right now.
We’ll do this run and we’ll say debug, make debug, and it needs to build first. And then I’ll say
debugging the program. And then we will do the GDB binary and give it an argument of
the executable and then later we can we can upgrade this to take a little script of commands
because the commands are going to start getting out of control so now if i do make debug if i
didn’t screw it up now it at least goes in there and i’ll do run and then we have a seg fault and
notice how it tells us right away hey you have a seg fault right here you’re accessing invalid
memory let’s do info locals just to see what’s up oh the p is actually a zero that’s a null pointer
explicitly oh whoops you know oh what have I done but it’s a really good idea to set your
pointers to null after you deallocate because if you don’t you might end up with undefined
behavior where sometimes the program doesn’t crash while you’re overriding junk data or reading junk
data but sometimes it does and you’re not really sure like why does it work sometimes and why does
it not work sometimes so let me comment this out and see if it’ll crash uh let’s just let’s just
make debug and then i’ll do run and then if we do info locals oh yeah okay so this is uh
it did seg fault so that’s good uh if we were unlucky then the program wouldn’t have crashed
it would have just started behaving strangely and um when we print out the value of p notice how it
looks like a pointer still like if we were to debug the program and print the pointer value
then it doesn’t really it looks the same it looks the same after we deallocated it right so that
this is called a dangling pointer meaning you deallocated the pointer but you forgot to set
it to null afterwards so then later when you’re trying to debug the program it’s a little confusing
because you’re like that looks like a regular pointer what did i do wrong so um it’s really
good practice to set your pointers to null right after you deallocate them that way when you’re
debugging later because something crashed instead of seeing a memory location on p you’ll see
On P, you’ll see something that looks definitely like a null pointer and print P.
Then it’s way easier to realize, oh, whoops, I was trying to use a dead pointer, a pointer that I deallocated.
Hopefully that makes sense so far.
Next thing I want to do is a small upgrade.
I can’t remember if it’s dash X or dash EX.
I think it’s dash X.
But you can write a little script.
I have a little script here called Good Doggo.
called good doggo you can just make any file name it anything you want i’m so i’m just naming it
good doggo.txt because my dog’s taking a little nap behind me as usual um but you could name this
gdb.txt or whatever it is you want so you can put inside of this script file any command that you
want gdb to execute when it launches so let’s just comment this stuff out real fast and i’ll do
I’ll just do run maybe for starters.
Because whenever I’ve been launching for debug,
I launch with GDB and then I type run manually, right?
So I want to save a little time.
So good doggo is the name of the script.
So when I invoke GDB, I am going to,
where is it right there?
Okay, it’s GDB.
And then I’m going to go dot, I think it’s X.
And then I’m going to say good doggo.txt.
If it’s not dash x, then it’s dash ex.
One of those executes the command that comes after,
and one of those executes the command script that comes after.
Let me just double check that this actually is going to work.
So make debug.
All right, okay, so it was dash x.
Dash x specifies a script that will be run.
Dash ex just specifies a command that you can put right in there.
Like I could have said dash ex run, and it would have ran right away.
But the script is more convenient, right?
Because we can save typing.
So notice how it ran right away and then there’s a seg fault.
Okay, so now let’s go a little bit deeper.
Let’s change this to false again now that we understand like null pointers and all that
stuff.
So we can just basically deal a little bit more with only what the main loop is doing.
Suppose we just still don’t really understand what the loop is doing, why our answer is
you know, good or bad.
So maybe I want to do a breakpoint at the top of that for loop.
loop gets to the top of its iteration, I want the program to pause so I can look around.
So I’m going to set up a breakpoint on line 22. And here’s how you set up breakpoints
in GDB. I’m going to go ahead and maybe do the terminal for now. And then I’ll stick that into
the script next. I will not remember that it’s line 22. That’s okay. I’m going to do quit.
And I’m going to do make build. Then I’m going to go GDB main just to jump in there.
and then i’m going to say break or just the letter b just to make a break point you type the name of
the source code file that you want to break in and then a colon and then the line number where
you want it to break so i think i think it actually was line 22 oh i can see it and then
maybe i want to have it break at line i don’t know maybe right here line 25 right before it increases
And then so I’m going to do an up arrow to just repeat the command so I can edit it real fast.
And then I’ll break again at line 28 and then maybe 30 and then 32.
So I’m going to go 28, 30 and 32.
30 and I’m just making up break points.
I just want to inspect the program and then maybe I’ll break at line 36 so I can see what the final answer is.
So I just have a bunch of break points set up.
Remember when the program is running now under GDB, every time it hits one of those lines,
every time it hits one of those lines the program will pause and i’ll have a chance to look around
at the variables and things so i’m not sure if i’ve set up the breakpoints correctly i can say
info breakpoints and it’ll show me all of my breakpoints notice how you can enable them and
disable them so let’s say for the sake of argument i want to disable the breakpoint at line 30 because
maybe i don’t really need that right now but i kind of want to keep it in the system for later
disable four because it’s number four.
It’s breakpoint number four.
So I can say disable four.
Then if I do info breakpoints again,
notice how there’s a little N on there,
meaning breakpoint four is disabled.
So I could re-enable it with a four
and then go info breakpoints again.
So now they’re all enabled.
I am going to maybe copy this into the script file real fast
so I don’t have to keep typing this over and over and over again.
Imagine if every single time you changed your program and recompiled it you had to type all of the breakpoints from scratch
That’s why I want you to use this little breakpoint script
So we’re going to do B to break at main.cpp line 22 and 25 and
28 and
30 and 32. I should have copy pasted the three dang it 36
And after we’re done setting up all the breakpoints
show me the breakpoints just so I can have a visual reminder. Keep in mind if you change too
much of your source code then you’re probably going to have to update these lines and that’s
okay but it’s a good idea to just at least you know kind of look at them a little bit so that’s
why I’m saying info breakpoints. And so then remember again the makefile all it’s doing when
I type make debug is it’s just launching this command right here it’s just saying gdb with the
with my gdb script so let me quit to get out of this and then i’m going to say clear and make
debug and notice how it did all that stuff for me it added the breakpoints it showed me the break
points and then it ran the program like i told it to and then it already broke on a breakpoint it
already break it break breakened it’s broken i don’t know i don’t think it’s broken uh so we’re
So we’re on breakpoint number one on line 22.
And here’s the for loop.
I can type all of my inspection stuff.
I can say info locals.
I can say print I, I can say print A, I can print whatever I want.
And then when I’m done kind of looking around and inspecting things,
I want to continue the program.
I don’t want to just stop it here.
So I’m just going to use the command continue.
And it goes right to the next breakpoint.
If I want to, you know, continue again, I can hit C.
continue again i can hit c or i can just hit enter you know to just sort of keep continuing as i
inspect and print things let’s see when can i get to break point number one is that what’s going on
here hang on a second what is break point number one oh i know what to do info break points
break point number one is that main.cpp line 22 is that actually going to get hit oh it’s
having issues here with my GUI. Okay. Line 22. Okay. So it’s not really hitting that anymore.
I guess it’s not going to think that it hits the top of the forelip. Okay. So I guess breakpoint
two is where we’re always going to be hitting. So let’s just suppose that I’m continuing until
I hit breakpoint number two. Suppose that the next 10 times I see breakpoint two, I don’t
actually want to stop and break on it. I just want to skip the next 10 iterations for some reason.
some reason you can say continue 10 and it’ll skip the next 10 times that it hits the number two
notice how if i hit continue a bunch of times we’re not really seeing the break point number
two anymore we’re seeing other break points and then eventually if i hit it enough times
we’ll probably see two again oh my god oh my god are we seeing it yet no
Okay, wait, are we seeing I’m freaking myself out.
Okay, so let’s continue 10 times on breakpoint three, then we’ll only see
breakpoint four, I guess.
So we can do continue 10 times on breakpoint four.
What is going on here?
Did I write this program in a weird way?
Hmm.
Well, trust me on this.
Let’s continue 100 on breakpoint three and then continue 100 on breakpoint four.
breakpoint 4. Okay, so now we’re just done with the whole entire program. I guess there must have
been a 2 there that I missed. So now we’re finally on breakpoint 6, which is when everything is
finished. Let me show you real fast that we can add more breakpoints in assembly just to prove
that we can debug assembly real fast. So if I want to debug assembly, I just have to type the name of
that source code file. If it was nested in a folder, like if you had like a complicated hierarchy of
of source code files you would just need to type the relative path but for now I’m just going to
be able to type the name of the file so assy.asm and let’s suppose that I want to break at line
16 just so I can see the registers that I set up so I’m going to do 16 and then I’m going to break
at assy.asm line 16 and then I’m going to run and that actually never gets called does it no no it
called does it no no it gets called I think I have a call up here somewhere
nope I don’t have a call okay let’s make a call this is gonna throw off all of my
C++ breakpoints so I’ll just comment them all out right now comment them all
out so I don’t have to redo them and this is a hybrid program so I’m gonna go
extern what is it extern C make a block where I name the function the reason we
name mangling so the AC symbol is going to show up as just its regular function
name rather than a bunch of extra stuff indicating the prototype so that we can
do overloading so we’re just going to disable that and then at the very top of
the program I’m just going to call it this should hopefully work let me just
do a regular make run just to make sure the whole program compiles okay now
debug script we’re gonna break on line 16 which is going to be letting us see
the registers okay so I’m gonna go make debug notice how it hit the breakpoint
in the assembly just the same as the C++ and we can print whatever we want now so
I’m just gonna say info registers and if we look carefully we can kind of see
that we modified racks REX is 15 so that’s expected RDI is 20 which is
R12 should be a giant number. Where’s R12? Right there. So you can see the state of your program at any point in time just by breaking on it.
I’m breaking on a certain line. So this is tremendously useful for debugging not just for higher level languages but also assembly.
What else can I do? Oh let’s put a global in the data section. So I’m gonna do, I don’t know, my thing or something like that and we’ll call it a byte array and I’ll just go hello.
I’ll say we have a thing one and a thing two.
Something like that.
And maybe thing two is a null terminated string,
whereas thing one is a regular thing.
We should be able to print those symbols.
If that’s not true, I’ll come back at a later time
and show you how to do it.
Anyway, so we’ll do make debug
to just kind of assemble everything again.
And we know how to do info registers.
We can print, you know, one register in particular,
print R12 if we wanted to.
History has not reached.
History has not reached 12.
Oh, I got to put R12.
Yeah, then we can get the, wait a minute, wait a minute.
Oh, I threw off the line numbers because I added the variables up here.
So now we’re going to break at 21.
Let me just fix that.
21.
We’ll do a quit.
Make debug again.
And now we’re at 21.
If I say info registers, we can see R12 is that big value.
you, but we can also print R12 directly. And we should be able to print my thing one, hopefully,
has an unknown type, oh, we have to cast it. So we can do like basic casting in GDB. So I’m going
to say this is a character pointer. Remember, all of the assembly symbols are basically pointers,
unless it’s an EQU, EQU variable. In that case, it’s more of a define. So I’m going to print
and then it says error cannot access the memory add address
what the heck did i do wrong how about that cannot access that all right i’ll come back in
another video because this wasn’t something that i prepared for just to print strings in globals
i’ll come back at some later date in the future like five years from now and i’ll just show you
how to print globals but i hope if you’re in assembly you probably don’t need to worry about
You just have globals, but the real problem for you is going to be what’s inside of your registers and so forth.
You can also deref, I think.
Let me see.
Okay, I’m going to move on from that.
So anyway, we got a script and we got a lot of basic GDB commands.
Is there anything else that I wanted to show you?
Let me just look at my notes real fast here to make sure I’m not forgetting to say anything.
make sure I’m not forgetting to say anything.
So we’re going to do debug symbols, console, quit, attach to binary,
launching the program, uncaught exception, breakpoints, info, delete,
enable, disable, run, continue, end times, info registers, printing.
Oh, we can print a register in binary.
Forgot to show that.
So we are at a breakpoint, I think.
And if we printed R12 with the regular print, we can also do P slash T to just
p slash t to just sort of print it in binary if you want to i think i might have said that already
either that or i said that like a couple days ago to some and then we can do info locals and
then print a variable and then we get the script file and then we can quit okay so i think this is
pretty much everything that i wanted to show you you now have a basic idea of what we can do inside
of gdb but keep in mind there is so much more you can do in gdb than i can fit in one video
can type help and you can see a list of other major you know areas that gdb can handle um you
can do uh let’s see i think it’s help and then like we’ve got information on aliases breakpoints
data you know whatever we can do i think help breakpoints to see more information on breakpoint
commands yeah so all of the things you can do with breakpoints is like all of these commands here
one page we have to enter to see one more page or see to see all of the results without using
paging anymore so i’m just hit c and so there’s like you know we can save trace points we can
try to catch exceptions we can enable disable break points there’s like unwinders which i’ve
never even used we can bookmark things we can you know start tracing memory we can rethrow
variables so just keep in mind gdp is incredibly powerful this video barely scratches the surface
but for a programmer who is new to debugging i think this will be very useful to you i hope it is
anyway thanks for watching this video i hope you learned a little bit of stuff and had a
little bit of fun um i will see you in the next video rest yourself and take a nap and have fun
and hug your your loved ones okay I’m out see you later hey everybody thanks
for watching this video again from the bottom of my heart I really appreciate
it I do hope you did learn something and have some fun if you could do me a
please a small little favor could you please subscribe and follow this channel
channel or these videos or whatever it is you do on the current social media
website that you’re looking at right now it would really mean the world to me
and it’ll help make more videos and grow this community so we’ll be able to do
more videos longer videos better videos or just I’ll be able to keep making
videos in general so please do do me a kindness and and subscribe you know
sometimes I’m sleeping in the middle of the night and I just wake up because I
know somebody subscribed or followed it just wakes me up and I get filled with
That’s exactly what happens every single time.
So you could do it as a nice favor to me,
or you could troll me if you want to just wake me up in the middle of the night.
Just subscribe, and then I’ll just wake up.
I promise that’s what will happen.
Also, if you look at the middle of the screen right now,
you should see a QR code, which you can scan in order to go to the website,
which I think is also named somewhere at the bottom of this video.
And it’ll take you to my main website,
where you can just kind of like see all the videos I published,
and the services and tutorials and things that I offer,
and all that good stuff.
things that I offer and all that good stuff. And, uh, if you have a suggestion for, uh, uh,
clarifications or errata, or just future videos that you want to see, please leave a comment.
Or if you just want to say, Hey, what’s up, what’s going on? You know, just send me a comment,
whatever. I also wake up for those in the middle of the night. I get, I wake up in a cold sweat
and I’m like, it would really, it really mean the world to me. I would really appreciate it. So
watching this video and enjoy the cool music as I fade into the darkness which is coming for us all.
Thank you.