Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
michael@0 | 3 | |
michael@0 | 4 | /* libunwind - a platform-independent unwind library |
michael@0 | 5 | Copyright 2011 Linaro Limited |
michael@0 | 6 | |
michael@0 | 7 | This file is part of libunwind. |
michael@0 | 8 | |
michael@0 | 9 | Permission is hereby granted, free of charge, to any person obtaining |
michael@0 | 10 | a copy of this software and associated documentation files (the |
michael@0 | 11 | "Software"), to deal in the Software without restriction, including |
michael@0 | 12 | without limitation the rights to use, copy, modify, merge, publish, |
michael@0 | 13 | distribute, sublicense, and/or sell copies of the Software, and to |
michael@0 | 14 | permit persons to whom the Software is furnished to do so, subject to |
michael@0 | 15 | the following conditions: |
michael@0 | 16 | |
michael@0 | 17 | The above copyright notice and this permission notice shall be |
michael@0 | 18 | included in all copies or substantial portions of the Software. |
michael@0 | 19 | |
michael@0 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
michael@0 | 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
michael@0 | 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
michael@0 | 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
michael@0 | 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
michael@0 | 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
michael@0 | 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
michael@0 | 27 | |
michael@0 | 28 | |
michael@0 | 29 | // Copyright (c) 2010, 2011 Google Inc. |
michael@0 | 30 | // All rights reserved. |
michael@0 | 31 | // |
michael@0 | 32 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 33 | // modification, are permitted provided that the following conditions are |
michael@0 | 34 | // met: |
michael@0 | 35 | // |
michael@0 | 36 | // * Redistributions of source code must retain the above copyright |
michael@0 | 37 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 38 | // * Redistributions in binary form must reproduce the above |
michael@0 | 39 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 40 | // in the documentation and/or other materials provided with the |
michael@0 | 41 | // distribution. |
michael@0 | 42 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 43 | // contributors may be used to endorse or promote products derived from |
michael@0 | 44 | // this software without specific prior written permission. |
michael@0 | 45 | // |
michael@0 | 46 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 47 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 48 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 49 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 50 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 51 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 52 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 53 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 54 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 55 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 56 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 57 | |
michael@0 | 58 | |
michael@0 | 59 | // Derived from libunwind, with extensive modifications. |
michael@0 | 60 | // This file is derived from the following files in |
michael@0 | 61 | // toolkit/crashreporter/google-breakpad: |
michael@0 | 62 | // src/common/arm_ex_to_module.h |
michael@0 | 63 | // src/common/memory_range.h |
michael@0 | 64 | // src/common/arm_ex_reader.h |
michael@0 | 65 | |
michael@0 | 66 | #ifndef LulExidxExt_h |
michael@0 | 67 | #define LulExidxExt_h |
michael@0 | 68 | |
michael@0 | 69 | #include "LulMainInt.h" |
michael@0 | 70 | |
michael@0 | 71 | using lul::LExpr; |
michael@0 | 72 | using lul::RuleSet; |
michael@0 | 73 | using lul::SecMap; |
michael@0 | 74 | |
michael@0 | 75 | namespace lul { |
michael@0 | 76 | |
michael@0 | 77 | typedef enum extab_cmd { |
michael@0 | 78 | ARM_EXIDX_CMD_FINISH, |
michael@0 | 79 | ARM_EXIDX_CMD_SUB_FROM_VSP, |
michael@0 | 80 | ARM_EXIDX_CMD_ADD_TO_VSP, |
michael@0 | 81 | ARM_EXIDX_CMD_REG_POP, |
michael@0 | 82 | ARM_EXIDX_CMD_REG_TO_SP, |
michael@0 | 83 | ARM_EXIDX_CMD_VFP_POP, |
michael@0 | 84 | ARM_EXIDX_CMD_WREG_POP, |
michael@0 | 85 | ARM_EXIDX_CMD_WCGR_POP, |
michael@0 | 86 | ARM_EXIDX_CMD_RESERVED, |
michael@0 | 87 | ARM_EXIDX_CMD_REFUSED, |
michael@0 | 88 | } extab_cmd_t; |
michael@0 | 89 | |
michael@0 | 90 | struct exidx_entry { |
michael@0 | 91 | uint32_t addr; |
michael@0 | 92 | uint32_t data; |
michael@0 | 93 | }; |
michael@0 | 94 | |
michael@0 | 95 | struct extab_data { |
michael@0 | 96 | extab_cmd_t cmd; |
michael@0 | 97 | uint32_t data; |
michael@0 | 98 | }; |
michael@0 | 99 | |
michael@0 | 100 | enum extab_cmd_flags { |
michael@0 | 101 | ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, |
michael@0 | 102 | ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX |
michael@0 | 103 | }; |
michael@0 | 104 | |
michael@0 | 105 | // Receives information from arm_ex_reader::ExceptionTableInfo |
michael@0 | 106 | // and adds it to the SecMap object |
michael@0 | 107 | // This is in effect the EXIDX summariser. |
michael@0 | 108 | class ARMExToModule { |
michael@0 | 109 | public: |
michael@0 | 110 | ARMExToModule(SecMap* smap, void(*log)(const char*)) : smap_(smap) |
michael@0 | 111 | , log_(log) { } |
michael@0 | 112 | ~ARMExToModule() { } |
michael@0 | 113 | void AddStackFrame(uintptr_t addr, size_t size); |
michael@0 | 114 | int ImproveStackFrame(const struct extab_data* edata); |
michael@0 | 115 | void DeleteStackFrame(); |
michael@0 | 116 | void SubmitStackFrame(); |
michael@0 | 117 | private: |
michael@0 | 118 | SecMap* smap_; |
michael@0 | 119 | LExpr vsp_; // Always appears to be of the form "sp + offset" |
michael@0 | 120 | RuleSet curr_rules_; // Also holds the address range being summarised |
michael@0 | 121 | // debugging message sink |
michael@0 | 122 | void (*log_)(const char*); |
michael@0 | 123 | int TranslateCmd(const struct extab_data* edata, LExpr& vsp); |
michael@0 | 124 | }; |
michael@0 | 125 | |
michael@0 | 126 | |
michael@0 | 127 | // (derived from) |
michael@0 | 128 | // memory_range.h: Define the google_breakpad::MemoryRange class, which |
michael@0 | 129 | // is a lightweight wrapper with a pointer and a length to encapsulate |
michael@0 | 130 | // a contiguous range of memory. |
michael@0 | 131 | |
michael@0 | 132 | // A lightweight wrapper with a pointer and a length to encapsulate a |
michael@0 | 133 | // contiguous range of memory. It provides helper methods for checked |
michael@0 | 134 | // access of a subrange of the memory. Its implemementation does not |
michael@0 | 135 | // allocate memory or call into libc functions, and is thus safer to use |
michael@0 | 136 | // in a crashed environment. |
michael@0 | 137 | class MemoryRange { |
michael@0 | 138 | public: |
michael@0 | 139 | |
michael@0 | 140 | MemoryRange(const void* data, size_t length) { |
michael@0 | 141 | Set(data, length); |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | // Sets this memory range to point to |data| and its length to |length|. |
michael@0 | 145 | void Set(const void* data, size_t length) { |
michael@0 | 146 | data_ = reinterpret_cast<const uint8_t*>(data); |
michael@0 | 147 | // Always set |length_| to zero if |data_| is NULL. |
michael@0 | 148 | length_ = data ? length : 0; |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | // Returns true if this range covers a subrange of |sub_length| bytes |
michael@0 | 152 | // at |sub_offset| bytes of this memory range, or false otherwise. |
michael@0 | 153 | bool Covers(size_t sub_offset, size_t sub_length) const { |
michael@0 | 154 | // The following checks verify that: |
michael@0 | 155 | // 1. sub_offset is within [ 0 .. length_ - 1 ] |
michael@0 | 156 | // 2. sub_offset + sub_length is within |
michael@0 | 157 | // [ sub_offset .. length_ ] |
michael@0 | 158 | return sub_offset < length_ && |
michael@0 | 159 | sub_offset + sub_length >= sub_offset && |
michael@0 | 160 | sub_offset + sub_length <= length_; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | // Returns a pointer to the beginning of this memory range. |
michael@0 | 164 | const uint8_t* data() const { return data_; } |
michael@0 | 165 | |
michael@0 | 166 | // Returns the length, in bytes, of this memory range. |
michael@0 | 167 | size_t length() const { return length_; } |
michael@0 | 168 | |
michael@0 | 169 | private: |
michael@0 | 170 | // Pointer to the beginning of this memory range. |
michael@0 | 171 | const uint8_t* data_; |
michael@0 | 172 | |
michael@0 | 173 | // Length, in bytes, of this memory range. |
michael@0 | 174 | size_t length_; |
michael@0 | 175 | }; |
michael@0 | 176 | |
michael@0 | 177 | |
michael@0 | 178 | // This class is a reader for ARM unwind information |
michael@0 | 179 | // from .ARM.exidx and .ARM.extab sections. |
michael@0 | 180 | class ExceptionTableInfo { |
michael@0 | 181 | public: |
michael@0 | 182 | ExceptionTableInfo(const char* exidx, size_t exidx_size, |
michael@0 | 183 | const char* extab, size_t extab_size, |
michael@0 | 184 | uint32_t text_last_svma, |
michael@0 | 185 | lul::ARMExToModule* handler, |
michael@0 | 186 | const char* mapping_addr, |
michael@0 | 187 | uint32_t loading_addr, |
michael@0 | 188 | uintptr_t text_bias, |
michael@0 | 189 | void (*log)(const char*)) |
michael@0 | 190 | : mr_exidx_(lul::MemoryRange(exidx, exidx_size)), |
michael@0 | 191 | mr_extab_(lul::MemoryRange(extab, extab_size)), |
michael@0 | 192 | text_last_svma_(text_last_svma), |
michael@0 | 193 | handler_(handler), mapping_addr_(mapping_addr), |
michael@0 | 194 | loading_addr_(loading_addr), |
michael@0 | 195 | text_bias_(text_bias), |
michael@0 | 196 | log_(log) { } |
michael@0 | 197 | |
michael@0 | 198 | ~ExceptionTableInfo() { } |
michael@0 | 199 | |
michael@0 | 200 | // Parses the entries in .ARM.exidx and possibly |
michael@0 | 201 | // in .ARM.extab tables, reports what we find to |
michael@0 | 202 | // arm_ex_to_module::ARMExToModule. |
michael@0 | 203 | void Start(); |
michael@0 | 204 | |
michael@0 | 205 | private: |
michael@0 | 206 | lul::MemoryRange mr_exidx_; |
michael@0 | 207 | lul::MemoryRange mr_extab_; |
michael@0 | 208 | uint32_t text_last_svma_; |
michael@0 | 209 | lul::ARMExToModule* handler_; |
michael@0 | 210 | const char* mapping_addr_; |
michael@0 | 211 | uint32_t loading_addr_; |
michael@0 | 212 | uintptr_t text_bias_; |
michael@0 | 213 | // debugging message sink |
michael@0 | 214 | void (*log_)(const char*); |
michael@0 | 215 | enum ExExtractResult { |
michael@0 | 216 | ExSuccess, // success |
michael@0 | 217 | ExInBufOverflow, // out-of-range while reading .exidx |
michael@0 | 218 | ExOutBufOverflow, // output buffer is too small |
michael@0 | 219 | ExCantUnwind, // this function is marked CANT_UNWIND |
michael@0 | 220 | ExCantRepresent, // entry valid, but we can't represent it |
michael@0 | 221 | ExInvalid // entry is invalid |
michael@0 | 222 | }; |
michael@0 | 223 | ExExtractResult |
michael@0 | 224 | ExtabEntryExtract(const struct lul::exidx_entry* entry, |
michael@0 | 225 | uint8_t* buf, size_t buf_size, |
michael@0 | 226 | /*OUT*/size_t* buf_used); |
michael@0 | 227 | |
michael@0 | 228 | int ExtabEntryDecode(const uint8_t* buf, size_t buf_size); |
michael@0 | 229 | }; |
michael@0 | 230 | |
michael@0 | 231 | } // namespace lul |
michael@0 | 232 | |
michael@0 | 233 | #endif // LulExidxExt_h |