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