13e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Copyright (c) 2010, Google Inc. 23e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// All rights reserved. 33e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// 43e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Redistribution and use in source and binary forms, with or without 53e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// modification, are permitted provided that the following conditions are 63e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// met: 73e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// 83e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// * Redistributions of source code must retain the above copyright 93e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// notice, this list of conditions and the following disclaimer. 103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// * Redistributions in binary form must reproduce the above 113e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// copyright notice, this list of conditions and the following disclaimer 123e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// in the documentation and/or other materials provided with the 133e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// distribution. 143e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// * Neither the name of Google Inc. nor the names of its 153e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// contributors may be used to endorse or promote products derived from 163e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// this software without specific prior written permission. 173e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// 183e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 193e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 203e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 213e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 223e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 233e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 243e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 253e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 263e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 273e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 283e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 293e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 303e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> 313e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 323e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// cfi_assembler.cc: Implementation of google_breakpad::CFISection class. 333e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy// See cfi_assembler.h for details. 343e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy#include "common/dwarf/cfi_assembler.h" 363e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 37e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h> 38e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdlib.h> 39e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek 403e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandynamespace google_breakpad { 41a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 42a76aaa1442d765410da36d743ef92748ea1b815ejimblandyusing dwarf2reader::DwarfPointerEncoding; 433e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 446162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comCFISection &CFISection::CIEHeader(uint64_t code_alignment_factor, 453e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy int data_alignment_factor, 463e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy unsigned return_address_register, 476162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint8_t version, 483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy const string &augmentation, 493e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy bool dwarf64) { 503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy assert(!entry_length_); 513e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_ = new PendingLength(); 52a76aaa1442d765410da36d743ef92748ea1b815ejimblandy in_fde_ = false; 533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 543e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy if (dwarf64) { 554f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek D32(kDwarf64InitialLengthMarker); 563e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D64(entry_length_->length); 573e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_->start = Here(); 584f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek D64(eh_frame_ ? kEHFrame64CIEIdentifier : kDwarf64CIEIdentifier); 593e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy } else { 603e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D32(entry_length_->length); 613e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_->start = Here(); 624f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek D32(eh_frame_ ? kEHFrame32CIEIdentifier : kDwarf32CIEIdentifier); 633e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy } 643e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D8(version); 653e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy AppendCString(augmentation); 663e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy ULEB128(code_alignment_factor); 673e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy LEB128(data_alignment_factor); 683e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy if (version == 1) 693e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D8(return_address_register); 703e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy else 713e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy ULEB128(return_address_register); 723e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy return *this; 733e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy} 743e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 753e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyCFISection &CFISection::FDEHeader(Label cie_pointer, 766162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint64_t initial_location, 776162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint64_t address_range, 783e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy bool dwarf64) { 793e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy assert(!entry_length_); 803e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_ = new PendingLength(); 81a76aaa1442d765410da36d743ef92748ea1b815ejimblandy in_fde_ = true; 82a76aaa1442d765410da36d743ef92748ea1b815ejimblandy fde_start_address_ = initial_location; 833e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 843e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy if (dwarf64) { 853e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D32(0xffffffff); 863e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D64(entry_length_->length); 873e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_->start = Here(); 88a76aaa1442d765410da36d743ef92748ea1b815ejimblandy if (eh_frame_) 89a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D64(Here() - cie_pointer); 90a76aaa1442d765410da36d743ef92748ea1b815ejimblandy else 91a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D64(cie_pointer); 923e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy } else { 933e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy D32(entry_length_->length); 943e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_->start = Here(); 95a76aaa1442d765410da36d743ef92748ea1b815ejimblandy if (eh_frame_) 96a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D32(Here() - cie_pointer); 97a76aaa1442d765410da36d743ef92748ea1b815ejimblandy else 98a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D32(cie_pointer); 993e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy } 100a76aaa1442d765410da36d743ef92748ea1b815ejimblandy EncodedPointer(initial_location); 101a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // The FDE length in an .eh_frame section uses the same encoding as the 102a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // initial location, but ignores the base address (selected by the upper 103a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // nybble of the encoding), as it's a length, not an address that can be 104a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // made relative. 105a76aaa1442d765410da36d743ef92748ea1b815ejimblandy EncodedPointer(address_range, 106a76aaa1442d765410da36d743ef92748ea1b815ejimblandy DwarfPointerEncoding(pointer_encoding_ & 0x0f)); 1073e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy return *this; 1083e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy} 1093e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 1103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyCFISection &CFISection::FinishEntry() { 1113e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy assert(entry_length_); 1123e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy Align(address_size_, dwarf2reader::DW_CFA_nop); 1133e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_->length = Here() - entry_length_->start; 1143e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy delete entry_length_; 1153e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy entry_length_ = NULL; 116a76aaa1442d765410da36d743ef92748ea1b815ejimblandy in_fde_ = false; 1173e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy return *this; 1183e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy} 1193e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy 1206162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comCFISection &CFISection::EncodedPointer(uint64_t address, 121a76aaa1442d765410da36d743ef92748ea1b815ejimblandy DwarfPointerEncoding encoding, 122a76aaa1442d765410da36d743ef92748ea1b815ejimblandy const EncodedPointerBases &bases) { 123a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // Omitted data is extremely easy to emit. 124a76aaa1442d765410da36d743ef92748ea1b815ejimblandy if (encoding == dwarf2reader::DW_EH_PE_omit) 125a76aaa1442d765410da36d743ef92748ea1b815ejimblandy return *this; 126a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 127a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // If (encoding & dwarf2reader::DW_EH_PE_indirect) != 0, then we assume 128a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // that ADDRESS is the address at which the pointer is stored --- in 129a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // other words, that bit has no effect on how we write the pointer. 130a76aaa1442d765410da36d743ef92748ea1b815ejimblandy encoding = DwarfPointerEncoding(encoding & ~dwarf2reader::DW_EH_PE_indirect); 131a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 132a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // Find the base address to which this pointer is relative. The upper 133a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // nybble of the encoding specifies this. 1346162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.com uint64_t base; 135a76aaa1442d765410da36d743ef92748ea1b815ejimblandy switch (encoding & 0xf0) { 136a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_absptr: base = 0; break; 137a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_pcrel: base = bases.cfi + Size(); break; 138a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_textrel: base = bases.text; break; 139a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_datarel: base = bases.data; break; 140a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_funcrel: base = fde_start_address_; break; 141a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_aligned: base = 0; break; 142a76aaa1442d765410da36d743ef92748ea1b815ejimblandy default: abort(); 143a76aaa1442d765410da36d743ef92748ea1b815ejimblandy }; 144a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 145a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // Make ADDRESS relative. Yes, this is appropriate even for "absptr" 146a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // values; see gcc/unwind-pe.h. 147a76aaa1442d765410da36d743ef92748ea1b815ejimblandy address -= base; 148a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 149a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // Align the pointer, if required. 150a76aaa1442d765410da36d743ef92748ea1b815ejimblandy if ((encoding & 0xf0) == dwarf2reader::DW_EH_PE_aligned) 151a76aaa1442d765410da36d743ef92748ea1b815ejimblandy Align(AddressSize()); 152a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 153a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // Append ADDRESS to this section in the appropriate form. For the 154a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // fixed-width forms, we don't need to differentiate between signed and 155a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // unsigned encodings, because ADDRESS has already been extended to 64 156a76aaa1442d765410da36d743ef92748ea1b815ejimblandy // bits before it was passed to us. 157a76aaa1442d765410da36d743ef92748ea1b815ejimblandy switch (encoding & 0x0f) { 158a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_absptr: 159a76aaa1442d765410da36d743ef92748ea1b815ejimblandy Address(address); 160a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 161a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 162a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_uleb128: 163a76aaa1442d765410da36d743ef92748ea1b815ejimblandy ULEB128(address); 164a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 165a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 166a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_sleb128: 167a76aaa1442d765410da36d743ef92748ea1b815ejimblandy LEB128(address); 168a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 169a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 170a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_udata2: 171a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_sdata2: 172a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D16(address); 173a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 174a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 175a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_udata4: 176a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_sdata4: 177a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D32(address); 178a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 179a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 180a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_udata8: 181a76aaa1442d765410da36d743ef92748ea1b815ejimblandy case dwarf2reader::DW_EH_PE_sdata8: 182a76aaa1442d765410da36d743ef92748ea1b815ejimblandy D64(address); 183a76aaa1442d765410da36d743ef92748ea1b815ejimblandy break; 184a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 185a76aaa1442d765410da36d743ef92748ea1b815ejimblandy default: 186a76aaa1442d765410da36d743ef92748ea1b815ejimblandy abort(); 187a76aaa1442d765410da36d743ef92748ea1b815ejimblandy } 188a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 189a76aaa1442d765410da36d743ef92748ea1b815ejimblandy return *this; 1903e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy}; 191a76aaa1442d765410da36d743ef92748ea1b815ejimblandy 1926162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint32_t CFISection::kDwarf64InitialLengthMarker; 1936162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint32_t CFISection::kDwarf32CIEIdentifier; 1946162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint64_t CFISection::kDwarf64CIEIdentifier; 1956162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint32_t CFISection::kEHFrame32CIEIdentifier; 1966162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comconst uint64_t CFISection::kEHFrame64CIEIdentifier; 1974f456b8c0d094d84b83d4c8eedff7937121e9de1ted.mielczarek 198a76aaa1442d765410da36d743ef92748ea1b815ejimblandy} // namespace google_breakpad 199