gecko-dev/toolkit/crashreporter/breakpad-patches/14-bug883126.patch
Mike Hommey 622c6ed12a Bug 886216 - Add missing breakpad patches. r=ted
--HG--
rename : toolkit/crashreporter/breakpad-patches/12-sht-arm-exidx-define.patch => toolkit/crashreporter/breakpad-patches/16-sht-arm-exidx-define.patch
2013-07-31 14:03:21 +09:00

347 lines
12 KiB
Diff

# HG changeset patch
# User Julian Seward <jseward@acm.org>
# Date 1372168568 -7200
# Tue Jun 25 15:56:08 2013 +0200
# Node ID 6d06a09b3f5624dd833bd6f905bfd88e3fdec00a
# Parent 11f7a9321b7d5d85eddc2db16e58e6870a7c4e06
Bug 883126 - Improve performance of EXIDX unwinding in Breakpad. r=ted
diff --git a/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc
--- a/src/common/arm_ex_to_module.cc
+++ b/src/common/arm_ex_to_module.cc
@@ -66,141 +66,126 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
using google_breakpad::ustr__pc;
using google_breakpad::ustr__lr;
using google_breakpad::ustr__sp;
+using google_breakpad::ustr__ZDra;
+using google_breakpad::ustr__ZDcfa;
using google_breakpad::Module;
using google_breakpad::ToUniqueString;
using google_breakpad::UniqueString;
namespace arm_ex_to_module {
// Translate command from extab_data to command for Module.
int ARMExToModule::TranslateCmd(const struct extab_data* edata,
- Module::StackFrameEntry* entry, string& vsp) {
+ Module::StackFrameEntry* entry,
+ Module::Expr& vsp) {
int ret = 0;
switch (edata->cmd) {
case ARM_EXIDX_CMD_FINISH:
/* Copy LR to PC if there isn't currently a rule for PC in force. */
if (entry->initial_rules.find(ustr__pc())
== entry->initial_rules.end()) {
if (entry->initial_rules.find(ustr__lr())
== entry->initial_rules.end()) {
- entry->initial_rules[ustr__pc()] = Module::Expr("lr");
+ entry->initial_rules[ustr__pc()] = Module::Expr(ustr__lr(),
+ 0, false); // "lr"
} else {
entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()];
}
}
break;
case ARM_EXIDX_CMD_SUB_FROM_VSP:
- {
- char c[16];
- sprintf(c, " %d -", edata->data);
- vsp += c;
- }
+ vsp = vsp.add_delta(- static_cast<long>(edata->data));
break;
case ARM_EXIDX_CMD_ADD_TO_VSP:
- {
- char c[16];
- sprintf(c, " %d +", edata->data);
- vsp += c;
- }
+ vsp = vsp.add_delta(static_cast<long>(edata->data));
break;
case ARM_EXIDX_CMD_REG_POP:
for (unsigned int i = 0; i < 16; i++) {
if (edata->data & (1 << i)) {
- entry->initial_rules[ToUniqueString(regnames[i])]
- = Module::Expr(vsp + " ^");
- vsp += " 4 +";
+ entry->initial_rules[ToUniqueString(regnames[i])] = vsp.deref();
+ vsp = vsp.add_delta(4);
}
}
/* Set cfa in case the SP got popped. */
if (edata->data & (1 << 13)) {
- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
- // It must be a postfix expression (we don't generate anything
- // else here), so return -1 to fail out if it isn't.
- if (!vsp_expr.isExprPostfix()) {
- ret = -1;
- break;
- };
- vsp = vsp_expr.getExprPostfix();
+ vsp = entry->initial_rules[ustr__sp()];
}
break;
case ARM_EXIDX_CMD_REG_TO_SP: {
assert (edata->data < 16);
const char* const regname = regnames[edata->data];
const UniqueString* regname_us = ToUniqueString(regname);
if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) {
- entry->initial_rules[ustr__sp()] = Module::Expr(regname);
+ entry->initial_rules[ustr__sp()] = Module::Expr(regname_us,
+ 0, false); // "regname"
} else {
entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us];
}
- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
- if (!vsp_expr.isExprPostfix()) {
- ret = -1;
- break;
- };
- vsp = vsp_expr.getExprPostfix();
+ vsp = entry->initial_rules[ustr__sp()];
break;
}
case ARM_EXIDX_CMD_VFP_POP:
/* Don't recover VFP registers, but be sure to adjust the stack
pointer. */
for (unsigned int i = ARM_EXBUF_START(edata->data);
i <= ARM_EXBUF_END(edata->data); i++) {
- vsp += " 8 +";
+ vsp = vsp.add_delta(8);
}
if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
- vsp += " 4 +";
+ vsp = vsp.add_delta(4);
}
break;
case ARM_EXIDX_CMD_WREG_POP:
for (unsigned int i = ARM_EXBUF_START(edata->data);
i <= ARM_EXBUF_END(edata->data); i++) {
- vsp += " 8 +";
+ vsp = vsp.add_delta(8);
}
break;
case ARM_EXIDX_CMD_WCGR_POP:
// Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
for (unsigned int i = 0; i < 4; i++) {
if (edata->data & (1 << i)) {
- vsp += " 4 +";
+ vsp = vsp.add_delta(4);
}
}
break;
case ARM_EXIDX_CMD_REFUSED:
case ARM_EXIDX_CMD_RESERVED:
ret = -1;
break;
}
return ret;
}
void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
stack_frame_entry_ = new Module::StackFrameEntry;
stack_frame_entry_->address = addr;
stack_frame_entry_->size = size;
- stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp");
- vsp_ = "sp";
+ Module::Expr sp_expr = Module::Expr(ustr__sp(), 0, false); // "sp"
+ stack_frame_entry_->initial_rules[ustr__ZDcfa()] = sp_expr; // ".cfa"
+ vsp_ = sp_expr;
}
int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) {
return TranslateCmd(edata, stack_frame_entry_, vsp_) ;
}
void ARMExToModule::DeleteStackFrame() {
delete stack_frame_entry_;
}
void ARMExToModule::SubmitStackFrame() {
// return address always winds up in pc
- stack_frame_entry_->initial_rules[ToUniqueString(kRA)]
+ stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra"
= stack_frame_entry_->initial_rules[ustr__pc()];
// the final value of vsp is the new value of sp
stack_frame_entry_->initial_rules[ustr__sp()] = vsp_;
module_->AddStackFrameEntry(stack_frame_entry_);
}
} // namespace arm_ex_to_module
diff --git a/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h
--- a/src/common/arm_ex_to_module.h
+++ b/src/common/arm_ex_to_module.h
@@ -89,19 +89,16 @@ struct extab_data {
uint32_t data;
};
enum extab_cmd_flags {
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
};
-const string kRA = ".ra";
-const string kCFA = ".cfa";
-
static const char* const regnames[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"fps", "cpsr"
};
// Receives information from arm_ex_reader::ExceptionTableInfo
@@ -113,17 +110,17 @@ class ARMExToModule {
~ARMExToModule() { }
void AddStackFrame(uintptr_t addr, size_t size);
int ImproveStackFrame(const struct extab_data* edata);
void DeleteStackFrame();
void SubmitStackFrame();
private:
Module* module_;
Module::StackFrameEntry* stack_frame_entry_;
- string vsp_;
+ Module::Expr vsp_;
int TranslateCmd(const struct extab_data* edata,
Module::StackFrameEntry* entry,
- string& vsp);
+ Module::Expr& vsp);
};
} // namespace arm_ex_to_module
#endif // COMMON_ARM_EX_TO_MODULE__
diff --git a/src/common/module.h b/src/common/module.h
--- a/src/common/module.h
+++ b/src/common/module.h
@@ -39,16 +39,20 @@
#define COMMON_LINUX_MODULE_H__
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
#include "common/symbol_data.h"
#include "common/using_std_string.h"
#include "common/unique_string.h"
#include "google_breakpad/common/breakpad_types.h"
namespace google_breakpad {
using std::set;
@@ -161,30 +165,98 @@ class Module {
// Construct an invalid expression
Expr() {
postfix_ = "";
ident_ = NULL;
offset_ = 0;
how_ = kExprInvalid;
}
bool isExprInvalid() const { return how_ == kExprInvalid; }
- bool isExprPostfix() const { return how_ == kExprPostfix; }
- // Return the postfix expression string. This is only
- // meaningful on Exprs for which isExprPostfix returns true.
- // In all other cases it returns an empty string.
- string getExprPostfix() const { return postfix_; }
+ // Return the postfix expression string, either directly,
+ // if this is a postfix expression, or by synthesising it
+ // for a simple expression.
+ string getExprPostfix() const {
+ switch (how_) {
+ case kExprPostfix:
+ return postfix_;
+ case kExprSimple:
+ case kExprSimpleMem: {
+ char buf[40];
+ sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+',
+ how_ == kExprSimple ? "" : " ^");
+ return string(FromUniqueString(ident_)) + string(buf);
+ }
+ case kExprInvalid:
+ default:
+ assert(0 && "getExprPostfix: invalid Module::Expr type");
+ return "Expr::genExprPostfix: kExprInvalid";
+ }
+ }
bool operator==(const Expr& other) const {
return how_ == other.how_ &&
ident_ == other.ident_ &&
offset_ == other.offset_ &&
postfix_ == other.postfix_;
}
+ // Returns an Expr which evaluates to |this| + |delta|
+ Expr add_delta(long delta) {
+ if (delta == 0) {
+ return *this;
+ }
+ // If it's a simple form expression of the form "identifier + offset",
+ // simply add |delta| on to |offset|. In the other two possible
+ // cases:
+ // *(identifier + offset)
+ // completely arbitrary postfix expression string
+ // the only option is to "downgrade" it to a postfix expression and add
+ // "+/- delta" at the end of the string, since the result can't be
+ // represented in the simple form.
+ switch (how_) {
+ case kExprSimpleMem:
+ case kExprPostfix: {
+ char buf[40];
+ sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+');
+ return Expr(getExprPostfix() + string(buf));
+ }
+ case kExprSimple:
+ return Expr(ident_, offset_ + delta, false);
+ case kExprInvalid:
+ default:
+ assert(0 && "add_delta: invalid Module::Expr type");
+ // Invalid inputs produce an invalid result
+ return Expr();
+ }
+ }
+
+ // Returns an Expr which evaluates to *|this|
+ Expr deref() {
+ // In the simplest case, a kExprSimple can be changed into a
+ // kExprSimpleMem. In all other cases it has to be dumped as a
+ // postfix string, and " ^" added at the end.
+ switch (how_) {
+ case kExprSimple: {
+ Expr t = *this;
+ t.how_ = kExprSimpleMem;
+ return t;
+ }
+ case kExprSimpleMem:
+ case kExprPostfix: {
+ return Expr(getExprPostfix() + " ^");
+ }
+ case kExprInvalid:
+ default:
+ assert(0 && "deref: invalid Module::Expr type");
+ // Invalid inputs produce an invalid result
+ return Expr();
+ }
+ }
+
// The identifier that gives the starting value for simple expressions.
const UniqueString* ident_;
// The offset to add for simple expressions.
long offset_;
// The Postfix expression string to evaluate for non-simple expressions.
string postfix_;
// The operation expressed by this expression.
ExprHow how_;