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