123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- //===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // Representation of data which is passed from the compiler-generated calls into
- // the ubsan runtime.
- //
- //===----------------------------------------------------------------------===//
- #ifndef UBSAN_VALUE_H
- #define UBSAN_VALUE_H
- // For now, only support Linux, FreeBSD and Darwin. Other platforms should
- // be easy to add, and probably work as-is.
- #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__APPLE__)
- #error "UBSan not supported for this platform!"
- #endif
- #include "sanitizer_common/sanitizer_atomic.h"
- #include "sanitizer_common/sanitizer_common.h"
- // FIXME: Move this out to a config header.
- #if __SIZEOF_INT128__
- __extension__ typedef __int128 s128;
- __extension__ typedef unsigned __int128 u128;
- #define HAVE_INT128_T 1
- #else
- #define HAVE_INT128_T 0
- #endif
- namespace __ubsan {
- /// \brief Largest integer types we support.
- #if HAVE_INT128_T
- typedef s128 SIntMax;
- typedef u128 UIntMax;
- #else
- typedef s64 SIntMax;
- typedef u64 UIntMax;
- #endif
- /// \brief Largest floating-point type we support.
- typedef long double FloatMax;
- /// \brief A description of a source location. This corresponds to Clang's
- /// \c PresumedLoc type.
- class SourceLocation {
- const char *Filename;
- u32 Line;
- u32 Column;
- public:
- SourceLocation() : Filename(), Line(), Column() {}
- SourceLocation(const char *Filename, unsigned Line, unsigned Column)
- : Filename(Filename), Line(Line), Column(Column) {}
- /// \brief Determine whether the source location is known.
- bool isInvalid() const { return !Filename; }
- /// \brief Atomically acquire a copy, disabling original in-place.
- /// Exactly one call to acquire() returns a copy that isn't disabled.
- SourceLocation acquire() {
- u32 OldColumn = __sanitizer::atomic_exchange(
- (__sanitizer::atomic_uint32_t *)&Column, ~u32(0),
- __sanitizer::memory_order_relaxed);
- return SourceLocation(Filename, Line, OldColumn);
- }
- /// \brief Determine if this Location has been disabled.
- /// Disabled SourceLocations are invalid to use.
- bool isDisabled() {
- return Column == ~u32(0);
- }
- /// \brief Get the presumed filename for the source location.
- const char *getFilename() const { return Filename; }
- /// \brief Get the presumed line number.
- unsigned getLine() const { return Line; }
- /// \brief Get the column within the presumed line.
- unsigned getColumn() const { return Column; }
- };
- /// \brief A description of a type.
- class TypeDescriptor {
- /// A value from the \c Kind enumeration, specifying what flavor of type we
- /// have.
- u16 TypeKind;
- /// A \c Type-specific value providing information which allows us to
- /// interpret the meaning of a ValueHandle of this type.
- u16 TypeInfo;
- /// The name of the type follows, in a format suitable for including in
- /// diagnostics.
- char TypeName[1];
- public:
- enum Kind {
- /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
- /// value. Remaining bits are log_2(bit width). The value representation is
- /// the integer itself if it fits into a ValueHandle, and a pointer to the
- /// integer otherwise.
- TK_Integer = 0x0000,
- /// A floating-point type. Low 16 bits are bit width. The value
- /// representation is that of bitcasting the floating-point value to an
- /// integer type.
- TK_Float = 0x0001,
- /// Any other type. The value representation is unspecified.
- TK_Unknown = 0xffff
- };
- const char *getTypeName() const { return TypeName; }
- Kind getKind() const {
- return static_cast<Kind>(TypeKind);
- }
- bool isIntegerTy() const { return getKind() == TK_Integer; }
- bool isSignedIntegerTy() const {
- return isIntegerTy() && (TypeInfo & 1);
- }
- bool isUnsignedIntegerTy() const {
- return isIntegerTy() && !(TypeInfo & 1);
- }
- unsigned getIntegerBitWidth() const {
- CHECK(isIntegerTy());
- return 1 << (TypeInfo >> 1);
- }
- bool isFloatTy() const { return getKind() == TK_Float; }
- unsigned getFloatBitWidth() const {
- CHECK(isFloatTy());
- return TypeInfo;
- }
- };
- /// \brief An opaque handle to a value.
- typedef uptr ValueHandle;
- /// \brief Representation of an operand value provided by the instrumented code.
- ///
- /// This is a combination of a TypeDescriptor (which is emitted as constant data
- /// as an operand to a handler function) and a ValueHandle (which is passed at
- /// runtime when a check failure occurs).
- class Value {
- /// The type of the value.
- const TypeDescriptor &Type;
- /// The encoded value itself.
- ValueHandle Val;
- /// Is \c Val a (zero-extended) integer?
- bool isInlineInt() const {
- CHECK(getType().isIntegerTy());
- const unsigned InlineBits = sizeof(ValueHandle) * 8;
- const unsigned Bits = getType().getIntegerBitWidth();
- return Bits <= InlineBits;
- }
- /// Is \c Val a (zero-extended) integer representation of a float?
- bool isInlineFloat() const {
- CHECK(getType().isFloatTy());
- const unsigned InlineBits = sizeof(ValueHandle) * 8;
- const unsigned Bits = getType().getFloatBitWidth();
- return Bits <= InlineBits;
- }
- public:
- Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
- const TypeDescriptor &getType() const { return Type; }
- /// \brief Get this value as a signed integer.
- SIntMax getSIntValue() const;
- /// \brief Get this value as an unsigned integer.
- UIntMax getUIntValue() const;
- /// \brief Decode this value, which must be a positive or unsigned integer.
- UIntMax getPositiveIntValue() const;
- /// Is this an integer with value -1?
- bool isMinusOne() const {
- return getType().isSignedIntegerTy() && getSIntValue() == -1;
- }
- /// Is this a negative integer?
- bool isNegative() const {
- return getType().isSignedIntegerTy() && getSIntValue() < 0;
- }
- /// \brief Get this value as a floating-point quantity.
- FloatMax getFloatValue() const;
- };
- } // namespace __ubsan
- #endif // UBSAN_VALUE_H
|