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