13e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// -*- mode: C++ -*-
23e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
33e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Copyright (c) 2010, Google Inc.
43e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// All rights reserved.
53e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//
63e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Redistribution and use in source and binary forms, with or without
73e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// modification, are permitted provided that the following conditions are
83e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// met:
93e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//
103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//     * Redistributions of source code must retain the above copyright
113e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// notice, this list of conditions and the following disclaimer.
123e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//     * Redistributions in binary form must reproduce the above
133e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// copyright notice, this list of conditions and the following disclaimer
143e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// in the documentation and/or other materials provided with the
153e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// distribution.
163e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//     * Neither the name of Google Inc. nor the names of its
173e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// contributors may be used to endorse or promote products derived from
183e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// this software without specific prior written permission.
193e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy//
203e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
213e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
233e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
243e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
253e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
263e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
273e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
283e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
293e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
303e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
313e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
323e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
333e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
344f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek// cfi_assembler.h: Define CFISection, a class for creating properly
353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// (and improperly) formatted DWARF CFI data for unit tests.
363e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
373e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#ifndef PROCESSOR_CFI_ASSEMBLER_H_
383e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#define PROCESSOR_CFI_ASSEMBLER_H_
393e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
403e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#include <string>
413e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
42a76aaa1442d765410da36d743ef92748ea1b815ejimblandy#include "common/dwarf/dwarf2enums.h"
43865df5af57922a4dc1e2a24e3f5c371d84f0f574jimblandy#include "common/test_assembler.h"
444e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h"
453e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#include "google_breakpad/common/breakpad_types.h"
463e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
473e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandynamespace google_breakpad {
483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
49a76aaa1442d765410da36d743ef92748ea1b815ejimblandyusing dwarf2reader::DwarfPointerEncoding;
5035c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing google_breakpad::test_assembler::Endianness;
5135c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing google_breakpad::test_assembler::Label;
5235c41e00ee2cf9280fe0122c75877ba70b41bb46ted.mielczarekusing google_breakpad::test_assembler::Section;
533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
543e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyclass CFISection: public Section {
553e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy public:
56a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
57a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // CFI augmentation strings beginning with 'z', defined by the
58a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Linux/IA-64 C++ ABI, can specify interesting encodings for
59a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // addresses appearing in FDE headers and call frame instructions (and
60a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // for additional fields whose presence the augmentation string
61a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // specifies). In particular, pointers can be specified to be relative
62a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // to various base address: the start of the .text section, the
63a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // location holding the address itself, and so on. These allow the
64a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // frame data to be position-independent even when they live in
65a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // write-protected pages. These variants are specified at the
66a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // following two URLs:
67a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  //
68a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
69a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
70a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  //
71a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // CFISection leaves the production of well-formed 'z'-augmented CIEs and
72a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // FDEs to the user, but does provide EncodedPointer, to emit
73a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // properly-encoded addresses for a given pointer encoding.
74a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // EncodedPointer uses an instance of this structure to find the base
75a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // addresses it should use; you can establish a default for all encoded
76a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // pointers appended to this section with SetEncodedPointerBases.
77a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  struct EncodedPointerBases {
78a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    EncodedPointerBases() : cfi(), text(), data() { }
79a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
80a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // The starting address of this CFI section in memory, for
81a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // DW_EH_PE_pcrel. DW_EH_PE_pcrel pointers may only be used in data
82a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // that has is loaded into the program's address space.
836162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t cfi;
84a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
85a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // The starting address of this file's .text section, for DW_EH_PE_textrel.
866162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t text;
87a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
88a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // The starting address of this file's .got or .eh_frame_hdr section,
89a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    // for DW_EH_PE_datarel.
906162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com    uint64_t data;
91a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  };
92a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
933e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Create a CFISection whose endianness is ENDIANNESS, and where
94a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // machine addresses are ADDRESS_SIZE bytes long. If EH_FRAME is
95a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // true, use the .eh_frame format, as described by the Linux
96a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Standards Base Core Specification, instead of the DWARF CFI
97a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // format.
98a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  CFISection(Endianness endianness, size_t address_size,
99a76aaa1442d765410da36d743ef92748ea1b815ejimblandy             bool eh_frame = false)
100a76aaa1442d765410da36d743ef92748ea1b815ejimblandy      : Section(endianness), address_size_(address_size), eh_frame_(eh_frame),
101a76aaa1442d765410da36d743ef92748ea1b815ejimblandy        pointer_encoding_(dwarf2reader::DW_EH_PE_absptr),
102a76aaa1442d765410da36d743ef92748ea1b815ejimblandy        encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) {
1033e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    // The 'start', 'Here', and 'Mark' members of a CFISection all refer
1043e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    // to section offsets.
1053e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    start() = 0;
1063e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  }
1073e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
1083e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Return this CFISection's address size.
1093e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  size_t AddressSize() const { return address_size_; }
1103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
111a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Return true if this CFISection uses the .eh_frame format, or
112a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // false if it contains ordinary DWARF CFI data.
113a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  bool ContainsEHFrame() const { return eh_frame_; }
114a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
115a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Use ENCODING for pointers in calls to FDEHeader and EncodedPointer.
116a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  void SetPointerEncoding(DwarfPointerEncoding encoding) {
117a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    pointer_encoding_ = encoding;
118a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
119a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
120a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Use the addresses in BASES as the base addresses for encoded
121a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // pointers in subsequent calls to FDEHeader or EncodedPointer.
122a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // This function makes a copy of BASES.
123a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  void SetEncodedPointerBases(const EncodedPointerBases &bases) {
124a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    encoded_pointer_bases_ = bases;
125a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
126a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
1273e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Append a Common Information Entry header to this section with the
1283e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // given values. If dwarf64 is true, use the 64-bit DWARF initial
1293e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // length format for the CIE's initial length. Return a reference to
1303e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // this section. You should call FinishEntry after writing the last
1313e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // instruction for the CIE.
1323e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  //
1333e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Before calling this function, you will typically want to use Mark
1343e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // or Here to make a label to pass to FDEHeader that refers to this
1353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // CIE's position in the section.
1366162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &CIEHeader(uint64_t code_alignment_factor,
1373e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy                        int data_alignment_factor,
1383e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy                        unsigned return_address_register,
1396162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                        uint8_t version = 3,
1403e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy                        const string &augmentation = "",
1413e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy                        bool dwarf64 = false);
1423e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
1433e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Append a Frame Description Entry header to this section with the
1443e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // given values. If dwarf64 is true, use the 64-bit DWARF initial
1453e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // length format for the CIE's initial length. Return a reference to
1463e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // this section. You should call FinishEntry after writing the last
1473e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // instruction for the CIE.
1483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  //
1493e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // This function doesn't support entries that are longer than
1503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // 0xffffff00 bytes. (The "initial length" is always a 32-bit
1513e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // value.) Nor does it support .debug_frame sections longer than
1523e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // 0xffffff00 bytes.
1533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &FDEHeader(Label cie_pointer,
1546162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                        uint64_t initial_location,
1556162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com                        uint64_t address_range,
1563e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy                        bool dwarf64 = false);
1573e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
1583e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Note the current position as the end of the last CIE or FDE we
1593e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // started, after padding with DW_CFA_nops for alignment. This
1603e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // defines the label representing the entry's length, cited in the
1613e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // entry's header. Return a reference to this section.
1623e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &FinishEntry();
1633e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
1643e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Append the contents of BLOCK as a DW_FORM_block value: an
1653e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // unsigned LEB128 length, followed by that many bytes of data.
1663e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &Block(const string &block) {
1673e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    ULEB128(block.size());
1683e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    Append(block);
1693e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    return *this;
1703e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  }
1713e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
172a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Append ADDRESS to this section, in the appropriate size and
173a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // endianness. Return a reference to this section.
1746162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &Address(uint64_t address) {
175a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    Section::Append(endianness(), address_size_, address);
176a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    return *this;
177a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
178a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  CFISection &Address(Label address) {
179a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    Section::Append(endianness(), address_size_, address);
180a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    return *this;
181a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
182a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
183a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Append ADDRESS to this section, using ENCODING and BASES. ENCODING
184a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // defaults to this section's default encoding, established by
185a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // SetPointerEncoding. BASES defaults to this section's bases, set by
186a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // SetEncodedPointerBases. If the DW_EH_PE_indirect bit is set in the
187a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // encoding, assume that ADDRESS is where the true address is stored.
188a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // Return a reference to this section.
189a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  //
190a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // (C++ doesn't let me use default arguments here, because I want to
191a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // refer to members of *this in the default argument expression.)
1926162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &EncodedPointer(uint64_t address) {
193a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    return EncodedPointer(address, pointer_encoding_, encoded_pointer_bases_);
194a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
1956162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) {
196a76aaa1442d765410da36d743ef92748ea1b815ejimblandy    return EncodedPointer(address, encoding, encoded_pointer_bases_);
197a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  }
1986162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding,
199a76aaa1442d765410da36d743ef92748ea1b815ejimblandy                             const EncodedPointerBases &bases);
200a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
2013e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Restate some member functions, to keep chaining working nicely.
2023e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &Mark(Label *label)   { Section::Mark(label); return *this; }
2036162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &D8(uint8_t v)       { Section::D8(v);       return *this; }
2046162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &D16(uint16_t v)     { Section::D16(v);      return *this; }
2053e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &D16(Label v)         { Section::D16(v);      return *this; }
2066162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &D32(uint32_t v)     { Section::D32(v);      return *this; }
2073e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &D32(const Label &v)  { Section::D32(v);      return *this; }
2086162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &D64(uint64_t v)     { Section::D64(v);      return *this; }
2093e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &D64(const Label &v)  { Section::D64(v);      return *this; }
2103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  CFISection &LEB128(long long v)  { Section::LEB128(v);   return *this; }
2116162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  CFISection &ULEB128(uint64_t v) { Section::ULEB128(v);  return *this; }
2123e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
2133e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy private:
2143e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // A length value that we've appended to the section, but is not yet
2153e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // known. LENGTH is the appended value; START is a label referring
2163e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // to the start of the data whose length was cited.
2173e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  struct PendingLength {
2183e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    Label length;
2193e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    Label start;
2203e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  };
2213e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
2224f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek  // Constants used in CFI/.eh_frame data:
2234f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek
2244f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek  // If the first four bytes of an "initial length" are this constant, then
2254f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek  // the data uses the 64-bit DWARF format, and the length itself is the
2264f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek  // subsequent eight bytes.
2276162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  static const uint32_t kDwarf64InitialLengthMarker = 0xffffffffU;
2284f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek
2294f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek  // The CIE identifier for 32- and 64-bit DWARF CFI and .eh_frame data.
2306162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  static const uint32_t kDwarf32CIEIdentifier = ~(uint32_t)0;
2316162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  static const uint64_t kDwarf64CIEIdentifier = ~(uint64_t)0;
2326162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  static const uint32_t kEHFrame32CIEIdentifier = 0;
2336162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  static const uint64_t kEHFrame64CIEIdentifier = 0;
2344f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek
2353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // The size of a machine address for the data in this section.
2363e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  size_t address_size_;
2373e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
238a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // If true, we are generating a Linux .eh_frame section, instead of
239a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // a standard DWARF .debug_frame section.
240a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  bool eh_frame_;
241a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
242a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // The encoding to use for FDE pointers.
243a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  DwarfPointerEncoding pointer_encoding_;
244a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
245a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // The base addresses to use when emitting encoded pointers.
246a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  EncodedPointerBases encoded_pointer_bases_;
247a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
2483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // The length value for the current entry.
2493e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  //
2503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Oddly, this must be dynamically allocated. Labels never get new
2513e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // values; they only acquire constraints on the value they already
2523e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // have, or assert if you assign them something incompatible. So
2533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // each header needs truly fresh Label objects to cite in their
2543e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // headers and track their positions. The alternative is explicit
2553e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // destructor invocation and a placement new. Ick.
2563e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  PendingLength *entry_length_;
257a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
258a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // True if we are currently emitting an FDE --- that is, we have
259a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // called FDEHeader but have not yet called FinishEntry.
260a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  bool in_fde_;
261a76aaa1442d765410da36d743ef92748ea1b815ejimblandy
262a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // If in_fde_ is true, this is its starting address. We use this for
263a76aaa1442d765410da36d743ef92748ea1b815ejimblandy  // emitting DW_EH_PE_funcrel pointers.
2646162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com  uint64_t fde_start_address_;
2653e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy};
2663e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
2673e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy}  // namespace google_breakpad
2683e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
2693e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#endif  // PROCESSOR_CFI_ASSEMBLER_H_
270