2013-08-30 18:12:58 +02:00
|
|
|
//===-- ubsan_value.h -------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
2019-08-14 10:47:11 +02:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-08-30 18:12:58 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Representation of data which is passed from the compiler-generated calls into
|
|
|
|
// the ubsan runtime.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef UBSAN_VALUE_H
|
|
|
|
#define UBSAN_VALUE_H
|
|
|
|
|
|
|
|
#include "sanitizer_common/sanitizer_atomic.h"
|
|
|
|
#include "sanitizer_common/sanitizer_common.h"
|
|
|
|
|
|
|
|
// FIXME: Move this out to a config header.
|
|
|
|
#if __SIZEOF_INT128__
|
2013-12-05 10:18:38 +01:00
|
|
|
__extension__ typedef __int128 s128;
|
|
|
|
__extension__ typedef unsigned __int128 u128;
|
2013-08-30 18:12:58 +02:00
|
|
|
#define HAVE_INT128_T 1
|
|
|
|
#else
|
|
|
|
#define HAVE_INT128_T 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace __ubsan {
|
|
|
|
|
|
|
|
/// \brief Largest integer types we support.
|
|
|
|
#if HAVE_INT128_T
|
|
|
|
typedef s128 SIntMax;
|
|
|
|
typedef u128 UIntMax;
|
|
|
|
#else
|
|
|
|
typedef s64 SIntMax;
|
|
|
|
typedef u64 UIntMax;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/// \brief Largest floating-point type we support.
|
|
|
|
typedef long double FloatMax;
|
|
|
|
|
|
|
|
/// \brief A description of a source location. This corresponds to Clang's
|
|
|
|
/// \c PresumedLoc type.
|
|
|
|
class SourceLocation {
|
|
|
|
const char *Filename;
|
|
|
|
u32 Line;
|
|
|
|
u32 Column;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SourceLocation() : Filename(), Line(), Column() {}
|
|
|
|
SourceLocation(const char *Filename, unsigned Line, unsigned Column)
|
|
|
|
: Filename(Filename), Line(Line), Column(Column) {}
|
|
|
|
|
|
|
|
/// \brief Determine whether the source location is known.
|
|
|
|
bool isInvalid() const { return !Filename; }
|
|
|
|
|
|
|
|
/// \brief Atomically acquire a copy, disabling original in-place.
|
|
|
|
/// Exactly one call to acquire() returns a copy that isn't disabled.
|
|
|
|
SourceLocation acquire() {
|
|
|
|
u32 OldColumn = __sanitizer::atomic_exchange(
|
|
|
|
(__sanitizer::atomic_uint32_t *)&Column, ~u32(0),
|
|
|
|
__sanitizer::memory_order_relaxed);
|
|
|
|
return SourceLocation(Filename, Line, OldColumn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Determine if this Location has been disabled.
|
|
|
|
/// Disabled SourceLocations are invalid to use.
|
|
|
|
bool isDisabled() {
|
|
|
|
return Column == ~u32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get the presumed filename for the source location.
|
|
|
|
const char *getFilename() const { return Filename; }
|
|
|
|
/// \brief Get the presumed line number.
|
|
|
|
unsigned getLine() const { return Line; }
|
|
|
|
/// \brief Get the column within the presumed line.
|
|
|
|
unsigned getColumn() const { return Column; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// \brief A description of a type.
|
|
|
|
class TypeDescriptor {
|
|
|
|
/// A value from the \c Kind enumeration, specifying what flavor of type we
|
|
|
|
/// have.
|
|
|
|
u16 TypeKind;
|
|
|
|
|
|
|
|
/// A \c Type-specific value providing information which allows us to
|
|
|
|
/// interpret the meaning of a ValueHandle of this type.
|
|
|
|
u16 TypeInfo;
|
|
|
|
|
|
|
|
/// The name of the type follows, in a format suitable for including in
|
|
|
|
/// diagnostics.
|
|
|
|
char TypeName[1];
|
|
|
|
|
|
|
|
public:
|
|
|
|
enum Kind {
|
|
|
|
/// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
|
|
|
|
/// value. Remaining bits are log_2(bit width). The value representation is
|
|
|
|
/// the integer itself if it fits into a ValueHandle, and a pointer to the
|
|
|
|
/// integer otherwise.
|
|
|
|
TK_Integer = 0x0000,
|
|
|
|
/// A floating-point type. Low 16 bits are bit width. The value
|
|
|
|
/// representation is that of bitcasting the floating-point value to an
|
|
|
|
/// integer type.
|
|
|
|
TK_Float = 0x0001,
|
|
|
|
/// Any other type. The value representation is unspecified.
|
|
|
|
TK_Unknown = 0xffff
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *getTypeName() const { return TypeName; }
|
|
|
|
|
|
|
|
Kind getKind() const {
|
|
|
|
return static_cast<Kind>(TypeKind);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isIntegerTy() const { return getKind() == TK_Integer; }
|
|
|
|
bool isSignedIntegerTy() const {
|
|
|
|
return isIntegerTy() && (TypeInfo & 1);
|
|
|
|
}
|
|
|
|
bool isUnsignedIntegerTy() const {
|
|
|
|
return isIntegerTy() && !(TypeInfo & 1);
|
|
|
|
}
|
|
|
|
unsigned getIntegerBitWidth() const {
|
|
|
|
CHECK(isIntegerTy());
|
|
|
|
return 1 << (TypeInfo >> 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isFloatTy() const { return getKind() == TK_Float; }
|
|
|
|
unsigned getFloatBitWidth() const {
|
|
|
|
CHECK(isFloatTy());
|
|
|
|
return TypeInfo;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief An opaque handle to a value.
|
|
|
|
typedef uptr ValueHandle;
|
|
|
|
|
2020-10-16 10:03:04 +02:00
|
|
|
/// Returns the class name of the given ObjC object, or null if the name
|
|
|
|
/// cannot be found.
|
|
|
|
const char *getObjCClassName(ValueHandle Pointer);
|
2013-08-30 18:12:58 +02:00
|
|
|
|
|
|
|
/// \brief Representation of an operand value provided by the instrumented code.
|
|
|
|
///
|
|
|
|
/// This is a combination of a TypeDescriptor (which is emitted as constant data
|
|
|
|
/// as an operand to a handler function) and a ValueHandle (which is passed at
|
|
|
|
/// runtime when a check failure occurs).
|
|
|
|
class Value {
|
|
|
|
/// The type of the value.
|
|
|
|
const TypeDescriptor &Type;
|
|
|
|
/// The encoded value itself.
|
|
|
|
ValueHandle Val;
|
|
|
|
|
|
|
|
/// Is \c Val a (zero-extended) integer?
|
|
|
|
bool isInlineInt() const {
|
|
|
|
CHECK(getType().isIntegerTy());
|
|
|
|
const unsigned InlineBits = sizeof(ValueHandle) * 8;
|
|
|
|
const unsigned Bits = getType().getIntegerBitWidth();
|
|
|
|
return Bits <= InlineBits;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Is \c Val a (zero-extended) integer representation of a float?
|
|
|
|
bool isInlineFloat() const {
|
|
|
|
CHECK(getType().isFloatTy());
|
|
|
|
const unsigned InlineBits = sizeof(ValueHandle) * 8;
|
|
|
|
const unsigned Bits = getType().getFloatBitWidth();
|
|
|
|
return Bits <= InlineBits;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
Value(const TypeDescriptor &Type, ValueHandle Val) : Type(Type), Val(Val) {}
|
|
|
|
|
|
|
|
const TypeDescriptor &getType() const { return Type; }
|
|
|
|
|
|
|
|
/// \brief Get this value as a signed integer.
|
|
|
|
SIntMax getSIntValue() const;
|
|
|
|
|
|
|
|
/// \brief Get this value as an unsigned integer.
|
|
|
|
UIntMax getUIntValue() const;
|
|
|
|
|
|
|
|
/// \brief Decode this value, which must be a positive or unsigned integer.
|
|
|
|
UIntMax getPositiveIntValue() const;
|
|
|
|
|
|
|
|
/// Is this an integer with value -1?
|
|
|
|
bool isMinusOne() const {
|
|
|
|
return getType().isSignedIntegerTy() && getSIntValue() == -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Is this a negative integer?
|
|
|
|
bool isNegative() const {
|
|
|
|
return getType().isSignedIntegerTy() && getSIntValue() < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get this value as a floating-point quantity.
|
|
|
|
FloatMax getFloatValue() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace __ubsan
|
|
|
|
|
|
|
|
#endif // UBSAN_VALUE_H
|