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__)
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
34namespace __ubsan {
35
36/// \brief Largest integer types we support.
37#if HAVE_INT128_T
38typedef s128 SIntMax;
39typedef u128 UIntMax;
40#else
41typedef s64 SIntMax;
42typedef u64 UIntMax;
43#endif
44
45/// \brief Largest floating-point type we support.
46typedef long double FloatMax;
47
48/// \brief A description of a source location. This corresponds to Clang's
49/// \c PresumedLoc type.
50class SourceLocation {
51  const char *Filename;
52  u32 Line;
53  u32 Column;
54
55public:
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.
88class 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
101public:
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.
142typedef 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).
150class 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
172public:
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