toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,269 @@
     1.4 +// -*- mode: c++ -*-
     1.5 +
     1.6 +// Copyright (c) 2010, Google Inc.
     1.7 +// All rights reserved.
     1.8 +//
     1.9 +// Redistribution and use in source and binary forms, with or without
    1.10 +// modification, are permitted provided that the following conditions are
    1.11 +// met:
    1.12 +//
    1.13 +//     * Redistributions of source code must retain the above copyright
    1.14 +// notice, this list of conditions and the following disclaimer.
    1.15 +//     * Redistributions in binary form must reproduce the above
    1.16 +// copyright notice, this list of conditions and the following disclaimer
    1.17 +// in the documentation and/or other materials provided with the
    1.18 +// distribution.
    1.19 +//     * Neither the name of Google Inc. nor the names of its
    1.20 +// contributors may be used to endorse or promote products derived from
    1.21 +// this software without specific prior written permission.
    1.22 +//
    1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.34 +
    1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    1.36 +
    1.37 +// Implementation of google_breakpad::DwarfCFIToModule.
    1.38 +// See dwarf_cfi_to_module.h for details.
    1.39 +
    1.40 +#include <sstream>
    1.41 +#include <iomanip>
    1.42 +
    1.43 +#include "common/dwarf_cfi_to_module.h"
    1.44 +#include "common/logging.h"
    1.45 +
    1.46 +namespace google_breakpad {
    1.47 +
    1.48 +using std::ostringstream;
    1.49 +
    1.50 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::MakeVector(
    1.51 +    const char* const* strings,
    1.52 +    size_t size) {
    1.53 +  vector<const UniqueString*> names(size, NULL);
    1.54 +  for (size_t i = 0; i < size; ++i) {
    1.55 +    names[i] = ToUniqueString(strings[i]);
    1.56 +  }
    1.57 +
    1.58 +  return names;
    1.59 +}
    1.60 +
    1.61 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::I386() {
    1.62 +  static const char *const names[] = {
    1.63 +    "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
    1.64 +    "$eip", "$eflags", "$unused1",
    1.65 +    "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    1.66 +    "$unused2", "$unused3",
    1.67 +    "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    1.68 +    "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    1.69 +    "$fcw", "$fsw", "$mxcsr",
    1.70 +    "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
    1.71 +    "$tr", "$ldtr"
    1.72 +  };
    1.73 +
    1.74 +  return MakeVector(names, sizeof(names) / sizeof(names[0]));
    1.75 +}
    1.76 +
    1.77 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::X86_64() {
    1.78 +  static const char *const names[] = {
    1.79 +    "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
    1.80 +    "$r8",  "$r9",  "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
    1.81 +    "$rip",
    1.82 +    "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    1.83 +    "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
    1.84 +    "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    1.85 +    "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    1.86 +    "$rflags",
    1.87 +    "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2",
    1.88 +    "$fs.base", "$gs.base", "$unused3", "$unused4",
    1.89 +    "$tr", "$ldtr",
    1.90 +    "$mxcsr", "$fcw", "$fsw"
    1.91 +  };
    1.92 +
    1.93 +  return MakeVector(names, sizeof(names) / sizeof(names[0]));
    1.94 +}
    1.95 +
    1.96 +// Per ARM IHI 0040A, section 3.1
    1.97 +vector<const UniqueString*> DwarfCFIToModule::RegisterNames::ARM() {
    1.98 +  static const char *const names[] = {
    1.99 +    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
   1.100 +    "r8",  "r9",  "r10", "r11", "r12", "sp",  "lr",  "pc",
   1.101 +    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
   1.102 +    "fps", "cpsr", "",   "",    "",    "",    "",    "",
   1.103 +    "",    "",    "",    "",    "",    "",    "",    "",
   1.104 +    "",    "",    "",    "",    "",    "",    "",    "",
   1.105 +    "",    "",    "",    "",    "",    "",    "",    "",
   1.106 +    "",    "",    "",    "",    "",    "",    "",    "",
   1.107 +    "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
   1.108 +    "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
   1.109 +    "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
   1.110 +    "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
   1.111 +    "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7"
   1.112 +  };
   1.113 +
   1.114 +  return MakeVector(names, sizeof(names) / sizeof(names[0]));
   1.115 +}
   1.116 +
   1.117 +bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
   1.118 +                             uint8 version, const string &augmentation,
   1.119 +                             unsigned return_address) {
   1.120 +  assert(!entry_);
   1.121 +
   1.122 +  // If dwarf2reader::CallFrameInfo can handle this version and
   1.123 +  // augmentation, then we should be okay with that, so there's no
   1.124 +  // need to check them here.
   1.125 +
   1.126 +  // Get ready to collect entries.
   1.127 +  entry_ = new Module::StackFrameEntry;
   1.128 +  entry_->address = address;
   1.129 +  entry_->size = length;
   1.130 +  entry_offset_ = offset;
   1.131 +  return_address_ = return_address;
   1.132 +
   1.133 +  // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
   1.134 +  // may not establish any rule for .ra if the return address column
   1.135 +  // is an ordinary register, and that register holds the return
   1.136 +  // address on entry to the function. So establish an initial .ra
   1.137 +  // rule citing the return address register.
   1.138 +  if (return_address_ < register_names_.size())
   1.139 +    entry_->initial_rules[ustr__ZDra()]
   1.140 +      = Module::Expr(register_names_[return_address_], 0, false);
   1.141 +
   1.142 +  return true;
   1.143 +}
   1.144 +
   1.145 +const UniqueString* DwarfCFIToModule::RegisterName(int i) {
   1.146 +  assert(entry_);
   1.147 +  if (i < 0) {
   1.148 +    assert(i == kCFARegister);
   1.149 +    return ustr__ZDcfa();
   1.150 +  }
   1.151 +  unsigned reg = i;
   1.152 +  if (reg == return_address_)
   1.153 +    return ustr__ZDra();
   1.154 +
   1.155 +  // Ensure that a non-empty name exists for this register value.
   1.156 +  if (reg < register_names_.size() && register_names_[reg] != ustr__empty())
   1.157 +    return register_names_[reg];
   1.158 +
   1.159 +  reporter_->UnnamedRegister(entry_offset_, reg);
   1.160 +  char buf[30];
   1.161 +  sprintf(buf, "unnamed_register%u", reg);
   1.162 +  return ToUniqueString(buf);
   1.163 +}
   1.164 +
   1.165 +void DwarfCFIToModule::Record(Module::Address address, int reg,
   1.166 +                              const Module::Expr &rule) {
   1.167 +  assert(entry_);
   1.168 +
   1.169 +  // Is this one of this entry's initial rules?
   1.170 +  if (address == entry_->address)
   1.171 +    entry_->initial_rules[RegisterName(reg)] = rule;
   1.172 +  // File it under the appropriate address.
   1.173 +  else
   1.174 +    entry_->rule_changes[address][RegisterName(reg)] = rule;
   1.175 +}
   1.176 +
   1.177 +bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
   1.178 +  reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
   1.179 +  // Treat this as a non-fatal error.
   1.180 +  return true;
   1.181 +}
   1.182 +
   1.183 +bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
   1.184 +  // reg + 0
   1.185 +  Module::Expr rule
   1.186 +    = Module::Expr(RegisterName(reg), 0, false);
   1.187 +  Record(address, reg, rule);
   1.188 +  return true;
   1.189 +}
   1.190 +
   1.191 +bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
   1.192 +                                  int base_register, long offset) {
   1.193 +  // *(base_register + offset)
   1.194 +  Module::Expr rule
   1.195 +    = Module::Expr(RegisterName(base_register), offset, true);
   1.196 +  Record(address, reg, rule);
   1.197 +  return true;
   1.198 +}
   1.199 +
   1.200 +bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
   1.201 +                                     int base_register, long offset) {
   1.202 +  // base_register + offset
   1.203 +  Module::Expr rule
   1.204 +    = Module::Expr(RegisterName(base_register), offset, false);
   1.205 +  Record(address, reg, rule);
   1.206 +  return true;
   1.207 +}
   1.208 +
   1.209 +bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
   1.210 +                                    int base_register) {
   1.211 +  // base_register + 0
   1.212 +  Module::Expr rule
   1.213 +    = Module::Expr(RegisterName(base_register), 0, false);
   1.214 +  Record(address, reg, rule);
   1.215 +  return true;
   1.216 +}
   1.217 +
   1.218 +bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
   1.219 +                                      const string &expression) {
   1.220 +  reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
   1.221 +  // Treat this as a non-fatal error.
   1.222 +  return true;
   1.223 +}
   1.224 +
   1.225 +bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
   1.226 +                                         const string &expression) {
   1.227 +  reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
   1.228 +  // Treat this as a non-fatal error.
   1.229 +  return true;
   1.230 +}
   1.231 +
   1.232 +bool DwarfCFIToModule::End() {
   1.233 +  module_->AddStackFrameEntry(entry_);
   1.234 +  entry_ = NULL;
   1.235 +  return true;
   1.236 +}
   1.237 +
   1.238 +void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
   1.239 +  BPLOG(INFO) << file_ << ", section '" << section_ 
   1.240 +    << "': the call frame entry at offset 0x" 
   1.241 +    << std::setbase(16) << offset << std::setbase(10)
   1.242 +    << " refers to register " << reg << ", whose name we don't know";
   1.243 +}
   1.244 +
   1.245 +void DwarfCFIToModule::Reporter::UndefinedNotSupported(
   1.246 +    size_t offset,
   1.247 +    const UniqueString* reg) {
   1.248 +  BPLOG(INFO) << file_ << ", section '" << section_ 
   1.249 +    << "': the call frame entry at offset 0x" 
   1.250 +    << std::setbase(16) << offset << std::setbase(10)
   1.251 +    << " sets the rule for register '" << FromUniqueString(reg)
   1.252 +    << "' to 'undefined', but the Breakpad symbol file format cannot "
   1.253 +    << " express this";
   1.254 +}
   1.255 +
   1.256 +void DwarfCFIToModule::Reporter::ExpressionsNotSupported(
   1.257 +    size_t offset,
   1.258 +    const UniqueString* reg) {
   1.259 +  static uint64_t n_complaints = 0; // This isn't threadsafe
   1.260 +  n_complaints++;
   1.261 +  if (!is_power_of_2(n_complaints))
   1.262 +    return;
   1.263 +  BPLOG(INFO) << file_ << ", section '" << section_ 
   1.264 +    << "': the call frame entry at offset 0x" 
   1.265 +    << std::setbase(16) << offset << std::setbase(10)
   1.266 +    << " uses a DWARF expression to describe how to recover register '"
   1.267 +    << FromUniqueString(reg) << "', but this translator cannot yet "
   1.268 +    << "translate DWARF expressions to Breakpad postfix expressions (shown "
   1.269 +    << n_complaints << " times)";
   1.270 +}
   1.271 +
   1.272 +} // namespace google_breakpad

mercurial