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