1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,269 @@ 1.4 +// -*- mode: C++ -*- 1.5 + 1.6 +// Copyright (c) 2010, Google Inc. 1.7 +// All rights reserved. 1.8 +// 1.9 +// Redistribution and use in source and binary forms, with or without 1.10 +// modification, are permitted provided that the following conditions are 1.11 +// met: 1.12 +// 1.13 +// * Redistributions of source code must retain the above copyright 1.14 +// notice, this list of conditions and the following disclaimer. 1.15 +// * Redistributions in binary form must reproduce the above 1.16 +// copyright notice, this list of conditions and the following disclaimer 1.17 +// in the documentation and/or other materials provided with the 1.18 +// distribution. 1.19 +// * Neither the name of Google Inc. nor the names of its 1.20 +// contributors may be used to endorse or promote products derived from 1.21 +// this software without specific prior written permission. 1.22 +// 1.23 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 + 1.35 +// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 1.36 + 1.37 +// cfi_assembler.h: Define CFISection, a class for creating properly 1.38 +// (and improperly) formatted DWARF CFI data for unit tests. 1.39 + 1.40 +#ifndef PROCESSOR_CFI_ASSEMBLER_H_ 1.41 +#define PROCESSOR_CFI_ASSEMBLER_H_ 1.42 + 1.43 +#include <string> 1.44 + 1.45 +#include "common/dwarf/dwarf2enums.h" 1.46 +#include "common/test_assembler.h" 1.47 +#include "common/using_std_string.h" 1.48 +#include "google_breakpad/common/breakpad_types.h" 1.49 + 1.50 +namespace google_breakpad { 1.51 + 1.52 +using dwarf2reader::DwarfPointerEncoding; 1.53 +using google_breakpad::test_assembler::Endianness; 1.54 +using google_breakpad::test_assembler::Label; 1.55 +using google_breakpad::test_assembler::Section; 1.56 + 1.57 +class CFISection: public Section { 1.58 + public: 1.59 + 1.60 + // CFI augmentation strings beginning with 'z', defined by the 1.61 + // Linux/IA-64 C++ ABI, can specify interesting encodings for 1.62 + // addresses appearing in FDE headers and call frame instructions (and 1.63 + // for additional fields whose presence the augmentation string 1.64 + // specifies). In particular, pointers can be specified to be relative 1.65 + // to various base address: the start of the .text section, the 1.66 + // location holding the address itself, and so on. These allow the 1.67 + // frame data to be position-independent even when they live in 1.68 + // write-protected pages. These variants are specified at the 1.69 + // following two URLs: 1.70 + // 1.71 + // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html 1.72 + // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 1.73 + // 1.74 + // CFISection leaves the production of well-formed 'z'-augmented CIEs and 1.75 + // FDEs to the user, but does provide EncodedPointer, to emit 1.76 + // properly-encoded addresses for a given pointer encoding. 1.77 + // EncodedPointer uses an instance of this structure to find the base 1.78 + // addresses it should use; you can establish a default for all encoded 1.79 + // pointers appended to this section with SetEncodedPointerBases. 1.80 + struct EncodedPointerBases { 1.81 + EncodedPointerBases() : cfi(), text(), data() { } 1.82 + 1.83 + // The starting address of this CFI section in memory, for 1.84 + // DW_EH_PE_pcrel. DW_EH_PE_pcrel pointers may only be used in data 1.85 + // that has is loaded into the program's address space. 1.86 + uint64_t cfi; 1.87 + 1.88 + // The starting address of this file's .text section, for DW_EH_PE_textrel. 1.89 + uint64_t text; 1.90 + 1.91 + // The starting address of this file's .got or .eh_frame_hdr section, 1.92 + // for DW_EH_PE_datarel. 1.93 + uint64_t data; 1.94 + }; 1.95 + 1.96 + // Create a CFISection whose endianness is ENDIANNESS, and where 1.97 + // machine addresses are ADDRESS_SIZE bytes long. If EH_FRAME is 1.98 + // true, use the .eh_frame format, as described by the Linux 1.99 + // Standards Base Core Specification, instead of the DWARF CFI 1.100 + // format. 1.101 + CFISection(Endianness endianness, size_t address_size, 1.102 + bool eh_frame = false) 1.103 + : Section(endianness), address_size_(address_size), eh_frame_(eh_frame), 1.104 + pointer_encoding_(dwarf2reader::DW_EH_PE_absptr), 1.105 + encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) { 1.106 + // The 'start', 'Here', and 'Mark' members of a CFISection all refer 1.107 + // to section offsets. 1.108 + start() = 0; 1.109 + } 1.110 + 1.111 + // Return this CFISection's address size. 1.112 + size_t AddressSize() const { return address_size_; } 1.113 + 1.114 + // Return true if this CFISection uses the .eh_frame format, or 1.115 + // false if it contains ordinary DWARF CFI data. 1.116 + bool ContainsEHFrame() const { return eh_frame_; } 1.117 + 1.118 + // Use ENCODING for pointers in calls to FDEHeader and EncodedPointer. 1.119 + void SetPointerEncoding(DwarfPointerEncoding encoding) { 1.120 + pointer_encoding_ = encoding; 1.121 + } 1.122 + 1.123 + // Use the addresses in BASES as the base addresses for encoded 1.124 + // pointers in subsequent calls to FDEHeader or EncodedPointer. 1.125 + // This function makes a copy of BASES. 1.126 + void SetEncodedPointerBases(const EncodedPointerBases &bases) { 1.127 + encoded_pointer_bases_ = bases; 1.128 + } 1.129 + 1.130 + // Append a Common Information Entry header to this section with the 1.131 + // given values. If dwarf64 is true, use the 64-bit DWARF initial 1.132 + // length format for the CIE's initial length. Return a reference to 1.133 + // this section. You should call FinishEntry after writing the last 1.134 + // instruction for the CIE. 1.135 + // 1.136 + // Before calling this function, you will typically want to use Mark 1.137 + // or Here to make a label to pass to FDEHeader that refers to this 1.138 + // CIE's position in the section. 1.139 + CFISection &CIEHeader(uint64_t code_alignment_factor, 1.140 + int data_alignment_factor, 1.141 + unsigned return_address_register, 1.142 + uint8_t version = 3, 1.143 + const string &augmentation = "", 1.144 + bool dwarf64 = false); 1.145 + 1.146 + // Append a Frame Description Entry header to this section with the 1.147 + // given values. If dwarf64 is true, use the 64-bit DWARF initial 1.148 + // length format for the CIE's initial length. Return a reference to 1.149 + // this section. You should call FinishEntry after writing the last 1.150 + // instruction for the CIE. 1.151 + // 1.152 + // This function doesn't support entries that are longer than 1.153 + // 0xffffff00 bytes. (The "initial length" is always a 32-bit 1.154 + // value.) Nor does it support .debug_frame sections longer than 1.155 + // 0xffffff00 bytes. 1.156 + CFISection &FDEHeader(Label cie_pointer, 1.157 + uint64_t initial_location, 1.158 + uint64_t address_range, 1.159 + bool dwarf64 = false); 1.160 + 1.161 + // Note the current position as the end of the last CIE or FDE we 1.162 + // started, after padding with DW_CFA_nops for alignment. This 1.163 + // defines the label representing the entry's length, cited in the 1.164 + // entry's header. Return a reference to this section. 1.165 + CFISection &FinishEntry(); 1.166 + 1.167 + // Append the contents of BLOCK as a DW_FORM_block value: an 1.168 + // unsigned LEB128 length, followed by that many bytes of data. 1.169 + CFISection &Block(const string &block) { 1.170 + ULEB128(block.size()); 1.171 + Append(block); 1.172 + return *this; 1.173 + } 1.174 + 1.175 + // Append ADDRESS to this section, in the appropriate size and 1.176 + // endianness. Return a reference to this section. 1.177 + CFISection &Address(uint64_t address) { 1.178 + Section::Append(endianness(), address_size_, address); 1.179 + return *this; 1.180 + } 1.181 + CFISection &Address(Label address) { 1.182 + Section::Append(endianness(), address_size_, address); 1.183 + return *this; 1.184 + } 1.185 + 1.186 + // Append ADDRESS to this section, using ENCODING and BASES. ENCODING 1.187 + // defaults to this section's default encoding, established by 1.188 + // SetPointerEncoding. BASES defaults to this section's bases, set by 1.189 + // SetEncodedPointerBases. If the DW_EH_PE_indirect bit is set in the 1.190 + // encoding, assume that ADDRESS is where the true address is stored. 1.191 + // Return a reference to this section. 1.192 + // 1.193 + // (C++ doesn't let me use default arguments here, because I want to 1.194 + // refer to members of *this in the default argument expression.) 1.195 + CFISection &EncodedPointer(uint64_t address) { 1.196 + return EncodedPointer(address, pointer_encoding_, encoded_pointer_bases_); 1.197 + } 1.198 + CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) { 1.199 + return EncodedPointer(address, encoding, encoded_pointer_bases_); 1.200 + } 1.201 + CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding, 1.202 + const EncodedPointerBases &bases); 1.203 + 1.204 + // Restate some member functions, to keep chaining working nicely. 1.205 + CFISection &Mark(Label *label) { Section::Mark(label); return *this; } 1.206 + CFISection &D8(uint8_t v) { Section::D8(v); return *this; } 1.207 + CFISection &D16(uint16_t v) { Section::D16(v); return *this; } 1.208 + CFISection &D16(Label v) { Section::D16(v); return *this; } 1.209 + CFISection &D32(uint32_t v) { Section::D32(v); return *this; } 1.210 + CFISection &D32(const Label &v) { Section::D32(v); return *this; } 1.211 + CFISection &D64(uint64_t v) { Section::D64(v); return *this; } 1.212 + CFISection &D64(const Label &v) { Section::D64(v); return *this; } 1.213 + CFISection &LEB128(long long v) { Section::LEB128(v); return *this; } 1.214 + CFISection &ULEB128(uint64_t v) { Section::ULEB128(v); return *this; } 1.215 + 1.216 + private: 1.217 + // A length value that we've appended to the section, but is not yet 1.218 + // known. LENGTH is the appended value; START is a label referring 1.219 + // to the start of the data whose length was cited. 1.220 + struct PendingLength { 1.221 + Label length; 1.222 + Label start; 1.223 + }; 1.224 + 1.225 + // Constants used in CFI/.eh_frame data: 1.226 + 1.227 + // If the first four bytes of an "initial length" are this constant, then 1.228 + // the data uses the 64-bit DWARF format, and the length itself is the 1.229 + // subsequent eight bytes. 1.230 + static const uint32_t kDwarf64InitialLengthMarker = 0xffffffffU; 1.231 + 1.232 + // The CIE identifier for 32- and 64-bit DWARF CFI and .eh_frame data. 1.233 + static const uint32_t kDwarf32CIEIdentifier = ~(uint32_t)0; 1.234 + static const uint64_t kDwarf64CIEIdentifier = ~(uint64_t)0; 1.235 + static const uint32_t kEHFrame32CIEIdentifier = 0; 1.236 + static const uint64_t kEHFrame64CIEIdentifier = 0; 1.237 + 1.238 + // The size of a machine address for the data in this section. 1.239 + size_t address_size_; 1.240 + 1.241 + // If true, we are generating a Linux .eh_frame section, instead of 1.242 + // a standard DWARF .debug_frame section. 1.243 + bool eh_frame_; 1.244 + 1.245 + // The encoding to use for FDE pointers. 1.246 + DwarfPointerEncoding pointer_encoding_; 1.247 + 1.248 + // The base addresses to use when emitting encoded pointers. 1.249 + EncodedPointerBases encoded_pointer_bases_; 1.250 + 1.251 + // The length value for the current entry. 1.252 + // 1.253 + // Oddly, this must be dynamically allocated. Labels never get new 1.254 + // values; they only acquire constraints on the value they already 1.255 + // have, or assert if you assign them something incompatible. So 1.256 + // each header needs truly fresh Label objects to cite in their 1.257 + // headers and track their positions. The alternative is explicit 1.258 + // destructor invocation and a placement new. Ick. 1.259 + PendingLength *entry_length_; 1.260 + 1.261 + // True if we are currently emitting an FDE --- that is, we have 1.262 + // called FDEHeader but have not yet called FinishEntry. 1.263 + bool in_fde_; 1.264 + 1.265 + // If in_fde_ is true, this is its starting address. We use this for 1.266 + // emitting DW_EH_PE_funcrel pointers. 1.267 + uint64_t fde_start_address_; 1.268 +}; 1.269 + 1.270 +} // namespace google_breakpad 1.271 + 1.272 +#endif // PROCESSOR_CFI_ASSEMBLER_H_