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