LCOV - app.info - toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc

LCOV - code coverage report
| Current view: | directory - toolkit/crashreporter/google-breakpad/src/common - dwarf_cfi_to_module.cc (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 80 | 59 | 73.8 %
| Date: | 2012-04-07 | Functions: | 18 | 12 | 66.7 %

           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                 :
          41                 : namespace google_breakpad {
          42                 :
          43                 : using std::ostringstream;
          44                 :
          45             248 : vector<string> DwarfCFIToModule::RegisterNames::MakeVector(
          46                 :     const char * const *strings,
          47                 :     size_t size) {
          48             248 :   vector<string> names(strings, strings + size);
          49                 :   return names;
          50                 : }
          51                 :
          52             248 : vector<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             248 :   return MakeVector(names, sizeof(names) / sizeof(names[0]));
          66                 : }
          67                 :
          68               0 : vector<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               0 :   return MakeVector(names, sizeof(names) / sizeof(names[0]));
          85                 : }
          86                 :
          87               0 : vector<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               0 :   return MakeVector(names, sizeof(names) / sizeof(names[0]));
          96                 : }
          97                 :
          98          706363 : bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
          99                 :                              uint8 version, const string &augmentation,
         100                 :                              unsigned return_address) {
         101          706363 :   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          706363 :   entry_ = new Module::StackFrameEntry;
         109          706363 :   entry_->address = address;
         110          706363 :   entry_->size = length;
         111          706363 :   entry_offset_ = offset;
         112          706363 :   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          706363 :   if (return_address_ < register_names_.size())
         120          706363 :     entry_->initial_rules[ra_name_] = register_names_[return_address_];
         121                 :
         122          706363 :   return true;
         123                 : }
         124                 :
         125        12885750 : string DwarfCFIToModule::RegisterName(int i) {
         126        12885750 :   assert(entry_);
         127        12885750 :   if (i < 0) {
         128         4959840 :     assert(i == kCFARegister);
         129         4959840 :     return cfa_name_;
         130                 :   }
         131         7925910 :   unsigned reg = i;
         132         7925910 :   if (reg == return_address_)
         133          706363 :     return ra_name_;
         134                 :
         135         7219547 :   if (0 <= reg && reg < register_names_.size())
         136         7219547 :     return register_names_[reg];
         137                 :
         138               0 :   reporter_->UnnamedRegister(entry_offset_, reg);
         139                 :   char buf[30];
         140               0 :   sprintf(buf, "unnamed_register%u", reg);
         141               0 :   return buf;
         142                 : }
         143                 :
         144         6442729 : void DwarfCFIToModule::Record(Module::Address address, int reg,
         145                 :                               const string &rule) {
         146         6442729 :   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        12885458 :   string shared_rule = *common_strings_.insert(rule).first;
         155                 :
         156                 :   // Is this one of this entry's initial rules?
         157         6442729 :   if (address == entry_->address)
         158         1412726 :     entry_->initial_rules[RegisterName(reg)] = shared_rule;
         159                 :   // File it under the appropriate address.
         160                 :   else
         161         5030003 :     entry_->rule_changes[address][RegisterName(reg)] = shared_rule;
         162         6442729 : }
         163                 :
         164               0 : bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
         165               0 :   reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
         166                 :   // Treat this as a non-fatal error.
         167               0 :   return true;
         168                 : }
         169                 :
         170         1482926 : bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
         171         2965852 :   ostringstream s;
         172         1482926 :   s << RegisterName(reg);
         173         1482926 :   Record(address, reg, s.str());
         174         1482926 :   return true;
         175                 : }
         176                 :
         177         2231570 : bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
         178                 :                                   int base_register, long offset) {
         179         4463140 :   ostringstream s;
         180         2231570 :   s << RegisterName(base_register) << " " << offset << " + ^";
         181         2231570 :   Record(address, reg, s.str());
         182         2231570 :   return true;
         183                 : }
         184                 :
         185         2728233 : bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
         186                 :                                      int base_register, long offset) {
         187         5456466 :   ostringstream s;
         188         2728233 :   s << RegisterName(base_register) << " " << offset << " +";
         189         2728233 :   Record(address, reg, s.str());
         190         2728233 :   return true;
         191                 : }
         192                 :
         193               0 : bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
         194                 :                                     int base_register) {
         195               0 :   ostringstream s;
         196               0 :   s << RegisterName(base_register);
         197               0 :   Record(address, reg, s.str());
         198               0 :   return true;
         199                 : }
         200                 :
         201             255 : bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
         202                 :                                       const string &expression) {
         203             255 :   reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
         204                 :   // Treat this as a non-fatal error.
         205             255 :   return true;
         206                 : }
         207                 :
         208              37 : bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
         209                 :                                          const string &expression) {
         210              37 :   reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
         211                 :   // Treat this as a non-fatal error.
         212              37 :   return true;
         213                 : }
         214                 :
         215          706363 : bool DwarfCFIToModule::End() {
         216          706363 :   module_->AddStackFrameEntry(entry_);
         217          706363 :   entry_ = NULL;
         218          706363 :   return true;
         219                 : }
         220                 :
         221               0 : void 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               0 :           file_.c_str(), section_.c_str(), offset, reg);
         226               0 : }
         227                 :
         228               0 : void 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               0 :           file_.c_str(), section_.c_str(), offset, reg.c_str());
         235               0 : }
         236                 :
         237             292 : void 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             292 :           file_.c_str(), section_.c_str(), offset, reg.c_str());
         245             292 : }
         246                 :
         247                 : } // namespace google_breakpad

Generated by: LCOV version 1.7