PageRenderTime 190ms CodeModel.GetById 168ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

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