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

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-04-21 | 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         7405087 :   DIEHandler() { }
         182         7405087 :   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          186191 :   virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
         206                 :                                       enum DwarfForm form,
         207                 :                                       const char* data,
         208          186191 :                                       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        12345017 :   virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
         245                 :                                        const AttributeList &attrs) {
         246        12345017 :     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         1179540 :   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            4780 :   RootDIEHandler() { }
         262            4780 :   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            4780 :   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