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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 # HG changeset patch
michael@0 2 # User Julian Seward <jseward@acm.org>
michael@0 3 # Date 1372168568 -7200
michael@0 4 # Tue Jun 25 15:56:08 2013 +0200
michael@0 5 # Node ID 6d06a09b3f5624dd833bd6f905bfd88e3fdec00a
michael@0 6 # Parent 11f7a9321b7d5d85eddc2db16e58e6870a7c4e06
michael@0 7 Bug 883126 - Improve performance of EXIDX unwinding in Breakpad. r=ted
michael@0 8
michael@0 9 diff --git a/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc
michael@0 10 --- a/src/common/arm_ex_to_module.cc
michael@0 11 +++ b/src/common/arm_ex_to_module.cc
michael@0 12 @@ -66,141 +66,126 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
michael@0 13
michael@0 14 #define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
michael@0 15 #define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
michael@0 16 #define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
michael@0 17
michael@0 18 using google_breakpad::ustr__pc;
michael@0 19 using google_breakpad::ustr__lr;
michael@0 20 using google_breakpad::ustr__sp;
michael@0 21 +using google_breakpad::ustr__ZDra;
michael@0 22 +using google_breakpad::ustr__ZDcfa;
michael@0 23 using google_breakpad::Module;
michael@0 24 using google_breakpad::ToUniqueString;
michael@0 25 using google_breakpad::UniqueString;
michael@0 26
michael@0 27 namespace arm_ex_to_module {
michael@0 28
michael@0 29 // Translate command from extab_data to command for Module.
michael@0 30 int ARMExToModule::TranslateCmd(const struct extab_data* edata,
michael@0 31 - Module::StackFrameEntry* entry, string& vsp) {
michael@0 32 + Module::StackFrameEntry* entry,
michael@0 33 + Module::Expr& vsp) {
michael@0 34 int ret = 0;
michael@0 35 switch (edata->cmd) {
michael@0 36 case ARM_EXIDX_CMD_FINISH:
michael@0 37 /* Copy LR to PC if there isn't currently a rule for PC in force. */
michael@0 38 if (entry->initial_rules.find(ustr__pc())
michael@0 39 == entry->initial_rules.end()) {
michael@0 40 if (entry->initial_rules.find(ustr__lr())
michael@0 41 == entry->initial_rules.end()) {
michael@0 42 - entry->initial_rules[ustr__pc()] = Module::Expr("lr");
michael@0 43 + entry->initial_rules[ustr__pc()] = Module::Expr(ustr__lr(),
michael@0 44 + 0, false); // "lr"
michael@0 45 } else {
michael@0 46 entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()];
michael@0 47 }
michael@0 48 }
michael@0 49 break;
michael@0 50 case ARM_EXIDX_CMD_SUB_FROM_VSP:
michael@0 51 - {
michael@0 52 - char c[16];
michael@0 53 - sprintf(c, " %d -", edata->data);
michael@0 54 - vsp += c;
michael@0 55 - }
michael@0 56 + vsp = vsp.add_delta(- static_cast<long>(edata->data));
michael@0 57 break;
michael@0 58 case ARM_EXIDX_CMD_ADD_TO_VSP:
michael@0 59 - {
michael@0 60 - char c[16];
michael@0 61 - sprintf(c, " %d +", edata->data);
michael@0 62 - vsp += c;
michael@0 63 - }
michael@0 64 + vsp = vsp.add_delta(static_cast<long>(edata->data));
michael@0 65 break;
michael@0 66 case ARM_EXIDX_CMD_REG_POP:
michael@0 67 for (unsigned int i = 0; i < 16; i++) {
michael@0 68 if (edata->data & (1 << i)) {
michael@0 69 - entry->initial_rules[ToUniqueString(regnames[i])]
michael@0 70 - = Module::Expr(vsp + " ^");
michael@0 71 - vsp += " 4 +";
michael@0 72 + entry->initial_rules[ToUniqueString(regnames[i])] = vsp.deref();
michael@0 73 + vsp = vsp.add_delta(4);
michael@0 74 }
michael@0 75 }
michael@0 76 /* Set cfa in case the SP got popped. */
michael@0 77 if (edata->data & (1 << 13)) {
michael@0 78 - Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
michael@0 79 - // It must be a postfix expression (we don't generate anything
michael@0 80 - // else here), so return -1 to fail out if it isn't.
michael@0 81 - if (!vsp_expr.isExprPostfix()) {
michael@0 82 - ret = -1;
michael@0 83 - break;
michael@0 84 - };
michael@0 85 - vsp = vsp_expr.getExprPostfix();
michael@0 86 + vsp = entry->initial_rules[ustr__sp()];
michael@0 87 }
michael@0 88 break;
michael@0 89 case ARM_EXIDX_CMD_REG_TO_SP: {
michael@0 90 assert (edata->data < 16);
michael@0 91 const char* const regname = regnames[edata->data];
michael@0 92 const UniqueString* regname_us = ToUniqueString(regname);
michael@0 93 if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) {
michael@0 94 - entry->initial_rules[ustr__sp()] = Module::Expr(regname);
michael@0 95 + entry->initial_rules[ustr__sp()] = Module::Expr(regname_us,
michael@0 96 + 0, false); // "regname"
michael@0 97 } else {
michael@0 98 entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us];
michael@0 99 }
michael@0 100 - Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
michael@0 101 - if (!vsp_expr.isExprPostfix()) {
michael@0 102 - ret = -1;
michael@0 103 - break;
michael@0 104 - };
michael@0 105 - vsp = vsp_expr.getExprPostfix();
michael@0 106 + vsp = entry->initial_rules[ustr__sp()];
michael@0 107 break;
michael@0 108 }
michael@0 109 case ARM_EXIDX_CMD_VFP_POP:
michael@0 110 /* Don't recover VFP registers, but be sure to adjust the stack
michael@0 111 pointer. */
michael@0 112 for (unsigned int i = ARM_EXBUF_START(edata->data);
michael@0 113 i <= ARM_EXBUF_END(edata->data); i++) {
michael@0 114 - vsp += " 8 +";
michael@0 115 + vsp = vsp.add_delta(8);
michael@0 116 }
michael@0 117 if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
michael@0 118 - vsp += " 4 +";
michael@0 119 + vsp = vsp.add_delta(4);
michael@0 120 }
michael@0 121 break;
michael@0 122 case ARM_EXIDX_CMD_WREG_POP:
michael@0 123 for (unsigned int i = ARM_EXBUF_START(edata->data);
michael@0 124 i <= ARM_EXBUF_END(edata->data); i++) {
michael@0 125 - vsp += " 8 +";
michael@0 126 + vsp = vsp.add_delta(8);
michael@0 127 }
michael@0 128 break;
michael@0 129 case ARM_EXIDX_CMD_WCGR_POP:
michael@0 130 // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
michael@0 131 for (unsigned int i = 0; i < 4; i++) {
michael@0 132 if (edata->data & (1 << i)) {
michael@0 133 - vsp += " 4 +";
michael@0 134 + vsp = vsp.add_delta(4);
michael@0 135 }
michael@0 136 }
michael@0 137 break;
michael@0 138 case ARM_EXIDX_CMD_REFUSED:
michael@0 139 case ARM_EXIDX_CMD_RESERVED:
michael@0 140 ret = -1;
michael@0 141 break;
michael@0 142 }
michael@0 143 return ret;
michael@0 144 }
michael@0 145
michael@0 146 void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
michael@0 147 stack_frame_entry_ = new Module::StackFrameEntry;
michael@0 148 stack_frame_entry_->address = addr;
michael@0 149 stack_frame_entry_->size = size;
michael@0 150 - stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp");
michael@0 151 - vsp_ = "sp";
michael@0 152 + Module::Expr sp_expr = Module::Expr(ustr__sp(), 0, false); // "sp"
michael@0 153 + stack_frame_entry_->initial_rules[ustr__ZDcfa()] = sp_expr; // ".cfa"
michael@0 154 + vsp_ = sp_expr;
michael@0 155 }
michael@0 156
michael@0 157 int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) {
michael@0 158 return TranslateCmd(edata, stack_frame_entry_, vsp_) ;
michael@0 159 }
michael@0 160
michael@0 161 void ARMExToModule::DeleteStackFrame() {
michael@0 162 delete stack_frame_entry_;
michael@0 163 }
michael@0 164
michael@0 165 void ARMExToModule::SubmitStackFrame() {
michael@0 166 // return address always winds up in pc
michael@0 167 - stack_frame_entry_->initial_rules[ToUniqueString(kRA)]
michael@0 168 + stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra"
michael@0 169 = stack_frame_entry_->initial_rules[ustr__pc()];
michael@0 170 // the final value of vsp is the new value of sp
michael@0 171 stack_frame_entry_->initial_rules[ustr__sp()] = vsp_;
michael@0 172 module_->AddStackFrameEntry(stack_frame_entry_);
michael@0 173 }
michael@0 174
michael@0 175 } // namespace arm_ex_to_module
michael@0 176 diff --git a/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h
michael@0 177 --- a/src/common/arm_ex_to_module.h
michael@0 178 +++ b/src/common/arm_ex_to_module.h
michael@0 179 @@ -89,19 +89,16 @@ struct extab_data {
michael@0 180 uint32_t data;
michael@0 181 };
michael@0 182
michael@0 183 enum extab_cmd_flags {
michael@0 184 ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
michael@0 185 ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
michael@0 186 };
michael@0 187
michael@0 188 -const string kRA = ".ra";
michael@0 189 -const string kCFA = ".cfa";
michael@0 190 -
michael@0 191 static const char* const regnames[] = {
michael@0 192 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
michael@0 193 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
michael@0 194 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
michael@0 195 "fps", "cpsr"
michael@0 196 };
michael@0 197
michael@0 198 // Receives information from arm_ex_reader::ExceptionTableInfo
michael@0 199 @@ -113,17 +110,17 @@ class ARMExToModule {
michael@0 200 ~ARMExToModule() { }
michael@0 201 void AddStackFrame(uintptr_t addr, size_t size);
michael@0 202 int ImproveStackFrame(const struct extab_data* edata);
michael@0 203 void DeleteStackFrame();
michael@0 204 void SubmitStackFrame();
michael@0 205 private:
michael@0 206 Module* module_;
michael@0 207 Module::StackFrameEntry* stack_frame_entry_;
michael@0 208 - string vsp_;
michael@0 209 + Module::Expr vsp_;
michael@0 210 int TranslateCmd(const struct extab_data* edata,
michael@0 211 Module::StackFrameEntry* entry,
michael@0 212 - string& vsp);
michael@0 213 + Module::Expr& vsp);
michael@0 214 };
michael@0 215
michael@0 216 } // namespace arm_ex_to_module
michael@0 217
michael@0 218 #endif // COMMON_ARM_EX_TO_MODULE__
michael@0 219 diff --git a/src/common/module.h b/src/common/module.h
michael@0 220 --- a/src/common/module.h
michael@0 221 +++ b/src/common/module.h
michael@0 222 @@ -39,16 +39,20 @@
michael@0 223 #define COMMON_LINUX_MODULE_H__
michael@0 224
michael@0 225 #include <iostream>
michael@0 226 #include <map>
michael@0 227 #include <set>
michael@0 228 #include <string>
michael@0 229 #include <vector>
michael@0 230
michael@0 231 +#include <assert.h>
michael@0 232 +#include <stdlib.h>
michael@0 233 +#include <stdio.h>
michael@0 234 +
michael@0 235 #include "common/symbol_data.h"
michael@0 236 #include "common/using_std_string.h"
michael@0 237 #include "common/unique_string.h"
michael@0 238 #include "google_breakpad/common/breakpad_types.h"
michael@0 239
michael@0 240 namespace google_breakpad {
michael@0 241
michael@0 242 using std::set;
michael@0 243 @@ -161,30 +165,98 @@ class Module {
michael@0 244 // Construct an invalid expression
michael@0 245 Expr() {
michael@0 246 postfix_ = "";
michael@0 247 ident_ = NULL;
michael@0 248 offset_ = 0;
michael@0 249 how_ = kExprInvalid;
michael@0 250 }
michael@0 251 bool isExprInvalid() const { return how_ == kExprInvalid; }
michael@0 252 - bool isExprPostfix() const { return how_ == kExprPostfix; }
michael@0 253
michael@0 254 - // Return the postfix expression string. This is only
michael@0 255 - // meaningful on Exprs for which isExprPostfix returns true.
michael@0 256 - // In all other cases it returns an empty string.
michael@0 257 - string getExprPostfix() const { return postfix_; }
michael@0 258 + // Return the postfix expression string, either directly,
michael@0 259 + // if this is a postfix expression, or by synthesising it
michael@0 260 + // for a simple expression.
michael@0 261 + string getExprPostfix() const {
michael@0 262 + switch (how_) {
michael@0 263 + case kExprPostfix:
michael@0 264 + return postfix_;
michael@0 265 + case kExprSimple:
michael@0 266 + case kExprSimpleMem: {
michael@0 267 + char buf[40];
michael@0 268 + sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+',
michael@0 269 + how_ == kExprSimple ? "" : " ^");
michael@0 270 + return string(FromUniqueString(ident_)) + string(buf);
michael@0 271 + }
michael@0 272 + case kExprInvalid:
michael@0 273 + default:
michael@0 274 + assert(0 && "getExprPostfix: invalid Module::Expr type");
michael@0 275 + return "Expr::genExprPostfix: kExprInvalid";
michael@0 276 + }
michael@0 277 + }
michael@0 278
michael@0 279 bool operator==(const Expr& other) const {
michael@0 280 return how_ == other.how_ &&
michael@0 281 ident_ == other.ident_ &&
michael@0 282 offset_ == other.offset_ &&
michael@0 283 postfix_ == other.postfix_;
michael@0 284 }
michael@0 285
michael@0 286 + // Returns an Expr which evaluates to |this| + |delta|
michael@0 287 + Expr add_delta(long delta) {
michael@0 288 + if (delta == 0) {
michael@0 289 + return *this;
michael@0 290 + }
michael@0 291 + // If it's a simple form expression of the form "identifier + offset",
michael@0 292 + // simply add |delta| on to |offset|. In the other two possible
michael@0 293 + // cases:
michael@0 294 + // *(identifier + offset)
michael@0 295 + // completely arbitrary postfix expression string
michael@0 296 + // the only option is to "downgrade" it to a postfix expression and add
michael@0 297 + // "+/- delta" at the end of the string, since the result can't be
michael@0 298 + // represented in the simple form.
michael@0 299 + switch (how_) {
michael@0 300 + case kExprSimpleMem:
michael@0 301 + case kExprPostfix: {
michael@0 302 + char buf[40];
michael@0 303 + sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+');
michael@0 304 + return Expr(getExprPostfix() + string(buf));
michael@0 305 + }
michael@0 306 + case kExprSimple:
michael@0 307 + return Expr(ident_, offset_ + delta, false);
michael@0 308 + case kExprInvalid:
michael@0 309 + default:
michael@0 310 + assert(0 && "add_delta: invalid Module::Expr type");
michael@0 311 + // Invalid inputs produce an invalid result
michael@0 312 + return Expr();
michael@0 313 + }
michael@0 314 + }
michael@0 315 +
michael@0 316 + // Returns an Expr which evaluates to *|this|
michael@0 317 + Expr deref() {
michael@0 318 + // In the simplest case, a kExprSimple can be changed into a
michael@0 319 + // kExprSimpleMem. In all other cases it has to be dumped as a
michael@0 320 + // postfix string, and " ^" added at the end.
michael@0 321 + switch (how_) {
michael@0 322 + case kExprSimple: {
michael@0 323 + Expr t = *this;
michael@0 324 + t.how_ = kExprSimpleMem;
michael@0 325 + return t;
michael@0 326 + }
michael@0 327 + case kExprSimpleMem:
michael@0 328 + case kExprPostfix: {
michael@0 329 + return Expr(getExprPostfix() + " ^");
michael@0 330 + }
michael@0 331 + case kExprInvalid:
michael@0 332 + default:
michael@0 333 + assert(0 && "deref: invalid Module::Expr type");
michael@0 334 + // Invalid inputs produce an invalid result
michael@0 335 + return Expr();
michael@0 336 + }
michael@0 337 + }
michael@0 338 +
michael@0 339 // The identifier that gives the starting value for simple expressions.
michael@0 340 const UniqueString* ident_;
michael@0 341 // The offset to add for simple expressions.
michael@0 342 long offset_;
michael@0 343 // The Postfix expression string to evaluate for non-simple expressions.
michael@0 344 string postfix_;
michael@0 345 // The operation expressed by this expression.
michael@0 346 ExprHow how_;

mercurial