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