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