Coverage for /Syzygy/core/address.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%79790.C++source

Line-by-line coverage:

   1    :  // Copyright 2011 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    :  
  15    :  #ifndef SYZYGY_CORE_ADDRESS_H_
  16    :  #define SYZYGY_CORE_ADDRESS_H_
  17    :  
  18    :  #include <iosfwd>
  19    :  #include "base/basictypes.h"
  20    :  #include "base/logging.h"
  21    :  #include "syzygy/common/align.h"
  22    :  #include "syzygy/core/serialization.h"
  23    :  
  24    :  namespace core {
  25    :  
  26    :  enum AddressType : uint8_t {
  27    :    kRelativeAddressType,
  28    :    kAbsoluteAddressType,
  29    :    kFileOffsetAddressType,
  30    :  };
  31    :  
  32    :  namespace detail {
  33    :  
  34    :  // This class implements an address in a PE image file.
  35    :  // Addresses are of three varieties:
  36    :  // - Relative addresses are relative to the base of the image, and thus do not
  37    :  //   change when the image is relocated. Bulk of the addresses in the PE image
  38    :  //   format itself are of this variety, and that's where relative addresses
  39    :  //   crop up most frequently.
  40    :  // - Absolute addresses are as the name indicates absolute, and those change
  41    :  //   when an image is relocated. Absolute addresses mostly occur in initialized
  42    :  //   data, and for each absolute datum in an image file, there will be a
  43    :  //   relocation entry calling out its location in the image.
  44    :  // - File offset addresses occur only in the debug data directory that I'm
  45    :  //   aware of, where the debug data is referred to both by a relative address
  46    :  //   and (presumably for convenience) by a file offset address.
  47    :  // This class is a lightweight wrapper for an integer, which can be freely
  48    :  // copied. The different address types are deliberately assignment
  49    :  // incompatible, which helps to avoid confusion when handling different
  50    :  // types of addresses in implementation.
  51    :  template <AddressType kType>
  52    :  class AddressImpl {
  53    :   public:
  54    :    static const AddressImpl kInvalidAddress;
  55    :  
  56  E :    AddressImpl() : value_(0) {}
  57  E :    explicit AddressImpl(uint32_t value) : value_(value) {}
  58  E :    AddressImpl(const AddressImpl<kType>& other)  // NOLINT
  59    :        : value_(other.value_) {}
  60    :  
  61  E :    AddressImpl<kType>& operator=(const AddressImpl<kType>& other) {
  62  E :      value_ = other.value_;
  63  E :      return *this;
  64  E :    }
  65    :  
  66    :    // Comparison operators to other concrete addresses.
  67  E :    bool operator<(const AddressImpl<kType>& other) const {
  68  E :      return value_ < other.value_;
  69  E :    }
  70  E :    bool operator<=(const AddressImpl<kType>& other) const {
  71  E :      return value_ <= other.value_;
  72  E :    }
  73  E :    bool operator>(const AddressImpl<kType>& other) const {
  74  E :      return value_ > other.value_;
  75  E :    }
  76  E :    bool operator>=(const AddressImpl<kType>& other) const {
  77  E :      return value_ >= other.value_;
  78  E :    }
  79  E :    bool operator==(const AddressImpl<kType>& other) const {
  80  E :      return value_ == other.value_;
  81  E :    }
  82  E :    bool operator!=(const AddressImpl<kType>& other) const {
  83  E :      return value_ != other.value_;
  84  E :    }
  85    :  
  86    :    // Arithmetic operators.
  87  E :    void operator+=(int32_t offset) { value_ += offset; }
  88  E :    void operator-=(int32_t offset) { value_ -= offset; }
  89  E :    AddressImpl<kType> operator+(size_t offset) const {
  90  E :      return AddressImpl<kType>(value_ + offset);
  91  E :    }
  92  E :    AddressImpl<kType> operator-(size_t offset) const {
  93  E :      return AddressImpl<kType>(value_ - offset);
  94  E :    }
  95  E :    int32_t operator-(const AddressImpl<kType>& other) const {
  96  E :      return value_ - other.value_;
  97  E :    }
  98    :  
  99    :    // Accessors and mutators.
 100  E :    static AddressType type() { return kType; }
 101  E :    uint32_t value() const { return value_; }
 102  E :    void set_value(uint32_t value) { value_ = value; }
 103    :  
 104    :    // @param alignment the alignment to be provided.
 105    :    // @returns an address that has been increased minimally to have the requested
 106    :    //     @p alignment.
 107  E :    AddressImpl<kType> AlignUp(size_t alignment) const {
 108  E :      return AddressImpl<kType>(common::AlignUp(value_, alignment));
 109  E :    }
 110    :  
 111    :    // Determines if this address has the provided @p alignment.
 112    :    // @param alignment the alignment to be tested against.
 113    :    // @returns true if the address is aligned to @p alignment, false otherwise.
 114  E :    bool IsAligned(size_t alignment) const {
 115  E :      return common::IsAligned(value_, alignment);
 116  E :    }
 117    :  
 118    :    // Determines the address alignment. If the value of the address is 0 then we
 119    :    // return the maximum alignment for a 32-bit address (0x80000000).
 120    :    // @returns the alignment of the address.
 121  E :    uint32_t GetAlignment() const { return common::GetAlignment(value_); }
 122    :  
 123    :    // For serialization.
 124  E :    bool Save(OutArchive *out_archive) const {
 125  E :      return out_archive->Save(value_);
 126  E :    }
 127  E :    bool Load(InArchive *in_archive) {
 128  E :      return in_archive->Load(&value_);
 129  E :    }
 130    :  
 131    :    friend std::ostream& operator<<(std::ostream& str,
 132    :                                    const AddressImpl<kType>& addr);
 133    :  
 134    :   private:
 135    :    uint32_t value_;
 136    :  };
 137    :  
 138    :  }  // namespace detail
 139    :  
 140    :  // These types represent the different addressing formats used in PE images.
 141    :  
 142    :  // A virtual address relative to the image base, often termed RVA in
 143    :  // documentation and in data structure comments.
 144    :  using RelativeAddress = detail::AddressImpl<kRelativeAddressType>;
 145    :  // An absolute address.
 146    :  using AbsoluteAddress = detail::AddressImpl<kAbsoluteAddressType>;
 147    :  // A file offset within an image file.
 148    :  using FileOffsetAddress = detail::AddressImpl<kFileOffsetAddressType>;
 149    :  
 150    :  // An address variant that can house any of the concrete address types.
 151    :  class AddressVariant {
 152    :   public:
 153  E :    AddressVariant() : type_(kRelativeAddressType), value_(0) {}
 154  E :    AddressVariant(AddressType type, uint32_t value)
 155    :        : type_(type), value_(value) {}
 156  E :    AddressVariant(const AddressVariant& other)  // NOLINT
 157    :        : type_(other.type_), value_(other.value_) {}
 158    :    template <AddressType kType>
 159    :    explicit AddressVariant(const detail::AddressImpl<kType>& other)
 160    :        : type_(kType), value_(other.value()) {}
 161    :  
 162    :    // Allow assignment from any address type.
 163    :    template <AddressType kType>
 164  E :    AddressVariant& operator=(const detail::AddressImpl<kType>& other) {
 165  E :      type_ = kType;
 166  E :      value_ = other.value();
 167  E :      return *this;
 168  E :    }
 169    :    AddressVariant& operator=(const AddressVariant& other);
 170    :  
 171    :    // Accessors and mutators.
 172  E :    AddressType type() const { return type_; }
 173  E :    uint32_t value() const { return value_; }
 174  E :    void set_type(AddressType type) { type_ = type; }
 175  E :    void set_value(uint32_t value) { value_ = value; }
 176    :  
 177    :    // Comparison operators.
 178    :    bool operator<(const AddressVariant& other) const;
 179    :    bool operator<=(const AddressVariant& other) const;
 180    :    bool operator>(const AddressVariant& other) const;
 181    :    bool operator>=(const AddressVariant& other) const;
 182    :    bool operator==(const AddressVariant& other) const;
 183    :    bool operator!=(const AddressVariant& other) const;
 184    :  
 185    :    // Arithmetic operators.
 186  E :    void operator+=(int32_t offset) { value_ += offset; }
 187  E :    void operator-=(int32_t offset) { value_ -= offset; }
 188  E :    AddressVariant operator+(size_t offset) const {
 189  E :      return AddressVariant(type_, value_ + offset);
 190  E :    }
 191    :    AddressVariant operator-(size_t offset) const {
 192    :      return AddressVariant(type_, value_ - offset);
 193    :    }
 194    :  
 195    :    // NOTE: No operator-(const AddressVariant&) is provided as the types may
 196    :    // not be consistent and the result may not make sense.
 197    :  
 198    :    // For extracting concrete address types.
 199    :    // @tparam kType the concrete address type.
 200    :    // @param addr the concrete address instance to be populated with the
 201    :    //     address in this variant.
 202    :    // @returns true on success (the type of this variant matches the type of
 203    :    //     the concrete class), false otherwise.
 204    :    template <AddressType kType>
 205  E :    bool Extract(detail::AddressImpl<kType>* addr) const {
 206  E :      DCHECK_NE(static_cast<detail::AddressImpl<kType>*>(nullptr), addr);
 207  E :      if (kType != type_)
 208  E :        return false;
 209  E :      addr->set_value(value_);
 210  E :      return true;
 211  E :    }
 212    :  
 213    :    // @param alignment the alignment to be provided.
 214    :    // @returns an address that has been increased minimally to have the requested
 215    :    //     @p alignment.
 216  E :    AddressVariant AlignUp(size_t alignment) const {
 217  E :      return AddressVariant(type_, common::AlignUp(value_, alignment));
 218  E :    }
 219    :  
 220    :    // Determines if this address has the provided @p alignment.
 221    :    // @param alignment the alignment to be tested against.
 222    :    // @returns true if the address is aligned to @p alignment, false otherwise.
 223    :    bool IsAligned(size_t alignment) const {
 224    :      return common::IsAligned(value_, alignment);
 225    :    }
 226    :  
 227    :    // Determines the address alignment. If the value of the address is 0 then we
 228    :    // return the maximum alignment for a 32-bit address (0x80000000).
 229    :    // @returns the alignment of the address.
 230    :    uint32_t GetAlignment() const { return common::GetAlignment(value_); }
 231    :  
 232    :    // For serialization.
 233    :    bool Save(OutArchive* out_archive) const;
 234    :    bool Load(InArchive* in_archive);
 235    :  
 236    :    friend std::ostream& operator<<(std::ostream& str,
 237    :                                    const AddressVariant& addr);
 238    :  
 239    :   private:
 240    :    AddressType type_;
 241    :    uint32_t value_;
 242    :  };
 243    :  
 244    :  }  // namespace core
 245    :  
 246    :  #endif  // SYZYGY_CORE_ADDRESS_H_

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