/thirdparty/breakpad/common/stabs_to_module.cc

http://github.com/tomahawk-player/tomahawk · C++ · 201 lines · 129 code · 20 blank · 52 comment · 24 complexity · 536b03413664b05d8e231e4f7ecfd5fb MD5 · raw file

  1. // Copyright (c) 2010 Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
  30. // dump_stabs.cc --- implement the StabsToModule class.
  31. #include <assert.h>
  32. #include <cxxabi.h>
  33. #include <stdarg.h>
  34. #include <stdio.h>
  35. #include <algorithm>
  36. #include "common/stabs_to_module.h"
  37. namespace google_breakpad {
  38. using std::string;
  39. // Demangle using abi call.
  40. // Older GCC may not support it.
  41. static string Demangle(const string &mangled) {
  42. int status = 0;
  43. char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
  44. if (status == 0 && demangled != NULL) {
  45. string str(demangled);
  46. free(demangled);
  47. return str;
  48. }
  49. return string(mangled);
  50. }
  51. StabsToModule::~StabsToModule() {
  52. // Free any functions we've accumulated but not added to the module.
  53. for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
  54. func_it != functions_.end(); func_it++)
  55. delete *func_it;
  56. // Free any function that we're currently within.
  57. delete current_function_;
  58. }
  59. bool StabsToModule::StartCompilationUnit(const char *name, uint64_t address,
  60. const char *build_directory) {
  61. assert(!in_compilation_unit_);
  62. in_compilation_unit_ = true;
  63. current_source_file_name_ = name;
  64. current_source_file_ = module_->FindFile(name);
  65. comp_unit_base_address_ = address;
  66. boundaries_.push_back(static_cast<Module::Address>(address));
  67. return true;
  68. }
  69. bool StabsToModule::EndCompilationUnit(uint64_t address) {
  70. assert(in_compilation_unit_);
  71. in_compilation_unit_ = false;
  72. comp_unit_base_address_ = 0;
  73. current_source_file_ = NULL;
  74. current_source_file_name_ = NULL;
  75. if (address)
  76. boundaries_.push_back(static_cast<Module::Address>(address));
  77. return true;
  78. }
  79. bool StabsToModule::StartFunction(const string &name,
  80. uint64_t address) {
  81. assert(!current_function_);
  82. Module::Function *f = new Module::Function;
  83. f->name = Demangle(name);
  84. f->address = address;
  85. f->size = 0; // We compute this in StabsToModule::Finalize().
  86. f->parameter_size = 0; // We don't provide this information.
  87. current_function_ = f;
  88. boundaries_.push_back(static_cast<Module::Address>(address));
  89. return true;
  90. }
  91. bool StabsToModule::EndFunction(uint64_t address) {
  92. assert(current_function_);
  93. // Functions in this compilation unit should have address bigger
  94. // than the compilation unit's starting address. There may be a lot
  95. // of duplicated entries for functions in the STABS data. We will
  96. // count on the Module to remove the duplicates.
  97. if (current_function_->address >= comp_unit_base_address_)
  98. functions_.push_back(current_function_);
  99. else
  100. delete current_function_;
  101. current_function_ = NULL;
  102. if (address)
  103. boundaries_.push_back(static_cast<Module::Address>(address));
  104. return true;
  105. }
  106. bool StabsToModule::Line(uint64_t address, const char *name, int number) {
  107. assert(current_function_);
  108. assert(current_source_file_);
  109. if (name != current_source_file_name_) {
  110. current_source_file_ = module_->FindFile(name);
  111. current_source_file_name_ = name;
  112. }
  113. Module::Line line;
  114. line.address = address;
  115. line.size = 0; // We compute this in StabsToModule::Finalize().
  116. line.file = current_source_file_;
  117. line.number = number;
  118. current_function_->lines.push_back(line);
  119. return true;
  120. }
  121. bool StabsToModule::Extern(const string &name, uint64_t address) {
  122. Module::Extern *ext = new Module::Extern;
  123. // Older libstdc++ demangle implementations can crash on unexpected
  124. // input, so be careful about what gets passed in.
  125. if (name.compare(0, 3, "__Z") == 0) {
  126. ext->name = Demangle(name.substr(1));
  127. } else if (name[0] == '_') {
  128. ext->name = name.substr(1);
  129. } else {
  130. ext->name = name;
  131. }
  132. ext->address = address;
  133. module_->AddExtern(ext);
  134. return true;
  135. }
  136. void StabsToModule::Warning(const char *format, ...) {
  137. va_list args;
  138. va_start(args, format);
  139. vfprintf(stderr, format, args);
  140. va_end(args);
  141. }
  142. void StabsToModule::Finalize() {
  143. // Sort our boundary list, so we can search it quickly.
  144. sort(boundaries_.begin(), boundaries_.end());
  145. // Sort all functions by address, just for neatness.
  146. sort(functions_.begin(), functions_.end(),
  147. Module::Function::CompareByAddress);
  148. for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
  149. func_it != functions_.end();
  150. func_it++) {
  151. Module::Function *f = *func_it;
  152. // Compute the function f's size.
  153. vector<Module::Address>::const_iterator boundary
  154. = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
  155. if (boundary != boundaries_.end())
  156. f->size = *boundary - f->address;
  157. else
  158. // If this is the last function in the module, and the STABS
  159. // reader was unable to give us its ending address, then assign
  160. // it a bogus, very large value. This will happen at most once
  161. // per module: since we've added all functions' addresses to the
  162. // boundary table, only one can be the last.
  163. f->size = kFallbackSize;
  164. // Compute sizes for each of the function f's lines --- if it has any.
  165. if (!f->lines.empty()) {
  166. stable_sort(f->lines.begin(), f->lines.end(),
  167. Module::Line::CompareByAddress);
  168. vector<Module::Line>::iterator last_line = f->lines.end() - 1;
  169. for (vector<Module::Line>::iterator line_it = f->lines.begin();
  170. line_it != last_line; line_it++)
  171. line_it[0].size = line_it[1].address - line_it[0].address;
  172. // Compute the size of the last line from f's end address.
  173. last_line->size = (f->address + f->size) - last_line->address;
  174. }
  175. }
  176. // Now that everything has a size, add our functions to the module, and
  177. // dispose of our private list.
  178. module_->AddFunctions(functions_.begin(), functions_.end());
  179. functions_.clear();
  180. }
  181. } // namespace google_breakpad