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 ¤t = 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 ¤t = 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 ¤t = 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 ¤t = 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 ¤t = 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 ¤t = 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