Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/ubsan/ubsan_value.cpp
35233 views
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
160