1 | //===-- ubsan_value.h -------------------------------------------*- C++ -*-===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Representation of data which is passed from the compiler-generated calls into |
10 | // the ubsan runtime. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | #ifndef UBSAN_VALUE_H |
14 | #define UBSAN_VALUE_H |
15 | |
16 | #include "sanitizer_common/sanitizer_atomic.h" |
17 | #include "sanitizer_common/sanitizer_common.h" |
18 | |
19 | // FIXME: Move this out to a config header. |
20 | #if __SIZEOF_INT128__ |
21 | __extension__ typedef __int128 s128; |
22 | __extension__ typedef unsigned __int128 u128; |
23 | #define HAVE_INT128_T 1 |
24 | #else |
25 | #define HAVE_INT128_T 0 |
26 | #endif |
27 | |
28 | namespace __ubsan { |
29 | |
30 | /// \brief Largest integer types we support. |
31 | #if HAVE_INT128_T |
32 | typedef s128 SIntMax; |
33 | typedef u128 UIntMax; |
34 | #else |
35 | typedef s64 SIntMax; |
36 | typedef u64 UIntMax; |
37 | #endif |
38 | |
39 | /// \brief Largest floating-point type we support. |
40 | typedef long double FloatMax; |
41 | |
42 | /// \brief A description of a source location. This corresponds to Clang's |
43 | /// \c PresumedLoc type. |
44 | class SourceLocation { |
45 | const char *Filename; |
46 | u32 Line; |
47 | u32 Column; |
48 | |
49 | public: |
50 | SourceLocation() : Filename(), Line(), Column() {} |
51 | SourceLocation(const char *Filename, unsigned Line, unsigned Column) |
52 | : Filename(Filename), Line(Line), Column(Column) {} |
53 | |
54 | /// \brief Determine whether the source location is known. |
55 | bool isInvalid() const { return !Filename; } |
56 | |
57 | /// \brief Atomically acquire a copy, disabling original in-place. |
58 | /// Exactly one call to acquire() returns a copy that isn't disabled. |
59 | SourceLocation acquire() { |
60 | u32 OldColumn = __sanitizer::atomic_exchange( |
61 | a: (__sanitizer::atomic_uint32_t *)&Column, v: ~u32(0), |
62 | mo: __sanitizer::memory_order_relaxed); |
63 | return SourceLocation(Filename, Line, OldColumn); |
64 | } |
65 | |
66 | /// \brief Determine if this Location has been disabled. |
67 | /// Disabled SourceLocations are invalid to use. |
68 | bool isDisabled() { |
69 | return Column == ~u32(0); |
70 | } |
71 | |
72 | /// \brief Get the presumed filename for the source location. |
73 | const char *getFilename() const { return Filename; } |
74 | /// \brief Get the presumed line number. |
75 | unsigned getLine() const { return Line; } |
76 | /// \brief Get the column within the presumed line. |
77 | unsigned getColumn() const { return Column; } |
78 | }; |
79 | |
80 | |
81 | /// \brief A description of a type. |
82 | class TypeDescriptor { |
83 | /// A value from the \c Kind enumeration, specifying what flavor of type we |
84 | /// have. |
85 | u16 TypeKind; |
86 | |
87 | /// A \c Type-specific value providing information which allows us to |
88 | /// interpret the meaning of a ValueHandle of this type. |
89 | u16 TypeInfo; |
90 | |
91 | /// The name of the type follows, in a format suitable for including in |
92 | /// diagnostics. |
93 | char TypeName[1]; |
94 | |
95 | public: |
96 | enum Kind { |
97 | /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned |
98 | /// value. Remaining bits are log_2(bit width). The value representation is |
99 | /// the integer itself if it fits into a ValueHandle, and a pointer to the |
100 | /// integer otherwise. |
101 | TK_Integer = 0x0000, |
102 | /// A floating-point type. Low 16 bits are bit width. The value |
103 | /// representation is that of bitcasting the floating-point value to an |
104 | /// integer type. |
105 | TK_Float = 0x0001, |
106 | /// An _BitInt(N) type. Lowest bit is 1 for a signed value, 0 for an |
107 | /// unsigned value. Remaining bits are log_2(bit_width). The value |
108 | /// representation is the integer itself if it fits into a ValueHandle, and |
109 | /// a pointer to the integer otherwise. TypeName contains the true width |
110 | /// of the type for the signed _BitInt(N) type stored after zero bit after |
111 | /// TypeName as 32-bit unsigned integer. |
112 | TK_BitInt = 0x0002, |
113 | /// Any other type. The value representation is unspecified. |
114 | TK_Unknown = 0xffff |
115 | }; |
116 | |
117 | const char *getTypeName() const { return TypeName; } |
118 | |
119 | Kind getKind() const { |
120 | return static_cast<Kind>(TypeKind); |
121 | } |
122 | |
123 | bool isIntegerTy() const { |
124 | return getKind() == TK_Integer || getKind() == TK_BitInt; |
125 | } |
126 | bool isBitIntTy() const { return getKind() == TK_BitInt; } |
127 | |
128 | bool isSignedIntegerTy() const { |
129 | return isIntegerTy() && (TypeInfo & 1); |
130 | } |
131 | bool isSignedBitIntTy() const { return isBitIntTy() && (TypeInfo & 1); } |
132 | bool isUnsignedIntegerTy() const { |
133 | return isIntegerTy() && !(TypeInfo & 1); |
134 | } |
135 | unsigned getIntegerBitWidth() const { |
136 | CHECK(isIntegerTy()); |
137 | return 1 << (TypeInfo >> 1); |
138 | } |
139 | |
140 | const char *getBitIntBitCountPointer() const { |
141 | DCHECK(isBitIntTy()); |
142 | DCHECK(isSignedBitIntTy()); |
143 | // Scan Name for zero and return the next address |
144 | const char *p = getTypeName(); |
145 | while (*p != '\0') |
146 | ++p; |
147 | // Return the next address |
148 | return p + 1; |
149 | } |
150 | |
151 | unsigned getIntegerBitCount() const { |
152 | DCHECK(isIntegerTy()); |
153 | if (isSignedBitIntTy()) { |
154 | u32 BitCountValue; |
155 | internal_memcpy(dest: &BitCountValue, src: getBitIntBitCountPointer(), |
156 | n: sizeof(BitCountValue)); |
157 | return BitCountValue; |
158 | } else |
159 | return getIntegerBitWidth(); |
160 | } |
161 | |
162 | bool isFloatTy() const { return getKind() == TK_Float; } |
163 | unsigned getFloatBitWidth() const { |
164 | CHECK(isFloatTy()); |
165 | return TypeInfo; |
166 | } |
167 | }; |
168 | |
169 | /// \brief An opaque handle to a value. |
170 | typedef uptr ValueHandle; |
171 | |
172 | /// Returns the class name of the given ObjC object, or null if the name |
173 | /// cannot be found. |
174 | const char *getObjCClassName(ValueHandle Pointer); |
175 | |
176 | /// \brief Representation of an operand value provided by the instrumented code. |
177 | /// |
178 | /// This is a combination of a TypeDescriptor (which is emitted as constant data |
179 | /// as an operand to a handler function) and a ValueHandle (which is passed at |
180 | /// runtime when a check failure occurs). |
181 | class Value { |
182 | /// The type of the value. |
183 | const TypeDescriptor &Type; |
184 | /// The encoded value itself. |
185 | ValueHandle Val; |
186 | |
187 | /// Is \c Val a (zero-extended) integer? |
188 | bool isInlineInt() const { |
189 | CHECK(getType().isIntegerTy()); |
190 | const unsigned InlineBits = sizeof(ValueHandle) * 8; |
191 | const unsigned Bits = getType().getIntegerBitWidth(); |
192 | return Bits <= InlineBits; |
193 | } |
194 | |
195 | /// Is \c Val a (zero-extended) integer representation of a float? |
196 | bool isInlineFloat() const { |
197 | CHECK(getType().isFloatTy()); |
198 | const unsigned InlineBits = sizeof(ValueHandle) * 8; |
199 | const unsigned Bits = getType().getFloatBitWidth(); |
200 | return Bits <= InlineBits; |
201 | } |
202 | |
203 | public: |
204 | Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {} |
205 | |
206 | const TypeDescriptor &getType() const { return Type; } |
207 | |
208 | /// \brief Get this value as a signed integer. |
209 | SIntMax getSIntValue() const; |
210 | |
211 | /// \brief Get this value as an unsigned integer. |
212 | UIntMax getUIntValue() const; |
213 | |
214 | /// \brief Decode this value, which must be a positive or unsigned integer. |
215 | UIntMax getPositiveIntValue() const; |
216 | |
217 | /// Is this an integer with value -1? |
218 | bool isMinusOne() const { |
219 | return getType().isSignedIntegerTy() && getSIntValue() == -1; |
220 | } |
221 | |
222 | /// Is this a negative integer? |
223 | bool isNegative() const { |
224 | return getType().isSignedIntegerTy() && getSIntValue() < 0; |
225 | } |
226 | |
227 | /// \brief Get this value as a floating-point quantity. |
228 | FloatMax getFloatValue() const; |
229 | }; |
230 | |
231 | } // namespace __ubsan |
232 | |
233 | #endif // UBSAN_VALUE_H |
234 |
Definitions
- SourceLocation
- SourceLocation
- SourceLocation
- isInvalid
- acquire
- isDisabled
- getFilename
- getLine
- getColumn
- TypeDescriptor
- Kind
- getTypeName
- getKind
- isIntegerTy
- isBitIntTy
- isSignedIntegerTy
- isSignedBitIntTy
- isUnsignedIntegerTy
- getIntegerBitWidth
- getBitIntBitCountPointer
- getIntegerBitCount
- isFloatTy
- getFloatBitWidth
- Value
- isInlineInt
- isInlineFloat
- Value
- getType
- isMinusOne
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more