toolkit/crashreporter/breakpad-patches/14-bug883126.patch

changeset 0
6474c204b198
     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_;

mercurial