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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial