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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 // -*- mode: c++ -*-
     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.
    31 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    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.
   156 #ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__
   157 #define COMMON_DWARF_DWARF2DIEHANDLER_H__
   159 #include <stack>
   160 #include <string>
   162 #include "common/dwarf/types.h"
   163 #include "common/dwarf/dwarf2enums.h"
   164 #include "common/dwarf/dwarf2reader.h"
   165 #include "common/using_std_string.h"
   167 namespace dwarf2reader {
   169 // A base class for handlers for specific DIE types.  The series of
   170 // calls made on a DIE handler is as follows:
   171 //
   172 // - for each attribute of the DIE:
   173 //   - ProcessAttributeX()
   174 // - EndAttributes()
   175 // - if that returned true, then for each child:
   176 //   - FindChildHandler()
   177 //   - if that returns a non-NULL pointer to a new handler:
   178 //     - recurse, with the new handler and the child die
   179 // - Finish()
   180 // - destruction
   181 class DIEHandler {
   182  public:
   183   DIEHandler() { }
   184   virtual ~DIEHandler() { }
   186   // When we visit a DIE, we first use these member functions to
   187   // report the DIE's attributes and their values.  These have the
   188   // same restrictions as the corresponding member functions of
   189   // dwarf2reader::Dwarf2Handler.
   190   //
   191   // Since DWARF does not specify in what order attributes must
   192   // appear, avoid making decisions in these functions that would be
   193   // affected by the presence of other attributes. The EndAttributes
   194   // function is a more appropriate place for such work, as all the
   195   // DIE's attributes have been seen at that point.
   196   //
   197   // The default definitions ignore the values they are passed.
   198   virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
   199                                         enum DwarfForm form,
   200                                         uint64 data) { }
   201   virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
   202                                       enum DwarfForm form,
   203                                       int64 data) { }
   204   virtual void ProcessAttributeReference(enum DwarfAttribute attr,
   205                                          enum DwarfForm form,
   206                                          uint64 data) { }
   207   virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
   208                                       enum DwarfForm form,
   209                                       const char* data,
   210                                       uint64 len) { }
   211   virtual void ProcessAttributeString(enum DwarfAttribute attr,
   212                                       enum DwarfForm form,
   213                                       const string& data) { }
   214   virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
   215                                          enum DwarfForm form,
   216                                          uint64 signture) { }
   218   // Once we have reported all the DIE's attributes' values, we call
   219   // this member function.  If it returns false, we skip all the DIE's
   220   // children.  If it returns true, we call FindChildHandler on each
   221   // child.  If that returns a handler object, we use that to visit
   222   // the child; otherwise, we skip the child.
   223   //
   224   // This is a good place to make decisions that depend on more than
   225   // one attribute. DWARF does not specify in what order attributes
   226   // must appear, so only when the EndAttributes function is called
   227   // does the handler have a complete picture of the DIE's attributes.
   228   //
   229   // The default definition elects to ignore the DIE's children.
   230   // You'll need to override this if you override FindChildHandler,
   231   // but at least the default behavior isn't to pass the children to
   232   // FindChildHandler, which then ignores them all.
   233   virtual bool EndAttributes() { return false; }
   235   // If EndAttributes returns true to indicate that some of the DIE's
   236   // children might be of interest, then we apply this function to
   237   // each of the DIE's children.  If it returns a handler object, then
   238   // we use that to visit the child DIE.  If it returns NULL, we skip
   239   // that child DIE (and all its descendants).
   240   //
   241   // OFFSET is the offset of the child; TAG indicates what kind of DIE
   242   // it is.
   243   //
   244   // The default definition skips all children.
   245   virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag) {
   246     return NULL;
   247   }
   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   virtual void Finish() { };
   255 };
   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   RootDIEHandler() { }
   262   virtual ~RootDIEHandler() { }
   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   virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
   270                                     uint8 offset_size, uint64 cu_length,
   271                                     uint8 dwarf_version) { return true; }
   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   virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag) { return true; }
   282 };
   284 class DIEDispatcher: public Dwarf2Handler {
   285  public:
   286   // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
   287   // the compilation unit's root die, as described for the DIEHandler
   288   // class.
   289   DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
   290   // Destroying a DIEDispatcher destroys all active handler objects
   291   // except the root handler.
   292   ~DIEDispatcher();
   293   bool StartCompilationUnit(uint64 offset, uint8 address_size,
   294                             uint8 offset_size, uint64 cu_length,
   295                             uint8 dwarf_version);
   296   bool StartDIE(uint64 offset, enum DwarfTag tag);
   297   void ProcessAttributeUnsigned(uint64 offset,
   298                                 enum DwarfAttribute attr,
   299                                 enum DwarfForm form,
   300                                 uint64 data);
   301   void ProcessAttributeSigned(uint64 offset,
   302                               enum DwarfAttribute attr,
   303                               enum DwarfForm form,
   304                               int64 data);
   305   void ProcessAttributeReference(uint64 offset,
   306                                  enum DwarfAttribute attr,
   307                                  enum DwarfForm form,
   308                                  uint64 data);
   309   void ProcessAttributeBuffer(uint64 offset,
   310                               enum DwarfAttribute attr,
   311                               enum DwarfForm form,
   312                               const char* data,
   313                               uint64 len);
   314   void ProcessAttributeString(uint64 offset,
   315                               enum DwarfAttribute attr,
   316                               enum DwarfForm form,
   317                               const string &data);
   318   void ProcessAttributeSignature(uint64 offset,
   319                                  enum DwarfAttribute attr,
   320                                  enum DwarfForm form,
   321                                  uint64 signature);
   322   void EndDIE(uint64 offset);
   324  private:
   326   // The type of a handler stack entry.  This includes some fields
   327   // which don't really need to be on the stack --- they could just be
   328   // single data members of DIEDispatcher --- but putting them here
   329   // makes it easier to see that the code is correct.
   330   struct HandlerStack {
   331     // The offset of the DIE for this handler stack entry.
   332     uint64 offset_;
   334     // The handler object interested in this DIE's attributes and
   335     // children.  If NULL, we're not interested in either.
   336     DIEHandler *handler_;
   338     // Have we reported the end of this DIE's attributes to the handler?
   339     bool reported_attributes_end_;
   340   };
   342   // Stack of DIE attribute handlers.  At StartDIE(D), the top of the
   343   // stack is the handler of D's parent, whom we may ask for a handler
   344   // for D itself.  At EndDIE(D), the top of the stack is D's handler.
   345   // Special cases:
   346   //
   347   // - Before we've seen the compilation unit's root DIE, the stack is
   348   //   empty; we'll call root_handler_'s special member functions, and
   349   //   perhaps push root_handler_ on the stack to look at the root's
   350   //   immediate children.
   351   //
   352   // - When we decide to ignore a subtree, we only push an entry on
   353   //   the stack for the root of the tree being ignored, rather than
   354   //   pushing lots of stack entries with handler_ set to NULL.
   355   std::stack<HandlerStack> die_handlers_;
   357   // The root handler.  We don't push it on die_handlers_ until we
   358   // actually get the StartDIE call for the root.
   359   RootDIEHandler *root_handler_;
   360 };
   362 } // namespace dwarf2reader
   363 #endif  // COMMON_DWARF_DWARF2DIEHANDLER_H__

mercurial