| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| <html> |
| <!-- Copyright (C) 1988-2015 Free Software Foundation, Inc. |
| |
| Permission is granted to copy, distribute and/or modify this document |
| under the terms of the GNU Free Documentation License, Version 1.3 or |
| any later version published by the Free Software Foundation; with the |
| Invariant Sections being "Free Software" and "Free Software Needs |
| Free Documentation", with the Front-Cover Texts being "A GNU Manual," |
| and with the Back-Cover Texts as in (a) below. |
| |
| (a) The FSF's Back-Cover Text is: "You are free to copy and modify |
| this GNU Manual. Buying copies from GNU Press supports the FSF in |
| developing GNU and promoting software freedom." --> |
| <!-- Created by GNU Texinfo 5.2, http://www.gnu.org/software/texinfo/ --> |
| <head> |
| <title>Debugging with GDB: Tail Call Frames</title> |
| |
| <meta name="description" content="Debugging with GDB: Tail Call Frames"> |
| <meta name="keywords" content="Debugging with GDB: Tail Call Frames"> |
| <meta name="resource-type" content="document"> |
| <meta name="distribution" content="global"> |
| <meta name="Generator" content="makeinfo"> |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
| <link href="index.html#Top" rel="start" title="Top"> |
| <link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index"> |
| <link href="index.html#SEC_Contents" rel="contents" title="Table of Contents"> |
| <link href="Optimized-Code.html#Optimized-Code" rel="up" title="Optimized Code"> |
| <link href="Macros.html#Macros" rel="next" title="Macros"> |
| <link href="Inline-Functions.html#Inline-Functions" rel="prev" title="Inline Functions"> |
| <style type="text/css"> |
| <!-- |
| a.summary-letter {text-decoration: none} |
| blockquote.smallquotation {font-size: smaller} |
| div.display {margin-left: 3.2em} |
| div.example {margin-left: 3.2em} |
| div.indentedblock {margin-left: 3.2em} |
| div.lisp {margin-left: 3.2em} |
| div.smalldisplay {margin-left: 3.2em} |
| div.smallexample {margin-left: 3.2em} |
| div.smallindentedblock {margin-left: 3.2em; font-size: smaller} |
| div.smalllisp {margin-left: 3.2em} |
| kbd {font-style:oblique} |
| pre.display {font-family: inherit} |
| pre.format {font-family: inherit} |
| pre.menu-comment {font-family: serif} |
| pre.menu-preformatted {font-family: serif} |
| pre.smalldisplay {font-family: inherit; font-size: smaller} |
| pre.smallexample {font-size: smaller} |
| pre.smallformat {font-family: inherit; font-size: smaller} |
| pre.smalllisp {font-size: smaller} |
| span.nocodebreak {white-space:nowrap} |
| span.nolinebreak {white-space:nowrap} |
| span.roman {font-family:serif; font-weight:normal} |
| span.sansserif {font-family:sans-serif; font-weight:normal} |
| ul.no-bullet {list-style: none} |
| --> |
| </style> |
| |
| |
| </head> |
| |
| <body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"> |
| <a name="Tail-Call-Frames"></a> |
| <div class="header"> |
| <p> |
| Previous: <a href="Inline-Functions.html#Inline-Functions" accesskey="p" rel="prev">Inline Functions</a>, Up: <a href="Optimized-Code.html#Optimized-Code" accesskey="u" rel="up">Optimized Code</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p> |
| </div> |
| <hr> |
| <a name="Tail-Call-Frames-1"></a> |
| <h3 class="section">11.2 Tail Call Frames</h3> |
| <a name="index-tail-call-frames_002c-debugging"></a> |
| |
| <p>Function <code>B</code> can call function <code>C</code> in its very last statement. In |
| unoptimized compilation the call of <code>C</code> is immediately followed by return |
| instruction at the end of <code>B</code> code. Optimizing compiler may replace the |
| call and return in function <code>B</code> into one jump to function <code>C</code> |
| instead. Such use of a jump instruction is called <em>tail call</em>. |
| </p> |
| <p>During execution of function <code>C</code>, there will be no indication in the |
| function call stack frames that it was tail-called from <code>B</code>. If function |
| <code>A</code> regularly calls function <code>B</code> which tail-calls function <code>C</code>, |
| then <small>GDB</small> will see <code>A</code> as the caller of <code>C</code>. However, in |
| some cases <small>GDB</small> can determine that <code>C</code> was tail-called from |
| <code>B</code>, and it will then create fictitious call frame for that, with the |
| return address set up as if <code>B</code> called <code>C</code> normally. |
| </p> |
| <p>This functionality is currently supported only by DWARF 2 debugging format and |
| the compiler has to produce ‘<samp>DW_TAG_GNU_call_site</samp>’ tags. With |
| <small>GCC</small>, you need to specify <samp>-O -g</samp> during compilation, to get |
| this information. |
| </p> |
| <p><kbd>info frame</kbd> command (see <a href="Frame-Info.html#Frame-Info">Frame Info</a>) will indicate the tail call frame |
| kind by text <code>tail call frame</code> such as in this sample <small>GDB</small> output: |
| </p> |
| <div class="smallexample"> |
| <pre class="smallexample">(gdb) x/i $pc - 2 |
| 0x40066b <b(int, double)+11>: jmp 0x400640 <c(int, double)> |
| (gdb) info frame |
| Stack level 1, frame at 0x7fffffffda30: |
| rip = 0x40066d in b (amd64-entry-value.cc:59); saved rip 0x4004c5 |
| tail call frame, caller of frame at 0x7fffffffda30 |
| source language c++. |
| Arglist at unknown address. |
| Locals at unknown address, Previous frame's sp is 0x7fffffffda30 |
| </pre></div> |
| |
| <p>The detection of all the possible code path executions can find them ambiguous. |
| There is no execution history stored (possible <a href="Reverse-Execution.html#Reverse-Execution">Reverse Execution</a> is never |
| used for this purpose) and the last known caller could have reached the known |
| callee by multiple different jump sequences. In such case <small>GDB</small> still |
| tries to show at least all the unambiguous top tail callers and all the |
| unambiguous bottom tail calees, if any. |
| </p> |
| <dl compact="compact"> |
| <dd><a name="set-debug-entry_002dvalues"></a></dd> |
| <dt><code>set debug entry-values</code></dt> |
| <dd><a name="index-set-debug-entry_002dvalues"></a> |
| <p>When set to on, enables printing of analysis messages for both frame argument |
| values at function entry and tail calls. It will show all the possible valid |
| tail calls code paths it has considered. It will also print the intersection |
| of them with the final unambiguous (possibly partial or even empty) code path |
| result. |
| </p> |
| </dd> |
| <dt><code>show debug entry-values</code></dt> |
| <dd><a name="index-show-debug-entry_002dvalues"></a> |
| <p>Show the current state of analysis messages printing for both frame argument |
| values at function entry and tail calls. |
| </p></dd> |
| </dl> |
| |
| <p>The analysis messages for tail calls can for example show why the virtual tail |
| call frame for function <code>c</code> has not been recognized (due to the indirect |
| reference by variable <code>x</code>): |
| </p> |
| <div class="smallexample"> |
| <pre class="smallexample">static void __attribute__((noinline, noclone)) c (void); |
| void (*x) (void) = c; |
| static void __attribute__((noinline, noclone)) a (void) { x++; } |
| static void __attribute__((noinline, noclone)) c (void) { a (); } |
| int main (void) { x (); return 0; } |
| |
| Breakpoint 1, DW_OP_GNU_entry_value resolving cannot find |
| DW_TAG_GNU_call_site 0x40039a in main |
| a () at t.c:3 |
| 3 static void __attribute__((noinline, noclone)) a (void) { x++; } |
| (gdb) bt |
| #0 a () at t.c:3 |
| #1 0x000000000040039a in main () at t.c:5 |
| </pre></div> |
| |
| <p>Another possibility is an ambiguous virtual tail call frames resolution: |
| </p> |
| <div class="smallexample"> |
| <pre class="smallexample">int i; |
| static void __attribute__((noinline, noclone)) f (void) { i++; } |
| static void __attribute__((noinline, noclone)) e (void) { f (); } |
| static void __attribute__((noinline, noclone)) d (void) { f (); } |
| static void __attribute__((noinline, noclone)) c (void) { d (); } |
| static void __attribute__((noinline, noclone)) b (void) |
| { if (i) c (); else e (); } |
| static void __attribute__((noinline, noclone)) a (void) { b (); } |
| int main (void) { a (); return 0; } |
| |
| tailcall: initial: 0x4004d2(a) 0x4004ce(b) 0x4004b2(c) 0x4004a2(d) |
| tailcall: compare: 0x4004d2(a) 0x4004cc(b) 0x400492(e) |
| tailcall: reduced: 0x4004d2(a) | |
| (gdb) bt |
| #0 f () at t.c:2 |
| #1 0x00000000004004d2 in a () at t.c:8 |
| #2 0x0000000000400395 in main () at t.c:9 |
| </pre></div> |
| |
| |
| |
| <p>Frames #0 and #2 are real, #1 is a virtual tail call frame. |
| The code can have possible execution paths <code>main→a→b→c→d→f</code> or |
| <code>main→a→b→e→f</code>, <small>GDB</small> cannot find which one from the inferior state. |
| </p> |
| <p><code>initial:</code> state shows some random possible calling sequence <small>GDB</small> |
| has found. It then finds another possible calling sequcen - that one is |
| prefixed by <code>compare:</code>. The non-ambiguous intersection of these two is |
| printed as the <code>reduced:</code> calling sequence. That one could have many |
| futher <code>compare:</code> and <code>reduced:</code> statements as long as there remain |
| any non-ambiguous sequence entries. |
| </p> |
| <p>For the frame of function <code>b</code> in both cases there are different possible |
| <code>$pc</code> values (<code>0x4004cc</code> or <code>0x4004ce</code>), therefore this frame is |
| also ambigous. The only non-ambiguous frame is the one for function <code>a</code>, |
| therefore this one is displayed to the user while the ambiguous frames are |
| omitted. |
| </p> |
| <p>There can be also reasons why printing of frame argument values at function |
| entry may fail: |
| </p> |
| <div class="smallexample"> |
| <pre class="smallexample">int v; |
| static void __attribute__((noinline, noclone)) c (int i) { v++; } |
| static void __attribute__((noinline, noclone)) a (int i); |
| static void __attribute__((noinline, noclone)) b (int i) { a (i); } |
| static void __attribute__((noinline, noclone)) a (int i) |
| { if (i) b (i - 1); else c (0); } |
| int main (void) { a (5); return 0; } |
| |
| (gdb) bt |
| #0 c (i=i@entry=0) at t.c:2 |
| #1 0x0000000000400428 in a (DW_OP_GNU_entry_value resolving has found |
| function "a" at 0x400420 can call itself via tail calls |
| i=<optimized out>) at t.c:6 |
| #2 0x000000000040036e in main () at t.c:7 |
| </pre></div> |
| |
| <p><small>GDB</small> cannot find out from the inferior state if and how many times did |
| function <code>a</code> call itself (via function <code>b</code>) as these calls would be |
| tail calls. Such tail calls would modify thue <code>i</code> variable, therefore |
| <small>GDB</small> cannot be sure the value it knows would be right - <small>GDB</small> |
| prints <code><optimized out></code> instead. |
| </p> |
| <hr> |
| <div class="header"> |
| <p> |
| Previous: <a href="Inline-Functions.html#Inline-Functions" accesskey="p" rel="prev">Inline Functions</a>, Up: <a href="Optimized-Code.html#Optimized-Code" accesskey="u" rel="up">Optimized Code</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p> |
| </div> |
| |
| |
| |
| </body> |
| </html> |