Quick Intro to gdb

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there this is Nick and this is a short video to talk about how to use gdb the kanui debugger this is going to be a very brief overview of the higher-level commands and such that you might generally encounter trying to use gdb particularly to debug a higher-level program such as one written in C so I've thrown together a simple test program it's basically a main program with a few variables including a string throw character string into this variable and I just have a for loop that iterates 10 times and does some semi random arithmetic and calls a subroutine the subroutine is call square doesn't actually do a square it takes an incoming argument reduces it modulo 10 multiplies by the other arguments and returns that it's a nonsense program it's just a way to to have some code to go after in the debugger so if we compile this using the regular GCC command and we try to run it invoke it with a gdb tat well if we just run test it just prints out a number it's no big deal if we want to debug it we can do gdb space test and that will bring in the executable image and you notice we get an error here saying that there's no debug in symbols found so if I try to look at my source code so I can say start to just start the debugger and if I try to list my source code there's no there's no information available so I can say examine 20 instructions starting at the program counter I can see the assembly language code for this version and it does tell me you know this is 4 bytes past the beginning 1 main program this is 11 bytes past and you can do some level of debugging like this and function names are still preserved so here's a call to my function square but this is not a really convenient way to debug a program that was written in C you can do it but that's a separate topic altogether so the better way to do this is when you compile your program you - G switch that means include symbolic debugging information so GCC - G and then output to test test dot C and now I can invoke my debugger GEB test but this time is going to read my symbolic information from my my debug file and this will give me a bunch of information about variable names and original source code instructions which makes debugging a lot easier so always begin by just saying start and I will basically begin the execution of your program and it will hit what's called a breakpoint so will stop executing at the beginning of your program there's basically two modes you operate in inside the debugger one is where the program itself is just free running and you have no control over it other than using control-c to interrupt it or typing in inputs and so on the other is when you're sitting at this debug prompt gdb and here the program is temporarily halted and you have the ability to do things like examine variables examine source code and so on and so forth so at this point we're at the gdb prompt we have the ability to interact with the debugger so the easiest command to use is just lists a list there's your source code and it's reading this from from the the debug information that we compiled so list will list ten instructions around the current program counter any command that I type if I just hit enter it will repeat the last command so if we want to do another list I can just hit enter and that means list the next ten instructions if I hit enter again that will list the next ten that takes me up to the end of my program so here's a copy of my source code and I can come back to this anytime I want and it's telling me that I'm sitting at line four of test dot C which is this initial curly bracket so I'm basically at the beginning of my main program all right what you probably want to do is single step through your program so there's two ways to do this mainly you can say step which means go ahead and execute one of my source code instructions so I'm sitting at that first curly brace if I say step it will go down to my first executable instruction which is this sum equals zero so it's about to execute this instruction and I can say print some and there's my current value of some if I say step one time that should have executed this instruction sum equals zero and now if I say print sum and if I spell it correctly I'll see that my sum is equal to zero so dollar one dollar two these are local values that the debugger sets up that I can use to go back and refer to previous commands gdb has you know gazillion different features and options and and parameters to it I'm touching on like maybe five of the gazillion things that you can do with gdb so you can always go and read online documentation out and to find all these embellishments so this is just a high-level view so what have we done so far we've done step two go ahead and step to the next line of instruction code and we've used print to print out the value of a variable so if I try to print the value of I it tells me I is equal to zero if I try to print the value of big while there is no big in the current context and remember our our main program we have two variables I and some up here we have a subroutine with arguments big and temp and a variable I all right so let's just step through this and see what happens I was going to say step and it's going into a for loop I'm just going to hit enter to do another step so now in my for loop I had I to sum and then I call this routine square when I hit enter again it tells me I'm in my routine square and I call it with arguments big equals 1 and temp equals 1 I said I equal to big a big is bigger than 10 do I equals I modulo 10 return I times 10 there's the end of our our subroutine and now we're back in our main program at line 11 we do another iteration of the loop and I can keep stepping like this and at any point I could say for example crimp big and in here I can see what the value of big is you can use P is an abbreviation for print most commands can be abbreviated to whatever length makes it unambiguous so if I just say P big it will show me the value of P of a big which is nine so I can step and come back through and if I just kind of bang on the return key eventually I'll loop through ten times and then I'll exit and once I exit I can't step any more because I'm out of my program so if I want to rerun that I can say start and I can start doing some steps so let's step the other in function bill your own way to step through your program it's really useful is next so you notice when I say step I go into my loop I say sum equals sum plus I I call my subroutine and now I start executing the codes of my subroutine suppose I'm not interested in what happens in that subroutine I'm only interested in what's happening in my main program instead of saying step I can say next and next will look like step except that like call a subroutine like here if I say next it won't single step through the subroutine it will go ahead call the subroutine silently and after it returns it will step to the next instruction of my current the current main program that I'm in so this is like a step over as opposed to a step into if you remember those from from assembly language programming step over will not go ahead and step through the subroutine calls it will continue stepping after you return from the subroutine so that's a little quicker way to step through a program if you know a subroutine is working correctly so let's restart that again and so that's step and that's next we know about printing the value of variables so let's step through a little bit here there's some equals zero now I'm going to copy hello into string and since I did not compile string copy myself that's part of the runtime library that was linked in step automatically skips over all that code and moves on to the next instruction in my my C code but here I should have copied a string into this string hello so if I say print string it shows me the contents of that string now string was set up to be a hundred and twenty characters and you can see the first six characters or h-e-l-l-o exclamation mark that's what I copied into it and then there's a null put at the end because strings are always null terminated and then all of this stuff this is the gibberish that you can potentially find showing up when you overflow in array bounds or you return address that's pointing to the wrong thing or stuff like that this is just random stuff that that is inside our character array but has not been explicitly initialized by us so that can be useful the other way to examine things in gdb is to use the X function so X is a much lower level function P understands what type of variables something is and will show you the contents of that variable in an appropriate way X is a much lower level way to examine memory inside the debugger so for example if I say X space string that shows me 6 C 6 C 6 5 4 e what is all that mean well the 48 is an H the 65 is an E and the 2 6 CS are L and L this is showing me the actual raw bytes that are sitting at the location designated string the address of string is this big long thing so I'm on 64-bit machine obviously and at that address I find 48 65 66 C if I do another X it will examine the next four locations there's a 6 F which is my oh there's twenty-one exclamation mark there's a zero which is a null another zero which is a null and if I examine one more the next byte is a nine that's my backslash T my tab my control I so we're examining raw memory at this point if I did an x-class B string that would examine a single byte at that address and if I do another X it will show me the next byte so now we can see that these things are in fact stored in the correct order h-e-l-l-o exclamation mark and then an all if I did an X / 10 D string it will examine byte by byte but it will show 10 bytes in succession so h-e-l-l-o exclamation mark null null character 9 and so on and so forth so there are lots of ways you can examine things in memory similarly I could print the value of I that's equal to 0 that's not terribly interesting let's step through a little bit so here's the value of big that's a nine and I could say X big let's not do that because big is is so when I did X string string remember is the address of the array because it's set up as an array but big is just a value but I can say print address big and there's the location memory where big is stored and now if I say examine examine a single byte at that address there's a nine if I examine the next three bytes I see a zero zero zero nine that's the value of the variable big which is nine so you get the idea hopefully you're just um examining memory locations by using the X command and again there's a zillion modifiers on that you can examine a different format different word sizes and so on so let's keep stepping through let's come back here we're in a for loop still we've iterated two times so now I is equal to three another useful thing to do is to put a watch variable on so for example I might say let's watch the value of I and I've set up a hardware watch point for I and now if I start stepping anytime that I changes it tells me what the old value was and what the new value was so that will set a watch point I can step through down here it said I equals big that did not trigger a watch point why because I'm inside a subroutine so this is a different value of I I is local and this gets into the notion of call frames a call frame has to do with what context you're looking at in your program so when I call a subroutine I have a different set of variables such as I in this case and that's that's obviously different from the I in the main program so I can keep stepping through this I'll come back I'll get to the top of my for loop again and here again I guess increased from four to five and and so on all right so I can also do a watch on a read if I want to know when the value of I is read I can say our watch eye and now I've got a read watch point set up for I and if I keep stepping I'll go into my subroutine come out of my subroutine here's my for loop so that generates a watch point because I change from five to six but then down here my next line of code will say some equals I and that will generate a read watch point for the value of I so it read a value of six then it added that two to sum and so on so you can set up watch points like this and if I say continue which says just keep running until you hit a breakpoint this will run my program until I hit something that's being watched so continue because read watch point on I because it's calling a subroutine if I continue again it will generate a break when I change the value of I and here again when I read the value of I so they can add it to some so here I'm stepping through my program very quickly and the only time that anything is is stopping my program is one of these watch points gets hit so that will exit the program very quickly and let's go ahead and start again so when I say start it clears out all my watch points and my break points and so on so here's a listing of my program suppose I want to stop whenever I come back from whenever I'm about to call my subroutine here I want to stop execution of my program I can make a breakpoint at line 13 so if I say 4 8 13 it sets up a hardware breakpoint now here's the program counter address where it's breaking but here's the line in my source code line 13 so now if I say continue it breaks when it gets to that line and each time though I say continue it runs through my code until I get back to that breakpoint so here I'm just stepping through very quickly and at each point I could print the value of sum I can say continue print the value of sum and so on all right so we've got steps we've got next we've got a way to print values we've got great points we've got watch points we've got read watch points so I could say watch let's go ahead and start this program and let's go ahead and watch some let's do a read watch on eye and let's do a break at line 12 so I've got some debug set in I run my code and as I'm running it I'm checking why the variables are changing the way they are and at some point I say hey what here's a problem I is equal to two okay so I debug my code I find what the problem is and now I'm done with my watch points I can say info watch and see all the watch points that I've set up I can say info break and see all the breakpoints I've set up which includes the watch points and I can delete those if I like for example if I say delete 12 that will get rid of this break point that I had a test plus 12 and so on so um so you can create watch points break points you can get rid of them and so on a couple of other things to look at so let's step through my program and here's my string copy here's the beginning of my loop and now I call my subroutine and I'm using steps instead of next so I'll actually go into my subroutine and I'm my subroutine on my line 22 I equals big and I'm doing an if statement if I say BT which means back-trace I can see what my call frames look like so this is telling me that my my first call frame was at line 13 in my main program test at that point it called a subroutine square and right now I'm sitting at line 23 in test which is inside that subroutine square this is like a stack trace it's showing me what is called what and what is that called what was the original thing called by and so on and all of my variables right now are in frame zero they're in my current frame so if I say print the value of big it shows me the value of big that's a variable inside a subroutine square if I say print the value of sum it doesn't know what I'm talking about because some is declared in my program right so sums a variable inside my main program and it does not exist inside square so printing some doesn't work if I look at my back trace though I see the frame 1 was my main programs frame so if I say frame 1 now I've switched to the context of my main program and if I say print some it will show me the value of some if here I say print big it doesn't know what I'm talking about because big was declared in the context of my subroutine which is frame 0 so if I go back to frame 0 I can print big and there's the value of big and now the value of sum is outside of my current context so I can keep stepping and continue and here's my value of sum is 1 a value of I is 2 so if I do a single step some should be equal to some plus I sum is equal to 3 so it's executed this instruction it always shows you the instruction that's about to be executed ok it stops before this instruction is executed so right now sum is equal to 3 and if I call square I'll go into my subroutine I'll pass it a value of 3 and a value of I which is 2 suppose I realize that some should have been equal to I don't know 23 so I could change my code but I want to see what happens if I set some to be the correct value so I can say set variable sum equals 23 and now sum is equal to 23 and if I step one time I call my subroutine square but I pass my first argument is sum which my subroutine calls big I pass that is 23 and I pass is two and now I can continue executing with that as the new value of sum so you can set the values of variables inside your program using this set variable command and that can be useful for debugging all right that's a boatload of information that's probably enough for now but basic commands list step next print mx4 examine watch our watch break info watch delete BTW for back trace frame for choosing a frame and I think that's enough to get you going when you're done just say quit it'll ask you if you want to quit because you're still running just say yes and you're back to no back to normal alright hope that helps have fun bye
Info
Channel: MyGeekAdventures
Views: 185,285
Rating: 4.9426384 out of 5
Keywords:
Id: xQ0ONbt-qPs
Channel Id: undefined
Length: 20min 17sec (1217 seconds)
Published: Fri Aug 23 2013
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.