ubsan_value.h 6.1 KB

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