OLD | NEW |
| (Empty) |
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 <cassert> | |
35 | |
36 #include "common/dwarf/dwarf2diehandler.h" | |
37 | |
38 namespace dwarf2reader { | |
39 | |
40 DIEDispatcher::~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 | |
49 bool 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 | |
57 bool 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 | |
113 void 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 | |
135 void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset, | |
136 enum DwarfAttribute attr, | |
137 enum DwarfForm form, | |
138 uint64 data) { | |
139 HandlerStack ¤t = 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 | |
145 void DIEDispatcher::ProcessAttributeSigned(uint64 offset, | |
146 enum DwarfAttribute attr, | |
147 enum DwarfForm form, | |
148 int64 data) { | |
149 HandlerStack ¤t = 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 | |
155 void DIEDispatcher::ProcessAttributeReference(uint64 offset, | |
156 enum DwarfAttribute attr, | |
157 enum DwarfForm form, | |
158 uint64 data) { | |
159 HandlerStack ¤t = 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 | |
165 void DIEDispatcher::ProcessAttributeBuffer(uint64 offset, | |
166 enum DwarfAttribute attr, | |
167 enum DwarfForm form, | |
168 const char* data, | |
169 uint64 len) { | |
170 HandlerStack ¤t = 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 | |
176 void DIEDispatcher::ProcessAttributeString(uint64 offset, | |
177 enum DwarfAttribute attr, | |
178 enum DwarfForm form, | |
179 const string& data) { | |
180 HandlerStack ¤t = 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 | |
186 } // namespace dwarf2reader | |
OLD | NEW |