annotate libsanitizer/ubsan/ubsan_value.h @ 138:fc828634a951

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