Home | History | Annotate | Download | only in ubsan
      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 
     29 namespace __ubsan {
     30 
     31 /// \brief Largest integer types we support.
     32 #if HAVE_INT128_T
     33 typedef s128 SIntMax;
     34 typedef u128 UIntMax;
     35 #else
     36 typedef s64 SIntMax;
     37 typedef u64 UIntMax;
     38 #endif
     39 
     40 /// \brief Largest floating-point type we support.
     41 typedef long double FloatMax;
     42 
     43 /// \brief A description of a source location. This corresponds to Clang's
     44 /// \c PresumedLoc type.
     45 class SourceLocation {
     46   const char *Filename;
     47   u32 Line;
     48   u32 Column;
     49 
     50 public:
     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.
     83 class 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 
     96 public:
     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.
    137 typedef 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).
    145 class 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 
    167 public:
    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