1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,191 @@ 1.4 + 1.5 +/* libunwind - a platform-independent unwind library 1.6 + Copyright 2011 Linaro Limited 1.7 + 1.8 +This file is part of libunwind. 1.9 + 1.10 +Permission is hereby granted, free of charge, to any person obtaining 1.11 +a copy of this software and associated documentation files (the 1.12 +"Software"), to deal in the Software without restriction, including 1.13 +without limitation the rights to use, copy, modify, merge, publish, 1.14 +distribute, sublicense, and/or sell copies of the Software, and to 1.15 +permit persons to whom the Software is furnished to do so, subject to 1.16 +the following conditions: 1.17 + 1.18 +The above copyright notice and this permission notice shall be 1.19 +included in all copies or substantial portions of the Software. 1.20 + 1.21 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1.22 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1.23 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1.24 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 1.25 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 1.26 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 1.27 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 1.28 + 1.29 +// Copyright (c) 2010 Google Inc. 1.30 +// All rights reserved. 1.31 +// 1.32 +// Redistribution and use in source and binary forms, with or without 1.33 +// modification, are permitted provided that the following conditions are 1.34 +// met: 1.35 +// 1.36 +// * Redistributions of source code must retain the above copyright 1.37 +// notice, this list of conditions and the following disclaimer. 1.38 +// * Redistributions in binary form must reproduce the above 1.39 +// copyright notice, this list of conditions and the following disclaimer 1.40 +// in the documentation and/or other materials provided with the 1.41 +// distribution. 1.42 +// * Neither the name of Google Inc. nor the names of its 1.43 +// contributors may be used to endorse or promote products derived from 1.44 +// this software without specific prior written permission. 1.45 +// 1.46 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.47 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.48 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.49 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.50 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.51 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.52 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.53 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.54 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.55 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.56 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.57 + 1.58 + 1.59 +// Derived from libunwind, with extensive modifications. 1.60 + 1.61 +#include "common/unique_string.h" 1.62 +#include "common/arm_ex_to_module.h" 1.63 + 1.64 +#include <stdio.h> 1.65 +#include <assert.h> 1.66 + 1.67 +// For big-picture comments on how the EXIDX reader works, 1.68 +// see arm_ex_reader.cc. 1.69 + 1.70 +#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) 1.71 +#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) 1.72 +#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) 1.73 + 1.74 +using google_breakpad::ustr__pc; 1.75 +using google_breakpad::ustr__lr; 1.76 +using google_breakpad::ustr__sp; 1.77 +using google_breakpad::ustr__ZDra; 1.78 +using google_breakpad::ustr__ZDcfa; 1.79 +using google_breakpad::Module; 1.80 +using google_breakpad::ToUniqueString; 1.81 +using google_breakpad::UniqueString; 1.82 + 1.83 +namespace arm_ex_to_module { 1.84 + 1.85 +// Translate command from extab_data to command for Module. 1.86 +int ARMExToModule::TranslateCmd(const struct extab_data* edata, 1.87 + Module::StackFrameEntry* entry, 1.88 + Module::Expr& vsp) { 1.89 + int ret = 0; 1.90 + switch (edata->cmd) { 1.91 + case ARM_EXIDX_CMD_FINISH: 1.92 + /* Copy LR to PC if there isn't currently a rule for PC in force. */ 1.93 + if (entry->initial_rules.find(ustr__pc()) 1.94 + == entry->initial_rules.end()) { 1.95 + if (entry->initial_rules.find(ustr__lr()) 1.96 + == entry->initial_rules.end()) { 1.97 + entry->initial_rules[ustr__pc()] = Module::Expr(ustr__lr(), 1.98 + 0, false); // "lr" 1.99 + } else { 1.100 + entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()]; 1.101 + } 1.102 + } 1.103 + break; 1.104 + case ARM_EXIDX_CMD_SUB_FROM_VSP: 1.105 + vsp = vsp.add_delta(- static_cast<long>(edata->data)); 1.106 + break; 1.107 + case ARM_EXIDX_CMD_ADD_TO_VSP: 1.108 + vsp = vsp.add_delta(static_cast<long>(edata->data)); 1.109 + break; 1.110 + case ARM_EXIDX_CMD_REG_POP: 1.111 + for (unsigned int i = 0; i < 16; i++) { 1.112 + if (edata->data & (1 << i)) { 1.113 + entry->initial_rules[ToUniqueString(regnames[i])] = vsp.deref(); 1.114 + vsp = vsp.add_delta(4); 1.115 + } 1.116 + } 1.117 + /* Set cfa in case the SP got popped. */ 1.118 + if (edata->data & (1 << 13)) { 1.119 + vsp = entry->initial_rules[ustr__sp()]; 1.120 + } 1.121 + break; 1.122 + case ARM_EXIDX_CMD_REG_TO_SP: { 1.123 + assert (edata->data < 16); 1.124 + const char* const regname = regnames[edata->data]; 1.125 + const UniqueString* regname_us = ToUniqueString(regname); 1.126 + if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) { 1.127 + entry->initial_rules[ustr__sp()] = Module::Expr(regname_us, 1.128 + 0, false); // "regname" 1.129 + } else { 1.130 + entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us]; 1.131 + } 1.132 + vsp = entry->initial_rules[ustr__sp()]; 1.133 + break; 1.134 + } 1.135 + case ARM_EXIDX_CMD_VFP_POP: 1.136 + /* Don't recover VFP registers, but be sure to adjust the stack 1.137 + pointer. */ 1.138 + for (unsigned int i = ARM_EXBUF_START(edata->data); 1.139 + i <= ARM_EXBUF_END(edata->data); i++) { 1.140 + vsp = vsp.add_delta(8); 1.141 + } 1.142 + if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) { 1.143 + vsp = vsp.add_delta(4); 1.144 + } 1.145 + break; 1.146 + case ARM_EXIDX_CMD_WREG_POP: 1.147 + for (unsigned int i = ARM_EXBUF_START(edata->data); 1.148 + i <= ARM_EXBUF_END(edata->data); i++) { 1.149 + vsp = vsp.add_delta(8); 1.150 + } 1.151 + break; 1.152 + case ARM_EXIDX_CMD_WCGR_POP: 1.153 + // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4" 1.154 + for (unsigned int i = 0; i < 4; i++) { 1.155 + if (edata->data & (1 << i)) { 1.156 + vsp = vsp.add_delta(4); 1.157 + } 1.158 + } 1.159 + break; 1.160 + case ARM_EXIDX_CMD_REFUSED: 1.161 + case ARM_EXIDX_CMD_RESERVED: 1.162 + ret = -1; 1.163 + break; 1.164 + } 1.165 + return ret; 1.166 +} 1.167 + 1.168 +void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) { 1.169 + stack_frame_entry_ = new Module::StackFrameEntry; 1.170 + stack_frame_entry_->address = addr; 1.171 + stack_frame_entry_->size = size; 1.172 + Module::Expr sp_expr = Module::Expr(ustr__sp(), 0, false); // "sp" 1.173 + stack_frame_entry_->initial_rules[ustr__ZDcfa()] = sp_expr; // ".cfa" 1.174 + vsp_ = sp_expr; 1.175 +} 1.176 + 1.177 +int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) { 1.178 + return TranslateCmd(edata, stack_frame_entry_, vsp_) ; 1.179 +} 1.180 + 1.181 +void ARMExToModule::DeleteStackFrame() { 1.182 + delete stack_frame_entry_; 1.183 +} 1.184 + 1.185 +void ARMExToModule::SubmitStackFrame() { 1.186 + // return address always winds up in pc 1.187 + stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra" 1.188 + = stack_frame_entry_->initial_rules[ustr__pc()]; 1.189 + // the final value of vsp is the new value of sp 1.190 + stack_frame_entry_->initial_rules[ustr__sp()] = vsp_; 1.191 + module_->AddStackFrameEntry(stack_frame_entry_); 1.192 +} 1.193 + 1.194 +} // namespace arm_ex_to_module