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