PageRenderTime 59ms CodeModel.GetById 14ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/thirdparty/breakpad/common/dwarf/dwarf2diehandler.cc

http://github.com/tomahawk-player/tomahawk
C++ | 196 lines | 118 code | 20 blank | 58 comment | 31 complexity | 11e0e9ad3ee2e4459334a17c9dd4fbaf MD5 | raw file
  1// Copyright (c) 2010 Google Inc. All Rights Reserved.
  2//
  3// Redistribution and use in source and binary forms, with or without
  4// modification, are permitted provided that the following conditions are
  5// met:
  6//
  7//     * Redistributions of source code must retain the above copyright
  8// notice, this list of conditions and the following disclaimer.
  9//     * Redistributions in binary form must reproduce the above
 10// copyright notice, this list of conditions and the following disclaimer
 11// in the documentation and/or other materials provided with the
 12// distribution.
 13//     * Neither the name of Google Inc. nor the names of its
 14// contributors may be used to endorse or promote products derived from
 15// this software without specific prior written permission.
 16//
 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28
 29// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 30
 31// dwarf2diehandler.cc: Implement the dwarf2reader::DieDispatcher class.
 32// See dwarf2diehandler.h for details.
 33
 34#include "common/dwarf/dwarf2diehandler.h"
 35
 36#include <assert.h>
 37
 38namespace dwarf2reader {
 39
 40DIEDispatcher::~DIEDispatcher() {
 41  while (!die_handlers_.empty()) {
 42    HandlerStack &entry = die_handlers_.top();
 43    if (entry.handler_ != root_handler_)
 44      delete entry.handler_;
 45    die_handlers_.pop();
 46  }
 47}
 48
 49bool DIEDispatcher::StartCompilationUnit(uint64 offset, uint8 address_size,
 50                                         uint8 offset_size, uint64 cu_length,
 51                                         uint8 dwarf_version) {
 52  return root_handler_->StartCompilationUnit(offset, address_size,
 53                                             offset_size, cu_length,
 54                                             dwarf_version);
 55}
 56
 57bool DIEDispatcher::StartDIE(uint64 offset, enum DwarfTag tag,
 58                             const AttributeList& attrs) {
 59  // The stack entry for the parent of this DIE, if there is one.
 60  HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
 61
 62  // Does this call indicate that we're done receiving the parent's
 63  // attributes' values?  If so, call its EndAttributes member function.
 64  if (parent && parent->handler_ && !parent->reported_attributes_end_) {
 65    parent->reported_attributes_end_ = true;
 66    if (!parent->handler_->EndAttributes()) {
 67      // Finish off this handler now. and edit *PARENT to indicate that
 68      // we don't want to visit any of the children.
 69      parent->handler_->Finish();
 70      if (parent->handler_ != root_handler_)
 71        delete parent->handler_;
 72      parent->handler_ = NULL;
 73      return false;
 74    }
 75  }
 76
 77  // Find a handler for this DIE.
 78  DIEHandler *handler;
 79  if (parent) {
 80    if (parent->handler_)
 81      // Ask the parent to find a handler.
 82      handler = parent->handler_->FindChildHandler(offset, tag, attrs);
 83    else
 84      // No parent handler means we're not interested in any of our
 85      // children.
 86      handler = NULL;
 87  } else {
 88    // This is the root DIE.  For a non-root DIE, the parent's handler
 89    // decides whether to visit it, but the root DIE has no parent
 90    // handler, so we have a special method on the root DIE handler
 91    // itself to decide.
 92    if (root_handler_->StartRootDIE(offset, tag, attrs))
 93      handler = root_handler_;
 94    else
 95      handler = NULL;
 96  }
 97
 98  // Push a handler stack entry for this new handler. As an
 99  // optimization, we don't push NULL-handler entries on top of other
100  // NULL-handler entries; we just let the oldest such entry stand for
101  // the whole subtree.
102  if (handler || !parent || parent->handler_) {
103    HandlerStack entry;
104    entry.offset_ = offset;
105    entry.handler_ = handler;
106    entry.reported_attributes_end_ = false;
107    die_handlers_.push(entry);
108  }
109
110  return handler != NULL;
111}
112
113void DIEDispatcher::EndDIE(uint64 offset) {
114  assert(!die_handlers_.empty());
115  HandlerStack *entry = &die_handlers_.top();
116  if (entry->handler_) {
117    // This entry had better be the handler for this DIE.
118    assert(entry->offset_ == offset);
119    // If a DIE has no children, this EndDIE call indicates that we're
120    // done receiving its attributes' values.
121    if (!entry->reported_attributes_end_)
122      entry->handler_->EndAttributes(); // Ignore return value: no children.
123    entry->handler_->Finish();
124    if (entry->handler_ != root_handler_)
125      delete entry->handler_;
126  } else {
127    // If this DIE is within a tree we're ignoring, then don't pop the
128    // handler stack: that entry stands for the whole tree.
129    if (entry->offset_ != offset)
130      return;
131  }
132  die_handlers_.pop();
133}
134
135void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset,
136                                             enum DwarfAttribute attr,
137                                             enum DwarfForm form,
138                                             uint64 data) {
139  HandlerStack &current = die_handlers_.top();
140  // This had better be an attribute of the DIE we were meant to handle.
141  assert(offset == current.offset_);
142  current.handler_->ProcessAttributeUnsigned(attr, form, data);
143}
144
145void DIEDispatcher::ProcessAttributeSigned(uint64 offset,
146                                           enum DwarfAttribute attr,
147                                           enum DwarfForm form,
148                                           int64 data) {
149  HandlerStack &current = die_handlers_.top();
150  // This had better be an attribute of the DIE we were meant to handle.
151  assert(offset == current.offset_);
152  current.handler_->ProcessAttributeSigned(attr, form, data);
153}
154
155void DIEDispatcher::ProcessAttributeReference(uint64 offset,
156                                              enum DwarfAttribute attr,
157                                              enum DwarfForm form,
158                                              uint64 data) {
159  HandlerStack &current = die_handlers_.top();
160  // This had better be an attribute of the DIE we were meant to handle.
161  assert(offset == current.offset_);
162  current.handler_->ProcessAttributeReference(attr, form, data);
163}
164
165void DIEDispatcher::ProcessAttributeBuffer(uint64 offset,
166                                           enum DwarfAttribute attr,
167                                           enum DwarfForm form,
168                                           const char* data,
169                                           uint64 len) {
170  HandlerStack &current = die_handlers_.top();
171  // This had better be an attribute of the DIE we were meant to handle.
172  assert(offset == current.offset_);
173  current.handler_->ProcessAttributeBuffer(attr, form, data, len);
174}
175
176void DIEDispatcher::ProcessAttributeString(uint64 offset,
177                                           enum DwarfAttribute attr,
178                                           enum DwarfForm form,
179                                           const std::string& data) {
180  HandlerStack &current = die_handlers_.top();
181  // This had better be an attribute of the DIE we were meant to handle.
182  assert(offset == current.offset_);
183  current.handler_->ProcessAttributeString(attr, form, data);
184}
185
186void DIEDispatcher::ProcessAttributeSignature(uint64 offset,
187                                              enum DwarfAttribute attr,
188                                              enum DwarfForm form,
189                                              uint64 signature) {
190  HandlerStack &current = die_handlers_.top();
191  // This had better be an attribute of the DIE we were meant to handle.
192  assert(offset == current.offset_);
193  current.handler_->ProcessAttributeSignature(attr, form, signature);
194}
195
196} // namespace dwarf2reader