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