brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · ee523cf Raw
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