diff --git a/include/Address.h b/include/Address.h new file mode 100644 index 000000000..ddf735adc --- /dev/null +++ b/include/Address.h @@ -0,0 +1,31 @@ + +#ifndef ADDRESS_H_ +#define ADDRESS_H_ + +#include "Value.h" + +namespace edb { + +class EDB_EXPORT address_t : public value64 { +public: + QString toPointerString(bool createdFromNativePointer = true) const; + QString toHexString() const; + + template + static address_t fromZeroExtended(const SmallData& data) { + return value64::fromZeroExtended(data); + } + + template + address_t(const T& val) : value64(val) { + } + + address_t() = default; + void normalize(); +}; + +using reg_t = address_t; + +} + +#endif diff --git a/include/Types.h b/include/Types.h index 655a647d0..57d8acfc0 100644 --- a/include/Types.h +++ b/include/Types.h @@ -20,24 +20,12 @@ along with this program. If not, see . #define TYPES_20071127_H_ #include "API.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "Value.h" +#include "Address.h" + #include #include -#include - -class Register; - -#ifdef _MSC_VER -extern "C" EDB_EXPORT void __fastcall long_double_to_double(const void* src, double* dest); -#endif +#include namespace edb { @@ -50,313 +38,6 @@ enum EVENT_STATUS { DEBUG_NEXT_HANDLER }; -namespace detail { - -template -struct sized_uint {}; - -template <> struct sized_uint<8> { using type = uint8_t; }; -template <> struct sized_uint<16> { using type = uint16_t; }; -template <> struct sized_uint<32> { using type = uint32_t; }; -template <> struct sized_uint<64> { using type = uint64_t; }; - -template -class ValueBase { - static_assert(ElementCount > 0, "ValueBase::value_ must be non-empty"); - -protected: - using ValueType = std::array::type, ElementCount>; - ValueType value_; - - explicit ValueBase(const std::vector& data,std::size_t offset = 0) { - assert(data.size() - offset >= sizeof(ValueType)); // check bounds, this can't be done at compile time - - auto dataStart = reinterpret_cast(&data); - std::memcpy(&value_, dataStart + offset, sizeof(value_)); - } - - template - explicit ValueBase(const Data& data, std::size_t offset = 0) { - static_assert(sizeof(Data) >= sizeof(ValueType), "ValueBase can only be constructed from large enough variable"); -#if defined __GNUG__ && __GNUC__ >= 5 || !defined __GNUG__ || defined __clang__ && __clang_major__*100+__clang_minor__>=306 - static_assert(std::is_trivially_copyable::value, "ValueBase can only be constructed from trivially copiable data"); -#endif - - assert(sizeof(Data) - offset >= sizeof(ValueType)); // check bounds, this can't be done at compile time - - auto dataStart = reinterpret_cast(&data); - std::memcpy(&value_, dataStart + offset, sizeof(value_)); - } - - template - void copyZeroExtended(const SmallData& data) { - static_assert(sizeof(SmallData) <= sizeof(ValueType), "It doesn't make sense to expand a larger type into a smaller type"); - - auto dataStart = reinterpret_cast(&data); - auto target = reinterpret_cast(&value_); - - std::memcpy(target, dataStart, sizeof(data)); - std::memset(target + sizeof(data), 0, sizeof(value_) - sizeof(data)); - } - - ValueBase() = default; - -public: - QString toHexString() const { - std::ostringstream ss; - - for(auto it = value_.rbegin(); it != value_.rend(); ++it) { - ss << std::setw(sizeof(*it) * 2) << std::setfill('0') << std::hex << +*it; // + to prevent printing uint8_t as a character - } - - return QString::fromStdString(ss.str()); - } - - ValueType& value() { return value_; } - const ValueType& value() const { return value_; } - bool operator==(const ValueBase& other) const { return value_ == other.value_; } - bool operator!=(const ValueBase& other) const { return !(*this == other); } -}; - -template -class SizedValue : public ValueBase { - static_assert((N % 8) == 0, "SizedValue must have multiple of 8 bits in size"); - -public: - using InnerValueType = typename sized_uint::type; - - SizedValue() = default; - - template ::value && !std::is_integral::value>::type> - explicit SizedValue (const Data& data, std::size_t offset = 0) : ValueBase(data,offset) { - static_assert(sizeof(SizedValue) * 8 == N, "Size is broken!"); - } - - template ::value>::type> - explicit SizedValue(Float floatVal) { - this->value_[0] = floatVal; - } - - template ::value>::type> - SizedValue(Integer integer) { - this->value_[0] = integer; - } - - SizedValue(const Register&) = delete; - - template - static SizedValue fromZeroExtended(const SmallData& data) { - SizedValue created; - created.copyZeroExtended(data); - return created; - } - - static SizedValue fromString(const QString& str, bool* ok = nullptr, int base = 10, bool Signed = false) { - - const qulonglong v = Signed ? str.toLongLong(ok, base) : str.toULongLong(ok, base); - - if(ok && !*ok) { - return SizedValue(0); - } - - // Check that the result fits into InnerValueType - SizedValue result(v); - if(result == v) { - return result; - } - - if(ok) { - *ok = false; - } - - return SizedValue(0); - } - - static SizedValue fromHexString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 16); } - static SizedValue fromSignedString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 10, true); } - static SizedValue fromCString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 0); } - - operator InnerValueType() const { return this->value_[0]; } - - QVariant toQVariant() const { return QVariant::fromValue(this->value_[0]); } - - SizedValue signExtended(std::size_t valueLength) const { - - SizedValue result(*this); - - if(valueLength == sizeof(*this)) { - return result; - } - - if(this->value_[0] & (1ull << (valueLength * 8 - 1))) { - result = -1ll; - std::memcpy(&result, this, valueLength); - } - - return result; - } - - QString toString() const { return QString("%1").arg(this->value_[0]); } - QString unsignedToString() const { return toString(); } - QString signedToString() const { return QString("%1").arg(typename std::make_signed::type(this->value_[0])); } - - using ValueBase::operator==; - using ValueBase::operator!=; - - template typename std::enable_if::value, bool>::type operator == (RHS rhs) const { return this->value_[0] == static_cast(rhs); } - template typename std::enable_if::value, bool>::type operator != (RHS rhs) const { return this->value_[0] != static_cast(rhs); } - template typename std::enable_if::value, bool>::type operator > (RHS rhs) const { return this->value_[0] > rhs; } - template typename std::enable_if::value, bool>::type operator < (RHS rhs) const { return this->value_[0] < rhs; } - template typename std::enable_if::value, bool>::type operator >= (RHS rhs) const { return this->value_[0] >= rhs; } - template typename std::enable_if::value, bool>::type operator <= (RHS rhs) const { return this->value_[0] <= rhs; } - template typename std::enable_if::value, SizedValue>::type operator + (RHS rhs) const { return SizedValue(this->value_[0] + rhs); } - template typename std::enable_if::value, SizedValue>::type operator - (RHS rhs) const { return SizedValue(this->value_[0] - rhs); } - template typename std::enable_if::value, SizedValue>::type operator & (RHS rhs) const { return SizedValue(this->value_[0] & rhs); } - template typename std::enable_if::value, SizedValue>::type operator % (RHS rhs) const { return SizedValue(this->value_[0] % rhs); } - template typename std::enable_if::value, SizedValue>::type operator += (RHS rhs) { this->value_[0] += rhs; return *this; } - template typename std::enable_if::value, SizedValue>::type operator -= (RHS rhs) { this->value_[0] -= rhs; return *this; } - template typename std::enable_if::value, SizedValue>::type operator ^= (RHS rhs) { this->value_[0] ^= rhs; return *this; } - template typename std::enable_if::value, SizedValue>::type operator &= (RHS rhs) { this->value_[0] &= rhs; return *this; } - template typename std::enable_if::value, SizedValue>::type operator |= (RHS rhs) { this->value_[0] |= rhs; return *this; } - template typename std::enable_if::value, SizedValue>::type operator >> (RHS rhs) const { return SizedValue(this->value_[0] >> rhs); } - template typename std::enable_if::value, SizedValue>::type operator << (RHS rhs) const { return SizedValue(this->value_[0] << rhs); } - - bool operator > (SizedValue other) const { return this->value_[0] > other.value_[0]; } - bool operator < (SizedValue other) const { return this->value_[0] < other.value_[0]; } - bool operator >= (SizedValue other) const { return this->value_[0] >= other.value_[0]; } - bool operator <= (SizedValue other) const { return this->value_[0] <= other.value_[0]; } - SizedValue operator + (const SizedValue& other) const { return SizedValue(this->value_[0] + other.value_[0]); } - SizedValue operator - (const SizedValue& other) const { return SizedValue(this->value_[0] - other.value_[0]); } - SizedValue operator += (SizedValue other) { this->value_[0] += other.value_[0]; return *this; } - SizedValue operator -= (SizedValue other) { this->value_[0] -= other.value_[0]; return *this; } - SizedValue operator ^= (SizedValue other) { this->value_[0] ^= other.value_[0]; return *this; } - SizedValue operator &= (SizedValue other) { this->value_[0] &= other.value_[0]; return *this; } - SizedValue operator |= (SizedValue other) { this->value_[0] |= other.value_[0]; return *this; } - SizedValue operator <<=(SizedValue other) { this->value_[0] <<=other.value_[0]; return *this; } - SizedValue operator >>=(SizedValue other) { this->value_[0] >>=other.value_[0]; return *this; } - SizedValue operator *= (SizedValue other) { this->value_[0] *= other.value_[0]; return *this; } - SizedValue operator /= (SizedValue other) { this->value_[0] /= other.value_[0]; return *this; } - SizedValue operator %= (SizedValue other) { this->value_[0] %= other.value_[0]; return *this; } - SizedValue operator ++ (int) { SizedValue copy(*this); ++this->value_[0]; return copy; } - SizedValue operator ++ () { ++this->value_[0]; return *this; } - SizedValue operator + () const { return *this; } - InnerValueType toUint() const { return this->value_[0]; } - InnerValueType& asUint() { return this->value_[0]; } - bool negative() const { return this->value_.back()>>(std::numeric_limits::digits-1); } -}; - -// Not using long double because for e.g. x86_64 it has 128 bits. -struct EDB_EXPORT Value80 : public ValueBase<16,5> { - Value80() = default; - - template - explicit Value80 (const Data& data, std::size_t offset=0) : ValueBase<16,5>(data,offset) { - static_assert(sizeof(Value80) * 8 == 80, "Size is broken!"); - } - - template - static Value80 fromZeroExtended(const SmallData& data) { - Value80 created; - created.copyZeroExtended(data); - return created; - } - - long double toFloatValue() const { -#ifdef _MSC_VER - double d; - long_double_to_double(&value_, &d); - return d; -#else - long double float80val; - std::memcpy(&float80val, &value_, sizeof(value_)); - return float80val; -#endif - } - - QString toString() const { - std::ostringstream ss; - ss << std::showpos << std::setprecision(20) << toFloatValue(); - return QString::fromStdString(ss.str()); - } - - bool negative() const { return value_[4] & 0x8000; } - SizedValue<16> exponent() const { return value_[4] & 0x7fff; } - SizedValue<64> mantissa() const { return SizedValue<64>(value_); } -}; - -static constexpr int LargeSizedValueElementWidth = 64; - -template -struct LargeSizedValue : public ValueBase { - using BaseClass = ValueBase; - - static_assert(N % LargeSizedValueElementWidth == 0, "LargeSizedValue must have multiple of 64 bits in size"); - - LargeSizedValue() = default; - - template - explicit LargeSizedValue (const Data& data, std::size_t offset = 0) : BaseClass(data,offset) { - static_assert(sizeof(LargeSizedValue) * 8 == N, "Size is broken!"); - } - - template - static LargeSizedValue fromZeroExtended(const SmallData& data) { - LargeSizedValue created; - created.copyZeroExtended(data); - return created; - } -}; -} - -// GPR on x86 -using value8 = detail::SizedValue<8>; -using value16 = detail::SizedValue<16>; -using value32 = detail::SizedValue<32>; - -// MMX/GPR(x86_64) -using value64 = detail::SizedValue<64>; - -// FPU -using value80 = detail::Value80; - -// SSE -using value128 = detail::LargeSizedValue<128>; - -// AVX -using value256 = detail::LargeSizedValue<256>; - -// AVX512 -using value512 = detail::LargeSizedValue<512>; - -static_assert(std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value && - std::is_standard_layout::value, "Fixed-sized values are intended to have standard layout"); - -class EDB_EXPORT address_t : public value64 { -public: - QString toPointerString(bool createdFromNativePointer = true) const; - QString toHexString() const; - - template - static address_t fromZeroExtended(const SmallData& data) { - return value64::fromZeroExtended(data); - } - - template - address_t(const T& val) : value64(val) { - } - - address_t() = default; - void normalize(); -}; - -using reg_t = address_t; - } template typename std::enable_if::value || @@ -365,8 +46,7 @@ template typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, -std::istream&>::type operator>>(std::istream& os, T& val) -{ +std::istream&>::type operator>>(std::istream& os, T& val) { os >> val.asUint(); return os; } @@ -377,8 +57,7 @@ template typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, -std::ostream&>::type operator<<(std::ostream& os, T val) -{ +std::ostream&>::type operator<<(std::ostream& os, T val) { os << val.toUint(); return os; } diff --git a/include/Value.h b/include/Value.h new file mode 100644 index 000000000..822a52daf --- /dev/null +++ b/include/Value.h @@ -0,0 +1,320 @@ + +#ifndef VALUE_H_ +#define VALUE_H_ + +#include "API.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class Register; + +#ifdef _MSC_VER +extern "C" EDB_EXPORT void __fastcall long_double_to_double(const void* src, double* dest); +#endif + +namespace edb { +namespace detail { + +static constexpr int LargeSizedValueElementWidth = 64; + +template +struct sized_uint {}; + +template <> struct sized_uint<8> { using type = std::uint8_t; }; +template <> struct sized_uint<16> { using type = std::uint16_t; }; +template <> struct sized_uint<32> { using type = std::uint32_t; }; +template <> struct sized_uint<64> { using type = std::uint64_t; }; + +template +class ValueBase { + static_assert(ElementCount > 0, "ValueBase::value_ must be non-empty"); + +protected: + using ValueType = std::array::type, ElementCount>; + ValueType value_; +#if 1 + explicit ValueBase(const std::vector& data,std::size_t offset = 0) { + assert(data.size() - offset >= sizeof(ValueType)); // check bounds, this can't be done at compile time + + auto dataStart = reinterpret_cast(&data); + std::memcpy(&value_, dataStart + offset, sizeof(value_)); + } +#endif + + template + explicit ValueBase(const Data& data, std::size_t offset = 0) { + static_assert(sizeof(Data) >= sizeof(ValueType), "ValueBase can only be constructed from large enough variable"); +#if defined __GNUG__ && __GNUC__ >= 5 || !defined __GNUG__ || defined __clang__ && __clang_major__*100+__clang_minor__>=306 + static_assert(std::is_trivially_copyable::value, "ValueBase can only be constructed from trivially copiable data"); +#endif + + assert(sizeof(Data) - offset >= sizeof(ValueType)); // check bounds, this can't be done at compile time + + auto dataStart = reinterpret_cast(&data); + std::memcpy(&value_, dataStart + offset, sizeof(value_)); + } + + template + void copyZeroExtended(const SmallData& data) { + static_assert(sizeof(SmallData) <= sizeof(ValueType), "It doesn't make sense to expand a larger type into a smaller type"); + + auto dataStart = reinterpret_cast(&data); + auto target = reinterpret_cast(&value_); + + std::memcpy(target, dataStart, sizeof(data)); + std::memset(target + sizeof(data), 0, sizeof(value_) - sizeof(data)); + } + + ValueBase() = default; + +public: + QString toHexString() const { + std::ostringstream ss; + + for(auto it = value_.rbegin(); it != value_.rend(); ++it) { + ss << std::setw(sizeof(*it) * 2) << std::setfill('0') << std::hex << +*it; // + to prevent printing uint8_t as a character + } + + return QString::fromStdString(ss.str()); + } + + ValueType& value() { return value_; } + const ValueType& value() const { return value_; } + bool operator==(const ValueBase& other) const { return value_ == other.value_; } + bool operator!=(const ValueBase& other) const { return !(*this == other); } +}; + +template +class SizedValue : public ValueBase { + static_assert((N % 8) == 0, "SizedValue must have multiple of 8 bits in size"); + +public: + using InnerValueType = typename sized_uint::type; + + SizedValue() = default; + + template ::value && !std::is_integral::value>::type> + explicit SizedValue (const Data& data, std::size_t offset) : ValueBase(data,offset) { + static_assert(sizeof(SizedValue) * 8 == N, "Size is broken!"); + } + + template ::value && !std::is_integral::value>::type> + explicit SizedValue (const Data& data) : ValueBase(data, 0) { + static_assert(sizeof(SizedValue) * 8 == N, "Size is broken!"); + } + + template ::value>::type> + explicit SizedValue(Float floatVal) { + this->value_[0] = floatVal; + } + + template ::value>::type> + SizedValue(Integer integer) { + this->value_[0] = integer; + } + + SizedValue(const Register&) = delete; + + template + static SizedValue fromZeroExtended(const SmallData& data) { + SizedValue created; + created.copyZeroExtended(data); + return created; + } + + static SizedValue fromString(const QString& str, bool* ok = nullptr, int base = 10, bool Signed = false) { + + const qulonglong v = Signed ? str.toLongLong(ok, base) : str.toULongLong(ok, base); + + if(ok && !*ok) { + return SizedValue(0); + } + + // Check that the result fits into InnerValueType + SizedValue result(v); + if(result == v) { + return result; + } + + if(ok) { + *ok = false; + } + + return SizedValue(0); + } + + static SizedValue fromHexString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 16); } + static SizedValue fromSignedString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 10, true); } + static SizedValue fromCString(const QString& str, bool* ok = nullptr) { return fromString(str, ok, 0); } + + operator InnerValueType() const { return this->value_[0]; } + + QVariant toQVariant() const { return QVariant::fromValue(this->value_[0]); } + + SizedValue signExtended(std::size_t valueLength) const { + + SizedValue result(*this); + + if(valueLength == sizeof(*this)) { + return result; + } + + if(this->value_[0] & (1ull << (valueLength * 8 - 1))) { + result = -1ll; + std::memcpy(&result, this, valueLength); + } + + return result; + } + + QString toString() const { return QString("%1").arg(this->value_[0]); } + QString unsignedToString() const { return toString(); } + QString signedToString() const { return QString("%1").arg(typename std::make_signed::type(this->value_[0])); } + + using ValueBase::operator==; + using ValueBase::operator!=; + + template typename std::enable_if::value, bool>::type operator == (RHS rhs) const { return this->value_[0] == static_cast(rhs); } + template typename std::enable_if::value, bool>::type operator != (RHS rhs) const { return this->value_[0] != static_cast(rhs); } + template typename std::enable_if::value, bool>::type operator > (RHS rhs) const { return this->value_[0] > rhs; } + template typename std::enable_if::value, bool>::type operator < (RHS rhs) const { return this->value_[0] < rhs; } + template typename std::enable_if::value, bool>::type operator >= (RHS rhs) const { return this->value_[0] >= rhs; } + template typename std::enable_if::value, bool>::type operator <= (RHS rhs) const { return this->value_[0] <= rhs; } + template typename std::enable_if::value, SizedValue>::type operator + (RHS rhs) const { return SizedValue(this->value_[0] + rhs); } + template typename std::enable_if::value, SizedValue>::type operator - (RHS rhs) const { return SizedValue(this->value_[0] - rhs); } + template typename std::enable_if::value, SizedValue>::type operator & (RHS rhs) const { return SizedValue(this->value_[0] & rhs); } + template typename std::enable_if::value, SizedValue>::type operator % (RHS rhs) const { return SizedValue(this->value_[0] % rhs); } + template typename std::enable_if::value, SizedValue>::type operator += (RHS rhs) { this->value_[0] += rhs; return *this; } + template typename std::enable_if::value, SizedValue>::type operator -= (RHS rhs) { this->value_[0] -= rhs; return *this; } + template typename std::enable_if::value, SizedValue>::type operator ^= (RHS rhs) { this->value_[0] ^= rhs; return *this; } + template typename std::enable_if::value, SizedValue>::type operator &= (RHS rhs) { this->value_[0] &= rhs; return *this; } + template typename std::enable_if::value, SizedValue>::type operator |= (RHS rhs) { this->value_[0] |= rhs; return *this; } + template typename std::enable_if::value, SizedValue>::type operator >> (RHS rhs) const { return SizedValue(this->value_[0] >> rhs); } + template typename std::enable_if::value, SizedValue>::type operator << (RHS rhs) const { return SizedValue(this->value_[0] << rhs); } + + bool operator > (SizedValue other) const { return this->value_[0] > other.value_[0]; } + bool operator < (SizedValue other) const { return this->value_[0] < other.value_[0]; } + bool operator >= (SizedValue other) const { return this->value_[0] >= other.value_[0]; } + bool operator <= (SizedValue other) const { return this->value_[0] <= other.value_[0]; } + SizedValue operator + (const SizedValue& other) const { return SizedValue(this->value_[0] + other.value_[0]); } + SizedValue operator - (const SizedValue& other) const { return SizedValue(this->value_[0] - other.value_[0]); } + SizedValue operator += (SizedValue other) { this->value_[0] += other.value_[0]; return *this; } + SizedValue operator -= (SizedValue other) { this->value_[0] -= other.value_[0]; return *this; } + SizedValue operator ^= (SizedValue other) { this->value_[0] ^= other.value_[0]; return *this; } + SizedValue operator &= (SizedValue other) { this->value_[0] &= other.value_[0]; return *this; } + SizedValue operator |= (SizedValue other) { this->value_[0] |= other.value_[0]; return *this; } + SizedValue operator <<=(SizedValue other) { this->value_[0] <<=other.value_[0]; return *this; } + SizedValue operator >>=(SizedValue other) { this->value_[0] >>=other.value_[0]; return *this; } + SizedValue operator *= (SizedValue other) { this->value_[0] *= other.value_[0]; return *this; } + SizedValue operator /= (SizedValue other) { this->value_[0] /= other.value_[0]; return *this; } + SizedValue operator %= (SizedValue other) { this->value_[0] %= other.value_[0]; return *this; } + SizedValue operator ++ (int) { SizedValue copy(*this); ++this->value_[0]; return copy; } + SizedValue operator ++ () { ++this->value_[0]; return *this; } + SizedValue operator + () const { return *this; } + InnerValueType toUint() const { return this->value_[0]; } + InnerValueType& asUint() { return this->value_[0]; } + bool negative() const { return this->value_.back()>>(std::numeric_limits::digits-1); } +}; + +// Not using long double because for e.g. x86_64 it has 128 bits. +struct EDB_EXPORT Value80 : public ValueBase<16,5> { + Value80() = default; + + template + explicit Value80 (const Data& data, std::size_t offset=0) : ValueBase<16,5>(data,offset) { + static_assert(sizeof(Value80) * 8 == 80, "Size is broken!"); + } + + template + static Value80 fromZeroExtended(const SmallData& data) { + Value80 created; + created.copyZeroExtended(data); + return created; + } + + long double toFloatValue() const { +#ifdef _MSC_VER + double d; + long_double_to_double(&value_, &d); + return d; +#else + long double float80val; + std::memcpy(&float80val, &value_, sizeof(value_)); + return float80val; +#endif + } + + QString toString() const { + std::ostringstream ss; + ss << std::showpos << std::setprecision(20) << toFloatValue(); + return QString::fromStdString(ss.str()); + } + + bool negative() const { return value_[4] & 0x8000; } + SizedValue<16> exponent() const { return value_[4] & 0x7fff; } + SizedValue<64> mantissa() const { return SizedValue<64>(value_); } +}; + +template +struct LargeSizedValue : public ValueBase { + using BaseClass = ValueBase; + + static_assert(N % LargeSizedValueElementWidth == 0, "LargeSizedValue must have multiple of 64 bits in size"); + + LargeSizedValue() = default; + + template + explicit LargeSizedValue (const Data& data, std::size_t offset = 0) : BaseClass(data,offset) { + static_assert(sizeof(LargeSizedValue) * 8 == N, "Size is broken!"); + } + + template + static LargeSizedValue fromZeroExtended(const SmallData& data) { + LargeSizedValue created; + created.copyZeroExtended(data); + return created; + } +}; + +} + +// GPR on x86 +using value8 = detail::SizedValue<8>; +using value16 = detail::SizedValue<16>; +using value32 = detail::SizedValue<32>; + +// MMX/GPR(x86_64) +using value64 = detail::SizedValue<64>; + +// FPU +using value80 = detail::Value80; + +// SSE +using value128 = detail::LargeSizedValue<128>; + +// AVX +using value256 = detail::LargeSizedValue<256>; + +// AVX512 +using value512 = detail::LargeSizedValue<512>; + +static_assert(std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value && + std::is_standard_layout::value, "Fixed-sized values are intended to have standard layout"); + +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4af412dec..21639aa60 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -164,6 +164,8 @@ set(edb_SRCS ${PROJECT_SOURCE_DIR}/include/Symbol.h ${PROJECT_SOURCE_DIR}/include/ThreadsModel.h ${PROJECT_SOURCE_DIR}/include/Types.h + ${PROJECT_SOURCE_DIR}/include/Value.h + ${PROJECT_SOURCE_DIR}/include/Address.h ${PROJECT_SOURCE_DIR}/include/Util.h ${PROJECT_SOURCE_DIR}/include/version.h )