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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 // -*- mode: c++ -*-
     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.
    32 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
    34 // Implementation of google_breakpad::DwarfCFIToModule.
    35 // See dwarf_cfi_to_module.h for details.
    37 #include <sstream>
    38 #include <iomanip>
    40 #include "common/dwarf_cfi_to_module.h"
    41 #include "common/logging.h"
    43 namespace google_breakpad {
    45 using std::ostringstream;
    47 vector<const UniqueString*> DwarfCFIToModule::RegisterNames::MakeVector(
    48     const char* const* strings,
    49     size_t size) {
    50   vector<const UniqueString*> names(size, NULL);
    51   for (size_t i = 0; i < size; ++i) {
    52     names[i] = ToUniqueString(strings[i]);
    53   }
    55   return names;
    56 }
    58 vector<const UniqueString*> DwarfCFIToModule::RegisterNames::I386() {
    59   static const char *const names[] = {
    60     "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
    61     "$eip", "$eflags", "$unused1",
    62     "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    63     "$unused2", "$unused3",
    64     "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    65     "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    66     "$fcw", "$fsw", "$mxcsr",
    67     "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
    68     "$tr", "$ldtr"
    69   };
    71   return MakeVector(names, sizeof(names) / sizeof(names[0]));
    72 }
    74 vector<const UniqueString*> DwarfCFIToModule::RegisterNames::X86_64() {
    75   static const char *const names[] = {
    76     "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
    77     "$r8",  "$r9",  "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
    78     "$rip",
    79     "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
    80     "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
    81     "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
    82     "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
    83     "$rflags",
    84     "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2",
    85     "$fs.base", "$gs.base", "$unused3", "$unused4",
    86     "$tr", "$ldtr",
    87     "$mxcsr", "$fcw", "$fsw"
    88   };
    90   return MakeVector(names, sizeof(names) / sizeof(names[0]));
    91 }
    93 // Per ARM IHI 0040A, section 3.1
    94 vector<const UniqueString*> DwarfCFIToModule::RegisterNames::ARM() {
    95   static const char *const names[] = {
    96     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
    97     "r8",  "r9",  "r10", "r11", "r12", "sp",  "lr",  "pc",
    98     "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
    99     "fps", "cpsr", "",   "",    "",    "",    "",    "",
   100     "",    "",    "",    "",    "",    "",    "",    "",
   101     "",    "",    "",    "",    "",    "",    "",    "",
   102     "",    "",    "",    "",    "",    "",    "",    "",
   103     "",    "",    "",    "",    "",    "",    "",    "",
   104     "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
   105     "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
   106     "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
   107     "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
   108     "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7"
   109   };
   111   return MakeVector(names, sizeof(names) / sizeof(names[0]));
   112 }
   114 bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
   115                              uint8 version, const string &augmentation,
   116                              unsigned return_address) {
   117   assert(!entry_);
   119   // If dwarf2reader::CallFrameInfo can handle this version and
   120   // augmentation, then we should be okay with that, so there's no
   121   // need to check them here.
   123   // Get ready to collect entries.
   124   entry_ = new Module::StackFrameEntry;
   125   entry_->address = address;
   126   entry_->size = length;
   127   entry_offset_ = offset;
   128   return_address_ = return_address;
   130   // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
   131   // may not establish any rule for .ra if the return address column
   132   // is an ordinary register, and that register holds the return
   133   // address on entry to the function. So establish an initial .ra
   134   // rule citing the return address register.
   135   if (return_address_ < register_names_.size())
   136     entry_->initial_rules[ustr__ZDra()]
   137       = Module::Expr(register_names_[return_address_], 0, false);
   139   return true;
   140 }
   142 const UniqueString* DwarfCFIToModule::RegisterName(int i) {
   143   assert(entry_);
   144   if (i < 0) {
   145     assert(i == kCFARegister);
   146     return ustr__ZDcfa();
   147   }
   148   unsigned reg = i;
   149   if (reg == return_address_)
   150     return ustr__ZDra();
   152   // Ensure that a non-empty name exists for this register value.
   153   if (reg < register_names_.size() && register_names_[reg] != ustr__empty())
   154     return register_names_[reg];
   156   reporter_->UnnamedRegister(entry_offset_, reg);
   157   char buf[30];
   158   sprintf(buf, "unnamed_register%u", reg);
   159   return ToUniqueString(buf);
   160 }
   162 void DwarfCFIToModule::Record(Module::Address address, int reg,
   163                               const Module::Expr &rule) {
   164   assert(entry_);
   166   // Is this one of this entry's initial rules?
   167   if (address == entry_->address)
   168     entry_->initial_rules[RegisterName(reg)] = rule;
   169   // File it under the appropriate address.
   170   else
   171     entry_->rule_changes[address][RegisterName(reg)] = rule;
   172 }
   174 bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
   175   reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
   176   // Treat this as a non-fatal error.
   177   return true;
   178 }
   180 bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
   181   // reg + 0
   182   Module::Expr rule
   183     = Module::Expr(RegisterName(reg), 0, false);
   184   Record(address, reg, rule);
   185   return true;
   186 }
   188 bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
   189                                   int base_register, long offset) {
   190   // *(base_register + offset)
   191   Module::Expr rule
   192     = Module::Expr(RegisterName(base_register), offset, true);
   193   Record(address, reg, rule);
   194   return true;
   195 }
   197 bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
   198                                      int base_register, long offset) {
   199   // base_register + offset
   200   Module::Expr rule
   201     = Module::Expr(RegisterName(base_register), offset, false);
   202   Record(address, reg, rule);
   203   return true;
   204 }
   206 bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
   207                                     int base_register) {
   208   // base_register + 0
   209   Module::Expr rule
   210     = Module::Expr(RegisterName(base_register), 0, false);
   211   Record(address, reg, rule);
   212   return true;
   213 }
   215 bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
   216                                       const string &expression) {
   217   reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
   218   // Treat this as a non-fatal error.
   219   return true;
   220 }
   222 bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
   223                                          const string &expression) {
   224   reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
   225   // Treat this as a non-fatal error.
   226   return true;
   227 }
   229 bool DwarfCFIToModule::End() {
   230   module_->AddStackFrameEntry(entry_);
   231   entry_ = NULL;
   232   return true;
   233 }
   235 void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
   236   BPLOG(INFO) << file_ << ", section '" << section_ 
   237     << "': the call frame entry at offset 0x" 
   238     << std::setbase(16) << offset << std::setbase(10)
   239     << " refers to register " << reg << ", whose name we don't know";
   240 }
   242 void DwarfCFIToModule::Reporter::UndefinedNotSupported(
   243     size_t offset,
   244     const UniqueString* reg) {
   245   BPLOG(INFO) << file_ << ", section '" << section_ 
   246     << "': the call frame entry at offset 0x" 
   247     << std::setbase(16) << offset << std::setbase(10)
   248     << " sets the rule for register '" << FromUniqueString(reg)
   249     << "' to 'undefined', but the Breakpad symbol file format cannot "
   250     << " express this";
   251 }
   253 void DwarfCFIToModule::Reporter::ExpressionsNotSupported(
   254     size_t offset,
   255     const UniqueString* reg) {
   256   static uint64_t n_complaints = 0; // This isn't threadsafe
   257   n_complaints++;
   258   if (!is_power_of_2(n_complaints))
   259     return;
   260   BPLOG(INFO) << file_ << ", section '" << section_ 
   261     << "': the call frame entry at offset 0x" 
   262     << std::setbase(16) << offset << std::setbase(10)
   263     << " uses a DWARF expression to describe how to recover register '"
   264     << FromUniqueString(reg) << "', but this translator cannot yet "
   265     << "translate DWARF expressions to Breakpad postfix expressions (shown "
   266     << n_complaints << " times)";
   267 }
   269 } // namespace google_breakpad

mercurial