/thirdparty/breakpad/common/dwarf_cfi_to_module.cc

http://github.com/tomahawk-player/tomahawk · C++ · 247 lines · 158 code · 37 blank · 52 comment · 8 complexity · d7c01a320ac68e12c9390797a7526cc7 MD5 · raw file

  1. // -*- mode: c++ -*-
  2. // Copyright (c) 2010, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
  31. // Implementation of google_breakpad::DwarfCFIToModule.
  32. // See dwarf_cfi_to_module.h for details.
  33. #include <sstream>
  34. #include "common/dwarf_cfi_to_module.h"
  35. namespace google_breakpad {
  36. using std::ostringstream;
  37. vector<string> DwarfCFIToModule::RegisterNames::MakeVector(
  38. const char * const *strings,
  39. size_t size) {
  40. vector<string> names(strings, strings + size);
  41. return names;
  42. }
  43. vector<string> DwarfCFIToModule::RegisterNames::I386() {
  44. static const char *const names[] = {
  45. "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
  46. "$eip", "$eflags", "$unused1",
  47. "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
  48. "$unused2", "$unused3",
  49. "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
  50. "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
  51. "$fcw", "$fsw", "$mxcsr",
  52. "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
  53. "$tr", "$ldtr"
  54. };
  55. return MakeVector(names, sizeof(names) / sizeof(names[0]));
  56. }
  57. vector<string> DwarfCFIToModule::RegisterNames::X86_64() {
  58. static const char *const names[] = {
  59. "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
  60. "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
  61. "$rip",
  62. "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
  63. "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
  64. "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
  65. "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
  66. "$rflags",
  67. "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2",
  68. "$fs.base", "$gs.base", "$unused3", "$unused4",
  69. "$tr", "$ldtr",
  70. "$mxcsr", "$fcw", "$fsw"
  71. };
  72. return MakeVector(names, sizeof(names) / sizeof(names[0]));
  73. }
  74. vector<string> DwarfCFIToModule::RegisterNames::ARM() {
  75. static const char *const names[] = {
  76. "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  77. "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
  78. "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
  79. "fps", "cpsr"
  80. };
  81. return MakeVector(names, sizeof(names) / sizeof(names[0]));
  82. }
  83. bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
  84. uint8 version, const string &augmentation,
  85. unsigned return_address) {
  86. assert(!entry_);
  87. // If dwarf2reader::CallFrameInfo can handle this version and
  88. // augmentation, then we should be okay with that, so there's no
  89. // need to check them here.
  90. // Get ready to collect entries.
  91. entry_ = new Module::StackFrameEntry;
  92. entry_->address = address;
  93. entry_->size = length;
  94. entry_offset_ = offset;
  95. return_address_ = return_address;
  96. // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
  97. // may not establish any rule for .ra if the return address column
  98. // is an ordinary register, and that register holds the return
  99. // address on entry to the function. So establish an initial .ra
  100. // rule citing the return address register.
  101. if (return_address_ < register_names_.size())
  102. entry_->initial_rules[ra_name_] = register_names_[return_address_];
  103. return true;
  104. }
  105. string DwarfCFIToModule::RegisterName(int i) {
  106. assert(entry_);
  107. if (i < 0) {
  108. assert(i == kCFARegister);
  109. return cfa_name_;
  110. }
  111. unsigned reg = i;
  112. if (reg == return_address_)
  113. return ra_name_;
  114. if (reg < register_names_.size())
  115. return register_names_[reg];
  116. reporter_->UnnamedRegister(entry_offset_, reg);
  117. char buf[30];
  118. sprintf(buf, "unnamed_register%u", reg);
  119. return buf;
  120. }
  121. void DwarfCFIToModule::Record(Module::Address address, int reg,
  122. const string &rule) {
  123. assert(entry_);
  124. // Place the name in our global set of strings, and then use the string
  125. // from the set. Even though the assignment looks like a copy, all the
  126. // major std::string implementations use reference counting internally,
  127. // so the effect is to have all our data structures share copies of rules
  128. // whenever possible. Since register names are drawn from a
  129. // vector<string>, register names are already shared.
  130. string shared_rule = *common_strings_.insert(rule).first;
  131. // Is this one of this entry's initial rules?
  132. if (address == entry_->address)
  133. entry_->initial_rules[RegisterName(reg)] = shared_rule;
  134. // File it under the appropriate address.
  135. else
  136. entry_->rule_changes[address][RegisterName(reg)] = shared_rule;
  137. }
  138. bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
  139. reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
  140. // Treat this as a non-fatal error.
  141. return true;
  142. }
  143. bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
  144. ostringstream s;
  145. s << RegisterName(reg);
  146. Record(address, reg, s.str());
  147. return true;
  148. }
  149. bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
  150. int base_register, long offset) {
  151. ostringstream s;
  152. s << RegisterName(base_register) << " " << offset << " + ^";
  153. Record(address, reg, s.str());
  154. return true;
  155. }
  156. bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
  157. int base_register, long offset) {
  158. ostringstream s;
  159. s << RegisterName(base_register) << " " << offset << " +";
  160. Record(address, reg, s.str());
  161. return true;
  162. }
  163. bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
  164. int base_register) {
  165. ostringstream s;
  166. s << RegisterName(base_register);
  167. Record(address, reg, s.str());
  168. return true;
  169. }
  170. bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
  171. const string &expression) {
  172. reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
  173. // Treat this as a non-fatal error.
  174. return true;
  175. }
  176. bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
  177. const string &expression) {
  178. reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
  179. // Treat this as a non-fatal error.
  180. return true;
  181. }
  182. bool DwarfCFIToModule::End() {
  183. module_->AddStackFrameEntry(entry_);
  184. entry_ = NULL;
  185. return true;
  186. }
  187. void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
  188. fprintf(stderr, "%s, section '%s': "
  189. "the call frame entry at offset 0x%zx refers to register %d,"
  190. " whose name we don't know\n",
  191. file_.c_str(), section_.c_str(), offset, reg);
  192. }
  193. void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset,
  194. const string &reg) {
  195. fprintf(stderr, "%s, section '%s': "
  196. "the call frame entry at offset 0x%zx sets the rule for "
  197. "register '%s' to 'undefined', but the Breakpad symbol file format"
  198. " cannot express this\n",
  199. file_.c_str(), section_.c_str(), offset, reg.c_str());
  200. }
  201. void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset,
  202. const string &reg) {
  203. fprintf(stderr, "%s, section '%s': "
  204. "the call frame entry at offset 0x%zx uses a DWARF expression to"
  205. " describe how to recover register '%s', "
  206. " but this translator cannot yet translate DWARF expressions to"
  207. " Breakpad postfix expressions\n",
  208. file_.c_str(), section_.c_str(), offset, reg.c_str());
  209. }
  210. } // namespace google_breakpad