Home | History | Annotate | Download | only in dwarf
      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 (at) mozilla.com> <jimb (at) red-bean.com>
     30 
     31 // dwarf2diehandler.cc: Implement the dwarf2reader::DieDispatcher class.
     32 // See dwarf2diehandler.h for details.
     33 
     34 #include <assert.h>
     35 
     36 #include <string>
     37 
     38 #include "common/dwarf/dwarf2diehandler.h"
     39 #include "common/using_std_string.h"
     40 
     41 namespace dwarf2reader {
     42 
     43 DIEDispatcher::~DIEDispatcher() {
     44   while (!die_handlers_.empty()) {
     45     HandlerStack &entry = die_handlers_.top();
     46     if (entry.handler_ != root_handler_)
     47       delete entry.handler_;
     48     die_handlers_.pop();
     49   }
     50 }
     51 
     52 bool DIEDispatcher::StartCompilationUnit(uint64 offset, uint8 address_size,
     53                                          uint8 offset_size, uint64 cu_length,
     54                                          uint8 dwarf_version) {
     55   return root_handler_->StartCompilationUnit(offset, address_size,
     56                                              offset_size, cu_length,
     57                                              dwarf_version);
     58 }
     59 
     60 bool DIEDispatcher::StartDIE(uint64 offset, enum DwarfTag tag) {
     61   // The stack entry for the parent of this DIE, if there is one.
     62   HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
     63 
     64   // Does this call indicate that we're done receiving the parent's
     65   // attributes' values?  If so, call its EndAttributes member function.
     66   if (parent && parent->handler_ && !parent->reported_attributes_end_) {
     67     parent->reported_attributes_end_ = true;
     68     if (!parent->handler_->EndAttributes()) {
     69       // Finish off this handler now. and edit *PARENT to indicate that
     70       // we don't want to visit any of the children.
     71       parent->handler_->Finish();
     72       if (parent->handler_ != root_handler_)
     73         delete parent->handler_;
     74       parent->handler_ = NULL;
     75       return false;
     76     }
     77   }
     78 
     79   // Find a handler for this DIE.
     80   DIEHandler *handler;
     81   if (parent) {
     82     if (parent->handler_)
     83       // Ask the parent to find a handler.
     84       handler = parent->handler_->FindChildHandler(offset, tag);
     85     else
     86       // No parent handler means we're not interested in any of our
     87       // children.
     88       handler = NULL;
     89   } else {
     90     // This is the root DIE.  For a non-root DIE, the parent's handler
     91     // decides whether to visit it, but the root DIE has no parent
     92     // handler, so we have a special method on the root DIE handler
     93     // itself to decide.
     94     if (root_handler_->StartRootDIE(offset, tag))
     95       handler = root_handler_;
     96     else
     97       handler = NULL;
     98   }
     99 
    100   // Push a handler stack entry for this new handler. As an
    101   // optimization, we don't push NULL-handler entries on top of other
    102   // NULL-handler entries; we just let the oldest such entry stand for
    103   // the whole subtree.
    104   if (handler || !parent || parent->handler_) {
    105     HandlerStack entry;
    106     entry.offset_ = offset;
    107     entry.handler_ = handler;
    108     entry.reported_attributes_end_ = false;
    109     die_handlers_.push(entry);
    110   }
    111 
    112   return handler != NULL;
    113 }
    114 
    115 void DIEDispatcher::EndDIE(uint64 offset) {
    116   assert(!die_handlers_.empty());
    117   HandlerStack *entry = &die_handlers_.top();
    118   if (entry->handler_) {
    119     // This entry had better be the handler for this DIE.
    120     assert(entry->offset_ == offset);
    121     // If a DIE has no children, this EndDIE call indicates that we're
    122     // done receiving its attributes' values.
    123     if (!entry->reported_attributes_end_)
    124       entry->handler_->EndAttributes(); // Ignore return value: no children.
    125     entry->handler_->Finish();
    126     if (entry->handler_ != root_handler_)
    127       delete entry->handler_;
    128   } else {
    129     // If this DIE is within a tree we're ignoring, then don't pop the
    130     // handler stack: that entry stands for the whole tree.
    131     if (entry->offset_ != offset)
    132       return;
    133   }
    134   die_handlers_.pop();
    135 }
    136 
    137 void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset,
    138                                              enum DwarfAttribute attr,
    139                                              enum DwarfForm form,
    140                                              uint64 data) {
    141   HandlerStack &current = die_handlers_.top();
    142   // This had better be an attribute of the DIE we were meant to handle.
    143   assert(offset == current.offset_);
    144   current.handler_->ProcessAttributeUnsigned(attr, form, data);
    145 }
    146 
    147 void DIEDispatcher::ProcessAttributeSigned(uint64 offset,
    148                                            enum DwarfAttribute attr,
    149                                            enum DwarfForm form,
    150                                            int64 data) {
    151   HandlerStack &current = die_handlers_.top();
    152   // This had better be an attribute of the DIE we were meant to handle.
    153   assert(offset == current.offset_);
    154   current.handler_->ProcessAttributeSigned(attr, form, data);
    155 }
    156 
    157 void DIEDispatcher::ProcessAttributeReference(uint64 offset,
    158                                               enum DwarfAttribute attr,
    159                                               enum DwarfForm form,
    160                                               uint64 data) {
    161   HandlerStack &current = die_handlers_.top();
    162   // This had better be an attribute of the DIE we were meant to handle.
    163   assert(offset == current.offset_);
    164   current.handler_->ProcessAttributeReference(attr, form, data);
    165 }
    166 
    167 void DIEDispatcher::ProcessAttributeBuffer(uint64 offset,
    168                                            enum DwarfAttribute attr,
    169                                            enum DwarfForm form,
    170                                            const char* data,
    171                                            uint64 len) {
    172   HandlerStack &current = die_handlers_.top();
    173   // This had better be an attribute of the DIE we were meant to handle.
    174   assert(offset == current.offset_);
    175   current.handler_->ProcessAttributeBuffer(attr, form, data, len);
    176 }
    177 
    178 void DIEDispatcher::ProcessAttributeString(uint64 offset,
    179                                            enum DwarfAttribute attr,
    180                                            enum DwarfForm form,
    181                                            const string& data) {
    182   HandlerStack &current = die_handlers_.top();
    183   // This had better be an attribute of the DIE we were meant to handle.
    184   assert(offset == current.offset_);
    185   current.handler_->ProcessAttributeString(attr, form, data);
    186 }
    187 
    188 void DIEDispatcher::ProcessAttributeSignature(uint64 offset,
    189                                               enum DwarfAttribute attr,
    190                                               enum DwarfForm form,
    191                                               uint64 signature) {
    192   HandlerStack &current = die_handlers_.top();
    193   // This had better be an attribute of the DIE we were meant to handle.
    194   assert(offset == current.offset_);
    195   current.handler_->ProcessAttributeSignature(attr, form, signature);
    196 }
    197 
    198 } // namespace dwarf2reader
    199