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