234 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Representation of data which is passed from the compiler-generated calls into10// the ubsan runtime.11//12//===----------------------------------------------------------------------===//13#ifndef UBSAN_VALUE_H14#define UBSAN_VALUE_H15 16#include "sanitizer_common/sanitizer_atomic.h"17#include "sanitizer_common/sanitizer_common.h"18 19// FIXME: Move this out to a config header.20#if __SIZEOF_INT128__21__extension__ typedef __int128 s128;22__extension__ typedef unsigned __int128 u128;23#define HAVE_INT128_T 124#else25#define HAVE_INT128_T 026#endif27 28namespace __ubsan {29 30/// \brief Largest integer types we support.31#if HAVE_INT128_T32typedef s128 SIntMax;33typedef u128 UIntMax;34#else35typedef s64 SIntMax;36typedef u64 UIntMax;37#endif38 39/// \brief Largest floating-point type we support.40typedef long double FloatMax;41 42/// \brief A description of a source location. This corresponds to Clang's43/// \c PresumedLoc type.44class SourceLocation {45 const char *Filename;46 u32 Line;47 u32 Column;48 49public:50 SourceLocation() : Filename(), Line(), Column() {}51 SourceLocation(const char *Filename, unsigned Line, unsigned Column)52 : Filename(Filename), Line(Line), Column(Column) {}53 54 /// \brief Determine whether the source location is known.55 bool isInvalid() const { return !Filename; }56 57 /// \brief Atomically acquire a copy, disabling original in-place.58 /// Exactly one call to acquire() returns a copy that isn't disabled.59 SourceLocation acquire() {60 u32 OldColumn = __sanitizer::atomic_exchange(61 (__sanitizer::atomic_uint32_t *)&Column, ~u32(0),62 __sanitizer::memory_order_relaxed);63 return SourceLocation(Filename, Line, OldColumn);64 }65 66 /// \brief Determine if this Location has been disabled.67 /// Disabled SourceLocations are invalid to use.68 bool isDisabled() {69 return Column == ~u32(0);70 }71 72 /// \brief Get the presumed filename for the source location.73 const char *getFilename() const { return Filename; }74 /// \brief Get the presumed line number.75 unsigned getLine() const { return Line; }76 /// \brief Get the column within the presumed line.77 unsigned getColumn() const { return Column; }78};79 80 81/// \brief A description of a type.82class TypeDescriptor {83 /// A value from the \c Kind enumeration, specifying what flavor of type we84 /// have.85 u16 TypeKind;86 87 /// A \c Type-specific value providing information which allows us to88 /// interpret the meaning of a ValueHandle of this type.89 u16 TypeInfo;90 91 /// The name of the type follows, in a format suitable for including in92 /// diagnostics.93 char TypeName[1];94 95public:96 enum Kind {97 /// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned98 /// value. Remaining bits are log_2(bit width). The value representation is99 /// the integer itself if it fits into a ValueHandle, and a pointer to the100 /// integer otherwise.101 TK_Integer = 0x0000,102 /// A floating-point type. Low 16 bits are bit width. The value103 /// representation is that of bitcasting the floating-point value to an104 /// integer type.105 TK_Float = 0x0001,106 /// An _BitInt(N) type. Lowest bit is 1 for a signed value, 0 for an107 /// unsigned value. Remaining bits are log_2(bit_width). The value108 /// representation is the integer itself if it fits into a ValueHandle, and109 /// a pointer to the integer otherwise. TypeName contains the true width110 /// of the type for the signed _BitInt(N) type stored after zero bit after111 /// TypeName as 32-bit unsigned integer.112 TK_BitInt = 0x0002,113 /// Any other type. The value representation is unspecified.114 TK_Unknown = 0xffff115 };116 117 const char *getTypeName() const { return TypeName; }118 119 Kind getKind() const {120 return static_cast<Kind>(TypeKind);121 }122 123 bool isIntegerTy() const {124 return getKind() == TK_Integer || getKind() == TK_BitInt;125 }126 bool isBitIntTy() const { return getKind() == TK_BitInt; }127 128 bool isSignedIntegerTy() const {129 return isIntegerTy() && (TypeInfo & 1);130 }131 bool isSignedBitIntTy() const { return isBitIntTy() && (TypeInfo & 1); }132 bool isUnsignedIntegerTy() const {133 return isIntegerTy() && !(TypeInfo & 1);134 }135 unsigned getIntegerBitWidth() const {136 CHECK(isIntegerTy());137 return 1 << (TypeInfo >> 1);138 }139 140 const char *getBitIntBitCountPointer() const {141 DCHECK(isBitIntTy());142 DCHECK(isSignedBitIntTy());143 // Scan Name for zero and return the next address144 const char *p = getTypeName();145 while (*p != '\0')146 ++p;147 // Return the next address148 return p + 1;149 }150 151 unsigned getIntegerBitCount() const {152 DCHECK(isIntegerTy());153 if (isSignedBitIntTy()) {154 u32 BitCountValue;155 internal_memcpy(&BitCountValue, getBitIntBitCountPointer(),156 sizeof(BitCountValue));157 return BitCountValue;158 } else159 return getIntegerBitWidth();160 }161 162 bool isFloatTy() const { return getKind() == TK_Float; }163 unsigned getFloatBitWidth() const {164 CHECK(isFloatTy());165 return TypeInfo;166 }167};168 169/// \brief An opaque handle to a value.170typedef uptr ValueHandle;171 172/// Returns the class name of the given ObjC object, or null if the name173/// cannot be found.174const char *getObjCClassName(ValueHandle Pointer);175 176/// \brief Representation of an operand value provided by the instrumented code.177///178/// This is a combination of a TypeDescriptor (which is emitted as constant data179/// as an operand to a handler function) and a ValueHandle (which is passed at180/// runtime when a check failure occurs).181class Value {182 /// The type of the value.183 const TypeDescriptor &Type;184 /// The encoded value itself.185 ValueHandle Val;186 187 /// Is \c Val a (zero-extended) integer?188 bool isInlineInt() const {189 CHECK(getType().isIntegerTy());190 const unsigned InlineBits = sizeof(ValueHandle) * 8;191 const unsigned Bits = getType().getIntegerBitWidth();192 return Bits <= InlineBits;193 }194 195 /// Is \c Val a (zero-extended) integer representation of a float?196 bool isInlineFloat() const {197 CHECK(getType().isFloatTy());198 const unsigned InlineBits = sizeof(ValueHandle) * 8;199 const unsigned Bits = getType().getFloatBitWidth();200 return Bits <= InlineBits;201 }202 203public:204 Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}205 206 const TypeDescriptor &getType() const { return Type; }207 208 /// \brief Get this value as a signed integer.209 SIntMax getSIntValue() const;210 211 /// \brief Get this value as an unsigned integer.212 UIntMax getUIntValue() const;213 214 /// \brief Decode this value, which must be a positive or unsigned integer.215 UIntMax getPositiveIntValue() const;216 217 /// Is this an integer with value -1?218 bool isMinusOne() const {219 return getType().isSignedIntegerTy() && getSIntValue() == -1;220 }221 222 /// Is this a negative integer?223 bool isNegative() const {224 return getType().isSignedIntegerTy() && getSIntValue() < 0;225 }226 227 /// \brief Get this value as a floating-point quantity.228 FloatMax getFloatValue() const;229};230 231} // namespace __ubsan232 233#endif // UBSAN_VALUE_H234