• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/toolchains/hndtools-armeabi-2013.11/share/doc/arm-arm-none-eabi/html/gdb/
1<html lang="en">
2<head>
3<title>Writing a Frame Filter - Debugging with GDB</title>
4<meta http-equiv="Content-Type" content="text/html">
5<meta name="description" content="Debugging with GDB">
6<meta name="generator" content="makeinfo 4.13">
7<link title="Top" rel="start" href="index.html#Top">
8<link rel="up" href="Python-API.html#Python-API" title="Python API">
9<link rel="prev" href="Frame-Decorator-API.html#Frame-Decorator-API" title="Frame Decorator API">
10<link rel="next" href="Inferiors-In-Python.html#Inferiors-In-Python" title="Inferiors In Python">
11<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
12<!--
13Copyright (C) 1988-2013 Free Software Foundation, Inc.
14
15Permission is granted to copy, distribute and/or modify this document
16under the terms of the GNU Free Documentation License, Version 1.3 or
17any later version published by the Free Software Foundation; with the
18Invariant Sections being ``Free Software'' and ``Free Software Needs
19Free Documentation'', with the Front-Cover Texts being ``A GNU Manual,''
20and with the Back-Cover Texts as in (a) below.
21
22(a) The FSF's Back-Cover Text is: ``You are free to copy and modify
23this GNU Manual.  Buying copies from GNU Press supports the FSF in
24developing GNU and promoting software freedom.''
25-->
26<meta http-equiv="Content-Style-Type" content="text/css">
27<style type="text/css"><!--
28  pre.display { font-family:inherit }
29  pre.format  { font-family:inherit }
30  pre.smalldisplay { font-family:inherit; font-size:smaller }
31  pre.smallformat  { font-family:inherit; font-size:smaller }
32  pre.smallexample { font-size:smaller }
33  pre.smalllisp    { font-size:smaller }
34  span.sc    { font-variant:small-caps }
35  span.roman { font-family:serif; font-weight:normal; } 
36  span.sansserif { font-family:sans-serif; font-weight:normal; } 
37--></style>
38<link rel="stylesheet" type="text/css" href="../cs.css">
39</head>
40<body>
41<div class="node">
42<a name="Writing-a-Frame-Filter"></a>
43<p>
44Next:&nbsp;<a rel="next" accesskey="n" href="Inferiors-In-Python.html#Inferiors-In-Python">Inferiors In Python</a>,
45Previous:&nbsp;<a rel="previous" accesskey="p" href="Frame-Decorator-API.html#Frame-Decorator-API">Frame Decorator API</a>,
46Up:&nbsp;<a rel="up" accesskey="u" href="Python-API.html#Python-API">Python API</a>
47<hr>
48</div>
49
50<h5 class="subsubsection">23.2.2.11 Writing a Frame Filter</h5>
51
52<p><a name="index-writing-a-frame-filter-1897"></a>
53There are three basic elements that a frame filter must implement: it
54must correctly implement the documented interface (see <a href="Frame-Filter-API.html#Frame-Filter-API">Frame Filter API</a>), it must register itself with <span class="sc">gdb</span>, and finally, it must
55decide if it is to work on the data provided by <span class="sc">gdb</span>.  In all
56cases, whether it works on the iterator or not, each frame filter must
57return an iterator.  A bare-bones frame filter follows the pattern in
58the following example.
59
60<pre class="smallexample">     import gdb
61     
62     class FrameFilter():
63     
64         def __init__(self):
65             # Frame filter attribute creation.
66             #
67             # 'name' is the name of the filter that GDB will display.
68             #
69             # 'priority' is the priority of the filter relative to other
70             # filters.
71             #
72             # 'enabled' is a boolean that indicates whether this filter is
73             # enabled and should be executed.
74     
75             self.name = "Foo"
76             self.priority = 100
77             self.enabled = True
78     
79             # Register this frame filter with the global frame_filters
80             # dictionary.
81             gdb.frame_filters[self.name] = self
82     
83         def filter(self, frame_iter):
84             # Just return the iterator.
85             return frame_iter
86</pre>
87   <p>The frame filter in the example above implements the three
88requirements for all frame filters.  It implements the API, self
89registers, and makes a decision on the iterator (in this case, it just
90returns the iterator untouched).
91
92   <p>The first step is attribute creation and assignment, and as shown in
93the comments the filter assigns the following attributes:  <code>name</code>,
94<code>priority</code> and whether the filter should be enabled with the
95<code>enabled</code> attribute.
96
97   <p>The second step is registering the frame filter with the dictionary or
98dictionaries that the frame filter has interest in.  As shown in the
99comments, this filter just registers itself with the global dictionary
100<code>gdb.frame_filters</code>.  As noted earlier, <code>gdb.frame_filters</code>
101is a dictionary that is initialized in the <code>gdb</code> module when
102<span class="sc">gdb</span> starts.  What dictionary a filter registers with is an
103important consideration.  Generally, if a filter is specific to a set
104of code, it should be registered either in the <code>objfile</code> or
105<code>progspace</code> dictionaries as they are specific to the program
106currently loaded in <span class="sc">gdb</span>.  The global dictionary is always
107present in <span class="sc">gdb</span> and is never unloaded.  Any filters registered
108with the global dictionary will exist until <span class="sc">gdb</span> exits.  To
109avoid filters that may conflict, it is generally better to register
110frame filters against the dictionaries that more closely align with
111the usage of the filter currently in question.  See <a href="Python-Auto_002dloading.html#Python-Auto_002dloading">Python Auto-loading</a>, for further information on auto-loading Python scripts.
112
113   <p><span class="sc">gdb</span> takes a hands-off approach to frame filter registration,
114therefore it is the frame filter's responsibility to ensure
115registration has occurred, and that any exceptions are handled
116appropriately.  In particular, you may wish to handle exceptions
117relating to Python dictionary key uniqueness.  It is mandatory that
118the dictionary key is the same as frame filter's <code>name</code>
119attribute.  When a user manages frame filters (see <a href="Frame-Filter-Management.html#Frame-Filter-Management">Frame Filter Management</a>), the names <span class="sc">gdb</span> will display are those contained
120in the <code>name</code> attribute.
121
122   <p>The final step of this example is the implementation of the
123<code>filter</code> method.  As shown in the example comments, we define the
124<code>filter</code> method and note that the method must take an iterator,
125and also must return an iterator.  In this bare-bones example, the
126frame filter is not very useful as it just returns the iterator
127untouched.  However this is a valid operation for frame filters that
128have the <code>enabled</code> attribute set, but decide not to operate on
129any frames.
130
131   <p>In the next example, the frame filter operates on all frames and
132utilizes a frame decorator to perform some work on the frames. 
133See <a href="Frame-Decorator-API.html#Frame-Decorator-API">Frame Decorator API</a>, for further information on the frame
134decorator interface.
135
136   <p>This example works on inlined frames.  It highlights frames which are
137inlined by tagging them with an &ldquo;[inlined]&rdquo; tag.  By applying a
138frame decorator to all frames with the Python <code>itertools imap</code>
139method, the example defers actions to the frame decorator.  Frame
140decorators are only processed when <span class="sc">gdb</span> prints the backtrace.
141
142   <p>This introduces a new decision making topic: whether to perform
143decision making operations at the filtering step, or at the printing
144step.  In this example's approach, it does not perform any filtering
145decisions at the filtering step beyond mapping a frame decorator to
146each frame.  This allows the actual decision making to be performed
147when each frame is printed.  This is an important consideration, and
148well worth reflecting upon when designing a frame filter.  An issue
149that frame filters should avoid is unwinding the stack if possible. 
150Some stacks can run very deep, into the tens of thousands in some
151cases.  To search every frame to determine if it is inlined ahead of
152time may be too expensive at the filtering step.  The frame filter
153cannot know how many frames it has to iterate over, and it would have
154to iterate through them all.  This ends up duplicating effort as
155<span class="sc">gdb</span> performs this iteration when it prints the frames.
156
157   <p>In this example decision making can be deferred to the printing step. 
158As each frame is printed, the frame decorator can examine each frame
159in turn when <span class="sc">gdb</span> iterates.  From a performance viewpoint,
160this is the most appropriate decision to make as it avoids duplicating
161the effort that the printing step would undertake anyway.  Also, if
162there are many frame filters unwinding the stack during filtering, it
163can substantially delay the printing of the backtrace which will
164result in large memory usage, and a poor user experience.
165
166<pre class="smallexample">     class InlineFilter():
167     
168         def __init__(self):
169             self.name = "InlinedFrameFilter"
170             self.priority = 100
171             self.enabled = True
172             gdb.frame_filters[self.name] = self
173     
174         def filter(self, frame_iter):
175             frame_iter = itertools.imap(InlinedFrameDecorator,
176                                         frame_iter)
177             return frame_iter
178</pre>
179   <p>This frame filter is somewhat similar to the earlier example, except
180that the <code>filter</code> method applies a frame decorator object called
181<code>InlinedFrameDecorator</code> to each element in the iterator.  The
182<code>imap</code> Python method is light-weight.  It does not proactively
183iterate over the iterator, but rather creates a new iterator which
184wraps the existing one.
185
186   <p>Below is the frame decorator for this example.
187
188<pre class="smallexample">     class InlinedFrameDecorator(FrameDecorator):
189     
190         def __init__(self, fobj):
191             super(InlinedFrameDecorator, self).__init__(fobj)
192     
193         def function(self):
194             frame = fobj.inferior_frame()
195             name = str(frame.name())
196     
197             if frame.type() == gdb.INLINE_FRAME:
198                 name = name + " [inlined]"
199     
200             return name
201</pre>
202   <p>This frame decorator only defines and overrides the <code>function</code>
203method.  It lets the supplied <code>FrameDecorator</code>, which is shipped
204with <span class="sc">gdb</span>, perform the other work associated with printing
205this frame.
206
207   <p>The combination of these two objects create this output from a
208backtrace:
209
210<pre class="smallexample">     #0  0x004004e0 in bar () at inline.c:11
211     #1  0x00400566 in max [inlined] (b=6, a=12) at inline.c:21
212     #2  0x00400566 in main () at inline.c:31
213</pre>
214   <p>So in the case of this example, a frame decorator is applied to all
215frames, regardless of whether they may be inlined or not.  As
216<span class="sc">gdb</span> iterates over the iterator produced by the frame filters,
217<span class="sc">gdb</span> executes each frame decorator which then makes a decision
218on what to print in the <code>function</code> callback.  Using a strategy
219like this is a way to defer decisions on the frame content to printing
220time.
221
222<h4 class="subheading">Eliding Frames</h4>
223
224<p>It might be that the above example is not desirable for representing
225inlined frames, and a hierarchical approach may be preferred.  If we
226want to hierarchically represent frames, the <code>elided</code> frame
227decorator interface might be preferable.
228
229   <p>This example approaches the issue with the <code>elided</code> method.  This
230example is quite long, but very simplistic.  It is out-of-scope for
231this section to write a complete example that comprehensively covers
232all approaches of finding and printing inlined frames.  However, this
233example illustrates the approach an author might use.
234
235   <p>This example comprises of three sections.
236
237<pre class="smallexample">     class InlineFrameFilter():
238     
239         def __init__(self):
240             self.name = "InlinedFrameFilter"
241             self.priority = 100
242             self.enabled = True
243             gdb.frame_filters[self.name] = self
244     
245         def filter(self, frame_iter):
246             return ElidingInlineIterator(frame_iter)
247</pre>
248   <p>This frame filter is very similar to the other examples.  The only
249difference is this frame filter is wrapping the iterator provided to
250it (<code>frame_iter</code>) with a custom iterator called
251<code>ElidingInlineIterator</code>.  This again defers actions to when
252<span class="sc">gdb</span> prints the backtrace, as the iterator is not traversed
253until printing.
254
255   <p>The iterator for this example is as follows.  It is in this section of
256the example where decisions are made on the content of the backtrace.
257
258<pre class="smallexample">     class ElidingInlineIterator:
259         def __init__(self, ii):
260             self.input_iterator = ii
261     
262         def __iter__(self):
263             return self
264     
265         def next(self):
266             frame = next(self.input_iterator)
267     
268             if frame.inferior_frame().type() != gdb.INLINE_FRAME:
269                 return frame
270     
271             try:
272                 eliding_frame = next(self.input_iterator)
273             except StopIteration:
274                 return frame
275             return ElidingFrameDecorator(eliding_frame, [frame])
276</pre>
277   <p>This iterator implements the Python iterator protocol.  When the
278<code>next</code> function is called (when <span class="sc">gdb</span> prints each frame),
279the iterator checks if this frame decorator, <code>frame</code>, is wrapping
280an inlined frame.  If it is not, it returns the existing frame decorator
281untouched.  If it is wrapping an inlined frame, it assumes that the
282inlined frame was contained within the next oldest frame,
283<code>eliding_frame</code>, which it fetches.  It then creates and returns a
284frame decorator, <code>ElidingFrameDecorator</code>, which contains both the
285elided frame, and the eliding frame.
286
287<pre class="smallexample">     class ElidingInlineDecorator(FrameDecorator):
288     
289         def __init__(self, frame, elided_frames):
290             super(ElidingInlineDecorator, self).__init__(frame)
291             self.frame = frame
292             self.elided_frames = elided_frames
293     
294         def elided(self):
295             return iter(self.elided_frames)
296</pre>
297   <p>This frame decorator overrides one function and returns the inlined
298frame in the <code>elided</code> method.  As before it lets
299<code>FrameDecorator</code> do the rest of the work involved in printing
300this frame.  This produces the following output.
301
302<pre class="smallexample">     #0  0x004004e0 in bar () at inline.c:11
303     #2  0x00400529 in main () at inline.c:25
304         #1  0x00400529 in max (b=6, a=12) at inline.c:15
305</pre>
306   <p>In that output, <code>max</code> which has been inlined into <code>main</code> is
307printed hierarchically.  Another approach would be to combine the
308<code>function</code> method, and the <code>elided</code> method to both print a
309marker in the inlined frame, and also show the hierarchical
310relationship.
311
312   </body></html>
313
314