PageRenderTime 37ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/common/dwarf/functioninfo.cc

http://github.com/tomahawk-player/tomahawk
C++ | 229 lines | 156 code | 27 blank | 46 comment | 34 complexity | 56173f41169047002500e42a01090abe MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, GPL-3.0, GPL-2.0
  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. // This is a client for the dwarf2reader to extract function and line
  29. // information from the debug info.
  30. #include <assert.h>
  31. #include <limits.h>
  32. #include <stdio.h>
  33. #include <map>
  34. #include <queue>
  35. #include <vector>
  36. #include <memory>
  37. #include "common/dwarf/functioninfo.h"
  38. #include "common/dwarf/bytereader.h"
  39. namespace dwarf2reader {
  40. CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
  41. std::vector<std::string>* dirs,
  42. LineMap* linemap):linemap_(linemap),
  43. files_(files),
  44. dirs_(dirs) {
  45. // The dirs and files are 1 indexed, so just make sure we put
  46. // nothing in the 0 vector.
  47. assert(dirs->size() == 0);
  48. assert(files->size() == 0);
  49. dirs->push_back("");
  50. SourceFileInfo s;
  51. s.name = "";
  52. s.lowpc = ULLONG_MAX;
  53. files->push_back(s);
  54. }
  55. void CULineInfoHandler::DefineDir(const std::string& name, uint32 dir_num) {
  56. // These should never come out of order, actually
  57. assert(dir_num == dirs_->size());
  58. dirs_->push_back(name);
  59. }
  60. void CULineInfoHandler::DefineFile(const std::string& name,
  61. int32 file_num, uint32 dir_num,
  62. uint64 mod_time, uint64 length) {
  63. assert(dir_num >= 0);
  64. assert(dir_num < dirs_->size());
  65. // These should never come out of order, actually.
  66. if (file_num == (int32)files_->size() || file_num == -1) {
  67. std::string dir = dirs_->at(dir_num);
  68. SourceFileInfo s;
  69. s.lowpc = ULLONG_MAX;
  70. if (dir == "") {
  71. s.name = name;
  72. } else {
  73. s.name = dir + "/" + name;
  74. }
  75. files_->push_back(s);
  76. } else {
  77. fprintf(stderr, "error in DefineFile");
  78. }
  79. }
  80. void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num,
  81. uint32 line_num, uint32 column_num) {
  82. if (file_num < files_->size()) {
  83. linemap_->insert(
  84. std::make_pair(address,
  85. std::make_pair(files_->at(file_num).name.c_str(),
  86. line_num)));
  87. if(address < files_->at(file_num).lowpc) {
  88. files_->at(file_num).lowpc = address;
  89. }
  90. } else {
  91. fprintf(stderr,"error in AddLine");
  92. }
  93. }
  94. bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
  95. uint8 address_size,
  96. uint8 offset_size,
  97. uint64 cu_length,
  98. uint8 dwarf_version) {
  99. current_compilation_unit_offset_ = offset;
  100. return true;
  101. }
  102. // For function info, we only care about subprograms and inlined
  103. // subroutines. For line info, the DW_AT_stmt_list lives in the
  104. // compile unit tag.
  105. bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag,
  106. const AttributeList& attrs) {
  107. switch (tag) {
  108. case DW_TAG_subprogram:
  109. case DW_TAG_inlined_subroutine: {
  110. current_function_info_ = new FunctionInfo;
  111. current_function_info_->lowpc = current_function_info_->highpc = 0;
  112. current_function_info_->name = "";
  113. current_function_info_->line = 0;
  114. current_function_info_->file = "";
  115. offset_to_funcinfo_->insert(std::make_pair(offset,
  116. current_function_info_));
  117. };
  118. // FALLTHROUGH
  119. case DW_TAG_compile_unit:
  120. return true;
  121. default:
  122. return false;
  123. }
  124. return false;
  125. }
  126. // Only care about the name attribute for functions
  127. void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
  128. enum DwarfAttribute attr,
  129. enum DwarfForm form,
  130. const std::string &data) {
  131. if (current_function_info_) {
  132. if (attr == DW_AT_name)
  133. current_function_info_->name = data;
  134. else if(attr == DW_AT_MIPS_linkage_name)
  135. current_function_info_->mangled_name = data;
  136. }
  137. }
  138. void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
  139. enum DwarfAttribute attr,
  140. enum DwarfForm form,
  141. uint64 data) {
  142. if (attr == DW_AT_stmt_list) {
  143. SectionMap::const_iterator iter = sections_.find("__debug_line");
  144. assert(iter != sections_.end());
  145. // this should be a scoped_ptr but we dont' use boost :-(
  146. std::auto_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
  147. iter->second.second - data,
  148. reader_, linehandler_));
  149. lireader->Start();
  150. } else if (current_function_info_) {
  151. switch (attr) {
  152. case DW_AT_low_pc:
  153. current_function_info_->lowpc = data;
  154. break;
  155. case DW_AT_high_pc:
  156. current_function_info_->highpc = data;
  157. break;
  158. case DW_AT_decl_line:
  159. current_function_info_->line = data;
  160. break;
  161. case DW_AT_decl_file:
  162. current_function_info_->file = files_->at(data).name;
  163. break;
  164. default:
  165. break;
  166. }
  167. }
  168. }
  169. void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
  170. enum DwarfAttribute attr,
  171. enum DwarfForm form,
  172. uint64 data) {
  173. if (current_function_info_) {
  174. switch (attr) {
  175. case DW_AT_specification: {
  176. // Some functions have a "specification" attribute
  177. // which means they were defined elsewhere. The name
  178. // attribute is not repeated, and must be taken from
  179. // the specification DIE. Here we'll assume that
  180. // any DIE referenced in this manner will already have
  181. // been seen, but that's not really required by the spec.
  182. FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
  183. if (iter != offset_to_funcinfo_->end()) {
  184. current_function_info_->name = iter->second->name;
  185. current_function_info_->mangled_name = iter->second->mangled_name;
  186. } else {
  187. // If you hit this, this code probably needs to be rewritten.
  188. fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", data, offset);
  189. }
  190. break;
  191. }
  192. default:
  193. break;
  194. }
  195. }
  196. }
  197. void CUFunctionInfoHandler::EndDIE(uint64 offset) {
  198. if (current_function_info_ && current_function_info_->lowpc)
  199. address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
  200. current_function_info_));
  201. }
  202. } // namespace dwarf2reader