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