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