llvm-project

Форк
0
/
ubsan_value.cpp 
158 строк · 5.1 Кб
1
//===-- ubsan_value.cpp ---------------------------------------------------===//
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 a runtime value, as marshaled from the generated code to
10
// the ubsan runtime.
11
//
12
//===----------------------------------------------------------------------===//
13

14
#include "ubsan_platform.h"
15
#if CAN_SANITIZE_UB
16
#include "ubsan_value.h"
17
#include "sanitizer_common/sanitizer_common.h"
18
#include "sanitizer_common/sanitizer_libc.h"
19
#include "sanitizer_common/sanitizer_mutex.h"
20

21
#if SANITIZER_APPLE
22
#include <dlfcn.h>
23
#endif
24

25
using namespace __ubsan;
26

27
typedef const char *(*ObjCGetClassNameTy)(void *);
28

29
const char *__ubsan::getObjCClassName(ValueHandle Pointer) {
30
#if SANITIZER_APPLE
31
  // We need to query the ObjC runtime for some information, but do not want
32
  // to introduce a static dependency from the ubsan runtime onto ObjC. Try to
33
  // grab a handle to the ObjC runtime used by the process.
34
  static bool AttemptedDlopen = false;
35
  static void *ObjCHandle = nullptr;
36
  static void *ObjCObjectGetClassName = nullptr;
37

38
  // Prevent threads from racing to dlopen().
39
  static __sanitizer::StaticSpinMutex Lock;
40
  {
41
    __sanitizer::SpinMutexLock Guard(&Lock);
42

43
    if (!AttemptedDlopen) {
44
      ObjCHandle = dlopen(
45
          "/usr/lib/libobjc.A.dylib",
46
          RTLD_LAZY         // Only bind symbols when used.
47
              | RTLD_LOCAL  // Only make symbols available via the handle.
48
              | RTLD_NOLOAD // Do not load the dylib, just grab a handle if the
49
                            // image is already loaded.
50
              | RTLD_FIRST  // Only search the image pointed-to by the handle.
51
      );
52
      AttemptedDlopen = true;
53
      if (!ObjCHandle)
54
        return nullptr;
55
      ObjCObjectGetClassName = dlsym(ObjCHandle, "object_getClassName");
56
    }
57
  }
58

59
  if (!ObjCObjectGetClassName)
60
    return nullptr;
61

62
  return ObjCGetClassNameTy(ObjCObjectGetClassName)((void *)Pointer);
63
#else
64
  return nullptr;
65
#endif
66
}
67

68
SIntMax Value::getSIntValue() const {
69
  CHECK(getType().isSignedIntegerTy());
70
  if (isInlineInt()) {
71
    // Val was zero-extended to ValueHandle. Sign-extend from original width
72
    // to SIntMax.
73
    const unsigned ExtraBits =
74
      sizeof(SIntMax) * 8 - getType().getIntegerBitWidth();
75
    return SIntMax(UIntMax(Val) << ExtraBits) >> ExtraBits;
76
  }
77
  if (getType().getIntegerBitWidth() == 64)
78
    return *reinterpret_cast<s64*>(Val);
79
#if HAVE_INT128_T
80
  if (getType().getIntegerBitWidth() == 128)
81
    return *reinterpret_cast<s128*>(Val);
82
#else
83
  if (getType().getIntegerBitWidth() == 128)
84
    UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
85
#endif
86
  UNREACHABLE("unexpected bit width");
87
}
88

89
UIntMax Value::getUIntValue() const {
90
  CHECK(getType().isUnsignedIntegerTy());
91
  if (isInlineInt())
92
    return Val;
93
  if (getType().getIntegerBitWidth() == 64)
94
    return *reinterpret_cast<u64*>(Val);
95
#if HAVE_INT128_T
96
  if (getType().getIntegerBitWidth() == 128)
97
    return *reinterpret_cast<u128*>(Val);
98
#else
99
  if (getType().getIntegerBitWidth() == 128)
100
    UNREACHABLE("libclang_rt.ubsan was built without __int128 support");
101
#endif
102
  UNREACHABLE("unexpected bit width");
103
}
104

105
UIntMax Value::getPositiveIntValue() const {
106
  if (getType().isUnsignedIntegerTy())
107
    return getUIntValue();
108
  SIntMax Val = getSIntValue();
109
  CHECK(Val >= 0);
110
  return Val;
111
}
112

113
/// Get the floating-point value of this object, extended to a long double.
114
/// These are always passed by address (our calling convention doesn't allow
115
/// them to be passed in floating-point registers, so this has little cost).
116
FloatMax Value::getFloatValue() const {
117
  CHECK(getType().isFloatTy());
118
  if (isInlineFloat()) {
119
    switch (getType().getFloatBitWidth()) {
120
#if 0
121
      // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion
122
      //        from '__fp16' to 'long double'.
123
      case 16: {
124
        __fp16 Value;
125
        internal_memcpy(&Value, &Val, 4);
126
        return Value;
127
      }
128
#endif
129
      case 32: {
130
        float Value;
131
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
132
       // For big endian the float value is in the last 4 bytes.
133
       // On some targets we may only have 4 bytes so we count backwards from
134
       // the end of Val to account for both the 32-bit and 64-bit cases.
135
       internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4);
136
#else
137
       internal_memcpy(&Value, &Val, 4);
138
#endif
139
        return Value;
140
      }
141
      case 64: {
142
        double Value;
143
        internal_memcpy(&Value, &Val, 8);
144
        return Value;
145
      }
146
    }
147
  } else {
148
    switch (getType().getFloatBitWidth()) {
149
    case 64: return *reinterpret_cast<double*>(Val);
150
    case 80: return *reinterpret_cast<long double*>(Val);
151
    case 96: return *reinterpret_cast<long double*>(Val);
152
    case 128: return *reinterpret_cast<long double*>(Val);
153
    }
154
  }
155
  UNREACHABLE("unexpected floating point bit width");
156
}
157

158
#endif  // CAN_SANITIZE_UB
159

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.