1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/breakpad-patches/14-bug883126.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,346 @@ 1.4 +# HG changeset patch 1.5 +# User Julian Seward <jseward@acm.org> 1.6 +# Date 1372168568 -7200 1.7 +# Tue Jun 25 15:56:08 2013 +0200 1.8 +# Node ID 6d06a09b3f5624dd833bd6f905bfd88e3fdec00a 1.9 +# Parent 11f7a9321b7d5d85eddc2db16e58e6870a7c4e06 1.10 +Bug 883126 - Improve performance of EXIDX unwinding in Breakpad. r=ted 1.11 + 1.12 +diff --git a/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc 1.13 +--- a/src/common/arm_ex_to_module.cc 1.14 ++++ b/src/common/arm_ex_to_module.cc 1.15 +@@ -66,141 +66,126 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE 1.16 + 1.17 + #define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) 1.18 + #define ARM_EXBUF_COUNT(x) ((x) & 0x0f) 1.19 + #define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) 1.20 + 1.21 + using google_breakpad::ustr__pc; 1.22 + using google_breakpad::ustr__lr; 1.23 + using google_breakpad::ustr__sp; 1.24 ++using google_breakpad::ustr__ZDra; 1.25 ++using google_breakpad::ustr__ZDcfa; 1.26 + using google_breakpad::Module; 1.27 + using google_breakpad::ToUniqueString; 1.28 + using google_breakpad::UniqueString; 1.29 + 1.30 + namespace arm_ex_to_module { 1.31 + 1.32 + // Translate command from extab_data to command for Module. 1.33 + int ARMExToModule::TranslateCmd(const struct extab_data* edata, 1.34 +- Module::StackFrameEntry* entry, string& vsp) { 1.35 ++ Module::StackFrameEntry* entry, 1.36 ++ Module::Expr& vsp) { 1.37 + int ret = 0; 1.38 + switch (edata->cmd) { 1.39 + case ARM_EXIDX_CMD_FINISH: 1.40 + /* Copy LR to PC if there isn't currently a rule for PC in force. */ 1.41 + if (entry->initial_rules.find(ustr__pc()) 1.42 + == entry->initial_rules.end()) { 1.43 + if (entry->initial_rules.find(ustr__lr()) 1.44 + == entry->initial_rules.end()) { 1.45 +- entry->initial_rules[ustr__pc()] = Module::Expr("lr"); 1.46 ++ entry->initial_rules[ustr__pc()] = Module::Expr(ustr__lr(), 1.47 ++ 0, false); // "lr" 1.48 + } else { 1.49 + entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()]; 1.50 + } 1.51 + } 1.52 + break; 1.53 + case ARM_EXIDX_CMD_SUB_FROM_VSP: 1.54 +- { 1.55 +- char c[16]; 1.56 +- sprintf(c, " %d -", edata->data); 1.57 +- vsp += c; 1.58 +- } 1.59 ++ vsp = vsp.add_delta(- static_cast<long>(edata->data)); 1.60 + break; 1.61 + case ARM_EXIDX_CMD_ADD_TO_VSP: 1.62 +- { 1.63 +- char c[16]; 1.64 +- sprintf(c, " %d +", edata->data); 1.65 +- vsp += c; 1.66 +- } 1.67 ++ vsp = vsp.add_delta(static_cast<long>(edata->data)); 1.68 + break; 1.69 + case ARM_EXIDX_CMD_REG_POP: 1.70 + for (unsigned int i = 0; i < 16; i++) { 1.71 + if (edata->data & (1 << i)) { 1.72 +- entry->initial_rules[ToUniqueString(regnames[i])] 1.73 +- = Module::Expr(vsp + " ^"); 1.74 +- vsp += " 4 +"; 1.75 ++ entry->initial_rules[ToUniqueString(regnames[i])] = vsp.deref(); 1.76 ++ vsp = vsp.add_delta(4); 1.77 + } 1.78 + } 1.79 + /* Set cfa in case the SP got popped. */ 1.80 + if (edata->data & (1 << 13)) { 1.81 +- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()]; 1.82 +- // It must be a postfix expression (we don't generate anything 1.83 +- // else here), so return -1 to fail out if it isn't. 1.84 +- if (!vsp_expr.isExprPostfix()) { 1.85 +- ret = -1; 1.86 +- break; 1.87 +- }; 1.88 +- vsp = vsp_expr.getExprPostfix(); 1.89 ++ vsp = entry->initial_rules[ustr__sp()]; 1.90 + } 1.91 + break; 1.92 + case ARM_EXIDX_CMD_REG_TO_SP: { 1.93 + assert (edata->data < 16); 1.94 + const char* const regname = regnames[edata->data]; 1.95 + const UniqueString* regname_us = ToUniqueString(regname); 1.96 + if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) { 1.97 +- entry->initial_rules[ustr__sp()] = Module::Expr(regname); 1.98 ++ entry->initial_rules[ustr__sp()] = Module::Expr(regname_us, 1.99 ++ 0, false); // "regname" 1.100 + } else { 1.101 + entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us]; 1.102 + } 1.103 +- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()]; 1.104 +- if (!vsp_expr.isExprPostfix()) { 1.105 +- ret = -1; 1.106 +- break; 1.107 +- }; 1.108 +- vsp = vsp_expr.getExprPostfix(); 1.109 ++ vsp = entry->initial_rules[ustr__sp()]; 1.110 + break; 1.111 + } 1.112 + case ARM_EXIDX_CMD_VFP_POP: 1.113 + /* Don't recover VFP registers, but be sure to adjust the stack 1.114 + pointer. */ 1.115 + for (unsigned int i = ARM_EXBUF_START(edata->data); 1.116 + i <= ARM_EXBUF_END(edata->data); i++) { 1.117 +- vsp += " 8 +"; 1.118 ++ vsp = vsp.add_delta(8); 1.119 + } 1.120 + if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) { 1.121 +- vsp += " 4 +"; 1.122 ++ vsp = vsp.add_delta(4); 1.123 + } 1.124 + break; 1.125 + case ARM_EXIDX_CMD_WREG_POP: 1.126 + for (unsigned int i = ARM_EXBUF_START(edata->data); 1.127 + i <= ARM_EXBUF_END(edata->data); i++) { 1.128 +- vsp += " 8 +"; 1.129 ++ vsp = vsp.add_delta(8); 1.130 + } 1.131 + break; 1.132 + case ARM_EXIDX_CMD_WCGR_POP: 1.133 + // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4" 1.134 + for (unsigned int i = 0; i < 4; i++) { 1.135 + if (edata->data & (1 << i)) { 1.136 +- vsp += " 4 +"; 1.137 ++ vsp = vsp.add_delta(4); 1.138 + } 1.139 + } 1.140 + break; 1.141 + case ARM_EXIDX_CMD_REFUSED: 1.142 + case ARM_EXIDX_CMD_RESERVED: 1.143 + ret = -1; 1.144 + break; 1.145 + } 1.146 + return ret; 1.147 + } 1.148 + 1.149 + void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) { 1.150 + stack_frame_entry_ = new Module::StackFrameEntry; 1.151 + stack_frame_entry_->address = addr; 1.152 + stack_frame_entry_->size = size; 1.153 +- stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp"); 1.154 +- vsp_ = "sp"; 1.155 ++ Module::Expr sp_expr = Module::Expr(ustr__sp(), 0, false); // "sp" 1.156 ++ stack_frame_entry_->initial_rules[ustr__ZDcfa()] = sp_expr; // ".cfa" 1.157 ++ vsp_ = sp_expr; 1.158 + } 1.159 + 1.160 + int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) { 1.161 + return TranslateCmd(edata, stack_frame_entry_, vsp_) ; 1.162 + } 1.163 + 1.164 + void ARMExToModule::DeleteStackFrame() { 1.165 + delete stack_frame_entry_; 1.166 + } 1.167 + 1.168 + void ARMExToModule::SubmitStackFrame() { 1.169 + // return address always winds up in pc 1.170 +- stack_frame_entry_->initial_rules[ToUniqueString(kRA)] 1.171 ++ stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra" 1.172 + = stack_frame_entry_->initial_rules[ustr__pc()]; 1.173 + // the final value of vsp is the new value of sp 1.174 + stack_frame_entry_->initial_rules[ustr__sp()] = vsp_; 1.175 + module_->AddStackFrameEntry(stack_frame_entry_); 1.176 + } 1.177 + 1.178 + } // namespace arm_ex_to_module 1.179 +diff --git a/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h 1.180 +--- a/src/common/arm_ex_to_module.h 1.181 ++++ b/src/common/arm_ex_to_module.h 1.182 +@@ -89,19 +89,16 @@ struct extab_data { 1.183 + uint32_t data; 1.184 + }; 1.185 + 1.186 + enum extab_cmd_flags { 1.187 + ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, 1.188 + ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX 1.189 + }; 1.190 + 1.191 +-const string kRA = ".ra"; 1.192 +-const string kCFA = ".cfa"; 1.193 +- 1.194 + static const char* const regnames[] = { 1.195 + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1.196 + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 1.197 + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 1.198 + "fps", "cpsr" 1.199 + }; 1.200 + 1.201 + // Receives information from arm_ex_reader::ExceptionTableInfo 1.202 +@@ -113,17 +110,17 @@ class ARMExToModule { 1.203 + ~ARMExToModule() { } 1.204 + void AddStackFrame(uintptr_t addr, size_t size); 1.205 + int ImproveStackFrame(const struct extab_data* edata); 1.206 + void DeleteStackFrame(); 1.207 + void SubmitStackFrame(); 1.208 + private: 1.209 + Module* module_; 1.210 + Module::StackFrameEntry* stack_frame_entry_; 1.211 +- string vsp_; 1.212 ++ Module::Expr vsp_; 1.213 + int TranslateCmd(const struct extab_data* edata, 1.214 + Module::StackFrameEntry* entry, 1.215 +- string& vsp); 1.216 ++ Module::Expr& vsp); 1.217 + }; 1.218 + 1.219 + } // namespace arm_ex_to_module 1.220 + 1.221 + #endif // COMMON_ARM_EX_TO_MODULE__ 1.222 +diff --git a/src/common/module.h b/src/common/module.h 1.223 +--- a/src/common/module.h 1.224 ++++ b/src/common/module.h 1.225 +@@ -39,16 +39,20 @@ 1.226 + #define COMMON_LINUX_MODULE_H__ 1.227 + 1.228 + #include <iostream> 1.229 + #include <map> 1.230 + #include <set> 1.231 + #include <string> 1.232 + #include <vector> 1.233 + 1.234 ++#include <assert.h> 1.235 ++#include <stdlib.h> 1.236 ++#include <stdio.h> 1.237 ++ 1.238 + #include "common/symbol_data.h" 1.239 + #include "common/using_std_string.h" 1.240 + #include "common/unique_string.h" 1.241 + #include "google_breakpad/common/breakpad_types.h" 1.242 + 1.243 + namespace google_breakpad { 1.244 + 1.245 + using std::set; 1.246 +@@ -161,30 +165,98 @@ class Module { 1.247 + // Construct an invalid expression 1.248 + Expr() { 1.249 + postfix_ = ""; 1.250 + ident_ = NULL; 1.251 + offset_ = 0; 1.252 + how_ = kExprInvalid; 1.253 + } 1.254 + bool isExprInvalid() const { return how_ == kExprInvalid; } 1.255 +- bool isExprPostfix() const { return how_ == kExprPostfix; } 1.256 + 1.257 +- // Return the postfix expression string. This is only 1.258 +- // meaningful on Exprs for which isExprPostfix returns true. 1.259 +- // In all other cases it returns an empty string. 1.260 +- string getExprPostfix() const { return postfix_; } 1.261 ++ // Return the postfix expression string, either directly, 1.262 ++ // if this is a postfix expression, or by synthesising it 1.263 ++ // for a simple expression. 1.264 ++ string getExprPostfix() const { 1.265 ++ switch (how_) { 1.266 ++ case kExprPostfix: 1.267 ++ return postfix_; 1.268 ++ case kExprSimple: 1.269 ++ case kExprSimpleMem: { 1.270 ++ char buf[40]; 1.271 ++ sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+', 1.272 ++ how_ == kExprSimple ? "" : " ^"); 1.273 ++ return string(FromUniqueString(ident_)) + string(buf); 1.274 ++ } 1.275 ++ case kExprInvalid: 1.276 ++ default: 1.277 ++ assert(0 && "getExprPostfix: invalid Module::Expr type"); 1.278 ++ return "Expr::genExprPostfix: kExprInvalid"; 1.279 ++ } 1.280 ++ } 1.281 + 1.282 + bool operator==(const Expr& other) const { 1.283 + return how_ == other.how_ && 1.284 + ident_ == other.ident_ && 1.285 + offset_ == other.offset_ && 1.286 + postfix_ == other.postfix_; 1.287 + } 1.288 + 1.289 ++ // Returns an Expr which evaluates to |this| + |delta| 1.290 ++ Expr add_delta(long delta) { 1.291 ++ if (delta == 0) { 1.292 ++ return *this; 1.293 ++ } 1.294 ++ // If it's a simple form expression of the form "identifier + offset", 1.295 ++ // simply add |delta| on to |offset|. In the other two possible 1.296 ++ // cases: 1.297 ++ // *(identifier + offset) 1.298 ++ // completely arbitrary postfix expression string 1.299 ++ // the only option is to "downgrade" it to a postfix expression and add 1.300 ++ // "+/- delta" at the end of the string, since the result can't be 1.301 ++ // represented in the simple form. 1.302 ++ switch (how_) { 1.303 ++ case kExprSimpleMem: 1.304 ++ case kExprPostfix: { 1.305 ++ char buf[40]; 1.306 ++ sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+'); 1.307 ++ return Expr(getExprPostfix() + string(buf)); 1.308 ++ } 1.309 ++ case kExprSimple: 1.310 ++ return Expr(ident_, offset_ + delta, false); 1.311 ++ case kExprInvalid: 1.312 ++ default: 1.313 ++ assert(0 && "add_delta: invalid Module::Expr type"); 1.314 ++ // Invalid inputs produce an invalid result 1.315 ++ return Expr(); 1.316 ++ } 1.317 ++ } 1.318 ++ 1.319 ++ // Returns an Expr which evaluates to *|this| 1.320 ++ Expr deref() { 1.321 ++ // In the simplest case, a kExprSimple can be changed into a 1.322 ++ // kExprSimpleMem. In all other cases it has to be dumped as a 1.323 ++ // postfix string, and " ^" added at the end. 1.324 ++ switch (how_) { 1.325 ++ case kExprSimple: { 1.326 ++ Expr t = *this; 1.327 ++ t.how_ = kExprSimpleMem; 1.328 ++ return t; 1.329 ++ } 1.330 ++ case kExprSimpleMem: 1.331 ++ case kExprPostfix: { 1.332 ++ return Expr(getExprPostfix() + " ^"); 1.333 ++ } 1.334 ++ case kExprInvalid: 1.335 ++ default: 1.336 ++ assert(0 && "deref: invalid Module::Expr type"); 1.337 ++ // Invalid inputs produce an invalid result 1.338 ++ return Expr(); 1.339 ++ } 1.340 ++ } 1.341 ++ 1.342 + // The identifier that gives the starting value for simple expressions. 1.343 + const UniqueString* ident_; 1.344 + // The offset to add for simple expressions. 1.345 + long offset_; 1.346 + // The Postfix expression string to evaluate for non-simple expressions. 1.347 + string postfix_; 1.348 + // The operation expressed by this expression. 1.349 + ExprHow how_;