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 that of bitcasting the floating-point value to an
    112     /// integer type.
    113     TK_Float = 0x0001,
    114     /// Any other type. The value representation is unspecified.
    115     TK_Unknown = 0xffff
    116   };
    117 
    118   const char *getTypeName() const { return TypeName; }
    119 
    120   Kind getKind() const {
    121     return static_cast<Kind>(TypeKind);
    122   }
    123 
    124   bool isIntegerTy() const { return getKind() == TK_Integer; }
    125   bool isSignedIntegerTy() const {
    126     return isIntegerTy() && (TypeInfo & 1);
    127   }
    128   bool isUnsignedIntegerTy() const {
    129     return isIntegerTy() && !(TypeInfo & 1);
    130   }
    131   unsigned getIntegerBitWidth() const {
    132     CHECK(isIntegerTy());
    133     return 1 << (TypeInfo >> 1);
    134   }
    135 
    136   bool isFloatTy() const { return getKind() == TK_Float; }
    137   unsigned getFloatBitWidth() const {
    138     CHECK(isFloatTy());
    139     return TypeInfo;
    140   }
    141 };
    142 
    143 /// \brief An opaque handle to a value.
    144 typedef uptr ValueHandle;
    145 
    146 
    147 /// \brief Representation of an operand value provided by the instrumented code.
    148 ///
    149 /// This is a combination of a TypeDescriptor (which is emitted as constant data
    150 /// as an operand to a handler function) and a ValueHandle (which is passed at
    151 /// runtime when a check failure occurs).
    152 class Value {
    153   /// The type of the value.
    154   const TypeDescriptor &Type;
    155   /// The encoded value itself.
    156   ValueHandle Val;
    157 
    158   /// Is \c Val a (zero-extended) integer?
    159   bool isInlineInt() const {
    160     CHECK(getType().isIntegerTy());
    161     const unsigned InlineBits = sizeof(ValueHandle) * 8;
    162     const unsigned Bits = getType().getIntegerBitWidth();
    163     return Bits <= InlineBits;
    164   }
    165 
    166   /// Is \c Val a (zero-extended) integer representation of a float?
    167   bool isInlineFloat() const {
    168     CHECK(getType().isFloatTy());
    169     const unsigned InlineBits = sizeof(ValueHandle) * 8;
    170     const unsigned Bits = getType().getFloatBitWidth();
    171     return Bits <= InlineBits;
    172   }
    173 
    174 public:
    175   Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
    176 
    177   const TypeDescriptor &getType() const { return Type; }
    178 
    179   /// \brief Get this value as a signed integer.
    180   SIntMax getSIntValue() const;
    181 
    182   /// \brief Get this value as an unsigned integer.
    183   UIntMax getUIntValue() const;
    184 
    185   /// \brief Decode this value, which must be a positive or unsigned integer.
    186   UIntMax getPositiveIntValue() const;
    187 
    188   /// Is this an integer with value -1?
    189   bool isMinusOne() const {
    190     return getType().isSignedIntegerTy() && getSIntValue() == -1;
    191   }
    192 
    193   /// Is this a negative integer?
    194   bool isNegative() const {
    195     return getType().isSignedIntegerTy() && getSIntValue() < 0;
    196   }
    197 
    198   /// \brief Get this value as a floating-point quantity.
    199   FloatMax getFloatValue() const;
    200 };
    201 
    202 } // namespace __ubsan
    203 
    204 #endif // UBSAN_VALUE_H
    205