146ba9697SNico Weber //===-- ubsan_value.cpp ---------------------------------------------------===// 246ba9697SNico Weber // 346ba9697SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 446ba9697SNico Weber // See https://llvm.org/LICENSE.txt for license information. 546ba9697SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 646ba9697SNico Weber // 746ba9697SNico Weber //===----------------------------------------------------------------------===// 846ba9697SNico Weber // 946ba9697SNico Weber // Representation of a runtime value, as marshaled from the generated code to 1046ba9697SNico Weber // the ubsan runtime. 1146ba9697SNico Weber // 1246ba9697SNico Weber //===----------------------------------------------------------------------===// 1346ba9697SNico Weber 1446ba9697SNico Weber #include "ubsan_platform.h" 1546ba9697SNico Weber #if CAN_SANITIZE_UB 1646ba9697SNico Weber #include "ubsan_value.h" 1746ba9697SNico Weber #include "sanitizer_common/sanitizer_common.h" 1846ba9697SNico Weber #include "sanitizer_common/sanitizer_libc.h" 198c4a65b9SVedant Kumar #include "sanitizer_common/sanitizer_mutex.h" 208c4a65b9SVedant Kumar 2132a425ecSJulian Lettner #if SANITIZER_APPLE 228c4a65b9SVedant Kumar #include <dlfcn.h> 238c4a65b9SVedant Kumar #endif 2446ba9697SNico Weber 2546ba9697SNico Weber using namespace __ubsan; 2646ba9697SNico Weber 278c4a65b9SVedant Kumar typedef const char *(*ObjCGetClassNameTy)(void *); 288c4a65b9SVedant Kumar 298c4a65b9SVedant Kumar const char *__ubsan::getObjCClassName(ValueHandle Pointer) { 3032a425ecSJulian Lettner #if SANITIZER_APPLE 318c4a65b9SVedant Kumar // We need to query the ObjC runtime for some information, but do not want 328c4a65b9SVedant Kumar // to introduce a static dependency from the ubsan runtime onto ObjC. Try to 338c4a65b9SVedant Kumar // grab a handle to the ObjC runtime used by the process. 348c4a65b9SVedant Kumar static bool AttemptedDlopen = false; 358c4a65b9SVedant Kumar static void *ObjCHandle = nullptr; 368c4a65b9SVedant Kumar static void *ObjCObjectGetClassName = nullptr; 378c4a65b9SVedant Kumar 388c4a65b9SVedant Kumar // Prevent threads from racing to dlopen(). 398c4a65b9SVedant Kumar static __sanitizer::StaticSpinMutex Lock; 408c4a65b9SVedant Kumar { 418c4a65b9SVedant Kumar __sanitizer::SpinMutexLock Guard(&Lock); 428c4a65b9SVedant Kumar 438c4a65b9SVedant Kumar if (!AttemptedDlopen) { 448c4a65b9SVedant Kumar ObjCHandle = dlopen( 458c4a65b9SVedant Kumar "/usr/lib/libobjc.A.dylib", 468c4a65b9SVedant Kumar RTLD_LAZY // Only bind symbols when used. 478c4a65b9SVedant Kumar | RTLD_LOCAL // Only make symbols available via the handle. 488c4a65b9SVedant Kumar | RTLD_NOLOAD // Do not load the dylib, just grab a handle if the 498c4a65b9SVedant Kumar // image is already loaded. 508c4a65b9SVedant Kumar | RTLD_FIRST // Only search the image pointed-to by the handle. 518c4a65b9SVedant Kumar ); 528c4a65b9SVedant Kumar AttemptedDlopen = true; 538c4a65b9SVedant Kumar if (!ObjCHandle) 548c4a65b9SVedant Kumar return nullptr; 558c4a65b9SVedant Kumar ObjCObjectGetClassName = dlsym(ObjCHandle, "object_getClassName"); 568c4a65b9SVedant Kumar } 578c4a65b9SVedant Kumar } 588c4a65b9SVedant Kumar 598c4a65b9SVedant Kumar if (!ObjCObjectGetClassName) 608c4a65b9SVedant Kumar return nullptr; 618c4a65b9SVedant Kumar 628c4a65b9SVedant Kumar return ObjCGetClassNameTy(ObjCObjectGetClassName)((void *)Pointer); 638c4a65b9SVedant Kumar #else 648c4a65b9SVedant Kumar return nullptr; 658c4a65b9SVedant Kumar #endif 668c4a65b9SVedant Kumar } 678c4a65b9SVedant Kumar 6846ba9697SNico Weber SIntMax Value::getSIntValue() const { 6946ba9697SNico Weber CHECK(getType().isSignedIntegerTy()); 7046ba9697SNico Weber // Val was zero-extended to ValueHandle. Sign-extend from original width 7146ba9697SNico Weber // to SIntMax. 7246ba9697SNico Weber const unsigned ExtraBits = 73*75cb7de4Searnol sizeof(SIntMax) * 8 - getType().getIntegerBitCount(); 74*75cb7de4Searnol if (isInlineInt()) { 7516ede095SMartin Liska return SIntMax(UIntMax(Val) << ExtraBits) >> ExtraBits; 7646ba9697SNico Weber } 77*75cb7de4Searnol if (getType().getIntegerBitWidth() == 64) { 78*75cb7de4Searnol return SIntMax(UIntMax(*reinterpret_cast<s64 *>(Val)) << ExtraBits) >> 79*75cb7de4Searnol ExtraBits; 80*75cb7de4Searnol } 8146ba9697SNico Weber #if HAVE_INT128_T 8246ba9697SNico Weber if (getType().getIntegerBitWidth() == 128) 83*75cb7de4Searnol return SIntMax(UIntMax(*reinterpret_cast<s128 *>(Val)) << ExtraBits) >> 84*75cb7de4Searnol ExtraBits; 8546ba9697SNico Weber #else 8646ba9697SNico Weber if (getType().getIntegerBitWidth() == 128) 8746ba9697SNico Weber UNREACHABLE("libclang_rt.ubsan was built without __int128 support"); 8846ba9697SNico Weber #endif 8946ba9697SNico Weber UNREACHABLE("unexpected bit width"); 9046ba9697SNico Weber } 9146ba9697SNico Weber 9246ba9697SNico Weber UIntMax Value::getUIntValue() const { 9346ba9697SNico Weber CHECK(getType().isUnsignedIntegerTy()); 9446ba9697SNico Weber if (isInlineInt()) 9546ba9697SNico Weber return Val; 9646ba9697SNico Weber if (getType().getIntegerBitWidth() == 64) 9746ba9697SNico Weber return *reinterpret_cast<u64*>(Val); 9846ba9697SNico Weber #if HAVE_INT128_T 9946ba9697SNico Weber if (getType().getIntegerBitWidth() == 128) 10046ba9697SNico Weber return *reinterpret_cast<u128*>(Val); 10146ba9697SNico Weber #else 10246ba9697SNico Weber if (getType().getIntegerBitWidth() == 128) 10346ba9697SNico Weber UNREACHABLE("libclang_rt.ubsan was built without __int128 support"); 10446ba9697SNico Weber #endif 10546ba9697SNico Weber UNREACHABLE("unexpected bit width"); 10646ba9697SNico Weber } 10746ba9697SNico Weber 10846ba9697SNico Weber UIntMax Value::getPositiveIntValue() const { 10946ba9697SNico Weber if (getType().isUnsignedIntegerTy()) 11046ba9697SNico Weber return getUIntValue(); 11146ba9697SNico Weber SIntMax Val = getSIntValue(); 11246ba9697SNico Weber CHECK(Val >= 0); 11346ba9697SNico Weber return Val; 11446ba9697SNico Weber } 11546ba9697SNico Weber 11646ba9697SNico Weber /// Get the floating-point value of this object, extended to a long double. 11746ba9697SNico Weber /// These are always passed by address (our calling convention doesn't allow 11846ba9697SNico Weber /// them to be passed in floating-point registers, so this has little cost). 11946ba9697SNico Weber FloatMax Value::getFloatValue() const { 12046ba9697SNico Weber CHECK(getType().isFloatTy()); 12146ba9697SNico Weber if (isInlineFloat()) { 12246ba9697SNico Weber switch (getType().getFloatBitWidth()) { 12346ba9697SNico Weber #if 0 12446ba9697SNico Weber // FIXME: OpenCL / NEON 'half' type. LLVM can't lower the conversion 12546ba9697SNico Weber // from '__fp16' to 'long double'. 12646ba9697SNico Weber case 16: { 12746ba9697SNico Weber __fp16 Value; 12846ba9697SNico Weber internal_memcpy(&Value, &Val, 4); 12946ba9697SNico Weber return Value; 13046ba9697SNico Weber } 13146ba9697SNico Weber #endif 13246ba9697SNico Weber case 32: { 13346ba9697SNico Weber float Value; 13446ba9697SNico Weber #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 13546ba9697SNico Weber // For big endian the float value is in the last 4 bytes. 13646ba9697SNico Weber // On some targets we may only have 4 bytes so we count backwards from 13746ba9697SNico Weber // the end of Val to account for both the 32-bit and 64-bit cases. 13846ba9697SNico Weber internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4); 13946ba9697SNico Weber #else 14046ba9697SNico Weber internal_memcpy(&Value, &Val, 4); 14146ba9697SNico Weber #endif 14246ba9697SNico Weber return Value; 14346ba9697SNico Weber } 14446ba9697SNico Weber case 64: { 14546ba9697SNico Weber double Value; 14646ba9697SNico Weber internal_memcpy(&Value, &Val, 8); 14746ba9697SNico Weber return Value; 14846ba9697SNico Weber } 14946ba9697SNico Weber } 15046ba9697SNico Weber } else { 15146ba9697SNico Weber switch (getType().getFloatBitWidth()) { 15246ba9697SNico Weber case 64: return *reinterpret_cast<double*>(Val); 15346ba9697SNico Weber case 80: return *reinterpret_cast<long double*>(Val); 15446ba9697SNico Weber case 96: return *reinterpret_cast<long double*>(Val); 15546ba9697SNico Weber case 128: return *reinterpret_cast<long double*>(Val); 15646ba9697SNico Weber } 15746ba9697SNico Weber } 15846ba9697SNico Weber UNREACHABLE("unexpected floating point bit width"); 15946ba9697SNico Weber } 16046ba9697SNico Weber 16146ba9697SNico Weber #endif // CAN_SANITIZE_UB 162