toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,363 @@
     1.4 +// -*- mode: c++ -*-
     1.5 +
     1.6 +// Copyright (c) 2010 Google Inc. All Rights Reserved.
     1.7 +//
     1.8 +// Redistribution and use in source and binary forms, with or without
     1.9 +// modification, are permitted provided that the following conditions are
    1.10 +// met:
    1.11 +//
    1.12 +//     * Redistributions of source code must retain the above copyright
    1.13 +// notice, this list of conditions and the following disclaimer.
    1.14 +//     * Redistributions in binary form must reproduce the above
    1.15 +// copyright notice, this list of conditions and the following disclaimer
    1.16 +// in the documentation and/or other materials provided with the
    1.17 +// distribution.
    1.18 +//     * Neither the name of Google Inc. nor the names of its
    1.19 +// contributors may be used to endorse or promote products derived from
    1.20 +// this software without specific prior written permission.
    1.21 +//
    1.22 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.23 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.24 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.25 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.26 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.27 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.28 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.29 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.30 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.31 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.32 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.33 +
    1.34 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    1.35 +
    1.36 +// dwarf2reader::CompilationUnit is a simple and direct parser for
    1.37 +// DWARF data, but its handler interface is not convenient to use.  In
    1.38 +// particular:
    1.39 +//
    1.40 +// - CompilationUnit calls Dwarf2Handler's member functions to report
    1.41 +//   every attribute's value, regardless of what sort of DIE it is.
    1.42 +//   As a result, the ProcessAttributeX functions end up looking like
    1.43 +//   this:
    1.44 +//
    1.45 +//     switch (parent_die_tag) {
    1.46 +//       case DW_TAG_x:
    1.47 +//         switch (attribute_name) {
    1.48 +//           case DW_AT_y:
    1.49 +//             handle attribute y of DIE type x
    1.50 +//           ...
    1.51 +//         } break;
    1.52 +//       ...
    1.53 +//     } 
    1.54 +//
    1.55 +//   In C++ it's much nicer to use virtual function dispatch to find
    1.56 +//   the right code for a given case than to switch on the DIE tag
    1.57 +//   like this.
    1.58 +//
    1.59 +// - Processing different kinds of DIEs requires different sets of
    1.60 +//   data: lexical block DIEs have start and end addresses, but struct
    1.61 +//   type DIEs don't.  It would be nice to be able to have separate
    1.62 +//   handler classes for separate kinds of DIEs, each with the members
    1.63 +//   appropriate to its role, instead of having one handler class that
    1.64 +//   needs to hold data for every DIE type.
    1.65 +//
    1.66 +// - There should be a separate instance of the appropriate handler
    1.67 +//   class for each DIE, instead of a single object with tables
    1.68 +//   tracking all the dies in the compilation unit.
    1.69 +//
    1.70 +// - It's not convenient to take some action after all a DIE's
    1.71 +//   attributes have been seen, but before visiting any of its
    1.72 +//   children.  The only indication you have that a DIE's attribute
    1.73 +//   list is complete is that you get either a StartDIE or an EndDIE
    1.74 +//   call.
    1.75 +//
    1.76 +// - It's not convenient to make use of the tree structure of the
    1.77 +//   DIEs.  Skipping all the children of a given die requires
    1.78 +//   maintaining state and returning false from StartDIE until we get
    1.79 +//   an EndDIE call with the appropriate offset.
    1.80 +//
    1.81 +// This interface tries to take care of all that.  (You're shocked, I'm sure.)
    1.82 +//
    1.83 +// Using the classes here, you provide an initial handler for the root
    1.84 +// DIE of the compilation unit.  Each handler receives its DIE's
    1.85 +// attributes, and provides fresh handler objects for children of
    1.86 +// interest, if any.  The three classes are:
    1.87 +//
    1.88 +// - DIEHandler: the base class for your DIE-type-specific handler
    1.89 +//   classes.
    1.90 +//
    1.91 +// - RootDIEHandler: derived from DIEHandler, the base class for your
    1.92 +//   root DIE handler class.
    1.93 +//
    1.94 +// - DIEDispatcher: derived from Dwarf2Handler, an instance of this
    1.95 +//   invokes your DIE-type-specific handler objects.
    1.96 +//
    1.97 +// In detail:
    1.98 +//
    1.99 +// - Define handler classes specialized for the DIE types you're
   1.100 +//   interested in.  These handler classes must inherit from
   1.101 +//   DIEHandler.  Thus:
   1.102 +//
   1.103 +//     class My_DW_TAG_X_Handler: public DIEHandler { ... };
   1.104 +//     class My_DW_TAG_Y_Handler: public DIEHandler { ... };
   1.105 +//
   1.106 +//   DIEHandler subclasses needn't correspond exactly to single DIE
   1.107 +//   types, as shown here; the point is that you can have several
   1.108 +//   different classes appropriate to different kinds of DIEs.
   1.109 +//
   1.110 +// - In particular, define a handler class for the compilation
   1.111 +//   unit's root DIE, that inherits from RootDIEHandler:
   1.112 +//
   1.113 +//     class My_DW_TAG_compile_unit_Handler: public RootDIEHandler { ... };
   1.114 +//
   1.115 +//   RootDIEHandler inherits from DIEHandler, adding a few additional
   1.116 +//   member functions for examining the compilation unit as a whole,
   1.117 +//   and other quirks of rootness.
   1.118 +//
   1.119 +// - Then, create a DIEDispatcher instance, passing it an instance of
   1.120 +//   your root DIE handler class, and use that DIEDispatcher as the
   1.121 +//   dwarf2reader::CompilationUnit's handler:
   1.122 +//
   1.123 +//     My_DW_TAG_compile_unit_Handler root_die_handler(...);
   1.124 +//     DIEDispatcher die_dispatcher(&root_die_handler);
   1.125 +//     CompilationUnit reader(sections, offset, bytereader, &die_dispatcher);
   1.126 +//
   1.127 +//   Here, 'die_dispatcher' acts as a shim between 'reader' and the
   1.128 +//   various DIE-specific handlers you have defined.
   1.129 +//
   1.130 +// - When you call reader.Start(), die_dispatcher behaves as follows,
   1.131 +//   starting with your root die handler and the compilation unit's
   1.132 +//   root DIE:
   1.133 +//
   1.134 +//   - It calls the handler's ProcessAttributeX member functions for
   1.135 +//     each of the DIE's attributes.
   1.136 +//
   1.137 +//   - It calls the handler's EndAttributes member function.  This
   1.138 +//     should return true if any of the DIE's children should be
   1.139 +//     visited, in which case:
   1.140 +//
   1.141 +//     - For each of the DIE's children, die_dispatcher calls the
   1.142 +//       DIE's handler's FindChildHandler member function.  If that
   1.143 +//       returns a pointer to a DIEHandler instance, then
   1.144 +//       die_dispatcher uses that handler to process the child, using
   1.145 +//       this procedure recursively.  Alternatively, if
   1.146 +//       FindChildHandler returns NULL, die_dispatcher ignores that
   1.147 +//       child and its descendants.
   1.148 +// 
   1.149 +//   - When die_dispatcher has finished processing all the DIE's
   1.150 +//     children, it invokes the handler's Finish() member function,
   1.151 +//     and destroys the handler.  (As a special case, it doesn't
   1.152 +//     destroy the root DIE handler.)
   1.153 +// 
   1.154 +// This allows the code for handling a particular kind of DIE to be
   1.155 +// gathered together in a single class, makes it easy to skip all the
   1.156 +// children or individual children of a particular DIE, and provides
   1.157 +// appropriate parental context for each die.
   1.158 +
   1.159 +#ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__
   1.160 +#define COMMON_DWARF_DWARF2DIEHANDLER_H__
   1.161 +
   1.162 +#include <stack>
   1.163 +#include <string>
   1.164 +
   1.165 +#include "common/dwarf/types.h"
   1.166 +#include "common/dwarf/dwarf2enums.h"
   1.167 +#include "common/dwarf/dwarf2reader.h"
   1.168 +#include "common/using_std_string.h"
   1.169 +
   1.170 +namespace dwarf2reader {
   1.171 +
   1.172 +// A base class for handlers for specific DIE types.  The series of
   1.173 +// calls made on a DIE handler is as follows:
   1.174 +//
   1.175 +// - for each attribute of the DIE:
   1.176 +//   - ProcessAttributeX()
   1.177 +// - EndAttributes()
   1.178 +// - if that returned true, then for each child:
   1.179 +//   - FindChildHandler()
   1.180 +//   - if that returns a non-NULL pointer to a new handler:
   1.181 +//     - recurse, with the new handler and the child die
   1.182 +// - Finish()
   1.183 +// - destruction
   1.184 +class DIEHandler {
   1.185 + public:
   1.186 +  DIEHandler() { }
   1.187 +  virtual ~DIEHandler() { }
   1.188 +
   1.189 +  // When we visit a DIE, we first use these member functions to
   1.190 +  // report the DIE's attributes and their values.  These have the
   1.191 +  // same restrictions as the corresponding member functions of
   1.192 +  // dwarf2reader::Dwarf2Handler.
   1.193 +  //
   1.194 +  // Since DWARF does not specify in what order attributes must
   1.195 +  // appear, avoid making decisions in these functions that would be
   1.196 +  // affected by the presence of other attributes. The EndAttributes
   1.197 +  // function is a more appropriate place for such work, as all the
   1.198 +  // DIE's attributes have been seen at that point.
   1.199 +  //
   1.200 +  // The default definitions ignore the values they are passed.
   1.201 +  virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
   1.202 +                                        enum DwarfForm form,
   1.203 +                                        uint64 data) { }
   1.204 +  virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
   1.205 +                                      enum DwarfForm form,
   1.206 +                                      int64 data) { }
   1.207 +  virtual void ProcessAttributeReference(enum DwarfAttribute attr,
   1.208 +                                         enum DwarfForm form,
   1.209 +                                         uint64 data) { }
   1.210 +  virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
   1.211 +                                      enum DwarfForm form,
   1.212 +                                      const char* data,
   1.213 +                                      uint64 len) { }
   1.214 +  virtual void ProcessAttributeString(enum DwarfAttribute attr,
   1.215 +                                      enum DwarfForm form,
   1.216 +                                      const string& data) { }
   1.217 +  virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
   1.218 +                                         enum DwarfForm form,
   1.219 +                                         uint64 signture) { }
   1.220 +
   1.221 +  // Once we have reported all the DIE's attributes' values, we call
   1.222 +  // this member function.  If it returns false, we skip all the DIE's
   1.223 +  // children.  If it returns true, we call FindChildHandler on each
   1.224 +  // child.  If that returns a handler object, we use that to visit
   1.225 +  // the child; otherwise, we skip the child.
   1.226 +  //
   1.227 +  // This is a good place to make decisions that depend on more than
   1.228 +  // one attribute. DWARF does not specify in what order attributes
   1.229 +  // must appear, so only when the EndAttributes function is called
   1.230 +  // does the handler have a complete picture of the DIE's attributes.
   1.231 +  //
   1.232 +  // The default definition elects to ignore the DIE's children.
   1.233 +  // You'll need to override this if you override FindChildHandler,
   1.234 +  // but at least the default behavior isn't to pass the children to
   1.235 +  // FindChildHandler, which then ignores them all.
   1.236 +  virtual bool EndAttributes() { return false; }
   1.237 +
   1.238 +  // If EndAttributes returns true to indicate that some of the DIE's
   1.239 +  // children might be of interest, then we apply this function to
   1.240 +  // each of the DIE's children.  If it returns a handler object, then
   1.241 +  // we use that to visit the child DIE.  If it returns NULL, we skip
   1.242 +  // that child DIE (and all its descendants).
   1.243 +  //
   1.244 +  // OFFSET is the offset of the child; TAG indicates what kind of DIE
   1.245 +  // it is.
   1.246 +  //
   1.247 +  // The default definition skips all children.
   1.248 +  virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag) {
   1.249 +    return NULL;
   1.250 +  }
   1.251 +
   1.252 +  // When we are done processing a DIE, we call this member function.
   1.253 +  // This happens after the EndAttributes call, all FindChildHandler
   1.254 +  // calls (if any), and all operations on the children themselves (if
   1.255 +  // any). We call Finish on every handler --- even if EndAttributes
   1.256 +  // returns false.
   1.257 +  virtual void Finish() { };
   1.258 +};
   1.259 +
   1.260 +// A subclass of DIEHandler, with additional kludges for handling the
   1.261 +// compilation unit's root die.
   1.262 +class RootDIEHandler: public DIEHandler {
   1.263 + public:
   1.264 +  RootDIEHandler() { }
   1.265 +  virtual ~RootDIEHandler() { }
   1.266 +
   1.267 +  // We pass the values reported via Dwarf2Handler::StartCompilationUnit
   1.268 +  // to this member function, and skip the entire compilation unit if it
   1.269 +  // returns false.  So the root DIE handler is actually also
   1.270 +  // responsible for handling the compilation unit metadata.
   1.271 +  // The default definition always visits the compilation unit.
   1.272 +  virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
   1.273 +                                    uint8 offset_size, uint64 cu_length,
   1.274 +                                    uint8 dwarf_version) { return true; }
   1.275 +
   1.276 +  // For the root DIE handler only, we pass the offset, tag and
   1.277 +  // attributes of the compilation unit's root DIE.  This is the only
   1.278 +  // way the root DIE handler can find the root DIE's tag.  If this
   1.279 +  // function returns true, we will visit the root DIE using the usual
   1.280 +  // DIEHandler methods; otherwise, we skip the entire compilation
   1.281 +  // unit.
   1.282 +  //
   1.283 +  // The default definition elects to visit the root DIE.
   1.284 +  virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag) { return true; }
   1.285 +};
   1.286 +
   1.287 +class DIEDispatcher: public Dwarf2Handler {
   1.288 + public:
   1.289 +  // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
   1.290 +  // the compilation unit's root die, as described for the DIEHandler
   1.291 +  // class.
   1.292 +  DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
   1.293 +  // Destroying a DIEDispatcher destroys all active handler objects
   1.294 +  // except the root handler.
   1.295 +  ~DIEDispatcher();
   1.296 +  bool StartCompilationUnit(uint64 offset, uint8 address_size,
   1.297 +                            uint8 offset_size, uint64 cu_length,
   1.298 +                            uint8 dwarf_version);
   1.299 +  bool StartDIE(uint64 offset, enum DwarfTag tag);
   1.300 +  void ProcessAttributeUnsigned(uint64 offset,
   1.301 +                                enum DwarfAttribute attr,
   1.302 +                                enum DwarfForm form,
   1.303 +                                uint64 data);
   1.304 +  void ProcessAttributeSigned(uint64 offset,
   1.305 +                              enum DwarfAttribute attr,
   1.306 +                              enum DwarfForm form,
   1.307 +                              int64 data);
   1.308 +  void ProcessAttributeReference(uint64 offset,
   1.309 +                                 enum DwarfAttribute attr,
   1.310 +                                 enum DwarfForm form,
   1.311 +                                 uint64 data);
   1.312 +  void ProcessAttributeBuffer(uint64 offset,
   1.313 +                              enum DwarfAttribute attr,
   1.314 +                              enum DwarfForm form,
   1.315 +                              const char* data,
   1.316 +                              uint64 len);
   1.317 +  void ProcessAttributeString(uint64 offset,
   1.318 +                              enum DwarfAttribute attr,
   1.319 +                              enum DwarfForm form,
   1.320 +                              const string &data);
   1.321 +  void ProcessAttributeSignature(uint64 offset,
   1.322 +                                 enum DwarfAttribute attr,
   1.323 +                                 enum DwarfForm form,
   1.324 +                                 uint64 signature);
   1.325 +  void EndDIE(uint64 offset);
   1.326 +
   1.327 + private:
   1.328 +
   1.329 +  // The type of a handler stack entry.  This includes some fields
   1.330 +  // which don't really need to be on the stack --- they could just be
   1.331 +  // single data members of DIEDispatcher --- but putting them here
   1.332 +  // makes it easier to see that the code is correct.
   1.333 +  struct HandlerStack {
   1.334 +    // The offset of the DIE for this handler stack entry.
   1.335 +    uint64 offset_;
   1.336 +
   1.337 +    // The handler object interested in this DIE's attributes and
   1.338 +    // children.  If NULL, we're not interested in either.
   1.339 +    DIEHandler *handler_;
   1.340 +
   1.341 +    // Have we reported the end of this DIE's attributes to the handler?
   1.342 +    bool reported_attributes_end_;
   1.343 +  };
   1.344 +
   1.345 +  // Stack of DIE attribute handlers.  At StartDIE(D), the top of the
   1.346 +  // stack is the handler of D's parent, whom we may ask for a handler
   1.347 +  // for D itself.  At EndDIE(D), the top of the stack is D's handler.
   1.348 +  // Special cases:
   1.349 +  //
   1.350 +  // - Before we've seen the compilation unit's root DIE, the stack is
   1.351 +  //   empty; we'll call root_handler_'s special member functions, and
   1.352 +  //   perhaps push root_handler_ on the stack to look at the root's
   1.353 +  //   immediate children.
   1.354 +  //
   1.355 +  // - When we decide to ignore a subtree, we only push an entry on
   1.356 +  //   the stack for the root of the tree being ignored, rather than
   1.357 +  //   pushing lots of stack entries with handler_ set to NULL.
   1.358 +  std::stack<HandlerStack> die_handlers_;
   1.359 +
   1.360 +  // The root handler.  We don't push it on die_handlers_ until we
   1.361 +  // actually get the StartDIE call for the root.
   1.362 +  RootDIEHandler *root_handler_;
   1.363 +};
   1.364 +
   1.365 +} // namespace dwarf2reader
   1.366 +#endif  // COMMON_DWARF_DWARF2DIEHANDLER_H__

mercurial