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:
SourceLocation()51   SourceLocation() : Filename(), Line(), Column() {}
SourceLocation(const char * Filename,unsigned Line,unsigned 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.
isInvalid()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.
acquire()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.
isDisabled()69   bool isDisabled() {
70     return Column == ~u32(0);
71   }
72 
73   /// \brief Get the presumed filename for the source location.
getFilename()74   const char *getFilename() const { return Filename; }
75   /// \brief Get the presumed line number.
getLine()76   unsigned getLine() const { return Line; }
77   /// \brief Get the column within the presumed line.
getColumn()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 
getTypeName()111   const char *getTypeName() const { return TypeName; }
112 
getKind()113   Kind getKind() const {
114     return static_cast<Kind>(TypeKind);
115   }
116 
isIntegerTy()117   bool isIntegerTy() const { return getKind() == TK_Integer; }
isSignedIntegerTy()118   bool isSignedIntegerTy() const {
119     return isIntegerTy() && (TypeInfo & 1);
120   }
isUnsignedIntegerTy()121   bool isUnsignedIntegerTy() const {
122     return isIntegerTy() && !(TypeInfo & 1);
123   }
getIntegerBitWidth()124   unsigned getIntegerBitWidth() const {
125     CHECK(isIntegerTy());
126     return 1 << (TypeInfo >> 1);
127   }
128 
isFloatTy()129   bool isFloatTy() const { return getKind() == TK_Float; }
getFloatBitWidth()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?
isInlineInt()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?
isInlineFloat()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:
Value(const TypeDescriptor & Type,ValueHandle Val)168   Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
169 
getType()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?
isMinusOne()182   bool isMinusOne() const {
183     return getType().isSignedIntegerTy() && getSIntValue() == -1;
184   }
185 
186   /// Is this a negative integer?
isNegative()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