1*ee754c2dSkamil //===-- ubsan_value.h -------------------------------------------*- C++ -*-===// 2*ee754c2dSkamil // 3*ee754c2dSkamil // The LLVM Compiler Infrastructure 4*ee754c2dSkamil // 5*ee754c2dSkamil // This file is distributed under the University of Illinois Open Source 6*ee754c2dSkamil // License. See LICENSE.TXT for details. 7*ee754c2dSkamil // 8*ee754c2dSkamil //===----------------------------------------------------------------------===// 9*ee754c2dSkamil // 10*ee754c2dSkamil // Representation of data which is passed from the compiler-generated calls into 11*ee754c2dSkamil // the ubsan runtime. 12*ee754c2dSkamil // 13*ee754c2dSkamil //===----------------------------------------------------------------------===// 14*ee754c2dSkamil #ifndef UBSAN_VALUE_H 15*ee754c2dSkamil #define UBSAN_VALUE_H 16*ee754c2dSkamil 17*ee754c2dSkamil #include "sanitizer_common/sanitizer_atomic.h" 18*ee754c2dSkamil #include "sanitizer_common/sanitizer_common.h" 19*ee754c2dSkamil 20*ee754c2dSkamil // FIXME: Move this out to a config header. 21*ee754c2dSkamil #if __SIZEOF_INT128__ 22*ee754c2dSkamil __extension__ typedef __int128 s128; 23*ee754c2dSkamil __extension__ typedef unsigned __int128 u128; 24*ee754c2dSkamil #define HAVE_INT128_T 1 25*ee754c2dSkamil #else 26*ee754c2dSkamil #define HAVE_INT128_T 0 27*ee754c2dSkamil #endif 28*ee754c2dSkamil 29*ee754c2dSkamil namespace __ubsan { 30*ee754c2dSkamil 31*ee754c2dSkamil /// \brief Largest integer types we support. 32*ee754c2dSkamil #if HAVE_INT128_T 33*ee754c2dSkamil typedef s128 SIntMax; 34*ee754c2dSkamil typedef u128 UIntMax; 35*ee754c2dSkamil #else 36*ee754c2dSkamil typedef s64 SIntMax; 37*ee754c2dSkamil typedef u64 UIntMax; 38*ee754c2dSkamil #endif 39*ee754c2dSkamil 40*ee754c2dSkamil /// \brief Largest floating-point type we support. 41*ee754c2dSkamil typedef long double FloatMax; 42*ee754c2dSkamil 43*ee754c2dSkamil /// \brief A description of a source location. This corresponds to Clang's 44*ee754c2dSkamil /// \c PresumedLoc type. 45*ee754c2dSkamil class SourceLocation { 46*ee754c2dSkamil const char *Filename; 47*ee754c2dSkamil u32 Line; 48*ee754c2dSkamil u32 Column; 49*ee754c2dSkamil 50*ee754c2dSkamil public: SourceLocation()51*ee754c2dSkamil SourceLocation() : Filename(), Line(), Column() {} SourceLocation(const char * Filename,unsigned Line,unsigned Column)52*ee754c2dSkamil SourceLocation(const char *Filename, unsigned Line, unsigned Column) 53*ee754c2dSkamil : Filename(Filename), Line(Line), Column(Column) {} 54*ee754c2dSkamil 55*ee754c2dSkamil /// \brief Determine whether the source location is known. isInvalid()56*ee754c2dSkamil bool isInvalid() const { return !Filename; } 57*ee754c2dSkamil 58*ee754c2dSkamil /// \brief Atomically acquire a copy, disabling original in-place. 59*ee754c2dSkamil /// Exactly one call to acquire() returns a copy that isn't disabled. acquire()60*ee754c2dSkamil SourceLocation acquire() { 61*ee754c2dSkamil u32 OldColumn = __sanitizer::atomic_exchange( 62*ee754c2dSkamil (__sanitizer::atomic_uint32_t *)&Column, ~u32(0), 63*ee754c2dSkamil __sanitizer::memory_order_relaxed); 64*ee754c2dSkamil return SourceLocation(Filename, Line, OldColumn); 65*ee754c2dSkamil } 66*ee754c2dSkamil 67*ee754c2dSkamil /// \brief Determine if this Location has been disabled. 68*ee754c2dSkamil /// Disabled SourceLocations are invalid to use. isDisabled()69*ee754c2dSkamil bool isDisabled() { 70*ee754c2dSkamil return Column == ~u32(0); 71*ee754c2dSkamil } 72*ee754c2dSkamil 73*ee754c2dSkamil /// \brief Get the presumed filename for the source location. getFilename()74*ee754c2dSkamil const char *getFilename() const { return Filename; } 75*ee754c2dSkamil /// \brief Get the presumed line number. getLine()76*ee754c2dSkamil unsigned getLine() const { return Line; } 77*ee754c2dSkamil /// \brief Get the column within the presumed line. getColumn()78*ee754c2dSkamil unsigned getColumn() const { return Column; } 79*ee754c2dSkamil }; 80*ee754c2dSkamil 81*ee754c2dSkamil 82*ee754c2dSkamil /// \brief A description of a type. 83*ee754c2dSkamil class TypeDescriptor { 84*ee754c2dSkamil /// A value from the \c Kind enumeration, specifying what flavor of type we 85*ee754c2dSkamil /// have. 86*ee754c2dSkamil u16 TypeKind; 87*ee754c2dSkamil 88*ee754c2dSkamil /// A \c Type-specific value providing information which allows us to 89*ee754c2dSkamil /// interpret the meaning of a ValueHandle of this type. 90*ee754c2dSkamil u16 TypeInfo; 91*ee754c2dSkamil 92*ee754c2dSkamil /// The name of the type follows, in a format suitable for including in 93*ee754c2dSkamil /// diagnostics. 94*ee754c2dSkamil char TypeName[1]; 95*ee754c2dSkamil 96*ee754c2dSkamil public: 97*ee754c2dSkamil enum Kind { 98*ee754c2dSkamil /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned 99*ee754c2dSkamil /// value. Remaining bits are log_2(bit width). The value representation is 100*ee754c2dSkamil /// the integer itself if it fits into a ValueHandle, and a pointer to the 101*ee754c2dSkamil /// integer otherwise. 102*ee754c2dSkamil TK_Integer = 0x0000, 103*ee754c2dSkamil /// A floating-point type. Low 16 bits are bit width. The value 104*ee754c2dSkamil /// representation is that of bitcasting the floating-point value to an 105*ee754c2dSkamil /// integer type. 106*ee754c2dSkamil TK_Float = 0x0001, 107*ee754c2dSkamil /// Any other type. The value representation is unspecified. 108*ee754c2dSkamil TK_Unknown = 0xffff 109*ee754c2dSkamil }; 110*ee754c2dSkamil getTypeName()111*ee754c2dSkamil const char *getTypeName() const { return TypeName; } 112*ee754c2dSkamil getKind()113*ee754c2dSkamil Kind getKind() const { 114*ee754c2dSkamil return static_cast<Kind>(TypeKind); 115*ee754c2dSkamil } 116*ee754c2dSkamil isIntegerTy()117*ee754c2dSkamil bool isIntegerTy() const { return getKind() == TK_Integer; } isSignedIntegerTy()118*ee754c2dSkamil bool isSignedIntegerTy() const { 119*ee754c2dSkamil return isIntegerTy() && (TypeInfo & 1); 120*ee754c2dSkamil } isUnsignedIntegerTy()121*ee754c2dSkamil bool isUnsignedIntegerTy() const { 122*ee754c2dSkamil return isIntegerTy() && !(TypeInfo & 1); 123*ee754c2dSkamil } getIntegerBitWidth()124*ee754c2dSkamil unsigned getIntegerBitWidth() const { 125*ee754c2dSkamil CHECK(isIntegerTy()); 126*ee754c2dSkamil return 1 << (TypeInfo >> 1); 127*ee754c2dSkamil } 128*ee754c2dSkamil isFloatTy()129*ee754c2dSkamil bool isFloatTy() const { return getKind() == TK_Float; } getFloatBitWidth()130*ee754c2dSkamil unsigned getFloatBitWidth() const { 131*ee754c2dSkamil CHECK(isFloatTy()); 132*ee754c2dSkamil return TypeInfo; 133*ee754c2dSkamil } 134*ee754c2dSkamil }; 135*ee754c2dSkamil 136*ee754c2dSkamil /// \brief An opaque handle to a value. 137*ee754c2dSkamil typedef uptr ValueHandle; 138*ee754c2dSkamil 139*ee754c2dSkamil 140*ee754c2dSkamil /// \brief Representation of an operand value provided by the instrumented code. 141*ee754c2dSkamil /// 142*ee754c2dSkamil /// This is a combination of a TypeDescriptor (which is emitted as constant data 143*ee754c2dSkamil /// as an operand to a handler function) and a ValueHandle (which is passed at 144*ee754c2dSkamil /// runtime when a check failure occurs). 145*ee754c2dSkamil class Value { 146*ee754c2dSkamil /// The type of the value. 147*ee754c2dSkamil const TypeDescriptor &Type; 148*ee754c2dSkamil /// The encoded value itself. 149*ee754c2dSkamil ValueHandle Val; 150*ee754c2dSkamil 151*ee754c2dSkamil /// Is \c Val a (zero-extended) integer? isInlineInt()152*ee754c2dSkamil bool isInlineInt() const { 153*ee754c2dSkamil CHECK(getType().isIntegerTy()); 154*ee754c2dSkamil const unsigned InlineBits = sizeof(ValueHandle) * 8; 155*ee754c2dSkamil const unsigned Bits = getType().getIntegerBitWidth(); 156*ee754c2dSkamil return Bits <= InlineBits; 157*ee754c2dSkamil } 158*ee754c2dSkamil 159*ee754c2dSkamil /// Is \c Val a (zero-extended) integer representation of a float? isInlineFloat()160*ee754c2dSkamil bool isInlineFloat() const { 161*ee754c2dSkamil CHECK(getType().isFloatTy()); 162*ee754c2dSkamil const unsigned InlineBits = sizeof(ValueHandle) * 8; 163*ee754c2dSkamil const unsigned Bits = getType().getFloatBitWidth(); 164*ee754c2dSkamil return Bits <= InlineBits; 165*ee754c2dSkamil } 166*ee754c2dSkamil 167*ee754c2dSkamil public: Value(const TypeDescriptor & Type,ValueHandle Val)168*ee754c2dSkamil Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {} 169*ee754c2dSkamil getType()170*ee754c2dSkamil const TypeDescriptor &getType() const { return Type; } 171*ee754c2dSkamil 172*ee754c2dSkamil /// \brief Get this value as a signed integer. 173*ee754c2dSkamil SIntMax getSIntValue() const; 174*ee754c2dSkamil 175*ee754c2dSkamil /// \brief Get this value as an unsigned integer. 176*ee754c2dSkamil UIntMax getUIntValue() const; 177*ee754c2dSkamil 178*ee754c2dSkamil /// \brief Decode this value, which must be a positive or unsigned integer. 179*ee754c2dSkamil UIntMax getPositiveIntValue() const; 180*ee754c2dSkamil 181*ee754c2dSkamil /// Is this an integer with value -1? isMinusOne()182*ee754c2dSkamil bool isMinusOne() const { 183*ee754c2dSkamil return getType().isSignedIntegerTy() && getSIntValue() == -1; 184*ee754c2dSkamil } 185*ee754c2dSkamil 186*ee754c2dSkamil /// Is this a negative integer? isNegative()187*ee754c2dSkamil bool isNegative() const { 188*ee754c2dSkamil return getType().isSignedIntegerTy() && getSIntValue() < 0; 189*ee754c2dSkamil } 190*ee754c2dSkamil 191*ee754c2dSkamil /// \brief Get this value as a floating-point quantity. 192*ee754c2dSkamil FloatMax getFloatValue() const; 193*ee754c2dSkamil }; 194*ee754c2dSkamil 195*ee754c2dSkamil } // namespace __ubsan 196*ee754c2dSkamil 197*ee754c2dSkamil #endif // UBSAN_VALUE_H 198