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