1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +// Copyright (c) 2010 Google Inc. All Rights Reserved. 1.5 +// 1.6 +// Redistribution and use in source and binary forms, with or without 1.7 +// modification, are permitted provided that the following conditions are 1.8 +// met: 1.9 +// 1.10 +// * Redistributions of source code must retain the above copyright 1.11 +// notice, this list of conditions and the following disclaimer. 1.12 +// * Redistributions in binary form must reproduce the above 1.13 +// copyright notice, this list of conditions and the following disclaimer 1.14 +// in the documentation and/or other materials provided with the 1.15 +// distribution. 1.16 +// * Neither the name of Google Inc. nor the names of its 1.17 +// contributors may be used to endorse or promote products derived from 1.18 +// this software without specific prior written permission. 1.19 +// 1.20 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.21 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.22 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.23 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.24 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.25 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.26 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.27 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.28 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.30 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + 1.32 +#include <assert.h> 1.33 +#include <stdlib.h> 1.34 + 1.35 +#include "common/dwarf/bytereader-inl.h" 1.36 +#include "common/dwarf/bytereader.h" 1.37 + 1.38 +namespace dwarf2reader { 1.39 + 1.40 +ByteReader::ByteReader(enum Endianness endian) 1.41 + :offset_reader_(NULL), address_reader_(NULL), endian_(endian), 1.42 + address_size_(0), offset_size_(0), 1.43 + have_section_base_(), have_text_base_(), have_data_base_(), 1.44 + have_function_base_() { } 1.45 + 1.46 +ByteReader::~ByteReader() { } 1.47 + 1.48 +void ByteReader::SetOffsetSize(uint8 size) { 1.49 + offset_size_ = size; 1.50 + assert(size == 4 || size == 8); 1.51 + if (size == 4) { 1.52 + this->offset_reader_ = &ByteReader::ReadFourBytes; 1.53 + } else { 1.54 + this->offset_reader_ = &ByteReader::ReadEightBytes; 1.55 + } 1.56 +} 1.57 + 1.58 +void ByteReader::SetAddressSize(uint8 size) { 1.59 + address_size_ = size; 1.60 + assert(size == 4 || size == 8); 1.61 + if (size == 4) { 1.62 + this->address_reader_ = &ByteReader::ReadFourBytes; 1.63 + } else { 1.64 + this->address_reader_ = &ByteReader::ReadEightBytes; 1.65 + } 1.66 +} 1.67 + 1.68 +uint64 ByteReader::ReadInitialLength(const char* start, size_t* len) { 1.69 + const uint64 initial_length = ReadFourBytes(start); 1.70 + start += 4; 1.71 + 1.72 + // In DWARF2/3, if the initial length is all 1 bits, then the offset 1.73 + // size is 8 and we need to read the next 8 bytes for the real length. 1.74 + if (initial_length == 0xffffffff) { 1.75 + SetOffsetSize(8); 1.76 + *len = 12; 1.77 + return ReadOffset(start); 1.78 + } else { 1.79 + SetOffsetSize(4); 1.80 + *len = 4; 1.81 + } 1.82 + return initial_length; 1.83 +} 1.84 + 1.85 +bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const { 1.86 + if (encoding == DW_EH_PE_omit) return true; 1.87 + if (encoding == DW_EH_PE_aligned) return true; 1.88 + if ((encoding & 0x7) > DW_EH_PE_udata8) 1.89 + return false; 1.90 + if ((encoding & 0x70) > DW_EH_PE_funcrel) 1.91 + return false; 1.92 + return true; 1.93 +} 1.94 + 1.95 +bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const { 1.96 + switch (encoding & 0x70) { 1.97 + case DW_EH_PE_absptr: return true; 1.98 + case DW_EH_PE_pcrel: return have_section_base_; 1.99 + case DW_EH_PE_textrel: return have_text_base_; 1.100 + case DW_EH_PE_datarel: return have_data_base_; 1.101 + case DW_EH_PE_funcrel: return have_function_base_; 1.102 + default: return false; 1.103 + } 1.104 +} 1.105 + 1.106 +uint64 ByteReader::ReadEncodedPointer(const char *buffer, 1.107 + DwarfPointerEncoding encoding, 1.108 + size_t *len) const { 1.109 + // UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't 1.110 + // see it here. 1.111 + assert(encoding != DW_EH_PE_omit); 1.112 + 1.113 + // The Linux Standards Base 4.0 does not make this clear, but the 1.114 + // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c) 1.115 + // agree that aligned pointers are always absolute, machine-sized, 1.116 + // machine-signed pointers. 1.117 + if (encoding == DW_EH_PE_aligned) { 1.118 + assert(have_section_base_); 1.119 + 1.120 + // We don't need to align BUFFER in *our* address space. Rather, we 1.121 + // need to find the next position in our buffer that would be aligned 1.122 + // when the .eh_frame section the buffer contains is loaded into the 1.123 + // program's memory. So align assuming that buffer_base_ gets loaded at 1.124 + // address section_base_, where section_base_ itself may or may not be 1.125 + // aligned. 1.126 + 1.127 + // First, find the offset to START from the closest prior aligned 1.128 + // address. 1.129 + uint64 skew = section_base_ & (AddressSize() - 1); 1.130 + // Now find the offset from that aligned address to buffer. 1.131 + uint64 offset = skew + (buffer - buffer_base_); 1.132 + // Round up to the next boundary. 1.133 + uint64 aligned = (offset + AddressSize() - 1) & -AddressSize(); 1.134 + // Convert back to a pointer. 1.135 + const char *aligned_buffer = buffer_base_ + (aligned - skew); 1.136 + // Finally, store the length and actually fetch the pointer. 1.137 + *len = aligned_buffer - buffer + AddressSize(); 1.138 + return ReadAddress(aligned_buffer); 1.139 + } 1.140 + 1.141 + // Extract the value first, ignoring whether it's a pointer or an 1.142 + // offset relative to some base. 1.143 + uint64 offset; 1.144 + switch (encoding & 0x0f) { 1.145 + case DW_EH_PE_absptr: 1.146 + // DW_EH_PE_absptr is weird, as it is used as a meaningful value for 1.147 + // both the high and low nybble of encoding bytes. When it appears in 1.148 + // the high nybble, it means that the pointer is absolute, not an 1.149 + // offset from some base address. When it appears in the low nybble, 1.150 + // as here, it means that the pointer is stored as a normal 1.151 + // machine-sized and machine-signed address. A low nybble of 1.152 + // DW_EH_PE_absptr does not imply that the pointer is absolute; it is 1.153 + // correct for us to treat the value as an offset from a base address 1.154 + // if the upper nybble is not DW_EH_PE_absptr. 1.155 + offset = ReadAddress(buffer); 1.156 + *len = AddressSize(); 1.157 + break; 1.158 + 1.159 + case DW_EH_PE_uleb128: 1.160 + offset = ReadUnsignedLEB128(buffer, len); 1.161 + break; 1.162 + 1.163 + case DW_EH_PE_udata2: 1.164 + offset = ReadTwoBytes(buffer); 1.165 + *len = 2; 1.166 + break; 1.167 + 1.168 + case DW_EH_PE_udata4: 1.169 + offset = ReadFourBytes(buffer); 1.170 + *len = 4; 1.171 + break; 1.172 + 1.173 + case DW_EH_PE_udata8: 1.174 + offset = ReadEightBytes(buffer); 1.175 + *len = 8; 1.176 + break; 1.177 + 1.178 + case DW_EH_PE_sleb128: 1.179 + offset = ReadSignedLEB128(buffer, len); 1.180 + break; 1.181 + 1.182 + case DW_EH_PE_sdata2: 1.183 + offset = ReadTwoBytes(buffer); 1.184 + // Sign-extend from 16 bits. 1.185 + offset = (offset ^ 0x8000) - 0x8000; 1.186 + *len = 2; 1.187 + break; 1.188 + 1.189 + case DW_EH_PE_sdata4: 1.190 + offset = ReadFourBytes(buffer); 1.191 + // Sign-extend from 32 bits. 1.192 + offset = (offset ^ 0x80000000ULL) - 0x80000000ULL; 1.193 + *len = 4; 1.194 + break; 1.195 + 1.196 + case DW_EH_PE_sdata8: 1.197 + // No need to sign-extend; this is the full width of our type. 1.198 + offset = ReadEightBytes(buffer); 1.199 + *len = 8; 1.200 + break; 1.201 + 1.202 + default: 1.203 + abort(); 1.204 + } 1.205 + 1.206 + // Find the appropriate base address. 1.207 + uint64 base; 1.208 + switch (encoding & 0x70) { 1.209 + case DW_EH_PE_absptr: 1.210 + base = 0; 1.211 + break; 1.212 + 1.213 + case DW_EH_PE_pcrel: 1.214 + assert(have_section_base_); 1.215 + base = section_base_ + (buffer - buffer_base_); 1.216 + break; 1.217 + 1.218 + case DW_EH_PE_textrel: 1.219 + assert(have_text_base_); 1.220 + base = text_base_; 1.221 + break; 1.222 + 1.223 + case DW_EH_PE_datarel: 1.224 + assert(have_data_base_); 1.225 + base = data_base_; 1.226 + break; 1.227 + 1.228 + case DW_EH_PE_funcrel: 1.229 + assert(have_function_base_); 1.230 + base = function_base_; 1.231 + break; 1.232 + 1.233 + default: 1.234 + abort(); 1.235 + } 1.236 + 1.237 + uint64 pointer = base + offset; 1.238 + 1.239 + // Remove inappropriate upper bits. 1.240 + if (AddressSize() == 4) 1.241 + pointer = pointer & 0xffffffff; 1.242 + else 1.243 + assert(AddressSize() == sizeof(uint64)); 1.244 + 1.245 + return pointer; 1.246 +} 1.247 + 1.248 +} // namespace dwarf2reader