diff options
author | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
commit | abdaadbcae30fe0c9a66c7516798279fdfd97750 (patch) | |
tree | 00a54a6e25601e43876d03c1a4a12a749d4a914c /share/doc/gdb/Tail-Call-Frames.html |
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
Change-Id: I7303388733328cd98ab9aa3c30236db67f2e9e9c
Diffstat (limited to 'share/doc/gdb/Tail-Call-Frames.html')
-rw-r--r-- | share/doc/gdb/Tail-Call-Frames.html | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/share/doc/gdb/Tail-Call-Frames.html b/share/doc/gdb/Tail-Call-Frames.html new file mode 100644 index 0000000..9d7364a --- /dev/null +++ b/share/doc/gdb/Tail-Call-Frames.html @@ -0,0 +1,229 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<!-- Copyright (C) 1988-2023 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.1, 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="previous" 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="previous">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_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_entry_value resolving cannot find +DW_TAG_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 sequence - 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 +further <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 ambiguous. 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_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 the <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="previous">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> |