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 29namespace __ubsan { 30 31/// \brief Largest integer types we support. 32#if HAVE_INT128_T 33typedef s128 SIntMax; 34typedef u128 UIntMax; 35#else 36typedef s64 SIntMax; 37typedef u64 UIntMax; 38#endif 39 40/// \brief Largest floating-point type we support. 41typedef long double FloatMax; 42 43/// \brief A description of a source location. This corresponds to Clang's 44/// \c PresumedLoc type. 45class SourceLocation { 46 const char *Filename; 47 u32 Line; 48 u32 Column; 49 50public: 51 SourceLocation() : Filename(), Line(), 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. 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. 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. 69 bool isDisabled() { 70 return Column == ~u32(0); 71 } 72 73 /// \brief Get the presumed filename for the source location. 74 const char *getFilename() const { return Filename; } 75 /// \brief Get the presumed line number. 76 unsigned getLine() const { return Line; } 77 /// \brief Get the column within the presumed line. 78 unsigned getColumn() const { return Column; } 79}; 80 81 82/// \brief A description of a type. 83class 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 96public: 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 111 const char *getTypeName() const { return TypeName; } 112 113 Kind getKind() const { 114 return static_cast<Kind>(TypeKind); 115 } 116 117 bool isIntegerTy() const { return getKind() == TK_Integer; } 118 bool isSignedIntegerTy() const { 119 return isIntegerTy() && (TypeInfo & 1); 120 } 121 bool isUnsignedIntegerTy() const { 122 return isIntegerTy() && !(TypeInfo & 1); 123 } 124 unsigned getIntegerBitWidth() const { 125 CHECK(isIntegerTy()); 126 return 1 << (TypeInfo >> 1); 127 } 128 129 bool isFloatTy() const { return getKind() == TK_Float; } 130 unsigned getFloatBitWidth() const { 131 CHECK(isFloatTy()); 132 return TypeInfo; 133 } 134}; 135 136/// \brief An opaque handle to a value. 137typedef 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). 145class 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? 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? 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 167public: 168 Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {} 169 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? 182 bool isMinusOne() const { 183 return getType().isSignedIntegerTy() && getSIntValue() == -1; 184 } 185 186 /// Is this a negative integer? 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