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