Coverage for /Syzygy/refinery/types/typed_data.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
78.4%1672130.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  #include "syzygy/refinery/types/typed_data.h"
  15    :  
  16    :  #include "base/logging.h"
  17    :  #include "syzygy/refinery/types/type_repository.h"
  18    :  
  19    :  namespace refinery {
  20    :  
  21    :  namespace {
  22    :  
  23  E :  bool IsFieldOf(TypePtr type, const UserDefinedType::Field& field) {
  24  E :    UserDefinedTypePtr udt;
  25  E :    if (!type->CastTo(&udt))
  26  i :      return false;
  27    :  
  28  E :    for (auto f : udt->fields()) {
  29  E :      if (f == field)
  30  E :        return true;
  31  E :    }
  32    :  
  33  i :    return false;
  34  E :  }
  35    :  
  36    :  }  // namespace
  37    :  
  38  E :  TypedData::TypedData() : bit_source_(nullptr) {
  39  E :  }
  40    :  
  41    :  TypedData::TypedData(BitSource* bit_source, TypePtr type, Address addr)
  42    :      : bit_source_(bit_source),
  43    :        type_(type),
  44    :        addr_(addr),
  45    :        bit_pos_(0),
  46  E :        bit_len_(0) {
  47  E :    DCHECK(bit_source_);
  48  E :    DCHECK(type_);
  49  E :  }
  50    :  
  51    :  TypedData::TypedData(BitSource* bit_source,
  52    :                       TypePtr type,
  53    :                       Address addr,
  54    :                       size_t bit_pos,
  55    :                       size_t bit_len)
  56    :      : bit_source_(bit_source),
  57    :        type_(type),
  58    :        addr_(addr),
  59    :        bit_pos_(bit_pos),
  60  E :        bit_len_(bit_len) {
  61  E :    DCHECK(bit_source_);
  62  E :    DCHECK(type_);
  63  E :    DCHECK(bit_pos >= 0 && bit_pos < type_->size() * 8);
  64  E :    DCHECK(bit_len >= 0 && bit_len < type_->size() * 8);
  65  E :  }
  66    :  
  67  E :  bool TypedData::IsValid() const {
  68  E :    return bit_source_ != nullptr && type_ != nullptr;
  69  E :  }
  70    :  
  71  E :  bool TypedData::IsPrimitiveType() const {
  72  E :    DCHECK(type_);
  73  E :    switch (type_->kind()) {
  74    :      case Type::BASIC_TYPE_KIND:
  75    :      case Type::POINTER_TYPE_KIND:
  76  E :        return true;
  77    :  
  78    :      default:
  79  E :        return false;
  80    :    }
  81  E :  }
  82    :  
  83  E :  bool TypedData::IsPointerType() const {
  84  E :    DCHECK(type_);
  85  E :    return type_->kind() == Type::POINTER_TYPE_KIND;
  86  E :  }
  87    :  
  88  E :  bool TypedData::IsArrayType() const {
  89  E :    DCHECK(type_);
  90  E :    return type_->kind() == Type::ARRAY_TYPE_KIND;
  91  E :  }
  92    :  
  93    :  bool TypedData::GetNamedField(const base::StringPiece16& name,
  94  E :                                TypedData* out) const {
  95  E :    DCHECK(out);
  96    :    // TODO(siggi): Does it ever make sense to request a nameless field?
  97  E :    DCHECK(!name.empty());
  98  E :    DCHECK(type_);
  99    :  
 100  E :    UserDefinedTypePtr udt;
 101  E :    if (!type_->CastTo(&udt))
 102  i :      return false;
 103    :  
 104  E :    for (size_t i = 0; i < udt->fields().size(); ++i) {
 105  E :      const UserDefinedType::Field& field = udt->fields()[i];
 106  E :      if (name == field.name()) {
 107  E :        TypePtr field_type = udt->GetFieldType(i);
 108  E :        DCHECK(field_type);
 109    :        *out = TypedData(bit_source_, field_type, addr() + field.offset(),
 110  E :                         field.bit_pos(), field.bit_len());
 111  E :        return true;
 112    :      }
 113  E :    }
 114    :  
 115  i :    return false;
 116  E :  }
 117    :  
 118    :  bool TypedData::GetField(const UserDefinedType::Field& field,
 119  E :                           TypedData* out) const {
 120  E :    DCHECK(out);
 121  E :    DCHECK(type_);
 122  E :    DCHECK(!IsPrimitiveType());
 123  E :    DCHECK(IsFieldOf(type_, field));
 124    :  
 125  E :    TypePtr field_type = type_->repository()->GetType(field.type_id());
 126  E :    *out = TypedData(bit_source_, field_type, addr() + field.offset());
 127  E :    return true;
 128  E :  }
 129    :  
 130  E :  bool TypedData::GetSignedValue(int64_t* value) const {
 131  E :    DCHECK(value);
 132  E :    DCHECK(IsPrimitiveType());
 133  E :    DCHECK(bit_source_);
 134    :  
 135  E :    int64 ret = 0;
 136  E :    switch (type_->size()) {
 137    :      case sizeof(int8_t): {
 138  i :        int8_t v8 = 0;
 139  i :        if (!GetData(&v8))
 140  i :          return false;
 141    :  
 142  i :        ret = v8;
 143  i :        break;
 144    :      }
 145    :  
 146    :      case sizeof(int16_t): {
 147  i :        int16_t v16 = 0;
 148  i :        if (!GetData(&v16))
 149  i :          return false;
 150    :  
 151  i :        ret = v16;
 152  i :        break;
 153    :      }
 154    :  
 155    :      case sizeof(int32_t): {
 156  E :        int32_t v32 = 0;
 157  E :        if (!GetData(&v32))
 158  i :          return false;
 159    :  
 160  E :        ret = v32;
 161  E :        break;
 162    :      }
 163    :  
 164    :      case sizeof(int64_t): {
 165  i :        int64_t v64 = 0;
 166  i :        if (!GetData(&v64))
 167  i :          return false;
 168    :  
 169  i :        ret = v64;
 170  i :        break;
 171    :      }
 172    :  
 173    :      default:
 174    :        // Wonky size - no can do this. Maybe this type is a float or such?
 175  i :        return false;
 176    :    }
 177    :  
 178    :    // Shift, mask and sign-extend bit fields.
 179  E :    if (bit_len_ != 0) {
 180    :      // Shift the bits into place.
 181  E :      ret >>= bit_pos_;
 182    :  
 183    :      // Mask to the used bits.
 184  E :      const uint64_t mask = (1ll << bit_len_) - 1;
 185  E :      ret &= mask;
 186    :  
 187    :      // Check the sign bit and extend out if set.
 188  E :      if (ret & (mask ^ (mask >> 1)))
 189  E :        ret |= (-1ll & ~mask);
 190    :    }
 191    :  
 192  E :    *value = ret;
 193  E :    return true;
 194  E :  }
 195    :  
 196  E :  bool TypedData::GetUnsignedValue(uint64_t* value) const {
 197  E :    DCHECK(value);
 198  E :    DCHECK(IsPrimitiveType());
 199  E :    DCHECK(bit_source_);
 200    :  
 201  E :    uint64 ret = 0;
 202  E :    switch (type_->size()) {
 203    :      case sizeof(uint8_t): {
 204  E :        uint8_t v8 = 0;
 205  E :        if (!GetData(&v8))
 206  i :          return false;
 207    :  
 208  E :        ret = v8;
 209  E :        break;
 210    :      }
 211    :  
 212    :      case sizeof(uint16_t): {
 213  i :        uint16_t v16 = 0;
 214  i :        if (!GetData(&v16))
 215  i :          return false;
 216    :  
 217  i :        ret = v16;
 218  i :        break;
 219    :      }
 220    :  
 221    :      case sizeof(uint32_t): {
 222  E :        uint32_t v32 = 0;
 223  E :        if (!GetData(&v32))
 224  E :          return false;
 225    :  
 226  E :        ret = v32;
 227  E :        break;
 228    :      }
 229    :  
 230    :      case sizeof(uint64_t): {
 231  i :        uint64_t v64 = 0;
 232  i :        if (!GetData(&v64))
 233  i :          return false;
 234    :  
 235  i :        ret = v64;
 236  i :        break;
 237    :      }
 238    :  
 239    :      default:
 240    :        // Wonky size - no can do this. Maybe this type is a float or such?
 241  i :        return false;
 242    :    }
 243    :  
 244    :    // Shift & mask bit fields.
 245  E :    if (bit_len_ != 0) {
 246    :      // Shift the bits uinto place.
 247  E :      ret >>= bit_pos_;
 248    :  
 249    :      // Mask to the used bits.
 250  E :      const uint64_t mask = (1ull << bit_len_) - 1;
 251  E :      ret &= mask;
 252    :    }
 253    :  
 254  E :    *value = ret;
 255  E :    return true;
 256  E :  }
 257    :  
 258  E :  bool TypedData::GetPointerValue(Address* value) const {
 259  E :    DCHECK(value);
 260  E :    DCHECK(IsPointerType());
 261  E :    DCHECK_EQ(0, bit_len_);  // Bitfields need not apply for pointer.
 262  E :    DCHECK(bit_source_);
 263    :  
 264  E :    PointerTypePtr ptr_type;
 265  E :    if (!type_->CastTo(&ptr_type))
 266  i :      return false;
 267    :  
 268    :    // Cater for 32- and 64-bit pointers.
 269  E :    if (ptr_type->size() == sizeof(uint32_t)) {
 270    :      // The pointer size is 32 bit.
 271  E :      uint32_t addr_32 = 0;
 272  E :      if (GetData(&addr_32)) {
 273  E :        *value = addr_32;
 274  E :        return true;
 275  E :      }
 276  i :    } else if (ptr_type->size() == sizeof(uint64_t)) {
 277    :      // The pointer size is 64 bit.
 278  i :      if (GetData(value))
 279  i :        return true;
 280    :    }
 281    :  
 282    :    // The pointer size is strange or we failed on retrieving the value.
 283  E :    return false;
 284  E :  }
 285    :  
 286  E :  bool TypedData::Dereference(TypedData* referenced_data) const {
 287  E :    DCHECK(referenced_data);
 288  E :    DCHECK(IsPointerType());
 289  E :    DCHECK(bit_source_);
 290    :  
 291  E :    PointerTypePtr ptr_type;
 292  E :    if (!type_->CastTo(&ptr_type))
 293  i :      return false;
 294    :  
 295  E :    TypePtr content_type = ptr_type->GetContentType();
 296  E :    if (!content_type)
 297  i :      return false;
 298    :  
 299  E :    Address addr = 0;
 300  E :    if (!GetPointerValue(&addr))
 301  E :      return false;
 302    :  
 303  E :    *referenced_data = TypedData(bit_source_, content_type, addr);
 304    :  
 305  E :    return true;
 306  E :  }
 307    :  
 308  E :  bool TypedData::GetArrayElement(size_t index, TypedData* element_data) const {
 309  E :    DCHECK(element_data);
 310  E :    DCHECK(IsArrayType());
 311  E :    DCHECK(bit_source_);
 312    :  
 313  E :    ArrayTypePtr array_ptr;
 314  E :    if (!type_->CastTo(&array_ptr))
 315  i :      return false;
 316    :  
 317  E :    if (index >= array_ptr->num_elements())
 318  E :      return false;
 319    :  
 320  E :    TypePtr element_type = array_ptr->GetElementType();
 321  E :    if (!element_type)
 322  i :      return false;
 323    :  
 324    :    *element_data = TypedData(bit_source_, element_type,
 325  E :                              addr() + index * element_type->size());
 326    :  
 327  E :    return true;
 328  E :  }
 329    :  
 330    :  bool TypedData::OffsetAndCast(ptrdiff_t offs,
 331    :                                TypePtr new_type,
 332  E :                                TypedData* output) const {
 333  E :    DCHECK(output);
 334  E :    if (!new_type)
 335  i :      return false;
 336  E :    if (!IsValid())
 337  i :      return false;
 338    :  
 339  E :    return OffsetBytesAndCast(offs * type()->size(), new_type, output);
 340  E :  }
 341    :  
 342    :  bool TypedData::OffsetBytesAndCast(ptrdiff_t offs,
 343    :                                     TypePtr new_type,
 344  E :                                     TypedData* output) const {
 345  E :    DCHECK(output);
 346  E :    if (!new_type)
 347  i :      return false;
 348  E :    if (!IsValid())
 349  i :      return false;
 350    :  
 351    :    // TODO(siggi): Validate the new range against the bit source with a new
 352    :    //     interface.
 353  E :    *output = TypedData(bit_source(), new_type, addr() + offs);
 354  E :    return true;
 355  E :  }
 356    :  
 357  E :  AddressRange TypedData::GetRange() const {
 358  E :    return AddressRange(addr(), type()->size());
 359  E :  }
 360    :  
 361  E :  bool TypedData::GetDataImpl(void* data, size_t data_size) const {
 362  E :    DCHECK(data);
 363  E :    DCHECK(IsPrimitiveType());
 364  E :    DCHECK(bit_source_);
 365    :  
 366  E :    if (data_size != type_->size())
 367  i :      return false;
 368    :  
 369  E :    return bit_source_->GetAll(GetRange(), data);
 370  E :  }
 371    :  
 372    :  }  // namespace refinery

Coverage information generated Thu Jan 14 17:40:38 2016.