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