1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,363 @@ 1.4 +// -*- mode: c++ -*- 1.5 + 1.6 +// Copyright (c) 2010 Google Inc. All Rights Reserved. 1.7 +// 1.8 +// Redistribution and use in source and binary forms, with or without 1.9 +// modification, are permitted provided that the following conditions are 1.10 +// met: 1.11 +// 1.12 +// * Redistributions of source code must retain the above copyright 1.13 +// notice, this list of conditions and the following disclaimer. 1.14 +// * Redistributions in binary form must reproduce the above 1.15 +// copyright notice, this list of conditions and the following disclaimer 1.16 +// in the documentation and/or other materials provided with the 1.17 +// distribution. 1.18 +// * Neither the name of Google Inc. nor the names of its 1.19 +// contributors may be used to endorse or promote products derived from 1.20 +// this software without specific prior written permission. 1.21 +// 1.22 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.23 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.24 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.25 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.26 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.27 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.28 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.29 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.30 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.31 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.32 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.33 + 1.34 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.35 + 1.36 +// dwarf2reader::CompilationUnit is a simple and direct parser for 1.37 +// DWARF data, but its handler interface is not convenient to use. In 1.38 +// particular: 1.39 +// 1.40 +// - CompilationUnit calls Dwarf2Handler's member functions to report 1.41 +// every attribute's value, regardless of what sort of DIE it is. 1.42 +// As a result, the ProcessAttributeX functions end up looking like 1.43 +// this: 1.44 +// 1.45 +// switch (parent_die_tag) { 1.46 +// case DW_TAG_x: 1.47 +// switch (attribute_name) { 1.48 +// case DW_AT_y: 1.49 +// handle attribute y of DIE type x 1.50 +// ... 1.51 +// } break; 1.52 +// ... 1.53 +// } 1.54 +// 1.55 +// In C++ it's much nicer to use virtual function dispatch to find 1.56 +// the right code for a given case than to switch on the DIE tag 1.57 +// like this. 1.58 +// 1.59 +// - Processing different kinds of DIEs requires different sets of 1.60 +// data: lexical block DIEs have start and end addresses, but struct 1.61 +// type DIEs don't. It would be nice to be able to have separate 1.62 +// handler classes for separate kinds of DIEs, each with the members 1.63 +// appropriate to its role, instead of having one handler class that 1.64 +// needs to hold data for every DIE type. 1.65 +// 1.66 +// - There should be a separate instance of the appropriate handler 1.67 +// class for each DIE, instead of a single object with tables 1.68 +// tracking all the dies in the compilation unit. 1.69 +// 1.70 +// - It's not convenient to take some action after all a DIE's 1.71 +// attributes have been seen, but before visiting any of its 1.72 +// children. The only indication you have that a DIE's attribute 1.73 +// list is complete is that you get either a StartDIE or an EndDIE 1.74 +// call. 1.75 +// 1.76 +// - It's not convenient to make use of the tree structure of the 1.77 +// DIEs. Skipping all the children of a given die requires 1.78 +// maintaining state and returning false from StartDIE until we get 1.79 +// an EndDIE call with the appropriate offset. 1.80 +// 1.81 +// This interface tries to take care of all that. (You're shocked, I'm sure.) 1.82 +// 1.83 +// Using the classes here, you provide an initial handler for the root 1.84 +// DIE of the compilation unit. Each handler receives its DIE's 1.85 +// attributes, and provides fresh handler objects for children of 1.86 +// interest, if any. The three classes are: 1.87 +// 1.88 +// - DIEHandler: the base class for your DIE-type-specific handler 1.89 +// classes. 1.90 +// 1.91 +// - RootDIEHandler: derived from DIEHandler, the base class for your 1.92 +// root DIE handler class. 1.93 +// 1.94 +// - DIEDispatcher: derived from Dwarf2Handler, an instance of this 1.95 +// invokes your DIE-type-specific handler objects. 1.96 +// 1.97 +// In detail: 1.98 +// 1.99 +// - Define handler classes specialized for the DIE types you're 1.100 +// interested in. These handler classes must inherit from 1.101 +// DIEHandler. Thus: 1.102 +// 1.103 +// class My_DW_TAG_X_Handler: public DIEHandler { ... }; 1.104 +// class My_DW_TAG_Y_Handler: public DIEHandler { ... }; 1.105 +// 1.106 +// DIEHandler subclasses needn't correspond exactly to single DIE 1.107 +// types, as shown here; the point is that you can have several 1.108 +// different classes appropriate to different kinds of DIEs. 1.109 +// 1.110 +// - In particular, define a handler class for the compilation 1.111 +// unit's root DIE, that inherits from RootDIEHandler: 1.112 +// 1.113 +// class My_DW_TAG_compile_unit_Handler: public RootDIEHandler { ... }; 1.114 +// 1.115 +// RootDIEHandler inherits from DIEHandler, adding a few additional 1.116 +// member functions for examining the compilation unit as a whole, 1.117 +// and other quirks of rootness. 1.118 +// 1.119 +// - Then, create a DIEDispatcher instance, passing it an instance of 1.120 +// your root DIE handler class, and use that DIEDispatcher as the 1.121 +// dwarf2reader::CompilationUnit's handler: 1.122 +// 1.123 +// My_DW_TAG_compile_unit_Handler root_die_handler(...); 1.124 +// DIEDispatcher die_dispatcher(&root_die_handler); 1.125 +// CompilationUnit reader(sections, offset, bytereader, &die_dispatcher); 1.126 +// 1.127 +// Here, 'die_dispatcher' acts as a shim between 'reader' and the 1.128 +// various DIE-specific handlers you have defined. 1.129 +// 1.130 +// - When you call reader.Start(), die_dispatcher behaves as follows, 1.131 +// starting with your root die handler and the compilation unit's 1.132 +// root DIE: 1.133 +// 1.134 +// - It calls the handler's ProcessAttributeX member functions for 1.135 +// each of the DIE's attributes. 1.136 +// 1.137 +// - It calls the handler's EndAttributes member function. This 1.138 +// should return true if any of the DIE's children should be 1.139 +// visited, in which case: 1.140 +// 1.141 +// - For each of the DIE's children, die_dispatcher calls the 1.142 +// DIE's handler's FindChildHandler member function. If that 1.143 +// returns a pointer to a DIEHandler instance, then 1.144 +// die_dispatcher uses that handler to process the child, using 1.145 +// this procedure recursively. Alternatively, if 1.146 +// FindChildHandler returns NULL, die_dispatcher ignores that 1.147 +// child and its descendants. 1.148 +// 1.149 +// - When die_dispatcher has finished processing all the DIE's 1.150 +// children, it invokes the handler's Finish() member function, 1.151 +// and destroys the handler. (As a special case, it doesn't 1.152 +// destroy the root DIE handler.) 1.153 +// 1.154 +// This allows the code for handling a particular kind of DIE to be 1.155 +// gathered together in a single class, makes it easy to skip all the 1.156 +// children or individual children of a particular DIE, and provides 1.157 +// appropriate parental context for each die. 1.158 + 1.159 +#ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__ 1.160 +#define COMMON_DWARF_DWARF2DIEHANDLER_H__ 1.161 + 1.162 +#include <stack> 1.163 +#include <string> 1.164 + 1.165 +#include "common/dwarf/types.h" 1.166 +#include "common/dwarf/dwarf2enums.h" 1.167 +#include "common/dwarf/dwarf2reader.h" 1.168 +#include "common/using_std_string.h" 1.169 + 1.170 +namespace dwarf2reader { 1.171 + 1.172 +// A base class for handlers for specific DIE types. The series of 1.173 +// calls made on a DIE handler is as follows: 1.174 +// 1.175 +// - for each attribute of the DIE: 1.176 +// - ProcessAttributeX() 1.177 +// - EndAttributes() 1.178 +// - if that returned true, then for each child: 1.179 +// - FindChildHandler() 1.180 +// - if that returns a non-NULL pointer to a new handler: 1.181 +// - recurse, with the new handler and the child die 1.182 +// - Finish() 1.183 +// - destruction 1.184 +class DIEHandler { 1.185 + public: 1.186 + DIEHandler() { } 1.187 + virtual ~DIEHandler() { } 1.188 + 1.189 + // When we visit a DIE, we first use these member functions to 1.190 + // report the DIE's attributes and their values. These have the 1.191 + // same restrictions as the corresponding member functions of 1.192 + // dwarf2reader::Dwarf2Handler. 1.193 + // 1.194 + // Since DWARF does not specify in what order attributes must 1.195 + // appear, avoid making decisions in these functions that would be 1.196 + // affected by the presence of other attributes. The EndAttributes 1.197 + // function is a more appropriate place for such work, as all the 1.198 + // DIE's attributes have been seen at that point. 1.199 + // 1.200 + // The default definitions ignore the values they are passed. 1.201 + virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr, 1.202 + enum DwarfForm form, 1.203 + uint64 data) { } 1.204 + virtual void ProcessAttributeSigned(enum DwarfAttribute attr, 1.205 + enum DwarfForm form, 1.206 + int64 data) { } 1.207 + virtual void ProcessAttributeReference(enum DwarfAttribute attr, 1.208 + enum DwarfForm form, 1.209 + uint64 data) { } 1.210 + virtual void ProcessAttributeBuffer(enum DwarfAttribute attr, 1.211 + enum DwarfForm form, 1.212 + const char* data, 1.213 + uint64 len) { } 1.214 + virtual void ProcessAttributeString(enum DwarfAttribute attr, 1.215 + enum DwarfForm form, 1.216 + const string& data) { } 1.217 + virtual void ProcessAttributeSignature(enum DwarfAttribute attr, 1.218 + enum DwarfForm form, 1.219 + uint64 signture) { } 1.220 + 1.221 + // Once we have reported all the DIE's attributes' values, we call 1.222 + // this member function. If it returns false, we skip all the DIE's 1.223 + // children. If it returns true, we call FindChildHandler on each 1.224 + // child. If that returns a handler object, we use that to visit 1.225 + // the child; otherwise, we skip the child. 1.226 + // 1.227 + // This is a good place to make decisions that depend on more than 1.228 + // one attribute. DWARF does not specify in what order attributes 1.229 + // must appear, so only when the EndAttributes function is called 1.230 + // does the handler have a complete picture of the DIE's attributes. 1.231 + // 1.232 + // The default definition elects to ignore the DIE's children. 1.233 + // You'll need to override this if you override FindChildHandler, 1.234 + // but at least the default behavior isn't to pass the children to 1.235 + // FindChildHandler, which then ignores them all. 1.236 + virtual bool EndAttributes() { return false; } 1.237 + 1.238 + // If EndAttributes returns true to indicate that some of the DIE's 1.239 + // children might be of interest, then we apply this function to 1.240 + // each of the DIE's children. If it returns a handler object, then 1.241 + // we use that to visit the child DIE. If it returns NULL, we skip 1.242 + // that child DIE (and all its descendants). 1.243 + // 1.244 + // OFFSET is the offset of the child; TAG indicates what kind of DIE 1.245 + // it is. 1.246 + // 1.247 + // The default definition skips all children. 1.248 + virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag) { 1.249 + return NULL; 1.250 + } 1.251 + 1.252 + // When we are done processing a DIE, we call this member function. 1.253 + // This happens after the EndAttributes call, all FindChildHandler 1.254 + // calls (if any), and all operations on the children themselves (if 1.255 + // any). We call Finish on every handler --- even if EndAttributes 1.256 + // returns false. 1.257 + virtual void Finish() { }; 1.258 +}; 1.259 + 1.260 +// A subclass of DIEHandler, with additional kludges for handling the 1.261 +// compilation unit's root die. 1.262 +class RootDIEHandler: public DIEHandler { 1.263 + public: 1.264 + RootDIEHandler() { } 1.265 + virtual ~RootDIEHandler() { } 1.266 + 1.267 + // We pass the values reported via Dwarf2Handler::StartCompilationUnit 1.268 + // to this member function, and skip the entire compilation unit if it 1.269 + // returns false. So the root DIE handler is actually also 1.270 + // responsible for handling the compilation unit metadata. 1.271 + // The default definition always visits the compilation unit. 1.272 + virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, 1.273 + uint8 offset_size, uint64 cu_length, 1.274 + uint8 dwarf_version) { return true; } 1.275 + 1.276 + // For the root DIE handler only, we pass the offset, tag and 1.277 + // attributes of the compilation unit's root DIE. This is the only 1.278 + // way the root DIE handler can find the root DIE's tag. If this 1.279 + // function returns true, we will visit the root DIE using the usual 1.280 + // DIEHandler methods; otherwise, we skip the entire compilation 1.281 + // unit. 1.282 + // 1.283 + // The default definition elects to visit the root DIE. 1.284 + virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag) { return true; } 1.285 +}; 1.286 + 1.287 +class DIEDispatcher: public Dwarf2Handler { 1.288 + public: 1.289 + // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for 1.290 + // the compilation unit's root die, as described for the DIEHandler 1.291 + // class. 1.292 + DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { } 1.293 + // Destroying a DIEDispatcher destroys all active handler objects 1.294 + // except the root handler. 1.295 + ~DIEDispatcher(); 1.296 + bool StartCompilationUnit(uint64 offset, uint8 address_size, 1.297 + uint8 offset_size, uint64 cu_length, 1.298 + uint8 dwarf_version); 1.299 + bool StartDIE(uint64 offset, enum DwarfTag tag); 1.300 + void ProcessAttributeUnsigned(uint64 offset, 1.301 + enum DwarfAttribute attr, 1.302 + enum DwarfForm form, 1.303 + uint64 data); 1.304 + void ProcessAttributeSigned(uint64 offset, 1.305 + enum DwarfAttribute attr, 1.306 + enum DwarfForm form, 1.307 + int64 data); 1.308 + void ProcessAttributeReference(uint64 offset, 1.309 + enum DwarfAttribute attr, 1.310 + enum DwarfForm form, 1.311 + uint64 data); 1.312 + void ProcessAttributeBuffer(uint64 offset, 1.313 + enum DwarfAttribute attr, 1.314 + enum DwarfForm form, 1.315 + const char* data, 1.316 + uint64 len); 1.317 + void ProcessAttributeString(uint64 offset, 1.318 + enum DwarfAttribute attr, 1.319 + enum DwarfForm form, 1.320 + const string &data); 1.321 + void ProcessAttributeSignature(uint64 offset, 1.322 + enum DwarfAttribute attr, 1.323 + enum DwarfForm form, 1.324 + uint64 signature); 1.325 + void EndDIE(uint64 offset); 1.326 + 1.327 + private: 1.328 + 1.329 + // The type of a handler stack entry. This includes some fields 1.330 + // which don't really need to be on the stack --- they could just be 1.331 + // single data members of DIEDispatcher --- but putting them here 1.332 + // makes it easier to see that the code is correct. 1.333 + struct HandlerStack { 1.334 + // The offset of the DIE for this handler stack entry. 1.335 + uint64 offset_; 1.336 + 1.337 + // The handler object interested in this DIE's attributes and 1.338 + // children. If NULL, we're not interested in either. 1.339 + DIEHandler *handler_; 1.340 + 1.341 + // Have we reported the end of this DIE's attributes to the handler? 1.342 + bool reported_attributes_end_; 1.343 + }; 1.344 + 1.345 + // Stack of DIE attribute handlers. At StartDIE(D), the top of the 1.346 + // stack is the handler of D's parent, whom we may ask for a handler 1.347 + // for D itself. At EndDIE(D), the top of the stack is D's handler. 1.348 + // Special cases: 1.349 + // 1.350 + // - Before we've seen the compilation unit's root DIE, the stack is 1.351 + // empty; we'll call root_handler_'s special member functions, and 1.352 + // perhaps push root_handler_ on the stack to look at the root's 1.353 + // immediate children. 1.354 + // 1.355 + // - When we decide to ignore a subtree, we only push an entry on 1.356 + // the stack for the root of the tree being ignored, rather than 1.357 + // pushing lots of stack entries with handler_ set to NULL. 1.358 + std::stack<HandlerStack> die_handlers_; 1.359 + 1.360 + // The root handler. We don't push it on die_handlers_ until we 1.361 + // actually get the StartDIE call for the root. 1.362 + RootDIEHandler *root_handler_; 1.363 +}; 1.364 + 1.365 +} // namespace dwarf2reader 1.366 +#endif // COMMON_DWARF_DWARF2DIEHANDLER_H__