Index: en_US.ISO8859-1/books/developers-handbook/book.xml =================================================================== --- en_US.ISO8859-1/books/developers-handbook/book.xml +++ en_US.ISO8859-1/books/developers-handbook/book.xml @@ -36,6 +36,8 @@ 2016 2017 2018 + 2019 + 2020 The FreeBSD Documentation Project Index: en_US.ISO8859-1/books/developers-handbook/tools/chapter.xml =================================================================== --- en_US.ISO8859-1/books/developers-handbook/tools/chapter.xml +++ en_US.ISO8859-1/books/developers-handbook/tools/chapter.xml @@ -832,7 +832,7 @@ - Use gdb to analyze the core (see + Use a debugger to analyze the core (see ). @@ -1325,75 +1325,386 @@ Debugging - The Debugger - - The debugger that comes with FreeBSD is called + Introduction to Available Debuggers + + Using a debugger allows running the program under more + controlled circumstances. Typically, it is possible to step + through the program a line at a time, inspect the value of + variables, change them, tell the debugger to run up to a + certain point and then stop, and so on. It is also possible + to attach to a program that is already running, or load a core + file to investigate why the program crashed. It is even + possible to debug the kernel, though that is a little trickier + than the user applications we will be discussing in this + section. + + This section is intended to be a quick introduction to + using debuggers and does not cover specialized topics such as + debugging the kernel. For more information about that, refer + to . + + The standard debugger supplied with + &os; &rel121.current; is called lldb + (LLVM debugger). As it is part of + the standard installation for that release, there is no need + to do anything special to use it. It has good command help, + accessible via the help command, as + well as a web + tutorial and documentation. + + + The lldb command is available for + &os; &rel1.current; from + ports or packages as + devel/llvm. This will install the + default version of lldb (currently 9.0). + + + The other debugger available with &os; is called gdb (GNU - debugger). You start it up by typing + debugger). Unlike lldb, it is not installed + by default on &os; &rel121.current;; to use it, install + devel/gdb from ports or packages. The + version installed by default on &os; &rel1.current; is + old and you should install devel/gdb there + as well. It has quite good on-line help, as well as a set of + info pages. + + Which one to use is largely a matter of taste. If + familiar with one only, use that one. People familiar + with neither or both but wanting to use one from inside + Emacs will need to use + gdb as lldb is + unsupported by Emacs. Otherwise, + try both and see which one you prefer. + + + + Using lldb + + + Starting lldb + + Start up lldb by typing + + &prompt.user; lldb -- progname + + + + Running a Program with lldb + + Compile the program with to get the + most out of using lldb. It will work + without, but will only display the name of the function + currently running, instead of the source code. If it + displays a line like: + + Breakpoint 1: where = temp`main, address = … + + (without an indication of source code filename and line + number) when setting a breakpoint, this means that the + program was not compiled with . + + + Most lldb commands have shorter + forms that can be used instead. The longer forms are + used here for clarity. + + + At the lldb prompt, type + breakpoint set -n main. This will + tell the debugger not to display the preliminary set-up code + in the program being run and to stop execution at the + beginning of your code. Now type + process launch to actually start the + program— it will start at the beginning of the set-up + code and then get stopped by the debugger when it calls + main(). + + To step through the program a line at a time, type + thread step-over. When the program + gets to a function call, step into it by typing + thread step-in. Once in a function + call, return from it by typing + thread step-out or use + up and down to + take a quick look at the caller. + + Here is a simple example of how to spot a mistake in a + program with lldb. This is our program + (with a deliberate mistake): + + #include <stdio.h> + +int bazz(int anint); + +main() { + int i; + + printf("This is my program\n"); + bazz(i); + return 0; +} + +int bazz(int anint) { + printf("You gave me %d\n", anint); + return anint; +} + + This program sets i to be + 5 and passes it to a function + bazz() which prints out the number we + gave it. + + Compiling and running the program displays + + &prompt.user; cc -g -o temp temp.c +&prompt.user; ./temp +This is my program +anint = -5360 + + That is not what was expected! Time to see what is going + on! + + &prompt.user; lldb -- temp +(lldb) target create "temp" +Current executable set to 'temp' (x86_64). +(lldb) breakpoint set -n main Skip the set-up code +Breakpoint 1: where = temp`main + 15 at temp.c:8:2, address = 0x00000000002012ef lldb puts breakpoint at main() +(lldb) process launch Run as far as main() +Process 9992 launching +Process 9992 launched: '/home/pauamma/tmp/temp' (x86_64) Program starts running + +Process 9992 stopped +* thread #1, name = 'temp', stop reason = breakpoint 1.1 lldb stops at main() + frame #0: 0x00000000002012ef temp`main at temp.c:8:2 + 5 main() { + 6 int i; + 7 +-> 8 printf("This is my program\n"); Indicates the line where it stopped + 9 bazz(i); + 10 return 0; + 11 } +(lldb) thread step-over Go to next line +This is my program Program prints out +Process 9992 stopped +* thread #1, name = 'temp', stop reason = step over + frame #0: 0x0000000000201300 temp`main at temp.c:9:7 + 6 int i; + 7 + 8 printf("This is my program\n"); +-> 9 bazz(i); + 10 return 0; + 11 } + 12 +(lldb) thread step-in step into bazz() +Process 9992 stopped +* thread #1, name = 'temp', stop reason = step in + frame #0: 0x000000000020132b temp`bazz(anint=-5360) at temp.c:14:29 lldb displays stack frame + 11 } + 12 + 13 int bazz(int anint) { +-> 14 printf("You gave me %d\n", anint); + 15 return anint; + 16 } +(lldb) + + Hang on a minute! How did anint get to + be -5360? Was it not set to + 5 in main()? Let us + move up to main() and have a + look. + + (lldb) up Move up call stack +frame #1: 0x000000000020130b temp`main at temp.c:9:2 lldb displays stack frame + 6 int i; + 7 + 8 printf("This is my program\n"); +-> 9 bazz(i); + 10 return 0; + 11 } + 12 +(lldb) frame variable i Show us the value of i +(int) i = -5360 lldb displays -5360 + + Oh dear! Looking at the code, we forgot to initialize + i. We meant to put + + +main() { + int i; + + i = 5; + printf("This is my program\n"); + + + but we left the i=5; line out. As we + did not initialize i, it had whatever + number happened to be in that area of memory when the + program ran, which in this case happened to be + -5360. + + + The lldb command displays the stack + frame every time we go into or out of a function, even if + we are using up and + down to move around the call stack. + This shows the name of the function and the values of its + arguments, which helps us keep track of where we are and + what is going on. (The stack is a storage area where the + program stores information about the arguments passed to + functions and where to go when it returns from a function + call.) + + + + + Examining a Core File with lldb + + A core file is basically a file which contains the + complete state of the process when it crashed. In + the good old days, programmers had to print + out hex listings of core files and sweat over machine code + manuals, but now life is a bit easier. Incidentally, under + FreeBSD and other 4.4BSD systems, a core file is called + progname.core + instead of just core, to make it + clearer which program a core file belongs to. + + To examine a core file, specify the name of the core + file in addition to the program itself. Instead of starting + up lldb in the usual way, type + lldb -c progname.core -- progname + + The debugger will display something like this: + + &prompt.user; lldb -c a.out.core -- a.out +(lldb) target create "a.out" --core "a.out.core" +Core file '/home/pauamma/tmp/a.out.core' (x86_64) was loaded. +(lldb) + + In this case, the program was called + a.out, so the core file is called + a.out.core. The debugger does not + display why the program crashed or where. For this, use + thread backtrace all. This will also + show how the function where the program dumped core was + called. + + (lldb) thread backtrace all +* thread #1, name = 'a.out', stop reason = signal SIGSEGV + * frame #0: 0x0000000000201347 a.out`bazz(anint=5) at temp2.c:17:10 + frame #1: 0x0000000000201312 a.out`main at temp2.c:10:2 + frame #2: 0x000000000020110f a.out`_start(ap=<unavailable>, cleanup=<unavailable>) at crt1.c:76:7 +(lldb) + + SIGSEGV indicates that the program + tried to access memory (run code or read/write data usually) + at a location that does not belong to it, but does not give + any specifics. For that, look at the source code at line 10 + of file temp2.c, in bazz(). The + backtrace also says that in this case, + bazz() was called from + main(). + + + + Attaching to a Running Program with lldb + + One of the neatest features about + lldb is that it can attach to a program + that is already running. Of course, that requires + sufficient permissions to do so. A common problem is + stepping through a program that forks and wanting to trace + the child, but the debugger will only trace the + parent. + + To do that, start up another lldb, + use ps to find the process ID for the + child, and do + + (lldb) process attach -p pid + + in lldb, and then debug as + usual. + + For that to work well, the code that + forks the child needs to do something + like the following (courtesy of the gdb + info pages): + + +if ((pid = fork()) < 0) /* _Always_ check this */ + error(); +else if (pid == 0) { /* child */ + int PauseMode = 1; + + while (PauseMode) + sleep(10); /* Wait until someone attaches to us */ + +} else { /* parent */ + + + Now all that is needed to do is attach to the child, set + PauseMode to 0 with + expr PauseMode = 0 and wait + for the sleep() call to return. + + + + + Using gdb + + + Starting gdb + + Start up gdb by typing &prompt.user; gdb progname although many people prefer to run it inside - Emacs. You can do this by: + Emacs. To do this, type: M-x gdb RET progname RET - Using a debugger allows you to run the program under more - controlled circumstances. Typically, you can step through the - program a line at a time, inspect the value of variables, - change them, tell the debugger to run up to a certain point - and then stop, and so on. You can even attach to a program - that is already running, or load a core file to investigate - why the program crashed. It is even possible to debug the - kernel, though that is a little trickier than the user - applications we will be discussing in this section. - - gdb has quite good on-line help, as - well as a set of info pages, so this section will concentrate - on a few of the basic commands. - - Finally, if you find its text-based command-prompt style - off-putting, there is a graphical front-end for it + Finally, for those finding its text-based command-prompt + style off-putting, there is a graphical front-end for it (devel/xxgdb) in the Ports Collection. - This section is intended to be an introduction to using - gdb and does not cover specialized topics - such as debugging the kernel. - - - - Running a Program in the Debugger - - You will need to have compiled the program with + + + + Running a Program with gdb + + Compile the program with to get the most out of using - gdb. It will work without, but you will - only see the name of the function you are in, instead of the - source code. If you see a line like: + gdb. It will work without, but will + only display the name of the function you are in, instead of the + source code. A line like: … (no debugging symbols found) … - when gdb starts up, you will know that - the program was not compiled with . + when gdb starts up means that the + program was not compiled with . At the gdb prompt, type break main. This will tell the - debugger that you are not interested in watching the - preliminary set-up code in the program being run, and that it - should stop execution at the beginning of your code. Now type - run to start the program—it will - start at the beginning of the set-up code and then get stopped - by the debugger when it calls main(). - (If you have ever wondered where main() - gets called from, now you know!). - - You can now step through the program, a line at a time, by - pressing n. If you get to a function call, - you can step into it by pressing s. Once - you are in a function call, you can return from stepping into - a function call by pressing f. You can - also use up and down to - take a quick look at the caller. + debugger to skip the preliminary set-up code in the program + being run and to stop execution at the beginning of your + code. Now type run to start the + program— it will start at the beginning of the set-up + code and then get stopped by the debugger when it calls + main(). + + To step through the program a line at a time, press + n. When at a function call, step into it + by pressing s. Once in a function call, + return from it by pressing f, or use + up and down to take + a quick look at the caller. Here is a simple example of how to spot a mistake in a program with gdb. This is our program @@ -1421,7 +1732,7 @@ bazz() which prints out the number we gave it. - When we compile and run the program we get + Compiling and running the program displays &prompt.user; cc -g -o temp temp.c &prompt.user; ./temp @@ -1449,7 +1760,7 @@ (gdb) Hang on a minute! How did anint get to be - 4231? Did we not we set it to be + 4231? Was it not set to 5 in main()? Let us move up to main() and have a look. @@ -1476,7 +1787,7 @@ 4231. - gdb displays the stack frame every + The gdb command displays the stack frame every time we go into or out of a function, even if we are using up and down to move around the call stack. This shows the name of the function @@ -1484,12 +1795,12 @@ of where we are and what is going on. (The stack is a storage area where the program stores information about the arguments passed to functions and where to go when it - returns from a function call). + returns from a function call.) - - - - Examining a Core File + + + + Examining a Core File with gdb A core file is basically a file which contains the complete state of the process when it crashed. In the @@ -1507,11 +1818,10 @@ (gdb) core progname.core - If you are not in the same directory as the core file, you - will have to do dir /path/to/core/file - first. - - You should see something like this: + If the core file is not in the current directory, type + dir /path/to/core/file first. + + The debugger should display something like this: &prompt.user; gdb a.out GDB is free software and you are welcome to distribute copies of it @@ -1547,19 +1857,19 @@ The end() function is called when a program crashes; in this case, the bazz() function was called from main(). - - - - Attaching to a Running Program + + + + Attaching to a Running Program with gdb One of the neatest features about gdb is that it can attach to a program that is already running. - Of course, that assumes you have sufficient permissions to do - so. A common problem is when you are stepping through a - program that forks, and you want to trace the child, but the - debugger will only let you trace the parent. - - What you do is start up another gdb, + Of course, that requires sufficient permissions to do + so. A common problem is stepping through a program that forks and + wanting to trace the child, but the + debugger will only trace the parent. + + To do that, start up another gdb, use ps to find the process ID for the child, and do @@ -1567,11 +1877,10 @@ in gdb, and then debug as usual. - That is all very well, you are probably - thinking, but by the time I have done that, the child - process will be over the hill and far away. Fear - not, gentle reader, here is how to do it (courtesy of the - gdb info pages): + For that to work well, the code that + forks the child needs to do something + like the following (courtesy of the gdb + info pages): if ((pid = fork()) < 0) /* _Always_ check this */ @@ -1585,9 +1894,10 @@ } else { /* parent */ - Now all you have to do is attach to the child, set + Now all that is needed to do is attach to the child, set PauseMode to 0, and wait for the sleep() call to return! +