/thirdparty/breakpad/processor/source_line_resolver_base.cc

http://github.com/tomahawk-player/tomahawk · C++ · 311 lines · 208 code · 53 blank · 50 comment · 52 complexity · 95968702c56e949bbf4e053615ba0896 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. //
  30. // source_line_resolver_base.cc: Implementation of SourceLineResolverBase.
  31. //
  32. // See source_line_resolver_base.h and source_line_resolver_base_types.h for
  33. // more documentation.
  34. //
  35. // Author: Siyang Xie (lambxsy@google.com)
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <sys/stat.h>
  39. #include <map>
  40. #include <utility>
  41. #include "google_breakpad/processor/source_line_resolver_base.h"
  42. #include "processor/source_line_resolver_base_types.h"
  43. #include "processor/module_factory.h"
  44. using std::map;
  45. using std::make_pair;
  46. namespace google_breakpad {
  47. SourceLineResolverBase::SourceLineResolverBase(
  48. ModuleFactory *module_factory)
  49. : modules_(new ModuleMap),
  50. memory_buffers_(new MemoryMap),
  51. module_factory_(module_factory) {
  52. }
  53. SourceLineResolverBase::~SourceLineResolverBase() {
  54. ModuleMap::iterator it;
  55. // Iterate through ModuleMap and delete all loaded modules.
  56. for (it = modules_->begin(); it != modules_->end(); ++it) {
  57. // Delete individual module.
  58. delete it->second;
  59. }
  60. // Delete the map of modules.
  61. delete modules_;
  62. MemoryMap::iterator iter = memory_buffers_->begin();
  63. for (; iter != memory_buffers_->end(); ++iter) {
  64. delete [] iter->second;
  65. }
  66. // Delete the map of memory buffers.
  67. delete memory_buffers_;
  68. delete module_factory_;
  69. }
  70. bool SourceLineResolverBase::ReadSymbolFile(char **symbol_data,
  71. const string &map_file) {
  72. if (symbol_data == NULL) {
  73. BPLOG(ERROR) << "Could not Read file into Null memory pointer";
  74. return false;
  75. }
  76. struct stat buf;
  77. int error_code = stat(map_file.c_str(), &buf);
  78. if (error_code == -1) {
  79. string error_string;
  80. error_code = ErrnoString(&error_string);
  81. BPLOG(ERROR) << "Could not open " << map_file <<
  82. ", error " << error_code << ": " << error_string;
  83. return false;
  84. }
  85. off_t file_size = buf.st_size;
  86. // Allocate memory for file contents, plus a null terminator
  87. // since we may use strtok() on the contents.
  88. *symbol_data = new char[file_size + 1];
  89. if (*symbol_data == NULL) {
  90. BPLOG(ERROR) << "Could not allocate memory for " << map_file;
  91. return false;
  92. }
  93. BPLOG(INFO) << "Opening " << map_file;
  94. FILE *f = fopen(map_file.c_str(), "rt");
  95. if (!f) {
  96. string error_string;
  97. error_code = ErrnoString(&error_string);
  98. BPLOG(ERROR) << "Could not open " << map_file <<
  99. ", error " << error_code << ": " << error_string;
  100. delete [] (*symbol_data);
  101. *symbol_data = NULL;
  102. return false;
  103. }
  104. AutoFileCloser closer(f);
  105. int items_read = 0;
  106. items_read = fread(*symbol_data, 1, file_size, f);
  107. if (items_read != file_size) {
  108. string error_string;
  109. error_code = ErrnoString(&error_string);
  110. BPLOG(ERROR) << "Could not slurp " << map_file <<
  111. ", error " << error_code << ": " << error_string;
  112. delete [] (*symbol_data);
  113. *symbol_data = NULL;
  114. return false;
  115. }
  116. (*symbol_data)[file_size] = '\0';
  117. return true;
  118. }
  119. bool SourceLineResolverBase::LoadModule(const CodeModule *module,
  120. const string &map_file) {
  121. if (module == NULL)
  122. return false;
  123. // Make sure we don't already have a module with the given name.
  124. if (modules_->find(module->code_file()) != modules_->end()) {
  125. BPLOG(INFO) << "Symbols for module " << module->code_file()
  126. << " already loaded";
  127. return false;
  128. }
  129. BPLOG(INFO) << "Loading symbols for module " << module->code_file()
  130. << " from " << map_file;
  131. char *memory_buffer;
  132. if (!ReadSymbolFile(&memory_buffer, map_file))
  133. return false;
  134. BPLOG(INFO) << "Read symbol file " << map_file << " succeeded";
  135. bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer);
  136. if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
  137. // memory_buffer has to stay alive as long as the module.
  138. memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
  139. } else {
  140. delete [] memory_buffer;
  141. }
  142. return load_result;
  143. }
  144. bool SourceLineResolverBase::LoadModuleUsingMapBuffer(
  145. const CodeModule *module, const string &map_buffer) {
  146. if (module == NULL)
  147. return false;
  148. // Make sure we don't already have a module with the given name.
  149. if (modules_->find(module->code_file()) != modules_->end()) {
  150. BPLOG(INFO) << "Symbols for module " << module->code_file()
  151. << " already loaded";
  152. return false;
  153. }
  154. char *memory_buffer = new char[map_buffer.size() + 1];
  155. if (memory_buffer == NULL) {
  156. BPLOG(ERROR) << "Could not allocate memory for " << module->code_file();
  157. return false;
  158. }
  159. // Can't use strcpy, as the data may contain '\0's before the end.
  160. memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size());
  161. memory_buffer[map_buffer.size()] = '\0';
  162. bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer);
  163. if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) {
  164. // memory_buffer has to stay alive as long as the module.
  165. memory_buffers_->insert(make_pair(module->code_file(), memory_buffer));
  166. } else {
  167. delete [] memory_buffer;
  168. }
  169. return load_result;
  170. }
  171. bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer(
  172. const CodeModule *module, char *memory_buffer) {
  173. if (!module)
  174. return false;
  175. // Make sure we don't already have a module with the given name.
  176. if (modules_->find(module->code_file()) != modules_->end()) {
  177. BPLOG(INFO) << "Symbols for module " << module->code_file()
  178. << " already loaded";
  179. return false;
  180. }
  181. BPLOG(INFO) << "Loading symbols for module " << module->code_file()
  182. << " from memory buffer";
  183. Module *basic_module = module_factory_->CreateModule(module->code_file());
  184. // Ownership of memory is NOT transfered to Module::LoadMapFromMemory().
  185. if (!basic_module->LoadMapFromMemory(memory_buffer)) {
  186. delete basic_module;
  187. return false;
  188. }
  189. modules_->insert(make_pair(module->code_file(), basic_module));
  190. return true;
  191. }
  192. bool SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule() {
  193. return true;
  194. }
  195. void SourceLineResolverBase::UnloadModule(const CodeModule *code_module) {
  196. if (!code_module)
  197. return;
  198. ModuleMap::iterator mod_iter = modules_->find(code_module->code_file());
  199. if (mod_iter != modules_->end()) {
  200. Module *symbol_module = mod_iter->second;
  201. delete symbol_module;
  202. modules_->erase(mod_iter);
  203. }
  204. if (ShouldDeleteMemoryBufferAfterLoadModule()) {
  205. // No-op. Because we never store any memory buffers.
  206. } else {
  207. // There may be a buffer stored locally, we need to find and delete it.
  208. MemoryMap::iterator iter = memory_buffers_->find(code_module->code_file());
  209. if (iter != memory_buffers_->end()) {
  210. delete [] iter->second;
  211. memory_buffers_->erase(iter);
  212. }
  213. }
  214. }
  215. bool SourceLineResolverBase::HasModule(const CodeModule *module) {
  216. if (!module)
  217. return false;
  218. return modules_->find(module->code_file()) != modules_->end();
  219. }
  220. void SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) {
  221. if (frame->module) {
  222. ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
  223. if (it != modules_->end()) {
  224. it->second->LookupAddress(frame);
  225. }
  226. }
  227. }
  228. WindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo(
  229. const StackFrame *frame) {
  230. if (frame->module) {
  231. ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
  232. if (it != modules_->end()) {
  233. return it->second->FindWindowsFrameInfo(frame);
  234. }
  235. }
  236. return NULL;
  237. }
  238. CFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo(
  239. const StackFrame *frame) {
  240. if (frame->module) {
  241. ModuleMap::const_iterator it = modules_->find(frame->module->code_file());
  242. if (it != modules_->end()) {
  243. return it->second->FindCFIFrameInfo(frame);
  244. }
  245. }
  246. return NULL;
  247. }
  248. bool SourceLineResolverBase::CompareString::operator()(
  249. const string &s1, const string &s2) const {
  250. return strcmp(s1.c_str(), s2.c_str()) < 0;
  251. }
  252. bool SourceLineResolverBase::Module::ParseCFIRuleSet(
  253. const string &rule_set, CFIFrameInfo *frame_info) const {
  254. CFIFrameInfoParseHandler handler(frame_info);
  255. CFIRuleParser parser(&handler);
  256. return parser.Parse(rule_set);
  257. }
  258. } // namespace google_breakpad