LCOV - code coverage report
Current view: directory - toolkit/crashreporter/google-breakpad/src/common/dwarf - dwarf2diehandler.h (source / functions) Found Hit Coverage
Test: app.info Lines: 25 10 40.0 %
Date: 2012-06-02 Functions: 18 8 44.4 %

       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         7395544 :   DIEHandler() { }
     182         7395544 :   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               0 :   virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
     197                 :                                         enum DwarfForm form,
     198               0 :                                         uint64 data) { }
     199               0 :   virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
     200                 :                                       enum DwarfForm form,
     201               0 :                                       int64 data) { }
     202               0 :   virtual void ProcessAttributeReference(enum DwarfAttribute attr,
     203                 :                                          enum DwarfForm form,
     204               0 :                                          uint64 data) { }
     205          185980 :   virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
     206                 :                                       enum DwarfForm form,
     207                 :                                       const char* data,
     208          185980 :                                       uint64 len) { }
     209               0 :   virtual void ProcessAttributeString(enum DwarfAttribute attr,
     210                 :                                       enum DwarfForm form,
     211               0 :                                       const string& data) { }
     212               0 :   virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
     213                 :                                          enum DwarfForm form,
     214               0 :                                          uint64 signture) { }
     215                 : 
     216                 :   // Once we have reported all the DIE's attributes' values, we call
     217                 :   // this member function.  If it returns false, we skip all the DIE's
     218                 :   // children.  If it returns true, we call FindChildHandler on each
     219                 :   // child.  If that returns a handler object, we use that to visit
     220                 :   // the child; otherwise, we skip the child.
     221                 :   //
     222                 :   // This is a good place to make decisions that depend on more than
     223                 :   // one attribute. DWARF does not specify in what order attributes
     224                 :   // must appear, so only when the EndAttributes function is called
     225                 :   // does the handler have a complete picture of the DIE's attributes.
     226                 :   //
     227                 :   // The default definition elects to ignore the DIE's children.
     228                 :   // You'll need to override this if you override FindChildHandler,
     229                 :   // but at least the default behavior isn't to pass the children to
     230                 :   // FindChildHandler, which then ignores them all.
     231               0 :   virtual bool EndAttributes() { return false; }
     232                 : 
     233                 :   // If EndAttributes returns true to indicate that some of the DIE's
     234                 :   // children might be of interest, then we apply this function to
     235                 :   // each of the DIE's children.  If it returns a handler object, then
     236                 :   // we use that to visit the child DIE.  If it returns NULL, we skip
     237                 :   // that child DIE (and all its descendants).
     238                 :   //
     239                 :   // OFFSET is the offset of the child; TAG indicates what kind of DIE
     240                 :   // it is; and ATTRS is the list of attributes the DIE will have, and
     241                 :   // their forms (their values are not provided).
     242                 :   //
     243                 :   // The default definition skips all children.
     244        12331600 :   virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
     245                 :                                        const AttributeList &attrs) {
     246        12331600 :     return NULL;
     247                 :   }
     248                 : 
     249                 :   // When we are done processing a DIE, we call this member function.
     250                 :   // This happens after the EndAttributes call, all FindChildHandler
     251                 :   // calls (if any), and all operations on the children themselves (if
     252                 :   // any). We call Finish on every handler --- even if EndAttributes
     253                 :   // returns false.
     254         1177645 :   virtual void Finish() { };
     255                 : };
     256                 : 
     257                 : // A subclass of DIEHandler, with additional kludges for handling the
     258                 : // compilation unit's root die.
     259                 : class RootDIEHandler: public DIEHandler {
     260                 :  public:
     261            4773 :   RootDIEHandler() { }
     262            4773 :   virtual ~RootDIEHandler() { }
     263                 : 
     264                 :   // We pass the values reported via Dwarf2Handler::StartCompilationUnit
     265                 :   // to this member function, and skip the entire compilation unit if it
     266                 :   // returns false.  So the root DIE handler is actually also
     267                 :   // responsible for handling the compilation unit metadata.
     268                 :   // The default definition always visits the compilation unit.
     269               0 :   virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
     270                 :                                     uint8 offset_size, uint64 cu_length,
     271               0 :                                     uint8 dwarf_version) { return true; }
     272                 : 
     273                 :   // For the root DIE handler only, we pass the offset, tag and
     274                 :   // attributes of the compilation unit's root DIE.  This is the only
     275                 :   // way the root DIE handler can find the root DIE's tag.  If this
     276                 :   // function returns true, we will visit the root DIE using the usual
     277                 :   // DIEHandler methods; otherwise, we skip the entire compilation
     278                 :   // unit.
     279                 :   //
     280                 :   // The default definition elects to visit the root DIE.
     281               0 :   virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag,
     282               0 :                             const AttributeList& attrs) { return true; }
     283                 : };
     284                 : 
     285                 : class DIEDispatcher: public Dwarf2Handler {
     286                 :  public:
     287                 :   // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
     288                 :   // the compilation unit's root die, as described for the DIEHandler
     289                 :   // class.
     290            4773 :   DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
     291                 :   // Destroying a DIEDispatcher destroys all active handler objects
     292                 :   // except the root handler.
     293                 :   ~DIEDispatcher();
     294                 :   bool StartCompilationUnit(uint64 offset, uint8 address_size,
     295                 :                             uint8 offset_size, uint64 cu_length,
     296                 :                             uint8 dwarf_version);
     297                 :   bool StartDIE(uint64 offset, enum DwarfTag tag,
     298                 :                 const AttributeList &attrs);
     299                 :   void ProcessAttributeUnsigned(uint64 offset,
     300                 :                                 enum DwarfAttribute attr,
     301                 :                                 enum DwarfForm form,
     302                 :                                 uint64 data);
     303                 :   void ProcessAttributeSigned(uint64 offset,
     304                 :                               enum DwarfAttribute attr,
     305                 :                               enum DwarfForm form,
     306                 :                               int64 data);
     307                 :   void ProcessAttributeReference(uint64 offset,
     308                 :                                  enum DwarfAttribute attr,
     309                 :                                  enum DwarfForm form,
     310                 :                                  uint64 data);
     311                 :   void ProcessAttributeBuffer(uint64 offset,
     312                 :                               enum DwarfAttribute attr,
     313                 :                               enum DwarfForm form,
     314                 :                               const char* data,
     315                 :                               uint64 len);
     316                 :   void ProcessAttributeString(uint64 offset,
     317                 :                               enum DwarfAttribute attr,
     318                 :                               enum DwarfForm form,
     319                 :                               const string &data);
     320                 :   void ProcessAttributeSignature(uint64 offset,
     321                 :                                  enum DwarfAttribute attr,
     322                 :                                  enum DwarfForm form,
     323                 :                                  uint64 signature);
     324                 :   void EndDIE(uint64 offset);
     325                 : 
     326                 :  private:
     327                 : 
     328                 :   // The type of a handler stack entry.  This includes some fields
     329                 :   // which don't really need to be on the stack --- they could just be
     330                 :   // single data members of DIEDispatcher --- but putting them here
     331                 :   // makes it easier to see that the code is correct.
     332                 :   struct HandlerStack {
     333                 :     // The offset of the DIE for this handler stack entry.
     334                 :     uint64 offset_;
     335                 : 
     336                 :     // The handler object interested in this DIE's attributes and
     337                 :     // children.  If NULL, we're not interested in either.
     338                 :     DIEHandler *handler_;
     339                 : 
     340                 :     // Have we reported the end of this DIE's attributes to the handler?
     341                 :     bool reported_attributes_end_;
     342                 :   };
     343                 : 
     344                 :   // Stack of DIE attribute handlers.  At StartDIE(D), the top of the
     345                 :   // stack is the handler of D's parent, whom we may ask for a handler
     346                 :   // for D itself.  At EndDIE(D), the top of the stack is D's handler.
     347                 :   // Special cases:
     348                 :   //
     349                 :   // - Before we've seen the compilation unit's root DIE, the stack is
     350                 :   //   empty; we'll call root_handler_'s special member functions, and
     351                 :   //   perhaps push root_handler_ on the stack to look at the root's
     352                 :   //   immediate children.
     353                 :   //
     354                 :   // - When we decide to ignore a subtree, we only push an entry on
     355                 :   //   the stack for the root of the tree being ignored, rather than
     356                 :   //   pushing lots of stack entries with handler_ set to NULL.
     357                 :   stack<HandlerStack> die_handlers_;
     358                 : 
     359                 :   // The root handler.  We don't push it on die_handlers_ until we
     360                 :   // actually get the StartDIE call for the root.
     361                 :   RootDIEHandler *root_handler_;
     362                 : };
     363                 : 
     364                 : } // namespace dwarf2reader
     365                 : #endif  // COMMON_DWARF_DWARF2DIEHANDLER_H__

Generated by: LCOV version 1.7