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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00300.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  m :  namespace refinery {
  20    :  
  21  m :  namespace {
  22    :  
  23  m :  bool IsFieldOf(TypePtr type, FieldPtr field) {
  24  m :    DCHECK(type); DCHECK(field);
  25    :  
  26  m :    UserDefinedTypePtr udt;
  27  m :    if (!type->CastTo(&udt))
  28  m :      return false;
  29    :  
  30  m :    for (FieldPtr f : udt->fields()) {
  31  m :      if (*f == *field)
  32  m :        return true;
  33  m :    }
  34    :  
  35  m :    return false;
  36  m :  }
  37    :  
  38  m :  }  // namespace
  39    :  
  40  m :  TypedData::TypedData() : bit_source_(nullptr) {
  41  m :  }
  42    :  
  43  m :  TypedData::TypedData(BitSource* bit_source, TypePtr type, Address addr)
  44  m :      : bit_source_(bit_source),
  45  m :        type_(type),
  46  m :        addr_(addr),
  47  m :        bit_pos_(0),
  48  m :        bit_len_(0) {
  49  m :    DCHECK(bit_source_);
  50  m :    DCHECK(type_);
  51  m :  }
  52    :  
  53  m :  TypedData::TypedData(BitSource* bit_source,
  54  m :                       TypePtr type,
  55  m :                       Address addr,
  56  m :                       uint8_t bit_pos,
  57  m :                       uint8_t bit_len)
  58  m :      : bit_source_(bit_source),
  59  m :        type_(type),
  60  m :        addr_(addr),
  61  m :        bit_pos_(bit_pos),
  62  m :        bit_len_(bit_len) {
  63  m :    DCHECK(bit_source_);
  64  m :    DCHECK(type_);
  65  m :    DCHECK(bit_pos >= 0 && bit_pos < type_->size() * 8);
  66  m :    DCHECK(bit_len >= 0 && bit_len < type_->size() * 8);
  67  m :  }
  68    :  
  69  m :  bool TypedData::IsValid() const {
  70  m :    return bit_source_ != nullptr && type_ != nullptr;
  71  m :  }
  72    :  
  73  m :  bool TypedData::IsPrimitiveType() const {
  74  m :    DCHECK(type_);
  75  m :    switch (type_->kind()) {
  76  m :      case Type::BASIC_TYPE_KIND:
  77  m :      case Type::POINTER_TYPE_KIND:
  78  m :        return true;
  79    :  
  80  m :      default:
  81  m :        return false;
  82  m :    }
  83  m :  }
  84    :  
  85  m :  bool TypedData::IsPointerType() const {
  86  m :    DCHECK(type_);
  87  m :    return type_->kind() == Type::POINTER_TYPE_KIND;
  88  m :  }
  89    :  
  90  m :  bool TypedData::IsArrayType() const {
  91  m :    DCHECK(type_);
  92  m :    return type_->kind() == Type::ARRAY_TYPE_KIND;
  93  m :  }
  94    :  
  95  m :  bool TypedData::IsUserDefinedType() const {
  96  m :    DCHECK(type_);
  97  m :    return type_->kind() == Type::USER_DEFINED_TYPE_KIND;
  98  m :  }
  99    :  
 100  m :  bool TypedData::GetNamedField(const base::StringPiece16& name,
 101  m :                                TypedData* out) const {
 102  m :    DCHECK(out);
 103    :    // TODO(siggi): Does it ever make sense to request a nameless field?
 104  m :    DCHECK(!name.empty());
 105  m :    DCHECK(type_);
 106    :  
 107  m :    UserDefinedTypePtr udt;
 108  m :    if (!type_->CastTo(&udt))
 109  m :      return false;
 110    :  
 111  m :    const UserDefinedType::Fields& fields = udt->fields();
 112  m :    for (size_t i = 0; i < fields.size(); ++i) {
 113  m :      FieldPtr field = fields[i];
 114    :  
 115  m :      MemberFieldPtr member;
 116  m :      if (!field->CastTo(&member))
 117  m :        continue;
 118    :  
 119  m :      if (name == member->name())
 120  m :        return GetField(i, out);
 121  m :    }
 122    :  
 123  m :    return false;
 124  m :  }
 125    :  
 126  m :  bool TypedData::GetField(size_t field_no, TypedData* out) const {
 127  m :    DCHECK(type_);
 128  m :    DCHECK(IsUserDefinedType());
 129  m :    DCHECK(out);
 130    :  
 131  m :    FieldPtr field;
 132  m :    if (!GetField(field_no, &field))
 133  m :      return false;
 134    :  
 135  m :    uint8_t bit_pos = 0U;
 136  m :    uint8_t bit_len = 0U;
 137  m :    MemberFieldPtr member;
 138  m :    if (field->CastTo(&member)) {
 139  m :      bit_pos = static_cast<uint8_t>(member->bit_pos());
 140  m :      bit_len = static_cast<uint8_t>(member->bit_len());
 141  m :    }
 142    :  
 143  m :    *out = TypedData(bit_source_, field->GetType(), addr() + field->offset(),
 144  m :                     bit_pos, bit_len);
 145  m :    return true;
 146  m :  }
 147    :  
 148  m :  bool TypedData::GetField(size_t field_no, FieldPtr* out) const {
 149  m :    DCHECK(type_);
 150  m :    DCHECK(IsUserDefinedType());
 151  m :    DCHECK(out);
 152    :  
 153  m :    UserDefinedTypePtr udt;
 154  m :    if (!type_->CastTo(&udt))
 155  m :      return false;
 156  m :    if (field_no >= udt->fields().size())
 157  m :      return false;
 158    :  
 159  m :    *out = udt->fields()[field_no];
 160  m :    return true;
 161  m :  }
 162    :  
 163  m :  bool TypedData::GetFieldCount(size_t* count) const {
 164  m :    DCHECK(type_);
 165  m :    DCHECK(IsUserDefinedType());
 166    :  
 167  m :    UserDefinedTypePtr udt;
 168  m :    if (!type_->CastTo(&udt))
 169  m :      return false;
 170    :  
 171  m :    *count = udt->fields().size();
 172  m :    return true;
 173  m :  }
 174    :  
 175  m :  bool TypedData::GetSignedValue(int64_t* value) const {
 176  m :    DCHECK(value);
 177  m :    DCHECK(IsPrimitiveType());
 178  m :    DCHECK(bit_source_);
 179    :  
 180  m :    int64_t ret = 0;
 181  m :    switch (type_->size()) {
 182  m :      case sizeof(int8_t): {
 183  m :        int8_t v8 = 0;
 184  m :        if (!GetData(&v8))
 185  m :          return false;
 186    :  
 187  m :        ret = v8;
 188  m :        break;
 189  m :      }
 190    :  
 191  m :      case sizeof(int16_t): {
 192  m :        int16_t v16 = 0;
 193  m :        if (!GetData(&v16))
 194  m :          return false;
 195    :  
 196  m :        ret = v16;
 197  m :        break;
 198  m :      }
 199    :  
 200  m :      case sizeof(int32_t): {
 201  m :        int32_t v32 = 0;
 202  m :        if (!GetData(&v32))
 203  m :          return false;
 204    :  
 205  m :        ret = v32;
 206  m :        break;
 207  m :      }
 208    :  
 209  m :      case sizeof(int64_t): {
 210  m :        int64_t v64 = 0;
 211  m :        if (!GetData(&v64))
 212  m :          return false;
 213    :  
 214  m :        ret = v64;
 215  m :        break;
 216  m :      }
 217    :  
 218  m :      default:
 219    :        // Wonky size - no can do this. Maybe this type is a float or such?
 220  m :        return false;
 221  m :    }
 222    :  
 223    :    // Shift, mask and sign-extend bit fields.
 224  m :    if (bit_len_ != 0) {
 225    :      // Shift the bits into place.
 226  m :      ret >>= bit_pos_;
 227    :  
 228    :      // Mask to the used bits.
 229  m :      const uint64_t mask = (1ll << bit_len_) - 1;
 230  m :      ret &= mask;
 231    :  
 232    :      // Check the sign bit and extend out if set.
 233  m :      if (ret & (mask ^ (mask >> 1)))
 234  m :        ret |= (-1ll & ~mask);
 235  m :    }
 236    :  
 237  m :    *value = ret;
 238  m :    return true;
 239  m :  }
 240    :  
 241  m :  bool TypedData::GetUnsignedValue(uint64_t* value) const {
 242  m :    DCHECK(value);
 243  m :    DCHECK(IsPrimitiveType());
 244  m :    DCHECK(bit_source_);
 245    :  
 246  m :    uint64_t ret = 0;
 247  m :    switch (type_->size()) {
 248  m :      case sizeof(uint8_t): {
 249  m :        uint8_t v8 = 0;
 250  m :        if (!GetData(&v8))
 251  m :          return false;
 252    :  
 253  m :        ret = v8;
 254  m :        break;
 255  m :      }
 256    :  
 257  m :      case sizeof(uint16_t): {
 258  m :        uint16_t v16 = 0;
 259  m :        if (!GetData(&v16))
 260  m :          return false;
 261    :  
 262  m :        ret = v16;
 263  m :        break;
 264  m :      }
 265    :  
 266  m :      case sizeof(uint32_t): {
 267  m :        uint32_t v32 = 0;
 268  m :        if (!GetData(&v32))
 269  m :          return false;
 270    :  
 271  m :        ret = v32;
 272  m :        break;
 273  m :      }
 274    :  
 275  m :      case sizeof(uint64_t): {
 276  m :        uint64_t v64 = 0;
 277  m :        if (!GetData(&v64))
 278  m :          return false;
 279    :  
 280  m :        ret = v64;
 281  m :        break;
 282  m :      }
 283    :  
 284  m :      default:
 285    :        // Wonky size - no can do this. Maybe this type is a float or such?
 286  m :        return false;
 287  m :    }
 288    :  
 289    :    // Shift & mask bit fields.
 290  m :    if (bit_len_ != 0) {
 291    :      // Shift the bits uinto place.
 292  m :      ret >>= bit_pos_;
 293    :  
 294    :      // Mask to the used bits.
 295  m :      const uint64_t mask = (1ull << bit_len_) - 1;
 296  m :      ret &= mask;
 297  m :    }
 298    :  
 299  m :    *value = ret;
 300  m :    return true;
 301  m :  }
 302    :  
 303  m :  bool TypedData::GetPointerValue(Address* value) const {
 304  m :    DCHECK(value);
 305  m :    DCHECK(IsPointerType());
 306  m :    DCHECK_EQ(0, bit_len_);  // Bitfields need not apply for pointer.
 307  m :    DCHECK(bit_source_);
 308    :  
 309  m :    PointerTypePtr ptr_type;
 310  m :    if (!type_->CastTo(&ptr_type))
 311  m :      return false;
 312    :  
 313    :    // Cater for 32- and 64-bit pointers.
 314  m :    if (ptr_type->size() == sizeof(uint32_t)) {
 315    :      // The pointer size is 32 bit.
 316  m :      uint32_t addr_32 = 0;
 317  m :      if (GetData(&addr_32)) {
 318  m :        *value = addr_32;
 319  m :        return true;
 320  m :      }
 321  m :    } else if (ptr_type->size() == sizeof(uint64_t)) {
 322    :      // The pointer size is 64 bit.
 323  m :      if (GetData(value))
 324  m :        return true;
 325  m :    }
 326    :  
 327    :    // The pointer size is strange or we failed on retrieving the value.
 328  m :    return false;
 329  m :  }
 330    :  
 331  m :  bool TypedData::Dereference(TypedData* referenced_data) const {
 332  m :    DCHECK(referenced_data);
 333  m :    DCHECK(IsPointerType());
 334  m :    DCHECK(bit_source_);
 335    :  
 336  m :    PointerTypePtr ptr_type;
 337  m :    if (!type_->CastTo(&ptr_type))
 338  m :      return false;
 339    :  
 340  m :    TypePtr content_type = ptr_type->GetContentType();
 341  m :    if (!content_type)
 342  m :      return false;
 343    :  
 344  m :    Address addr = 0;
 345  m :    if (!GetPointerValue(&addr))
 346  m :      return false;
 347    :  
 348  m :    *referenced_data = TypedData(bit_source_, content_type, addr);
 349    :  
 350  m :    return true;
 351  m :  }
 352    :  
 353  m :  bool TypedData::GetArrayElement(size_t index, TypedData* element_data) const {
 354  m :    DCHECK(element_data);
 355  m :    DCHECK(IsArrayType());
 356  m :    DCHECK(bit_source_);
 357    :  
 358  m :    ArrayTypePtr array_ptr;
 359  m :    if (!type_->CastTo(&array_ptr))
 360  m :      return false;
 361    :  
 362  m :    if (index >= array_ptr->num_elements())
 363  m :      return false;
 364    :  
 365  m :    TypePtr element_type = array_ptr->GetElementType();
 366  m :    if (!element_type)
 367  m :      return false;
 368    :  
 369  m :    *element_data = TypedData(bit_source_, element_type,
 370  m :                              addr() + index * element_type->size());
 371    :  
 372  m :    return true;
 373  m :  }
 374    :  
 375  m :  bool TypedData::OffsetAndCast(ptrdiff_t offs,
 376  m :                                TypePtr new_type,
 377  m :                                TypedData* output) const {
 378  m :    DCHECK(output);
 379  m :    if (!new_type)
 380  m :      return false;
 381  m :    if (!IsValid())
 382  m :      return false;
 383    :  
 384  m :    return OffsetBytesAndCast(offs * type()->size(), new_type, output);
 385  m :  }
 386    :  
 387  m :  bool TypedData::OffsetBytesAndCast(ptrdiff_t offs,
 388  m :                                     TypePtr new_type,
 389  m :                                     TypedData* output) const {
 390  m :    DCHECK(output);
 391  m :    if (!new_type)
 392  m :      return false;
 393  m :    if (!IsValid())
 394  m :      return false;
 395    :  
 396    :    // TODO(siggi): Validate the new range against the bit source with a new
 397    :    //     interface.
 398  m :    *output = TypedData(bit_source(), new_type, addr() + offs);
 399  m :    return true;
 400  m :  }
 401    :  
 402  m :  AddressRange TypedData::GetRange() const {
 403  m :    return AddressRange(addr(), type()->size());
 404  m :  }
 405    :  
 406  m :  bool TypedData::GetDataImpl(void* data, size_t data_size) const {
 407  m :    DCHECK(data);
 408  m :    DCHECK(IsPrimitiveType());
 409  m :    DCHECK(bit_source_);
 410    :  
 411  m :    if (data_size != type_->size())
 412  m :      return false;
 413    :  
 414  m :    return bit_source_->GetAll(GetRange(), data);
 415  m :  }
 416    :  
 417  m :  }  // namespace refinery

Coverage information generated Fri Jul 29 11:00:21 2016.