Changeset View
Standalone View
en_US.ISO8859-1/books/developers-handbook/tools/chapter.xml
Show First 20 Lines • Show All 826 Lines • ▼ Show 20 Lines | 2.1 ^ 6 = 85.766121</screen> | ||||
<qandaentry> | <qandaentry> | ||||
<question> | <question> | ||||
<para>Fascinating stuff, but what I am supposed to do | <para>Fascinating stuff, but what I am supposed to do | ||||
now?</para> | now?</para> | ||||
</question> | </question> | ||||
<answer> | <answer> | ||||
<para>Use <command>gdb</command> to analyze the core (see | <para>Use a debugger to analyze the core (see | ||||
<xref linkend="debugging"/>).</para> | <xref linkend="debugging"/>).</para> | ||||
</answer> | </answer> | ||||
</qandaentry> | </qandaentry> | ||||
<qandaentry> | <qandaentry> | ||||
<question> | <question> | ||||
<para>When my program dumped core, it said something about | <para>When my program dumped core, it said something about | ||||
a <errorname>segmentation fault</errorname>. What is | a <errorname>segmentation fault</errorname>. What is | ||||
▲ Show 20 Lines • Show All 476 Lines • ▼ Show 20 Lines | <application>Emacs</application>, do <userinput>C-h | ||||
i</userinput>).</para> | i</userinput>).</para> | ||||
</sect2> | </sect2> | ||||
</sect1> | </sect1> | ||||
<sect1 xml:id="debugging"> | <sect1 xml:id="debugging"> | ||||
<title>Debugging</title> | <title>Debugging</title> | ||||
<sect2> | <sect2> | ||||
<title>The Debugger</title> | <title>Introduction to Available Debuggers</title> | ||||
<para>The debugger that comes with FreeBSD is called | |||||
<command>gdb</command> (<application>GNU | |||||
debugger</application>). You start it up by typing</para> | |||||
<screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput></screen> | |||||
<para>although many people prefer to run it inside | |||||
<application>Emacs</application>. You can do this by:</para> | |||||
<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen> | |||||
<para>Using a debugger allows you to run the program under more | <para>Using a debugger allows you to run the program under more | ||||
controlled circumstances. Typically, you can step through the | controlled circumstances. Typically, you can step through the | ||||
program a line at a time, inspect the value of variables, | program a line at a time, inspect the value of variables, | ||||
bcr: Here is a leftover "you". | |||||
change them, tell the debugger to run up to a certain point | 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 | and then stop, and so on. You can even attach to a program | ||||
that is already running, or load a core file to investigate | that is already running, or load a core file to investigate | ||||
why the program crashed. It is even possible to debug the | why the program crashed. It is even possible to debug the | ||||
kernel, though that is a little trickier than the user | kernel, though that is a little trickier than the user | ||||
applications we will be discussing in this section.</para> | applications we will be discussing in this section.</para> | ||||
<para><command>gdb</command> has quite good on-line help, as | <para>This section is intended to be a quick introduction to | ||||
well as a set of info pages, so this section will concentrate | using debuggers and does not cover specialized topics such as | ||||
on a few of the basic commands.</para> | debugging the kernel. For more information about that, refer | ||||
to <xref linkend="kerneldebug" />.</para> | |||||
<para>The standard debugger supplied with | |||||
&os; &rel121.current; is called <command>lldb</command> | |||||
(<application>LLVM debugger</application>). As it is part of | |||||
the standard installation for that release, you do not have 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>.</para> | |||||
<note> | |||||
<para><command>lldb</command> is available for | |||||
&os; &rel1.current; <link | |||||
emasteUnsubmitted Done Inline Actions&rel1 - typo? emaste: `&rel1` - typo? | |||||
pauamma_gundo.comAuthorUnsubmitted Done Inline ActionsNo, rel1.current is defined in share/xml/release.ent and used in several places, including the (users') handbook, to refer (currently) to 11.3. (Whether the "current" bit is still appropriate is more than I caan say, though.) pauamma_gundo.com: No, rel1.current is defined in share/xml/release.ent and used in several places, including the… | |||||
xlink:href="&url.books.handbook;/ports.html">from ports or | |||||
packages as <package>devel/llvm80</package></link>. If | |||||
emasteUnsubmitted Done Inline Actionswe have llvm60, llvm70, llvm80, llvm90, llvm10 available, with just llvm as a meta package to pick the default - we should reference that one here. emaste: we have llvm60, llvm70, llvm80, llvm90, llvm10 available, with just llvm as a meta package to… | |||||
installed that way, the command name to invoke it is | |||||
<userinput>lldb80</userinput> instead of | |||||
emasteUnsubmitted Done Inline Actionsand we'll need to clarify lldb80/lldb90 etc. emaste: and we'll need to clarify lldb80/lldb90 etc. | |||||
<userinput>lldb</userinput> and you will need to use that | |||||
command name everywhere below.</para> | |||||
</note> | |||||
<para>The other debugger available with &os; is called | |||||
<command>gdb</command> (<application>GNU | |||||
debugger</application>). Unlike lldb, it is not installed | |||||
by default on &os; &rel121.current;; you need to <link | |||||
xlink:href="&url.books.handbook;/ports.html">install | |||||
<package>devel/gdb</package> from ports or | |||||
packages</link>. It is, however, installed by default on &os; | |||||
&rel1.current;. <command>gdb</command> has quite good | |||||
emasteUnsubmitted Done Inline ActionsNote though that it's still GDB 6.1 there, which is obsolete/buggy; developers wishing to use GDB will still want to install the gdb package/port. emaste: Note though that it's still GDB 6.1 there, which is obsolete/buggy; developers wishing to use… | |||||
on-line help, as well as a set of info pages.</para> | |||||
<para>Which one to use is largely a matter of taste. If you are | |||||
familiar with one only, use that one. If you are familiar | |||||
with neither or both but want to use one from inside | |||||
<application>Emacs</application>, you should use | |||||
<command>gdb</command> as <command>lldb</command> is | |||||
unsupported by <application>Emacs</application>. Otherwise, | |||||
you could try both and see which one you prefer.</para> | |||||
Done Inline Actionsanother "your". You can replace it with "the" here. bcr: another "your". You can replace it with "the" here. | |||||
</sect2> | |||||
<sect2> | |||||
<title>Using lldb</title> | |||||
Done Inline ActionsHere is a "you". bcr: Here is a "you". | |||||
Done Inline Actionss/your/the/ bcr: s/your/the/ | |||||
<sect3> | |||||
<title>Starting lldb</title> | |||||
<para>You start up lldb by typing</para> | |||||
<screen>&prompt.user; <userinput>lldb -- <replaceable>progname</replaceable></userinput></screen> | |||||
emasteUnsubmitted Done Inline Actionscan be lldb <progname> -- <program arguments> - for example, lldb /bin/ls -- /tmp as an aside it seems the lldb man page has an error here, using a single dash: Passing an executable as a positional argument prepares lldb to debug the given executable. Arguments passed after - are considered arguments to the debugged executable. lldb -arch x86_64 /path/to/program - -arch arvm7 emaste: can be `lldb <progname> -- <program arguments>` - for example, `lldb /bin/ls -- /tmp`
as an… | |||||
pauamma_gundo.comAuthorUnsubmitted Done Inline ActionsManpage (at least in 12.1) says lldb wants -f before the executable if you're going to put it before the --, so I'm tempted to leave it this way. (Same manpage has -- everywhere I can see, too.) pauamma_gundo.com: Manpage (at least in 12.1) says lldb wants -f before the executable if you're going to put it… | |||||
</sect3> | |||||
<sect3> | |||||
<title>Running a Program with lldb</title> | |||||
<para>Ensure you have compiled the program with | |||||
<option>-g</option> to get the most out of using | |||||
<command>lldb</command>. 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:</para> | |||||
emasteUnsubmitted Done Inline Actions(-g is also needed on any libraries the program uses, to get the most out of a debugger. Not sure it's necessary to mention in the mini tutorial though) emaste: (-g is also needed on any libraries the program uses, to get the most out of a debugger. Not… | |||||
pauamma_gundo.comAuthorUnsubmitted Done Inline Actionsgdb section doesn't mention that, and I largely reproduced it for content that's not specific to one debugger. Should I add it in both? pauamma_gundo.com: gdb section doesn't mention that, and I largely reproduced it for content that's not specific… | |||||
emasteUnsubmitted Done Inline ActionsIt's fine to leave it as is, we can perhaps do another pass over this later on when lldb improves (specifically, gains kernel support) emaste: It's fine to leave it as is, we can perhaps do another pass over this later on when lldb… | |||||
<screen>Breakpoint 1: where = temp`main, address = …</screen> | |||||
<para>(without an indication of source code filename and line | |||||
number) when setting a breakpoint, you will know that the | |||||
program was not compiled with <option>-g</option>.</para> | |||||
<para>At the <command>lldb</command> prompt, type | |||||
<userinput>breakpoint set -n main</userinput>. 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 <userinput>process launch</userinput> 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 | |||||
<function>main()</function>. (If you have ever wondered | |||||
where <function>main()</function> gets called from, now you | |||||
know!).</para> | |||||
emasteUnsubmitted Done Inline ActionsIt might be useful to mention the shorter forms / GDB compat options before this? emaste: It might be useful to mention the shorter forms / GDB compat options before this? | |||||
<para>You can now step through the program, a line at a time, | |||||
by typing <userinput>thread step-over</userinput>. If you | |||||
get to a function call, you can step into it by typing | |||||
<userinput>thread step-in</userinput>. Once you are in a | |||||
function call, you can return from it by typing | |||||
<userinput>thread step-out</userinput>. You can also use | |||||
Done Inline Actionsheh, your garbage value changed :) emaste: heh, your garbage value changed :) | |||||
<userinput>up</userinput> and <userinput>down</userinput> to | |||||
take a quick look at the caller.</para> | |||||
<tip> | |||||
emasteUnsubmitted Done Inline Actionsi.e., wrt the comment above, move this tip before the preceding paragraphs. emaste: i.e., wrt the comment above, move this tip before the preceding paragraphs. | |||||
<para>Most <command>lldb</command> commands have shorter | |||||
forms that you can use instead. The longer forms are | |||||
used here for clarity.</para> | |||||
</tip> | |||||
<para>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):</para> | |||||
<programlisting>#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; | |||||
}</programlisting> | |||||
<para>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.</para> | |||||
<para>When we compile and run the program we get</para> | |||||
<screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput> | |||||
&prompt.user; <userinput>./temp</userinput> | |||||
This is my program | |||||
anint = 4231</screen> | |||||
<para>That was not what we expected! Time to see what is going | |||||
on!</para> | |||||
<screen>&prompt.user; <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 | |||||
-> 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"); | |||||
-> 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>gdb displays stack frame</lineannotation> | |||||
11 } | |||||
12 | |||||
13 int bazz(int anint) { | |||||
-> 14 printf("You gave me %d\n", anint); | |||||
15 return anint; | |||||
16 } | |||||
(lldb)</screen> | |||||
<para>Hang on a minute! How did <symbol>anint</symbol> get to | |||||
be <literal>-5360</literal>? Did we not set it to be | |||||
<literal>5</literal> in <function>main()</function>? Let us | |||||
move up to <function>main()</function> and have a | |||||
look.</para> | |||||
<screen>(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"); | |||||
-> 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></screen> | |||||
Done Inline Actionss/FreeBSD/&os;/ bcr: s/FreeBSD/&os;/ | |||||
<para>Oh dear! Looking at the code, we forgot to initialize | |||||
<symbol>i</symbol>. We meant to put</para> | |||||
<programlisting><lineannotation>…</lineannotation> | |||||
main() { | |||||
int i; | |||||
i = 5; | |||||
printf("This is my program\n"); | |||||
<lineannotation>…</lineannotation></programlisting> | |||||
<para>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>.</para> | |||||
<note> | |||||
<para><command>lldb</command> displays the stack frame every | |||||
debdrupUnsubmitted Done Inline ActionsThis sentence needs to start with a capitalized word, for example "The lldb command displays..." debdrup: This sentence needs to start with a capitalized word, for example "The lldb command displays..." | |||||
time we go into or out of a function, even if we are using | |||||
<userinput>up</userinput> and <userinput>down</userinput> | |||||
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.)</para> | |||||
</note> | |||||
</sect3> | |||||
<sect3> | |||||
<title>Examining a Core File with lldb</title> | |||||
<para>A core file is basically a file which contains the | |||||
complete state of the process when it crashed. In | |||||
<quote>the good old days</quote>, 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 | |||||
<filename><replaceable>progname</replaceable>.core</filename> | |||||
instead of just <filename>core</filename>, to make it | |||||
clearer which program a core file belongs to.</para> | |||||
<para>To examine a core file, you need to specify the name of | |||||
the core file in addition to the program itself. Instead of | |||||
starting up <command>lldb</command> in the usual way, type | |||||
<userinput>lldb -c <replaceable>progname</replaceable>.core -- <replaceable>progname</replaceable></userinput></para> | |||||
<para>You should see something like this:</para> | |||||
<screen>&prompt.user; <userinput>lldb -c a.out.core -- a.out</userinput> | |||||
(lldb) target create "a.out" --core "a.out.core" | |||||
Core file '/home/pauamma/tmp/a.out.core' (x86_64) was loaded. | |||||
(lldb)</screen> | |||||
<para>In this case, the program was called | |||||
<filename>a.out</filename>, so the core file is called | |||||
<filename>a.out.core</filename>. We cannot see why the | |||||
program crashed or where. For this, we need to use | |||||
<userinput>thread backtrace all</userinput>. This will also | |||||
tell us how the function where the program dumped core was | |||||
called.</para> | |||||
<screen>(lldb) <userinput>thread backtrace all</userinput> | |||||
* 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)</screen> | |||||
<para><literal>SIGSEGV</literal> 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, we would need to look at the | |||||
source code at line 10 of file temp2.c, in | |||||
<function>bazz()</function>. The backtrace also tells us | |||||
that in this case, the <function>bazz()</function> function | |||||
was called from <function>main()</function>.</para> | |||||
</sect3> | |||||
<sect3> | |||||
<title>Attaching to a Running Program with lldb</title> | |||||
<para>One of the neatest features about | |||||
<command>lldb</command> 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.</para> | |||||
<para>What you do is start up another <command>lldb</command>, | |||||
use <command>ps</command> to find the process ID for the | |||||
child, and do</para> | |||||
<screen>(lldb) <userinput>process attach -p <replaceable>pid</replaceable></userinput></screen> | |||||
<para>in <command>lldb</command>, and then debug as | |||||
usual.</para> | |||||
<para><quote>That is all very well,</quote> you are probably | |||||
thinking, <quote>but by the time I have done that, the child | |||||
process will be over the hill and far away</quote>. Fear | |||||
not, gentle reader, here is how to do it (courtesy of the | |||||
<command>gdb</command> info pages):</para> | |||||
<programlisting><lineannotation>…</lineannotation> | |||||
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 */ | |||||
<lineannotation>…</lineannotation> | |||||
} else { /* parent */ | |||||
<lineannotation>…</lineannotation></programlisting> | |||||
<para>Now all you have to do is attach to the child, set | |||||
<symbol>PauseMode</symbol> to <literal>0</literal> with | |||||
<userinput>expr PauseMode = 0</userinput> and wait | |||||
for the <function>sleep()</function> call to return!</para> | |||||
</sect3> | |||||
</sect2> | |||||
<sect2> | |||||
<title>Using gdb</title> | |||||
<sect3> | |||||
<title>Starting gdb</title> | |||||
<para>You start up gdb by typing</para> | |||||
<screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput></screen> | |||||
<para>although many people prefer to run it inside | |||||
<application>Emacs</application>. You can do this | |||||
by:</para> | |||||
<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen> | |||||
<para>Finally, if you find its text-based command-prompt style | <para>Finally, if you find its text-based command-prompt style | ||||
off-putting, there is a graphical front-end for it | off-putting, there is a graphical front-end for it | ||||
(<package>devel/xxgdb</package>) in the Ports | (<package>devel/xxgdb</package>) in the Ports | ||||
Collection.</para> | Collection.</para> | ||||
<para>This section is intended to be an introduction to using | </sect3> | ||||
<command>gdb</command> and does not cover specialized topics | |||||
such as debugging the kernel.</para> | |||||
</sect2> | |||||
<sect2> | <sect3> | ||||
<title>Running a Program in the Debugger</title> | <title>Running a Program with gdb</title> | ||||
<para>You will need to have compiled the program with | <para>You will need to have compiled the program with | ||||
<option>-g</option> to get the most out of using | <option>-g</option> to get the most out of using | ||||
<command>gdb</command>. It will work without, but you will | <command>gdb</command>. It will work without, but you will | ||||
only see the name of the function you are in, instead of the | only see the name of the function you are in, instead of the | ||||
source code. If you see a line like:</para> | source code. If you see a line like:</para> | ||||
<screen>… (no debugging symbols found) …</screen> | <screen>… (no debugging symbols found) …</screen> | ||||
<para>when <command>gdb</command> starts up, you will know that | <para>when <command>gdb</command> starts up, you will know | ||||
the program was not compiled with <option>-g</option>.</para> | that the program was not compiled with | ||||
<option>-g</option>.</para> | |||||
<para>At the <command>gdb</command> prompt, type | <para>At the <command>gdb</command> prompt, type | ||||
<userinput>break main</userinput>. This will tell the | <userinput>break main</userinput>. This will tell the | ||||
debugger that you are not interested in watching the | debugger that you are not interested in watching the | ||||
preliminary set-up code in the program being run, and that it | preliminary set-up code in the program being run, and that | ||||
should stop execution at the beginning of your code. Now type | it should stop execution at the beginning of your code. Now | ||||
<userinput>run</userinput> to start the program—it will | type <userinput>run</userinput> to start the program— | ||||
start at the beginning of the set-up code and then get stopped | it will start at the beginning of the set-up code and then | ||||
by the debugger when it calls <function>main()</function>. | get stopped by the debugger when it calls | ||||
(If you have ever wondered where <function>main()</function> | <function>main()</function>. (If you have ever wondered | ||||
gets called from, now you know!).</para> | where <function>main()</function> gets called from, now you | ||||
know!).</para> | |||||
<para>You can now step through the program, a line at a time, by | <para>You can now step through the program, a line at a time, | ||||
pressing <command>n</command>. If you get to a function call, | by pressing <command>n</command>. If you get to a function | ||||
you can step into it by pressing <command>s</command>. Once | call, you can step into it by pressing <command>s</command>. | ||||
you are in a function call, you can return from stepping into | Once you are in a function call, you can return from | ||||
a function call by pressing <command>f</command>. You can | stepping into a function call by pressing | ||||
also use <command>up</command> and <command>down</command> to | <command>f</command>. You can also use | ||||
take a quick look at the caller.</para> | <command>up</command> and <command>down</command> to take | ||||
a quick look at the caller.</para> | |||||
<para>Here is a simple example of how to spot a mistake in a | <para>Here is a simple example of how to spot a mistake in a | ||||
program with <command>gdb</command>. This is our program | program with <command>gdb</command>. This is our program | ||||
(with a deliberate mistake):</para> | (with a deliberate mistake):</para> | ||||
<programlisting>#include <stdio.h> | <programlisting>#include <stdio.h> | ||||
int bazz(int anint); | int bazz(int anint); | ||||
main() { | main() { | ||||
int i; | int i; | ||||
printf("This is my program\n"); | printf("This is my program\n"); | ||||
bazz(i); | bazz(i); | ||||
return 0; | return 0; | ||||
} | } | ||||
int bazz(int anint) { | int bazz(int anint) { | ||||
printf("You gave me %d\n", anint); | printf("You gave me %d\n", anint); | ||||
return anint; | return anint; | ||||
}</programlisting> | }</programlisting> | ||||
<para>This program sets <symbol>i</symbol> to be | <para>This program sets <symbol>i</symbol> to be | ||||
<literal>5</literal> and passes it to a function | <literal>5</literal> and passes it to a function | ||||
<function>bazz()</function> which prints out the number we | <function>bazz()</function> which prints out the number we | ||||
gave it.</para> | gave it.</para> | ||||
<para>When we compile and run the program we get</para> | <para>When we compile and run the program we get</para> | ||||
<screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput> | <screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput> | ||||
&prompt.user; <userinput>./temp</userinput> | &prompt.user; <userinput>./temp</userinput> | ||||
This is my program | This is my program | ||||
anint = 4231</screen> | anint = 4231</screen> | ||||
<para>That was not what we expected! Time to see what is going | <para>That was not what we expected! Time to see what is going | ||||
on!</para> | on!</para> | ||||
<screen>&prompt.user; <userinput>gdb temp</userinput> | <screen>&prompt.user; <userinput>gdb temp</userinput> | ||||
GDB is free software and you are welcome to distribute copies of it | GDB is free software and you are welcome to distribute copies of it | ||||
under certain conditions; type "show copying" to see the conditions. | under certain conditions; type "show copying" to see the conditions. | ||||
There is absolutely no warranty for GDB; type "show warranty" for details. | There is absolutely no warranty for GDB; type "show warranty" for details. | ||||
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc. | GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc. | ||||
(gdb) <userinput>break main</userinput> <lineannotation>Skip the set-up code</lineannotation> | (gdb) <userinput>break main</userinput> <lineannotation>Skip the set-up code</lineannotation> | ||||
Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation>gdb puts breakpoint at main()</lineannotation> | Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation>gdb puts breakpoint at main()</lineannotation> | ||||
(gdb) <userinput>run</userinput> <lineannotation>Run as far as main()</lineannotation> | (gdb) <userinput>run</userinput> <lineannotation>Run as far as main()</lineannotation> | ||||
Starting program: /home/james/tmp/temp <lineannotation>Program starts running</lineannotation> | Starting program: /home/james/tmp/temp <lineannotation>Program starts running</lineannotation> | ||||
Breakpoint 1, main () at temp.c:9 <lineannotation>gdb stops at main()</lineannotation> | Breakpoint 1, main () at temp.c:9 <lineannotation>gdb stops at main()</lineannotation> | ||||
(gdb) <userinput>n</userinput> <lineannotation>Go to next line</lineannotation> | (gdb) <userinput>n</userinput> <lineannotation>Go to next line</lineannotation> | ||||
This is my program <lineannotation>Program prints out</lineannotation> | This is my program <lineannotation>Program prints out</lineannotation> | ||||
(gdb) <userinput>s</userinput> <lineannotation>step into bazz()</lineannotation> | (gdb) <userinput>s</userinput> <lineannotation>step into bazz()</lineannotation> | ||||
bazz (anint=4231) at temp.c:17 <lineannotation>gdb displays stack frame</lineannotation> | bazz (anint=4231) at temp.c:17 <lineannotation>gdb displays stack frame</lineannotation> | ||||
(gdb)</screen> | (gdb)</screen> | ||||
<para>Hang on a minute! How did <symbol>anint</symbol> get to be | <para>Hang on a minute! How did <symbol>anint</symbol> get to | ||||
<literal>4231</literal>? Did we not we set it to be | be <literal>4231</literal>? Did we not set it to be | ||||
<literal>5</literal> in <function>main()</function>? Let us | <literal>5</literal> in <function>main()</function>? Let us | ||||
move up to <function>main()</function> and have a look.</para> | move up to <function>main()</function> and have a | ||||
look.</para> | |||||
<screen>(gdb) <userinput>up</userinput> <lineannotation>Move up call stack</lineannotation> | <screen>(gdb) <userinput>up</userinput> <lineannotation>Move up call stack</lineannotation> | ||||
#1 0x1625 in main () at temp.c:11 <lineannotation>gdb displays stack frame</lineannotation> | #1 0x1625 in main () at temp.c:11 <lineannotation>gdb displays stack frame</lineannotation> | ||||
(gdb) <userinput>p i</userinput> <lineannotation>Show us the value of i</lineannotation> | (gdb) <userinput>p i</userinput> <lineannotation>Show us the value of i</lineannotation> | ||||
$1 = 4231 <lineannotation>gdb displays 4231</lineannotation></screen> | $1 = 4231 <lineannotation>gdb displays 4231</lineannotation></screen> | ||||
<para>Oh dear! Looking at the code, we forgot to initialize | <para>Oh dear! Looking at the code, we forgot to initialize | ||||
<symbol>i</symbol>. We meant to put</para> | <symbol>i</symbol>. We meant to put</para> | ||||
<programlisting><lineannotation>…</lineannotation> | <programlisting><lineannotation>…</lineannotation> | ||||
main() { | main() { | ||||
int i; | int i; | ||||
i = 5; | i = 5; | ||||
printf("This is my program\n"); | printf("This is my program\n"); | ||||
<lineannotation>…</lineannotation></programlisting> | <lineannotation>…</lineannotation></programlisting> | ||||
<para>but we left the <literal>i=5;</literal> line out. As we | <para>but we left the <literal>i=5;</literal> line out. As we | ||||
did not initialize <symbol>i</symbol>, it had whatever number | did not initialize <symbol>i</symbol>, it had whatever | ||||
happened to be in that area of memory when the program ran, | number happened to be in that area of memory when the | ||||
which in this case happened to be | program ran, which in this case happened to be | ||||
<literal>4231</literal>.</para> | <literal>4231</literal>.</para> | ||||
<note> | <note> | ||||
<para><command>gdb</command> displays the stack frame every | <para><command>gdb</command> displays the stack frame every | ||||
time we go into or out of a function, even if we are using | time we go into or out of a function, even if we are using | ||||
<command>up</command> and <command>down</command> to move | <command>up</command> and <command>down</command> to move | ||||
around the call stack. This shows the name of the function | around the call stack. This shows the name of the | ||||
and the values of its arguments, which helps us keep track | function and the values of its arguments, which helps us | ||||
of where we are and what is going on. (The stack is a | keep track of where we are and what is going on. (The | ||||
storage area where the program stores information about the | stack is a storage area where the program stores | ||||
arguments passed to functions and where to go when it | information about the arguments passed to functions and | ||||
returns from a function call).</para> | where to go when it returns from a function call.)</para> | ||||
</note> | </note> | ||||
</sect2> | </sect3> | ||||
<sect2> | <sect3> | ||||
<title>Examining a Core File</title> | <title>Examining a Core File with gdb</title> | ||||
<para>A core file is basically a file which contains the | <para>A core file is basically a file which contains the | ||||
complete state of the process when it crashed. In <quote>the | complete state of the process when it crashed. In | ||||
good old days</quote>, programmers had to print out hex | <quote>the good old days</quote>, programmers had to print | ||||
listings of core files and sweat over machine code manuals, | out hex listings of core files and sweat over machine code | ||||
but now life is a bit easier. Incidentally, under FreeBSD and | manuals, but now life is a bit easier. Incidentally, under | ||||
other 4.4BSD systems, a core file is called | FreeBSD and other 4.4BSD systems, a core file is called | ||||
<filename><replaceable>progname</replaceable>.core</filename> | <filename><replaceable>progname</replaceable>.core</filename> | ||||
instead of just <filename>core</filename>, to make it clearer | instead of just <filename>core</filename>, to make it | ||||
which program a core file belongs to.</para> | clearer which program a core file belongs to.</para> | ||||
<para>To examine a core file, start up <command>gdb</command> in | <para>To examine a core file, start up <command>gdb</command> | ||||
the usual way. Instead of typing <command>break</command> or | in the usual way. Instead of typing | ||||
<command>run</command>, type</para> | <command>break</command> or <command>run</command>, | ||||
type</para> | |||||
<screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen> | <screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen> | ||||
<para>If you are not in the same directory as the core file, you | <para>If you are not in the same directory as the core file, | ||||
will have to do <userinput>dir /path/to/core/file</userinput> | you will have to do <userinput>dir | ||||
first.</para> | /path/to/core/file</userinput> first.</para> | ||||
<para>You should see something like this:</para> | <para>You should see something like this:</para> | ||||
<screen>&prompt.user; <userinput>gdb a.out</userinput> | <screen>&prompt.user; <userinput>gdb a.out</userinput> | ||||
GDB is free software and you are welcome to distribute copies of it | GDB is free software and you are welcome to distribute copies of it | ||||
under certain conditions; type "show copying" to see the conditions. | under certain conditions; type "show copying" to see the conditions. | ||||
There is absolutely no warranty for GDB; type "show warranty" for details. | There is absolutely no warranty for GDB; type "show warranty" for details. | ||||
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc. | GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc. | ||||
(gdb) <userinput>core a.out.core</userinput> | (gdb) <userinput>core a.out.core</userinput> | ||||
Core was generated by `a.out'. | Core was generated by `a.out'. | ||||
Program terminated with signal 11, Segmentation fault. | Program terminated with signal 11, Segmentation fault. | ||||
Cannot access memory at address 0x7020796d. | Cannot access memory at address 0x7020796d. | ||||
#0 0x164a in bazz (anint=0x5) at temp.c:17 | #0 0x164a in bazz (anint=0x5) at temp.c:17 | ||||
(gdb)</screen> | (gdb)</screen> | ||||
<para>In this case, the program was called | <para>In this case, the program was called | ||||
<filename>a.out</filename>, so the core file is called | <filename>a.out</filename>, so the core file is called | ||||
<filename>a.out.core</filename>. We can see that the program | <filename>a.out.core</filename>. We can see that the | ||||
crashed due to trying to access an area in memory that was not | program crashed due to trying to access an area in memory | ||||
available to it in a function called | that was not available to it in a function called | ||||
<function>bazz</function>.</para> | <function>bazz</function>.</para> | ||||
<para>Sometimes it is useful to be able to see how a function | <para>Sometimes it is useful to be able to see how a function | ||||
was called, as the problem could have occurred a long way up | was called, as the problem could have occurred a long way up | ||||
the call stack in a complex program. <command>bt</command> | the call stack in a complex program. <command>bt</command> | ||||
causes <command>gdb</command> to print out a back-trace of the | causes <command>gdb</command> to print out a back-trace of | ||||
call stack:</para> | the call stack:</para> | ||||
<screen>(gdb) <userinput>bt</userinput> | <screen>(gdb) <userinput>bt</userinput> | ||||
#0 0x164a in bazz (anint=0x5) at temp.c:17 | #0 0x164a in bazz (anint=0x5) at temp.c:17 | ||||
#1 0xefbfd888 in end () | #1 0xefbfd888 in end () | ||||
#2 0x162c in main () at temp.c:11 | #2 0x162c in main () at temp.c:11 | ||||
(gdb)</screen> | (gdb)</screen> | ||||
<para>The <function>end()</function> function is called when a | <para>The <function>end()</function> function is called when a | ||||
Done Inline ActionsI think "the code that calls fork() on the child" is perhaps easier to read than "the code that fork()s the child", but in addition it's also more technically correct. debdrup: I think "the code that calls fork() on the child" is perhaps easier to read than "the code that… | |||||
program crashes; in this case, the <function>bazz()</function> | program crashes; in this case, the | ||||
function was called from <function>main()</function>.</para> | <function>bazz()</function> function was called from | ||||
</sect2> | <function>main()</function>.</para> | ||||
</sect3> | |||||
<sect2> | <sect3> | ||||
<title>Attaching to a Running Program</title> | <title>Attaching to a Running Program with gdb</title> | ||||
<para>One of the neatest features about <command>gdb</command> | <para>One of the neatest features about <command>gdb</command> | ||||
is that it can attach to a program that is already running. | is that it can attach to a program that is already running. | ||||
Of course, that assumes you have sufficient permissions to do | Of course, that assumes you have sufficient permissions to | ||||
so. A common problem is when you are stepping through a | do so. A common problem is when you are stepping through a | ||||
program that forks, and you want to trace the child, but the | program that forks, and you want to trace the child, but the | ||||
debugger will only let you trace the parent.</para> | debugger will only let you trace the parent.</para> | ||||
<para>What you do is start up another <command>gdb</command>, | <para>What you do is start up another <command>gdb</command>, | ||||
use <command>ps</command> to find the process ID for the | use <command>ps</command> to find the process ID for the | ||||
child, and do</para> | child, and do</para> | ||||
<screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen> | <screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen> | ||||
<para>in <command>gdb</command>, and then debug as usual.</para> | <para>in <command>gdb</command>, and then debug as | ||||
usual.</para> | |||||
<para><quote>That is all very well,</quote> you are probably | <para><quote>That is all very well,</quote> you are probably | ||||
thinking, <quote>but by the time I have done that, the child | thinking, <quote>but by the time I have done that, the child | ||||
process will be over the hill and far away</quote>. Fear | process will be over the hill and far away</quote>. Fear | ||||
not, gentle reader, here is how to do it (courtesy of the | not, gentle reader, here is how to do it (courtesy of the | ||||
<command>gdb</command> info pages):</para> | <command>gdb</command> info pages):</para> | ||||
<programlisting><lineannotation>…</lineannotation> | <programlisting><lineannotation>…</lineannotation> | ||||
if ((pid = fork()) < 0) /* _Always_ check this */ | if ((pid = fork()) < 0) /* _Always_ check this */ | ||||
error(); | error(); | ||||
else if (pid == 0) { /* child */ | else if (pid == 0) { /* child */ | ||||
int PauseMode = 1; | int PauseMode = 1; | ||||
while (PauseMode) | while (PauseMode) | ||||
sleep(10); /* Wait until someone attaches to us */ | sleep(10); /* Wait until someone attaches to us */ | ||||
<lineannotation>…</lineannotation> | <lineannotation>…</lineannotation> | ||||
} else { /* parent */ | } else { /* parent */ | ||||
<lineannotation>…</lineannotation></programlisting> | <lineannotation>…</lineannotation></programlisting> | ||||
<para>Now all you have to do is attach to the child, set | <para>Now all you have to do is attach to the child, set | ||||
Done Inline Actionss/to do is/is to/ debdrup: s/to do is/is to/ | |||||
<symbol>PauseMode</symbol> to <literal>0</literal>, and wait | <symbol>PauseMode</symbol> to <literal>0</literal>, and wait | ||||
for the <function>sleep()</function> call to return!</para> | for the <function>sleep()</function> call to return!</para> | ||||
</sect3> | |||||
emasteUnsubmitted Done Inline Actions@bcr it would be nice if we can commit these whitespace fixes independently, first; how best to handle that? emaste: @bcr it would be nice if we can commit these whitespace fixes independently, first; how best to… | |||||
bcrUnsubmitted Done Inline ActionsOnce we have the text we want (i.e. approved), I can give it a whitespace sweep before the commit. This way, we can concentrate on the content for now. bcr: Once we have the text we want (i.e. approved), I can give it a whitespace sweep before the… | |||||
emasteUnsubmitted Done Inline ActionsI mean, it's harder to concentrate on the content because there are these whitespace changes included also., emaste: I mean, it's harder to concentrate on the content because there are these whitespace changes… | |||||
bcrUnsubmitted Done Inline ActionsOh, now I get it. Ah well, I think it's fine if a new-ish submitter does not know (all of) our rules yet. bcr: Oh, now I get it. Ah well, I think it's fine if a new-ish submitter does not know (all of) our… | |||||
pauamma_gundo.comAuthorUnsubmitted Done Inline ActionsOK, I'll undo the whitespace and wordwrap changes, then. pauamma_gundo.com: OK, I'll undo the whitespace and wordwrap changes, then. | |||||
</sect2> | </sect2> | ||||
</sect1> | </sect1> | ||||
<sect1 xml:id="emacs"> | <sect1 xml:id="emacs"> | ||||
<title>Using Emacs as a Development Environment</title> | <title>Using Emacs as a Development Environment</title> | ||||
<sect2> | <sect2> | ||||
<title>Emacs</title> | <title>Emacs</title> | ||||
▲ Show 20 Lines • Show All 651 Lines • Show Last 20 Lines |
Here is a leftover "you".