diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc new file mode 100644 index 0000000000..94542b5ea9 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc @@ -0,0 +1,199 @@ +// Copyright (c) 2010 Google Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> + +// dwarf2diehandler.cc: Implement the dwarf2reader::DieDispatcher class. +// See dwarf2diehandler.h for details. + +#include <assert.h> +#include <stdint.h> + +#include <string> + +#include "common/dwarf/dwarf2diehandler.h" +#include "common/using_std_string.h" + +namespace dwarf2reader { + +DIEDispatcher::~DIEDispatcher() { + while (!die_handlers_.empty()) { + HandlerStack &entry = die_handlers_.top(); + if (entry.handler_ != root_handler_) + delete entry.handler_; + die_handlers_.pop(); + } +} + +bool DIEDispatcher::StartCompilationUnit(uint64 offset, uint8 address_size, + uint8 offset_size, uint64 cu_length, + uint8 dwarf_version) { + return root_handler_->StartCompilationUnit(offset, address_size, + offset_size, cu_length, + dwarf_version); +} + +bool DIEDispatcher::StartDIE(uint64 offset, enum DwarfTag tag) { + // The stack entry for the parent of this DIE, if there is one. + HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top(); + + // Does this call indicate that we're done receiving the parent's + // attributes' values? If so, call its EndAttributes member function. + if (parent && parent->handler_ && !parent->reported_attributes_end_) { + parent->reported_attributes_end_ = true; + if (!parent->handler_->EndAttributes()) { + // Finish off this handler now. and edit *PARENT to indicate that + // we don't want to visit any of the children. + parent->handler_->Finish(); + if (parent->handler_ != root_handler_) + delete parent->handler_; + parent->handler_ = NULL; + return false; + } + } + + // Find a handler for this DIE. + DIEHandler *handler; + if (parent) { + if (parent->handler_) + // Ask the parent to find a handler. + handler = parent->handler_->FindChildHandler(offset, tag); + else + // No parent handler means we're not interested in any of our + // children. + handler = NULL; + } else { + // This is the root DIE. For a non-root DIE, the parent's handler + // decides whether to visit it, but the root DIE has no parent + // handler, so we have a special method on the root DIE handler + // itself to decide. + if (root_handler_->StartRootDIE(offset, tag)) + handler = root_handler_; + else + handler = NULL; + } + + // Push a handler stack entry for this new handler. As an + // optimization, we don't push NULL-handler entries on top of other + // NULL-handler entries; we just let the oldest such entry stand for + // the whole subtree. + if (handler || !parent || parent->handler_) { + HandlerStack entry; + entry.offset_ = offset; + entry.handler_ = handler; + entry.reported_attributes_end_ = false; + die_handlers_.push(entry); + } + + return handler != NULL; +} + +void DIEDispatcher::EndDIE(uint64 offset) { + assert(!die_handlers_.empty()); + HandlerStack *entry = &die_handlers_.top(); + if (entry->handler_) { + // This entry had better be the handler for this DIE. + assert(entry->offset_ == offset); + // If a DIE has no children, this EndDIE call indicates that we're + // done receiving its attributes' values. + if (!entry->reported_attributes_end_) + entry->handler_->EndAttributes(); // Ignore return value: no children. + entry->handler_->Finish(); + if (entry->handler_ != root_handler_) + delete entry->handler_; + } else { + // If this DIE is within a tree we're ignoring, then don't pop the + // handler stack: that entry stands for the whole tree. + if (entry->offset_ != offset) + return; + } + die_handlers_.pop(); +} + +void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 data) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeUnsigned(attr, form, data); +} + +void DIEDispatcher::ProcessAttributeSigned(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + int64 data) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeSigned(attr, form, data); +} + +void DIEDispatcher::ProcessAttributeReference(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 data) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeReference(attr, form, data); +} + +void DIEDispatcher::ProcessAttributeBuffer(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const uint8_t *data, + uint64 len) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeBuffer(attr, form, data, len); +} + +void DIEDispatcher::ProcessAttributeString(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + const string& data) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeString(attr, form, data); +} + +void DIEDispatcher::ProcessAttributeSignature(uint64 offset, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64 signature) { + HandlerStack ¤t = die_handlers_.top(); + // This had better be an attribute of the DIE we were meant to handle. + assert(offset == current.offset_); + current.handler_->ProcessAttributeSignature(attr, form, signature); +} + +} // namespace dwarf2reader |