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 <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
~DIEDispatcher()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
StartCompilationUnit(uint64 offset,uint8 address_size,uint8 offset_size,uint64 cu_length,uint8 dwarf_version)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
StartDIE(uint64 offset,enum DwarfTag tag)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
EndDIE(uint64 offset)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
ProcessAttributeUnsigned(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,uint64 data)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
ProcessAttributeSigned(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,int64 data)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
ProcessAttributeReference(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,uint64 data)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
ProcessAttributeBuffer(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,const char * data,uint64 len)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
ProcessAttributeString(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,const string & data)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
ProcessAttributeSignature(uint64 offset,enum DwarfAttribute attr,enum DwarfForm form,uint64 signature)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