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