The translation is temporarily closed for contributions due to maintenance, please come back later.

Source string Read only

(itstool) path: sect3/para
Context English State
Debugging
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 <xref linkend="kerneldebug"/>.
The standard debugger supplied with FreeBSD 12.1 is called <command>lldb</command> (<application>LLVM debugger</application>). 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 <userinput>help</userinput> command, as well as <link xlink:href="https://lldb.llvm.org/">a web tutorial and documentation</link>.
The <command>lldb</command> command is available for FreeBSD 11.3 <link xlink:href="@@URL_RELPREFIX@@/doc/en_US.ISO8859-1/books/handbook/ports-using.html">from ports or packages</link> as <package>devel/llvm</package>. This will install the default version of lldb (currently 9.0).
The other debugger available with FreeBSD is called <command>gdb</command> (<application>GNU debugger</application>). Unlike lldb, it is not installed by default on FreeBSD 12.1; to use it, <link xlink:href="@@URL_RELPREFIX@@/doc/en_US.ISO8859-1/books/handbook/ports-using.html">install</link> <package>devel/gdb</package> from ports or packages. The version installed by default on FreeBSD 11.3 is old; instead, install <package>devel/gdb</package> 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 <application>Emacs</application> will need to use <command>gdb</command> as <command>lldb</command> is unsupported by <application>Emacs</application>. Otherwise, try both and see which one you prefer.
Using lldb
Starting lldb
Start up lldb by typing
<prompt>%</prompt> <userinput>lldb -- <replaceable>progname</replaceable></userinput>
Running a Program with lldb
Compile the program with <option>-g</option> to get the most out of using <command>lldb</command>. 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 <option>-g</option>.
Most <command>lldb</command> commands have shorter forms that can be used instead. The longer forms are used here for clarity.
At the <command>lldb</command> prompt, type <userinput>breakpoint set -n main</userinput>. 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 the program's code. Now type <userinput>process launch</userinput> 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 <function>main()</function>.
To step through the program a line at a time, type <userinput>thread step-over</userinput>. When the program gets to a function call, step into it by typing <userinput>thread step-in</userinput>. Once in a function call, return from it by typing <userinput>thread step-out</userinput> or use <userinput>up</userinput> and <userinput>down</userinput> to take a quick look at the caller.
Here is a simple example of how to spot a mistake in a program with <command>lldb</command>. This is our program (with a deliberate mistake):
#include &lt;stdio.h&gt;

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 <symbol>i</symbol> to be <literal>5</literal> and passes it to a function <function>bazz()</function> which prints out the number we gave it.
Compiling and running the program displays
<prompt>%</prompt> <userinput>cc -g -o temp temp.c</userinput>
<prompt>%</prompt> <userinput>./temp</userinput>
This is my program
anint = -5360
That is not what was expected! Time to see what is going on!
<prompt>%</prompt> <userinput>lldb -- temp</userinput>
(lldb) target create "temp"
Current executable set to 'temp' (x86_64).
(lldb) <userinput>breakpoint set -n main</userinput> <lineannotation>Skip the set-up code</lineannotation>
Breakpoint 1: where = temp`main + 15 at temp.c:8:2, address = 0x00000000002012ef <lineannotation>lldb puts breakpoint at main()</lineannotation>
(lldb) <userinput>process launch</userinput> <lineannotation>Run as far as main()</lineannotation>
Process 9992 launching
Process 9992 launched: '/home/pauamma/tmp/temp' (x86_64) <lineannotation>Program starts running</lineannotation>

Process 9992 stopped
* thread #1, name = 'temp', stop reason = breakpoint 1.1 <lineannotation>lldb stops at main()</lineannotation>
frame #0: 0x00000000002012ef temp`main at temp.c:8:2
5 main() {
6 int i;
7
-&gt; 8 printf("This is my program\n"); <lineannotation>Indicates the line where it stopped</lineannotation>
9 bazz(i);
10 return 0;
11 }
(lldb) <userinput>thread step-over</userinput> <lineannotation>Go to next line</lineannotation>
This is my program <lineannotation>Program prints out</lineannotation>
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");
-&gt; 9 bazz(i);
10 return 0;
11 }
12
(lldb) <userinput>thread step-in</userinput> <lineannotation>step into bazz()</lineannotation>
Process 9992 stopped
* thread #1, name = 'temp', stop reason = step in
frame #0: 0x000000000020132b temp`bazz(anint=-5360) at temp.c:14:29 <lineannotation>lldb displays stack frame</lineannotation>
11 }
12
13 int bazz(int anint) {
-&gt; 14 printf("You gave me %d\n", anint);
15 return anint;
16 }
(lldb)
Hang on a minute! How did <symbol>anint</symbol> get to be <literal>-5360</literal>? Was it not set to <literal>5</literal> in <function>main()</function>? Let us move up to <function>main()</function> and have a look.
(lldb) <userinput>up</userinput> <lineannotation>Move up call stack</lineannotation>
frame #1: 0x000000000020130b temp`main at temp.c:9:2 <lineannotation>lldb displays stack frame</lineannotation>
6 int i;
7
8 printf("This is my program\n");
-&gt; 9 bazz(i);
10 return 0;
11 }
12
(lldb) <userinput>frame variable i</userinput> <lineannotation>Show us the value of i</lineannotation>
(int) i = -5360 <lineannotation>lldb displays -5360</lineannotation>
Oh dear! Looking at the code, we forgot to initialize <symbol>i</symbol>. We meant to put
<lineannotation>…</lineannotation>
main() {
int i;

i = 5;
printf("This is my program\n");
<lineannotation>…</lineannotation>
but we left the <literal>i=5;</literal> line out. As we did not initialize <symbol>i</symbol>, it had whatever number happened to be in that area of memory when the program ran, which in this case happened to be <literal>-5360</literal>.

Loading…

New source string 7 months ago
Browse all component changes

Source information

Source string comment
(itstool) path: sect3/para
Flags
read-only
Source string location
book.translate.xml:1789
String age
7 months ago
Source string age
7 months ago
Translation file
books/developers-handbook.pot, string 332