• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SourceLocation()58   SourceLocation() : Filename(), Line(), Column() {}
SourceLocation(const char * Filename,unsigned Line,unsigned 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.
isInvalid()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.
acquire()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.
isDisabled()76   bool isDisabled() {
77     return Column == ~u32(0);
78   }
79 
80   /// \brief Get the presumed filename for the source location.
getFilename()81   const char *getFilename() const { return Filename; }
82   /// \brief Get the presumed line number.
getLine()83   unsigned getLine() const { return Line; }
84   /// \brief Get the column within the presumed line.
getColumn()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 
getTypeName()117   const char *getTypeName() const { return TypeName; }
118 
getKind()119   Kind getKind() const {
120     return static_cast<Kind>(TypeKind);
121   }
122 
isIntegerTy()123   bool isIntegerTy() const { return getKind() == TK_Integer; }
isSignedIntegerTy()124   bool isSignedIntegerTy() const {
125     return isIntegerTy() && (TypeInfo & 1);
126   }
isUnsignedIntegerTy()127   bool isUnsignedIntegerTy() const {
128     return isIntegerTy() && !(TypeInfo & 1);
129   }
getIntegerBitWidth()130   unsigned getIntegerBitWidth() const {
131     CHECK(isIntegerTy());
132     return 1 << (TypeInfo >> 1);
133   }
134 
isFloatTy()135   bool isFloatTy() const { return getKind() == TK_Float; }
getFloatBitWidth()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?
isInlineInt()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:
Value(const TypeDescriptor & Type,ValueHandle Val)166   Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
167 
getType()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?
isMinusOne()180   bool isMinusOne() const {
181     return getType().isSignedIntegerTy() && getSIntValue() == -1;
182   }
183 
184   /// Is this a negative integer?
isNegative()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