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