/thirdparty/breakpad/common/dwarf/dwarf2diehandler.cc

http://github.com/tomahawk-player/tomahawk · C++ · 196 lines · 118 code · 20 blank · 58 comment · 31 complexity · 11e0e9ad3ee2e4459334a17c9dd4fbaf MD5 · raw file

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