toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc

changeset 0
6474c204b198
     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

mercurial