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
28namespace __ubsan {
29
30/// \brief Largest integer types we support.
31#if HAVE_INT128_T
32typedef s128 SIntMax;
33typedef u128 UIntMax;
34#else
35typedef s64 SIntMax;
36typedef u64 UIntMax;
37#endif
38
39/// \brief Largest floating-point type we support.
40typedef long double FloatMax;
41
42/// \brief A description of a source location. This corresponds to Clang's
43/// \c PresumedLoc type.
44class SourceLocation {
45 const char *Filename;
46 u32 Line;
47 u32 Column;
48
49public:
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.
82class 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
95public:
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.
170typedef uptr ValueHandle;
171
172/// Returns the class name of the given ObjC object, or null if the name
173/// cannot be found.
174const 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).
181class 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
203public:
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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of compiler-rt/lib/ubsan/ubsan_value.h