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