Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Side by Side Diff: experimental/visual_studio_plugin/third_party/breakpad/common/dwarf/dwarf2diehandler.h

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // -*- mode: c++ -*-
2
3 // Copyright (c) 2010 Google Inc. All Rights Reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
32
33 // dwarf2reader::CompilationUnit is a simple and direct parser for
34 // DWARF data, but its handler interface is not convenient to use. In
35 // particular:
36 //
37 // - CompilationUnit calls Dwarf2Handler's member functions to report
38 // every attribute's value, regardless of what sort of DIE it is.
39 // As a result, the ProcessAttributeX functions end up looking like
40 // this:
41 //
42 // switch (parent_die_tag) {
43 // case DW_TAG_x:
44 // switch (attribute_name) {
45 // case DW_AT_y:
46 // handle attribute y of DIE type x
47 // ...
48 // } break;
49 // ...
50 // }
51 //
52 // In C++ it's much nicer to use virtual function dispatch to find
53 // the right code for a given case than to switch on the DIE tag
54 // like this.
55 //
56 // - Processing different kinds of DIEs requires different sets of
57 // data: lexical block DIEs have start and end addresses, but struct
58 // type DIEs don't. It would be nice to be able to have separate
59 // handler classes for separate kinds of DIEs, each with the members
60 // appropriate to its role, instead of having one handler class that
61 // needs to hold data for every DIE type.
62 //
63 // - There should be a separate instance of the appropriate handler
64 // class for each DIE, instead of a single object with tables
65 // tracking all the dies in the compilation unit.
66 //
67 // - It's not convenient to take some action after all a DIE's
68 // attributes have been seen, but before visiting any of its
69 // children. The only indication you have that a DIE's attribute
70 // list is complete is that you get either a StartDIE or an EndDIE
71 // call.
72 //
73 // - It's not convenient to make use of the tree structure of the
74 // DIEs. Skipping all the children of a given die requires
75 // maintaining state and returning false from StartDIE until we get
76 // an EndDIE call with the appropriate offset.
77 //
78 // This interface tries to take care of all that. (You're shocked, I'm sure.)
79 //
80 // Using the classes here, you provide an initial handler for the root
81 // DIE of the compilation unit. Each handler receives its DIE's
82 // attributes, and provides fresh handler objects for children of
83 // interest, if any. The three classes are:
84 //
85 // - DIEHandler: the base class for your DIE-type-specific handler
86 // classes.
87 //
88 // - RootDIEHandler: derived from DIEHandler, the base class for your
89 // root DIE handler class.
90 //
91 // - DIEDispatcher: derived from Dwarf2Handler, an instance of this
92 // invokes your DIE-type-specific handler objects.
93 //
94 // In detail:
95 //
96 // - Define handler classes specialized for the DIE types you're
97 // interested in. These handler classes must inherit from
98 // DIEHandler. Thus:
99 //
100 // class My_DW_TAG_X_Handler: public DIEHandler { ... };
101 // class My_DW_TAG_Y_Handler: public DIEHandler { ... };
102 //
103 // DIEHandler subclasses needn't correspond exactly to single DIE
104 // types, as shown here; the point is that you can have several
105 // different classes appropriate to different kinds of DIEs.
106 //
107 // - In particular, define a handler class for the compilation
108 // unit's root DIE, that inherits from RootDIEHandler:
109 //
110 // class My_DW_TAG_compile_unit_Handler: public RootDIEHandler { ... };
111 //
112 // RootDIEHandler inherits from DIEHandler, adding a few additional
113 // member functions for examining the compilation unit as a whole,
114 // and other quirks of rootness.
115 //
116 // - Then, create a DIEDispatcher instance, passing it an instance of
117 // your root DIE handler class, and use that DIEDispatcher as the
118 // dwarf2reader::CompilationUnit's handler:
119 //
120 // My_DW_TAG_compile_unit_Handler root_die_handler(...);
121 // DIEDispatcher die_dispatcher(&root_die_handler);
122 // CompilationUnit reader(sections, offset, bytereader, &die_dispatcher);
123 //
124 // Here, 'die_dispatcher' acts as a shim between 'reader' and the
125 // various DIE-specific handlers you have defined.
126 //
127 // - When you call reader.Start(), die_dispatcher behaves as follows,
128 // starting with your root die handler and the compilation unit's
129 // root DIE:
130 //
131 // - It calls the handler's ProcessAttributeX member functions for
132 // each of the DIE's attributes.
133 //
134 // - It calls the handler's EndAttributes member function. This
135 // should return true if any of the DIE's children should be
136 // visited, in which case:
137 //
138 // - For each of the DIE's children, die_dispatcher calls the
139 // DIE's handler's FindChildHandler member function. If that
140 // returns a pointer to a DIEHandler instance, then
141 // die_dispatcher uses that handler to process the child, using
142 // this procedure recursively. Alternatively, if
143 // FindChildHandler returns NULL, die_dispatcher ignores that
144 // child and its descendants.
145 //
146 // - When die_dispatcher has finished processing all the DIE's
147 // children, it invokes the handler's Finish() member function,
148 // and destroys the handler. (As a special case, it doesn't
149 // destroy the root DIE handler.)
150 //
151 // This allows the code for handling a particular kind of DIE to be
152 // gathered together in a single class, makes it easy to skip all the
153 // children or individual children of a particular DIE, and provides
154 // appropriate parental context for each die.
155
156 #ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__
157 #define COMMON_DWARF_DWARF2DIEHANDLER_H__
158
159 #include <stack>
160
161 #include "common/dwarf/types.h"
162 #include "common/dwarf/dwarf2enums.h"
163 #include "common/dwarf/dwarf2reader.h"
164
165 namespace dwarf2reader {
166
167 // A base class for handlers for specific DIE types. The series of
168 // calls made on a DIE handler is as follows:
169 //
170 // - for each attribute of the DIE:
171 // - ProcessAttributeX()
172 // - EndAttributes()
173 // - if that returned true, then for each child:
174 // - FindChildHandler()
175 // - if that returns a non-NULL pointer to a new handler:
176 // - recurse, with the new handler and the child die
177 // - Finish()
178 // - destruction
179 class DIEHandler {
180 public:
181 DIEHandler() { }
182 virtual ~DIEHandler() { }
183
184 // When we visit a DIE, we first use these member functions to
185 // report the DIE's attributes and their values. These have the
186 // same restrictions as the corresponding member functions of
187 // dwarf2reader::Dwarf2Handler.
188 //
189 // Since DWARF does not specify in what order attributes must
190 // appear, avoid making decisions in these functions that would be
191 // affected by the presence of other attributes. The EndAttributes
192 // function is a more appropriate place for such work, as all the
193 // DIE's attributes have been seen at that point.
194 //
195 // The default definitions ignore the values they are passed.
196 virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
197 enum DwarfForm form,
198 uint64 data) { }
199 virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
200 enum DwarfForm form,
201 int64 data) { }
202 virtual void ProcessAttributeReference(enum DwarfAttribute attr,
203 enum DwarfForm form,
204 uint64 data) { }
205 virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
206 enum DwarfForm form,
207 const char* data,
208 uint64 len) { }
209 virtual void ProcessAttributeString(enum DwarfAttribute attr,
210 enum DwarfForm form,
211 const string& data) { }
212
213 // Once we have reported all the DIE's attributes' values, we call
214 // this member function. If it returns false, we skip all the DIE's
215 // children. If it returns true, we call FindChildHandler on each
216 // child. If that returns a handler object, we use that to visit
217 // the child; otherwise, we skip the child.
218 //
219 // This is a good place to make decisions that depend on more than
220 // one attribute. DWARF does not specify in what order attributes
221 // must appear, so only when the EndAttributes function is called
222 // does the handler have a complete picture of the DIE's attributes.
223 //
224 // The default definition elects to ignore the DIE's children.
225 // You'll need to override this if you override FindChildHandler,
226 // but at least the default behavior isn't to pass the children to
227 // FindChildHandler, which then ignores them all.
228 virtual bool EndAttributes() { return false; }
229
230 // If EndAttributes returns true to indicate that some of the DIE's
231 // children might be of interest, then we apply this function to
232 // each of the DIE's children. If it returns a handler object, then
233 // we use that to visit the child DIE. If it returns NULL, we skip
234 // that child DIE (and all its descendants).
235 //
236 // OFFSET is the offset of the child; TAG indicates what kind of DIE
237 // it is; and ATTRS is the list of attributes the DIE will have, and
238 // their forms (their values are not provided).
239 //
240 // The default definition skips all children.
241 virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
242 const AttributeList &attrs) {
243 return NULL;
244 }
245
246 // When we are done processing a DIE, we call this member function.
247 // This happens after the EndAttributes call, all FindChildHandler
248 // calls (if any), and all operations on the children themselves (if
249 // any). We call Finish on every handler --- even if EndAttributes
250 // returns false.
251 virtual void Finish() { };
252 };
253
254 // A subclass of DIEHandler, with additional kludges for handling the
255 // compilation unit's root die.
256 class RootDIEHandler: public DIEHandler {
257 public:
258 RootDIEHandler() { }
259 virtual ~RootDIEHandler() { }
260
261 // We pass the values reported via Dwarf2Handler::StartCompilationUnit
262 // to this member function, and skip the entire compilation unit if it
263 // returns false. So the root DIE handler is actually also
264 // responsible for handling the compilation unit metadata.
265 // The default definition always visits the compilation unit.
266 virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
267 uint8 offset_size, uint64 cu_length,
268 uint8 dwarf_version) { return true; }
269
270 // For the root DIE handler only, we pass the offset, tag and
271 // attributes of the compilation unit's root DIE. This is the only
272 // way the root DIE handler can find the root DIE's tag. If this
273 // function returns true, we will visit the root DIE using the usual
274 // DIEHandler methods; otherwise, we skip the entire compilation
275 // unit.
276 //
277 // The default definition elects to visit the root DIE.
278 virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag,
279 const AttributeList& attrs) { return true; }
280 };
281
282 class DIEDispatcher: public Dwarf2Handler {
283 public:
284 // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
285 // the compilation unit's root die, as described for the DIEHandler
286 // class.
287 DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
288 // Destroying a DIEDispatcher destroys all active handler objects
289 // except the root handler.
290 ~DIEDispatcher();
291 bool StartCompilationUnit(uint64 offset, uint8 address_size,
292 uint8 offset_size, uint64 cu_length,
293 uint8 dwarf_version);
294 bool StartDIE(uint64 offset, enum DwarfTag tag,
295 const AttributeList &attrs);
296 void ProcessAttributeUnsigned(uint64 offset,
297 enum DwarfAttribute attr,
298 enum DwarfForm form,
299 uint64 data);
300 void ProcessAttributeSigned(uint64 offset,
301 enum DwarfAttribute attr,
302 enum DwarfForm form,
303 int64 data);
304 void ProcessAttributeReference(uint64 offset,
305 enum DwarfAttribute attr,
306 enum DwarfForm form,
307 uint64 data);
308 void ProcessAttributeBuffer(uint64 offset,
309 enum DwarfAttribute attr,
310 enum DwarfForm form,
311 const char* data,
312 uint64 len);
313 void ProcessAttributeString(uint64 offset,
314 enum DwarfAttribute attr,
315 enum DwarfForm form,
316 const string &data);
317 void EndDIE(uint64 offset);
318
319 private:
320
321 // The type of a handler stack entry. This includes some fields
322 // which don't really need to be on the stack --- they could just be
323 // single data members of DIEDispatcher --- but putting them here
324 // makes it easier to see that the code is correct.
325 struct HandlerStack {
326 // The offset of the DIE for this handler stack entry.
327 uint64 offset_;
328
329 // The handler object interested in this DIE's attributes and
330 // children. If NULL, we're not interested in either.
331 DIEHandler *handler_;
332
333 // Have we reported the end of this DIE's attributes to the handler?
334 bool reported_attributes_end_;
335 };
336
337 // Stack of DIE attribute handlers. At StartDIE(D), the top of the
338 // stack is the handler of D's parent, whom we may ask for a handler
339 // for D itself. At EndDIE(D), the top of the stack is D's handler.
340 // Special cases:
341 //
342 // - Before we've seen the compilation unit's root DIE, the stack is
343 // empty; we'll call root_handler_'s special member functions, and
344 // perhaps push root_handler_ on the stack to look at the root's
345 // immediate children.
346 //
347 // - When we decide to ignore a subtree, we only push an entry on
348 // the stack for the root of the tree being ignored, rather than
349 // pushing lots of stack entries with handler_ set to NULL.
350 stack<HandlerStack> die_handlers_;
351
352 // The root handler. We don't push it on die_handlers_ until we
353 // actually get the StartDIE call for the root.
354 RootDIEHandler *root_handler_;
355 };
356
357 } // namespace dwarf2reader
358 #endif // COMMON_DWARF_DWARF2DIEHANDLER_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698