1*9712c20fSFrederick Mayle // -*- mode: C++ -*- 2*9712c20fSFrederick Mayle 3*9712c20fSFrederick Mayle // Copyright 2010 Google LLC 4*9712c20fSFrederick Mayle // 5*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without 6*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are 7*9712c20fSFrederick Mayle // met: 8*9712c20fSFrederick Mayle // 9*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright 10*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer. 11*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above 12*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer 13*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the 14*9712c20fSFrederick Mayle // distribution. 15*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its 16*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from 17*9712c20fSFrederick Mayle // this software without specific prior written permission. 18*9712c20fSFrederick Mayle // 19*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*9712c20fSFrederick Mayle 31*9712c20fSFrederick Mayle // Original author: Jim Blandy <[email protected]> <[email protected]> 32*9712c20fSFrederick Mayle 33*9712c20fSFrederick Mayle // cfi_assembler.h: Define CFISection, a class for creating properly 34*9712c20fSFrederick Mayle // (and improperly) formatted DWARF CFI data for unit tests. 35*9712c20fSFrederick Mayle 36*9712c20fSFrederick Mayle #ifndef PROCESSOR_CFI_ASSEMBLER_H_ 37*9712c20fSFrederick Mayle #define PROCESSOR_CFI_ASSEMBLER_H_ 38*9712c20fSFrederick Mayle 39*9712c20fSFrederick Mayle #include <string> 40*9712c20fSFrederick Mayle 41*9712c20fSFrederick Mayle #include "common/dwarf/dwarf2enums.h" 42*9712c20fSFrederick Mayle #include "common/test_assembler.h" 43*9712c20fSFrederick Mayle #include "common/using_std_string.h" 44*9712c20fSFrederick Mayle #include "google_breakpad/common/breakpad_types.h" 45*9712c20fSFrederick Mayle 46*9712c20fSFrederick Mayle namespace google_breakpad { 47*9712c20fSFrederick Mayle 48*9712c20fSFrederick Mayle using google_breakpad::test_assembler::Label; 49*9712c20fSFrederick Mayle using google_breakpad::test_assembler::Section; 50*9712c20fSFrederick Mayle 51*9712c20fSFrederick Mayle class CFISection: public Section { 52*9712c20fSFrederick Mayle public: 53*9712c20fSFrederick Mayle 54*9712c20fSFrederick Mayle // CFI augmentation strings beginning with 'z', defined by the 55*9712c20fSFrederick Mayle // Linux/IA-64 C++ ABI, can specify interesting encodings for 56*9712c20fSFrederick Mayle // addresses appearing in FDE headers and call frame instructions (and 57*9712c20fSFrederick Mayle // for additional fields whose presence the augmentation string 58*9712c20fSFrederick Mayle // specifies). In particular, pointers can be specified to be relative 59*9712c20fSFrederick Mayle // to various base address: the start of the .text section, the 60*9712c20fSFrederick Mayle // location holding the address itself, and so on. These allow the 61*9712c20fSFrederick Mayle // frame data to be position-independent even when they live in 62*9712c20fSFrederick Mayle // write-protected pages. These variants are specified at the 63*9712c20fSFrederick Mayle // following two URLs: 64*9712c20fSFrederick Mayle // 65*9712c20fSFrederick Mayle // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html 66*9712c20fSFrederick Mayle // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 67*9712c20fSFrederick Mayle // 68*9712c20fSFrederick Mayle // CFISection leaves the production of well-formed 'z'-augmented CIEs and 69*9712c20fSFrederick Mayle // FDEs to the user, but does provide EncodedPointer, to emit 70*9712c20fSFrederick Mayle // properly-encoded addresses for a given pointer encoding. 71*9712c20fSFrederick Mayle // EncodedPointer uses an instance of this structure to find the base 72*9712c20fSFrederick Mayle // addresses it should use; you can establish a default for all encoded 73*9712c20fSFrederick Mayle // pointers appended to this section with SetEncodedPointerBases. 74*9712c20fSFrederick Mayle struct EncodedPointerBases { EncodedPointerBasesEncodedPointerBases75*9712c20fSFrederick Mayle EncodedPointerBases() : cfi(), text(), data() { } 76*9712c20fSFrederick Mayle 77*9712c20fSFrederick Mayle // The starting address of this CFI section in memory, for 78*9712c20fSFrederick Mayle // DW_EH_PE_pcrel. DW_EH_PE_pcrel pointers may only be used in data 79*9712c20fSFrederick Mayle // that has is loaded into the program's address space. 80*9712c20fSFrederick Mayle uint64_t cfi; 81*9712c20fSFrederick Mayle 82*9712c20fSFrederick Mayle // The starting address of this file's .text section, for DW_EH_PE_textrel. 83*9712c20fSFrederick Mayle uint64_t text; 84*9712c20fSFrederick Mayle 85*9712c20fSFrederick Mayle // The starting address of this file's .got or .eh_frame_hdr section, 86*9712c20fSFrederick Mayle // for DW_EH_PE_datarel. 87*9712c20fSFrederick Mayle uint64_t data; 88*9712c20fSFrederick Mayle }; 89*9712c20fSFrederick Mayle 90*9712c20fSFrederick Mayle // Create a CFISection whose endianness is ENDIANNESS, and where 91*9712c20fSFrederick Mayle // machine addresses are ADDRESS_SIZE bytes long. If EH_FRAME is 92*9712c20fSFrederick Mayle // true, use the .eh_frame format, as described by the Linux 93*9712c20fSFrederick Mayle // Standards Base Core Specification, instead of the DWARF CFI 94*9712c20fSFrederick Mayle // format. 95*9712c20fSFrederick Mayle CFISection(google_breakpad::test_assembler::Endianness endianness, size_t address_size, 96*9712c20fSFrederick Mayle bool eh_frame = false) Section(endianness)97*9712c20fSFrederick Mayle : Section(endianness), address_size_(address_size), eh_frame_(eh_frame), 98*9712c20fSFrederick Mayle pointer_encoding_(DW_EH_PE_absptr), 99*9712c20fSFrederick Mayle encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) { 100*9712c20fSFrederick Mayle // The 'start', 'Here', and 'Mark' members of a CFISection all refer 101*9712c20fSFrederick Mayle // to section offsets. 102*9712c20fSFrederick Mayle start() = 0; 103*9712c20fSFrederick Mayle } 104*9712c20fSFrederick Mayle 105*9712c20fSFrederick Mayle // Return this CFISection's address size. AddressSize()106*9712c20fSFrederick Mayle size_t AddressSize() const { return address_size_; } 107*9712c20fSFrederick Mayle 108*9712c20fSFrederick Mayle // Return true if this CFISection uses the .eh_frame format, or 109*9712c20fSFrederick Mayle // false if it contains ordinary DWARF CFI data. ContainsEHFrame()110*9712c20fSFrederick Mayle bool ContainsEHFrame() const { return eh_frame_; } 111*9712c20fSFrederick Mayle 112*9712c20fSFrederick Mayle // Use ENCODING for pointers in calls to FDEHeader and EncodedPointer. SetPointerEncoding(DwarfPointerEncoding encoding)113*9712c20fSFrederick Mayle void SetPointerEncoding(DwarfPointerEncoding encoding) { 114*9712c20fSFrederick Mayle pointer_encoding_ = encoding; 115*9712c20fSFrederick Mayle } 116*9712c20fSFrederick Mayle 117*9712c20fSFrederick Mayle // Use the addresses in BASES as the base addresses for encoded 118*9712c20fSFrederick Mayle // pointers in subsequent calls to FDEHeader or EncodedPointer. 119*9712c20fSFrederick Mayle // This function makes a copy of BASES. SetEncodedPointerBases(const EncodedPointerBases & bases)120*9712c20fSFrederick Mayle void SetEncodedPointerBases(const EncodedPointerBases& bases) { 121*9712c20fSFrederick Mayle encoded_pointer_bases_ = bases; 122*9712c20fSFrederick Mayle } 123*9712c20fSFrederick Mayle 124*9712c20fSFrederick Mayle // Append a Common Information Entry header to this section with the 125*9712c20fSFrederick Mayle // given values. If dwarf64 is true, use the 64-bit DWARF initial 126*9712c20fSFrederick Mayle // length format for the CIE's initial length. Return a reference to 127*9712c20fSFrederick Mayle // this section. You should call FinishEntry after writing the last 128*9712c20fSFrederick Mayle // instruction for the CIE. 129*9712c20fSFrederick Mayle // 130*9712c20fSFrederick Mayle // Before calling this function, you will typically want to use Mark 131*9712c20fSFrederick Mayle // or Here to make a label to pass to FDEHeader that refers to this 132*9712c20fSFrederick Mayle // CIE's position in the section. 133*9712c20fSFrederick Mayle CFISection& CIEHeader(uint64_t code_alignment_factor, 134*9712c20fSFrederick Mayle int data_alignment_factor, 135*9712c20fSFrederick Mayle unsigned return_address_register, 136*9712c20fSFrederick Mayle uint8_t version = 3, 137*9712c20fSFrederick Mayle const string& augmentation = "", 138*9712c20fSFrederick Mayle bool dwarf64 = false, 139*9712c20fSFrederick Mayle uint8_t address_size = 8, 140*9712c20fSFrederick Mayle uint8_t segment_size = 0); 141*9712c20fSFrederick Mayle 142*9712c20fSFrederick Mayle // Append a Frame Description Entry header to this section with the 143*9712c20fSFrederick Mayle // given values. If dwarf64 is true, use the 64-bit DWARF initial 144*9712c20fSFrederick Mayle // length format for the CIE's initial length. Return a reference to 145*9712c20fSFrederick Mayle // this section. You should call FinishEntry after writing the last 146*9712c20fSFrederick Mayle // instruction for the CIE. 147*9712c20fSFrederick Mayle // 148*9712c20fSFrederick Mayle // This function doesn't support entries that are longer than 149*9712c20fSFrederick Mayle // 0xffffff00 bytes. (The "initial length" is always a 32-bit 150*9712c20fSFrederick Mayle // value.) Nor does it support .debug_frame sections longer than 151*9712c20fSFrederick Mayle // 0xffffff00 bytes. 152*9712c20fSFrederick Mayle CFISection& FDEHeader(Label cie_pointer, 153*9712c20fSFrederick Mayle uint64_t initial_location, 154*9712c20fSFrederick Mayle uint64_t address_range, 155*9712c20fSFrederick Mayle bool dwarf64 = false); 156*9712c20fSFrederick Mayle 157*9712c20fSFrederick Mayle // Note the current position as the end of the last CIE or FDE we 158*9712c20fSFrederick Mayle // started, after padding with DW_CFA_nops for alignment. This 159*9712c20fSFrederick Mayle // defines the label representing the entry's length, cited in the 160*9712c20fSFrederick Mayle // entry's header. Return a reference to this section. 161*9712c20fSFrederick Mayle CFISection& FinishEntry(); 162*9712c20fSFrederick Mayle 163*9712c20fSFrederick Mayle // Append the contents of BLOCK as a DW_FORM_block value: an 164*9712c20fSFrederick Mayle // unsigned LEB128 length, followed by that many bytes of data. Block(const string & block)165*9712c20fSFrederick Mayle CFISection& Block(const string& block) { 166*9712c20fSFrederick Mayle ULEB128(block.size()); 167*9712c20fSFrederick Mayle Append(block); 168*9712c20fSFrederick Mayle return *this; 169*9712c20fSFrederick Mayle } 170*9712c20fSFrederick Mayle 171*9712c20fSFrederick Mayle // Append ADDRESS to this section, in the appropriate size and 172*9712c20fSFrederick Mayle // endianness. Return a reference to this section. Address(uint64_t address)173*9712c20fSFrederick Mayle CFISection& Address(uint64_t address) { 174*9712c20fSFrederick Mayle Section::Append(endianness(), address_size_, address); 175*9712c20fSFrederick Mayle return *this; 176*9712c20fSFrederick Mayle } Address(Label address)177*9712c20fSFrederick Mayle CFISection& Address(Label address) { 178*9712c20fSFrederick Mayle Section::Append(endianness(), address_size_, address); 179*9712c20fSFrederick Mayle return *this; 180*9712c20fSFrederick Mayle } 181*9712c20fSFrederick Mayle 182*9712c20fSFrederick Mayle // Append ADDRESS to this section, using ENCODING and BASES. ENCODING 183*9712c20fSFrederick Mayle // defaults to this section's default encoding, established by 184*9712c20fSFrederick Mayle // SetPointerEncoding. BASES defaults to this section's bases, set by 185*9712c20fSFrederick Mayle // SetEncodedPointerBases. If the DW_EH_PE_indirect bit is set in the 186*9712c20fSFrederick Mayle // encoding, assume that ADDRESS is where the true address is stored. 187*9712c20fSFrederick Mayle // Return a reference to this section. 188*9712c20fSFrederick Mayle // 189*9712c20fSFrederick Mayle // (C++ doesn't let me use default arguments here, because I want to 190*9712c20fSFrederick Mayle // refer to members of *this in the default argument expression.) EncodedPointer(uint64_t address)191*9712c20fSFrederick Mayle CFISection& EncodedPointer(uint64_t address) { 192*9712c20fSFrederick Mayle return EncodedPointer(address, pointer_encoding_, encoded_pointer_bases_); 193*9712c20fSFrederick Mayle } EncodedPointer(uint64_t address,DwarfPointerEncoding encoding)194*9712c20fSFrederick Mayle CFISection& EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) { 195*9712c20fSFrederick Mayle return EncodedPointer(address, encoding, encoded_pointer_bases_); 196*9712c20fSFrederick Mayle } 197*9712c20fSFrederick Mayle CFISection& EncodedPointer(uint64_t address, DwarfPointerEncoding encoding, 198*9712c20fSFrederick Mayle const EncodedPointerBases& bases); 199*9712c20fSFrederick Mayle 200*9712c20fSFrederick Mayle // Restate some member functions, to keep chaining working nicely. Mark(Label * label)201*9712c20fSFrederick Mayle CFISection& Mark(Label* label) { Section::Mark(label); return *this; } D8(uint8_t v)202*9712c20fSFrederick Mayle CFISection& D8(uint8_t v) { Section::D8(v); return *this; } D16(uint16_t v)203*9712c20fSFrederick Mayle CFISection& D16(uint16_t v) { Section::D16(v); return *this; } D16(Label v)204*9712c20fSFrederick Mayle CFISection& D16(Label v) { Section::D16(v); return *this; } D32(uint32_t v)205*9712c20fSFrederick Mayle CFISection& D32(uint32_t v) { Section::D32(v); return *this; } D32(const Label & v)206*9712c20fSFrederick Mayle CFISection& D32(const Label& v) { Section::D32(v); return *this; } D64(uint64_t v)207*9712c20fSFrederick Mayle CFISection& D64(uint64_t v) { Section::D64(v); return *this; } D64(const Label & v)208*9712c20fSFrederick Mayle CFISection& D64(const Label& v) { Section::D64(v); return *this; } LEB128(long long v)209*9712c20fSFrederick Mayle CFISection& LEB128(long long v) { Section::LEB128(v); return *this; } ULEB128(uint64_t v)210*9712c20fSFrederick Mayle CFISection& ULEB128(uint64_t v) { Section::ULEB128(v); return *this; } 211*9712c20fSFrederick Mayle 212*9712c20fSFrederick Mayle private: 213*9712c20fSFrederick Mayle // A length value that we've appended to the section, but is not yet 214*9712c20fSFrederick Mayle // known. LENGTH is the appended value; START is a label referring 215*9712c20fSFrederick Mayle // to the start of the data whose length was cited. 216*9712c20fSFrederick Mayle struct PendingLength { 217*9712c20fSFrederick Mayle Label length; 218*9712c20fSFrederick Mayle Label start; 219*9712c20fSFrederick Mayle }; 220*9712c20fSFrederick Mayle 221*9712c20fSFrederick Mayle // Constants used in CFI/.eh_frame data: 222*9712c20fSFrederick Mayle 223*9712c20fSFrederick Mayle // If the first four bytes of an "initial length" are this constant, then 224*9712c20fSFrederick Mayle // the data uses the 64-bit DWARF format, and the length itself is the 225*9712c20fSFrederick Mayle // subsequent eight bytes. 226*9712c20fSFrederick Mayle static const uint32_t kDwarf64InitialLengthMarker = 0xffffffffU; 227*9712c20fSFrederick Mayle 228*9712c20fSFrederick Mayle // The CIE identifier for 32- and 64-bit DWARF CFI and .eh_frame data. 229*9712c20fSFrederick Mayle static const uint32_t kDwarf32CIEIdentifier = ~(uint32_t)0; 230*9712c20fSFrederick Mayle static const uint64_t kDwarf64CIEIdentifier = ~(uint64_t)0; 231*9712c20fSFrederick Mayle static const uint32_t kEHFrame32CIEIdentifier = 0; 232*9712c20fSFrederick Mayle static const uint64_t kEHFrame64CIEIdentifier = 0; 233*9712c20fSFrederick Mayle 234*9712c20fSFrederick Mayle // The size of a machine address for the data in this section. 235*9712c20fSFrederick Mayle size_t address_size_; 236*9712c20fSFrederick Mayle 237*9712c20fSFrederick Mayle // If true, we are generating a Linux .eh_frame section, instead of 238*9712c20fSFrederick Mayle // a standard DWARF .debug_frame section. 239*9712c20fSFrederick Mayle bool eh_frame_; 240*9712c20fSFrederick Mayle 241*9712c20fSFrederick Mayle // The encoding to use for FDE pointers. 242*9712c20fSFrederick Mayle DwarfPointerEncoding pointer_encoding_; 243*9712c20fSFrederick Mayle 244*9712c20fSFrederick Mayle // The base addresses to use when emitting encoded pointers. 245*9712c20fSFrederick Mayle EncodedPointerBases encoded_pointer_bases_; 246*9712c20fSFrederick Mayle 247*9712c20fSFrederick Mayle // The length value for the current entry. 248*9712c20fSFrederick Mayle // 249*9712c20fSFrederick Mayle // Oddly, this must be dynamically allocated. Labels never get new 250*9712c20fSFrederick Mayle // values; they only acquire constraints on the value they already 251*9712c20fSFrederick Mayle // have, or assert if you assign them something incompatible. So 252*9712c20fSFrederick Mayle // each header needs truly fresh Label objects to cite in their 253*9712c20fSFrederick Mayle // headers and track their positions. The alternative is explicit 254*9712c20fSFrederick Mayle // destructor invocation and a placement new. Ick. 255*9712c20fSFrederick Mayle PendingLength *entry_length_; 256*9712c20fSFrederick Mayle 257*9712c20fSFrederick Mayle // True if we are currently emitting an FDE --- that is, we have 258*9712c20fSFrederick Mayle // called FDEHeader but have not yet called FinishEntry. 259*9712c20fSFrederick Mayle bool in_fde_; 260*9712c20fSFrederick Mayle 261*9712c20fSFrederick Mayle // If in_fde_ is true, this is its starting address. We use this for 262*9712c20fSFrederick Mayle // emitting DW_EH_PE_funcrel pointers. 263*9712c20fSFrederick Mayle uint64_t fde_start_address_; 264*9712c20fSFrederick Mayle }; 265*9712c20fSFrederick Mayle 266*9712c20fSFrederick Mayle } // namespace google_breakpad 267*9712c20fSFrederick Mayle 268*9712c20fSFrederick Mayle #endif // PROCESSOR_CFI_ASSEMBLER_H_ 269