ubsan_value.h 6.0 KB

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