1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<!-- Copyright (C) 1988-2021 Free Software Foundation, Inc. 4 5Permission is granted to copy, distribute and/or modify this document 6under the terms of the GNU Free Documentation License, Version 1.3 or 7any later version published by the Free Software Foundation; with the 8Invariant Sections being "Free Software" and "Free Software Needs 9Free Documentation", with the Front-Cover Texts being "A GNU Manual," 10and with the Back-Cover Texts as in (a) below. 11 12(a) The FSF's Back-Cover Text is: "You are free to copy and modify 13this GNU Manual. Buying copies from GNU Press supports the FSF in 14developing GNU and promoting software freedom." --> 15<!-- Created by GNU Texinfo 5.1, http://www.gnu.org/software/texinfo/ --> 16<head> 17<title>Debugging with GDB: Unwinding Frames in Python</title> 18 19<meta name="description" content="Debugging with GDB: Unwinding Frames in Python"> 20<meta name="keywords" content="Debugging with GDB: Unwinding Frames in Python"> 21<meta name="resource-type" content="document"> 22<meta name="distribution" content="global"> 23<meta name="Generator" content="makeinfo"> 24<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 25<link href="index.html#Top" rel="start" title="Top"> 26<link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index"> 27<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents"> 28<link href="Python-API.html#Python-API" rel="up" title="Python API"> 29<link href="Xmethods-In-Python.html#Xmethods-In-Python" rel="next" title="Xmethods In Python"> 30<link href="Writing-a-Frame-Filter.html#Writing-a-Frame-Filter" rel="previous" title="Writing a Frame Filter"> 31<style type="text/css"> 32<!-- 33a.summary-letter {text-decoration: none} 34blockquote.smallquotation {font-size: smaller} 35div.display {margin-left: 3.2em} 36div.example {margin-left: 3.2em} 37div.indentedblock {margin-left: 3.2em} 38div.lisp {margin-left: 3.2em} 39div.smalldisplay {margin-left: 3.2em} 40div.smallexample {margin-left: 3.2em} 41div.smallindentedblock {margin-left: 3.2em; font-size: smaller} 42div.smalllisp {margin-left: 3.2em} 43kbd {font-style:oblique} 44pre.display {font-family: inherit} 45pre.format {font-family: inherit} 46pre.menu-comment {font-family: serif} 47pre.menu-preformatted {font-family: serif} 48pre.smalldisplay {font-family: inherit; font-size: smaller} 49pre.smallexample {font-size: smaller} 50pre.smallformat {font-family: inherit; font-size: smaller} 51pre.smalllisp {font-size: smaller} 52span.nocodebreak {white-space:nowrap} 53span.nolinebreak {white-space:nowrap} 54span.roman {font-family:serif; font-weight:normal} 55span.sansserif {font-family:sans-serif; font-weight:normal} 56ul.no-bullet {list-style: none} 57--> 58</style> 59 60 61</head> 62 63<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000"> 64<a name="Unwinding-Frames-in-Python"></a> 65<div class="header"> 66<p> 67Next: <a href="Xmethods-In-Python.html#Xmethods-In-Python" accesskey="n" rel="next">Xmethods In Python</a>, Previous: <a href="Writing-a-Frame-Filter.html#Writing-a-Frame-Filter" accesskey="p" rel="previous">Writing a Frame Filter</a>, Up: <a href="Python-API.html#Python-API" accesskey="u" rel="up">Python API</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> 68</div> 69<hr> 70<a name="Unwinding-Frames-in-Python-1"></a> 71<h4 class="subsubsection">23.2.2.12 Unwinding Frames in Python</h4> 72<a name="index-unwinding-frames-in-Python"></a> 73 74<p>In <small>GDB</small> terminology “unwinding” is the process of finding 75the previous frame (that is, caller’s) from the current one. An 76unwinder has three methods. The first one checks if it can handle 77given frame (“sniff” it). For the frames it can sniff an unwinder 78provides two additional methods: it can return frame’s ID, and it can 79fetch registers from the previous frame. A running <small>GDB</small> 80mantains a list of the unwinders and calls each unwinder’s sniffer in 81turn until it finds the one that recognizes the current frame. There 82is an API to register an unwinder. 83</p> 84<p>The unwinders that come with <small>GDB</small> handle standard frames. 85However, mixed language applications (for example, an application 86running Java Virtual Machine) sometimes use frame layouts that cannot 87be handled by the <small>GDB</small> unwinders. You can write Python code 88that can handle such custom frames. 89</p> 90<p>You implement a frame unwinder in Python as a class with which has two 91attributes, <code>name</code> and <code>enabled</code>, with obvious meanings, and 92a single method <code>__call__</code>, which examines a given frame and 93returns an object (an instance of <code>gdb.UnwindInfo class)</code> 94describing it. If an unwinder does not recognize a frame, it should 95return <code>None</code>. The code in <small>GDB</small> that enables writing 96unwinders in Python uses this object to return frame’s ID and previous 97frame registers when <small>GDB</small> core asks for them. 98</p> 99<p>An unwinder should do as little work as possible. Some otherwise 100innocuous operations can cause problems (even crashes, as this code is 101not not well-hardened yet). For example, making an inferior call from 102an unwinder is unadvisable, as an inferior call will reset 103<small>GDB</small>’s stack unwinding process, potentially causing re-entrant 104unwinding. 105</p> 106<a name="Unwinder-Input"></a> 107<h4 class="subheading">Unwinder Input</h4> 108 109<p>An object passed to an unwinder (a <code>gdb.PendingFrame</code> instance) 110provides a method to read frame’s registers: 111</p> 112<dl> 113<dt><a name="index-PendingFrame_002eread_005fregister"></a>Function: <strong>PendingFrame.read_register</strong> <em>(reg)</em></dt> 114<dd><p>This method returns the contents of the register <var>reg</var> in the 115frame as a <code>gdb.Value</code> object. For a description of the 116acceptable values of <var>reg</var> see 117<a href="Frames-In-Python.html#gdbpy_005fframe_005fread_005fregister">Frame.read_register</a>. If <var>reg</var> 118does not name a register for the current architecture, this method 119will throw an exception. 120</p> 121<p>Note that this method will always return a <code>gdb.Value</code> for a 122valid register name. This does not mean that the value will be valid. 123For example, you may request a register that an earlier unwinder could 124not unwind—the value will be unavailable. Instead, the 125<code>gdb.Value</code> returned from this method will be lazy; that is, its 126underlying bits will not be fetched until it is first used. So, 127attempting to use such a value will cause an exception at the point of 128use. 129</p> 130<p>The type of the returned <code>gdb.Value</code> depends on the register and 131the architecture. It is common for registers to have a scalar type, 132like <code>long long</code>; but many other types are possible, such as 133pointer, pointer-to-function, floating point or vector types. 134</p></dd></dl> 135 136<p>It also provides a factory method to create a <code>gdb.UnwindInfo</code> 137instance to be returned to <small>GDB</small>: 138</p> 139<dl> 140<dt><a name="index-PendingFrame_002ecreate_005funwind_005finfo"></a>Function: <strong>PendingFrame.create_unwind_info</strong> <em>(frame_id)</em></dt> 141<dd><p>Returns a new <code>gdb.UnwindInfo</code> instance identified by given 142<var>frame_id</var>. The argument is used to build <small>GDB</small>’s frame ID 143using one of functions provided by <small>GDB</small>. <var>frame_id</var>’s attributes 144determine which function will be used, as follows: 145</p> 146<dl compact="compact"> 147<dt><code>sp, pc</code></dt> 148<dd><p>The frame is identified by the given stack address and PC. The stack 149address must be chosen so that it is constant throughout the lifetime 150of the frame, so a typical choice is the value of the stack pointer at 151the start of the function—in the DWARF standard, this would be the 152“Call Frame Address”. 153</p> 154<p>This is the most common case by far. The other cases are documented 155for completeness but are only useful in specialized situations. 156</p> 157</dd> 158<dt><code>sp, pc, special</code></dt> 159<dd><p>The frame is identified by the stack address, the PC, and a 160“special” address. The special address is used on architectures 161that can have frames that do not change the stack, but which are still 162distinct, for example the IA-64, which has a second stack for 163registers. Both <var>sp</var> and <var>special</var> must be constant 164throughout the lifetime of the frame. 165</p> 166</dd> 167<dt><code>sp</code></dt> 168<dd><p>The frame is identified by the stack address only. Any other stack 169frame with a matching <var>sp</var> will be considered to match this frame. 170Inside gdb, this is called a “wild frame”. You will never need 171this. 172</p></dd> 173</dl> 174 175<p>Each attribute value should be an instance of <code>gdb.Value</code>. 176</p> 177</dd></dl> 178 179<dl> 180<dt><a name="index-PendingFrame_002earchitecture"></a>Function: <strong>PendingFrame.architecture</strong> <em>()</em></dt> 181<dd><p>Return the <code>gdb.Architecture</code> (see <a href="Architectures-In-Python.html#Architectures-In-Python">Architectures In Python</a>) 182for this <code>gdb.PendingFrame</code>. This represents the architecture of 183the particular frame being unwound. 184</p></dd></dl> 185 186<a name="Unwinder-Output_003a-UnwindInfo"></a> 187<h4 class="subheading">Unwinder Output: UnwindInfo</h4> 188 189<p>Use <code>PendingFrame.create_unwind_info</code> method described above to 190create a <code>gdb.UnwindInfo</code> instance. Use the following method to 191specify caller registers that have been saved in this frame: 192</p> 193<dl> 194<dt><a name="index-gdb_002eUnwindInfo_002eadd_005fsaved_005fregister"></a>Function: <strong>gdb.UnwindInfo.add_saved_register</strong> <em>(reg, value)</em></dt> 195<dd><p><var>reg</var> identifies the register, for a description of the acceptable 196values see <a href="Frames-In-Python.html#gdbpy_005fframe_005fread_005fregister">Frame.read_register</a>. 197<var>value</var> is a register value (a <code>gdb.Value</code> object). 198</p></dd></dl> 199 200<a name="Unwinder-Skeleton-Code"></a> 201<h4 class="subheading">Unwinder Skeleton Code</h4> 202 203<p><small>GDB</small> comes with the module containing the base <code>Unwinder</code> 204class. Derive your unwinder class from it and structure the code as 205follows: 206</p> 207<div class="smallexample"> 208<pre class="smallexample">from gdb.unwinders import Unwinder 209 210class FrameId(object): 211 def __init__(self, sp, pc): 212 self.sp = sp 213 self.pc = pc 214 215 216class MyUnwinder(Unwinder): 217 def __init__(....): 218 super(MyUnwinder, self).__init___(<expects unwinder name argument>) 219 220 def __call__(pending_frame): 221 if not <we recognize frame>: 222 return None 223 # Create UnwindInfo. Usually the frame is identified by the stack 224 # pointer and the program counter. 225 sp = pending_frame.read_register(<SP number>) 226 pc = pending_frame.read_register(<PC number>) 227 unwind_info = pending_frame.create_unwind_info(FrameId(sp, pc)) 228 229 # Find the values of the registers in the caller's frame and 230 # save them in the result: 231 unwind_info.add_saved_register(<register>, <value>) 232 .... 233 234 # Return the result: 235 return unwind_info 236 237</pre></div> 238 239<a name="Registering-a-Unwinder"></a> 240<h4 class="subheading">Registering a Unwinder</h4> 241 242<p>An object file, a program space, and the <small>GDB</small> proper can have 243unwinders registered with it. 244</p> 245<p>The <code>gdb.unwinders</code> module provides the function to register a 246unwinder: 247</p> 248<dl> 249<dt><a name="index-gdb_002eunwinder_002eregister_005funwinder"></a>Function: <strong>gdb.unwinder.register_unwinder</strong> <em>(locus, unwinder, replace=False)</em></dt> 250<dd><p><var>locus</var> is specifies an object file or a program space to which 251<var>unwinder</var> is added. Passing <code>None</code> or <code>gdb</code> adds 252<var>unwinder</var> to the <small>GDB</small>’s global unwinder list. The newly 253added <var>unwinder</var> will be called before any other unwinder from the 254same locus. Two unwinders in the same locus cannot have the same 255name. An attempt to add a unwinder with already existing name raises 256an exception unless <var>replace</var> is <code>True</code>, in which case the 257old unwinder is deleted. 258</p></dd></dl> 259 260<a name="Unwinder-Precedence"></a> 261<h4 class="subheading">Unwinder Precedence</h4> 262 263<p><small>GDB</small> first calls the unwinders from all the object files in no 264particular order, then the unwinders from the current program space, 265and finally the unwinders from <small>GDB</small>. 266</p> 267<hr> 268<div class="header"> 269<p> 270Next: <a href="Xmethods-In-Python.html#Xmethods-In-Python" accesskey="n" rel="next">Xmethods In Python</a>, Previous: <a href="Writing-a-Frame-Filter.html#Writing-a-Frame-Filter" accesskey="p" rel="previous">Writing a Frame Filter</a>, Up: <a href="Python-API.html#Python-API" accesskey="u" rel="up">Python API</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> 271</div> 272 273 274 275</body> 276</html> 277