diff --git a/ChangeLog.md b/ChangeLog.md index 493ac0b5be56b..fdb9284ba54bc 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,7 @@ See docs/process.md for more on how version tagging works. 4.0.24 (in development) ----------------------- +- compiler-rt was updated to LLVM 21.1.8. (#26405) 4.0.23 - 01/10/26 ----------------- diff --git a/system/lib/compiler-rt/lib/asan/asan_activation.cpp b/system/lib/compiler-rt/lib/asan/asan_activation.cpp index 1757838600ca6..5796a7cb06eff 100644 --- a/system/lib/compiler-rt/lib/asan/asan_activation.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_activation.cpp @@ -58,7 +58,7 @@ static struct AsanDeactivatedFlags { cf.verbosity = Verbosity(); cf.help = false; // this is activation-specific help - // Check if activation flags need to be overriden. + // Check if activation flags need to be overridden. if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) { parser.ParseString(env); } diff --git a/system/lib/compiler-rt/lib/asan/asan_allocator.cpp b/system/lib/compiler-rt/lib/asan/asan_allocator.cpp index 3a55c2af65653..d3c0288285b86 100644 --- a/system/lib/compiler-rt/lib/asan/asan_allocator.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_allocator.cpp @@ -424,10 +424,15 @@ struct Allocator { PoisonShadow(chunk, allocated_size, kAsanHeapLeftRedzoneMagic); } - void ReInitialize(const AllocatorOptions &options) { + // Apply provided AllocatorOptions to an Allocator + void ApplyOptions(const AllocatorOptions &options) { SetAllocatorMayReturnNull(options.may_return_null); allocator.SetReleaseToOSIntervalMs(options.release_to_os_interval_ms); SharedInitCode(options); + } + + void ReInitialize(const AllocatorOptions &options) { + ApplyOptions(options); // Poison all existing allocation's redzones. if (CanPoisonMemory()) { @@ -977,6 +982,11 @@ void ReInitializeAllocator(const AllocatorOptions &options) { instance.ReInitialize(options); } +// Apply provided AllocatorOptions to an Allocator +void ApplyAllocatorOptions(const AllocatorOptions &options) { + instance.ApplyOptions(options); +} + void GetAllocatorOptions(AllocatorOptions *options) { instance.GetOptions(options); } diff --git a/system/lib/compiler-rt/lib/asan/asan_allocator.h b/system/lib/compiler-rt/lib/asan/asan_allocator.h index db8dc3bebfc62..247d8bb77c984 100644 --- a/system/lib/compiler-rt/lib/asan/asan_allocator.h +++ b/system/lib/compiler-rt/lib/asan/asan_allocator.h @@ -47,6 +47,7 @@ struct AllocatorOptions { void InitializeAllocator(const AllocatorOptions &options); void ReInitializeAllocator(const AllocatorOptions &options); void GetAllocatorOptions(AllocatorOptions *options); +void ApplyAllocatorOptions(const AllocatorOptions &options); class AsanChunkView { public: @@ -238,7 +239,7 @@ using PrimaryAllocator = PrimaryAllocatorASVT; typedef CompactSizeClassMap SizeClassMap; template struct AP32 { - static const uptr kSpaceBeg = 0; + static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN; static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kMetadataSize = 0; typedef __asan::SizeClassMap SizeClassMap; diff --git a/system/lib/compiler-rt/lib/asan/asan_descriptions.cpp b/system/lib/compiler-rt/lib/asan/asan_descriptions.cpp index c9f3e4d682d95..0c30959b23e28 100644 --- a/system/lib/compiler-rt/lib/asan/asan_descriptions.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_descriptions.cpp @@ -211,10 +211,10 @@ bool GetStackAddressInformation(uptr addr, uptr access_size, descr->frame_pc = access.frame_pc; descr->frame_descr = access.frame_descr; -#if SANITIZER_PPC64V1 - // On PowerPC64 ELFv1, the address of a function actually points to a - // three-doubleword data structure with the first field containing - // the address of the function's code. +#if SANITIZER_PPC64V1 || SANITIZER_AIX + // On PowerPC64 ELFv1 or AIX, the address of a function actually points to a + // three-doubleword (or three-word for 32-bit AIX) data structure with + // the first field containing the address of the function's code. descr->frame_pc = *reinterpret_cast(descr->frame_pc); #endif descr->frame_pc += 16; @@ -444,6 +444,16 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size, data.kind = kAddressKindShadow; return; } + + // Check global first. On AIX, some global data defined in shared libraries + // are put to the STACK region for unknown reasons. Check global first can + // workaround this issue. + // TODO: Look into whether there's a different solution to this problem. + if (GetGlobalAddressInformation(addr, access_size, &data.global)) { + data.kind = kAddressKindGlobal; + return; + } + if (GetHeapAddressInformation(addr, access_size, &data.heap)) { data.kind = kAddressKindHeap; return; @@ -461,10 +471,6 @@ AddressDescription::AddressDescription(uptr addr, uptr access_size, return; } - if (GetGlobalAddressInformation(addr, access_size, &data.global)) { - data.kind = kAddressKindGlobal; - return; - } data.kind = kAddressKindWild; data.wild.addr = addr; data.wild.access_size = access_size; diff --git a/system/lib/compiler-rt/lib/asan/asan_errors.cpp b/system/lib/compiler-rt/lib/asan/asan_errors.cpp index 48db35b993ec0..a1d5f7f144faf 100644 --- a/system/lib/compiler-rt/lib/asan/asan_errors.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_errors.cpp @@ -12,8 +12,10 @@ //===----------------------------------------------------------------------===// #include "asan_errors.h" + #include "asan_descriptions.h" #include "asan_mapping.h" +#include "asan_poisoning.h" #include "asan_report.h" #include "asan_stack.h" #include "sanitizer_common/sanitizer_stackdepot.h" @@ -611,6 +613,44 @@ static void PrintShadowMemoryForAddress(uptr addr) { Printf("%s", str.data()); } +static void CheckPoisonRecords(uptr addr) { + if (!AddrIsInMem(addr)) + return; + + u8 *shadow_addr = (u8 *)MemToShadow(addr); + // If we are in the partial right redzone, look at the next shadow byte. + if (*shadow_addr > 0 && *shadow_addr < 128) + shadow_addr++; + u8 shadow_val = *shadow_addr; + + if (shadow_val != kAsanUserPoisonedMemoryMagic) + return; + + Printf("\n"); + + if (flags()->poison_history_size <= 0) { + Printf( + "NOTE: the stack trace above identifies the code that *accessed* " + "the poisoned memory.\n"); + Printf( + "To identify the code that *poisoned* the memory, try the " + "experimental setting ASAN_OPTIONS=poison_history_size=.\n"); + return; + } + + PoisonRecord record; + if (FindPoisonRecord(addr, record)) { + StackTrace poison_stack = StackDepotGet(record.stack_id); + if (poison_stack.size > 0) { + Printf("Memory was manually poisoned by thread T%u:\n", record.thread_id); + poison_stack.Print(); + } + } else { + Printf("ERROR: no matching poison tracking record found.\n"); + Printf("Try a larger value for ASAN_OPTIONS=poison_history_size=.\n"); + } +} + void ErrorGeneric::Print() { Decorator d; Printf("%s", d.Error()); @@ -634,6 +674,9 @@ void ErrorGeneric::Print() { PrintContainerOverflowHint(); ReportErrorSummary(bug_descr, &stack); PrintShadowMemoryForAddress(addr); + + // This is an experimental flag, hence we don't make a special handler. + CheckPoisonRecords(addr); } } // namespace __asan diff --git a/system/lib/compiler-rt/lib/asan/asan_fake_stack.cpp b/system/lib/compiler-rt/lib/asan/asan_fake_stack.cpp index 7443ff166984d..0f696075fb78d 100644 --- a/system/lib/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -27,6 +27,7 @@ static const u64 kAllocaRedzoneMask = 31UL; // For small size classes inline PoisonShadow for better performance. ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { + CHECK(AddrIsAlignedByGranularity(ptr + size)); u64 *shadow = reinterpret_cast(MemToShadow(ptr)); if (ASAN_SHADOW_SCALE == 3 && class_id <= 6) { // This code expects ASAN_SHADOW_SCALE=3. @@ -39,6 +40,11 @@ ALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) { // The size class is too big, it's cheaper to poison only size bytes. PoisonShadow(ptr, size, static_cast(magic)); } + + if (magic == 0) { + uptr redzone_size = FakeStack::BytesInSizeClass(class_id) - size; + PoisonShadow(ptr + size, redzone_size, kAsanStackRightRedzoneMagic); + } } FakeStack *FakeStack::Create(uptr stack_size_log) { diff --git a/system/lib/compiler-rt/lib/asan/asan_flags.cpp b/system/lib/compiler-rt/lib/asan/asan_flags.cpp index 8a33ac3413d61..16975a1bde2a6 100644 --- a/system/lib/compiler-rt/lib/asan/asan_flags.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_flags.cpp @@ -177,6 +177,7 @@ static void InitializeDefaultFlags() { DisplayHelpMessages(&asan_parser); } +// Validate flags and report incompatible configurations static void ProcessFlags() { Flags *f = flags(); @@ -250,11 +251,12 @@ void InitializeFlags() { ProcessFlags(); #if SANITIZER_WINDOWS - // On Windows, weak symbols are emulated by having the user program - // register which weak functions are defined. - // The ASAN DLL will initialize flags prior to user module initialization, - // so __asan_default_options will not point to the user definition yet. - // We still want to ensure we capture when options are passed via + // On Windows, weak symbols (such as the `__asan_default_options` function) + // are emulated by having the user program register which weak functions are + // defined. The ASAN DLL will initialize flags prior to user module + // initialization, so __asan_default_options will not point to the user + // definition yet. We still want to ensure we capture when options are passed + // via // __asan_default_options, so we add a callback to be run // when it is registered with the runtime. @@ -265,21 +267,13 @@ void InitializeFlags() { // __sanitizer_register_weak_function. AddRegisterWeakFunctionCallback( reinterpret_cast(__asan_default_options), []() { - FlagParser asan_parser; - - RegisterAsanFlags(&asan_parser, flags()); - RegisterCommonFlags(&asan_parser); - asan_parser.ParseString(__asan_default_options()); - - DisplayHelpMessages(&asan_parser); + // We call `InitializeDefaultFlags` again, instead of just parsing + // `__asan_default_options` directly, to ensure that flags set through + // `ASAN_OPTS` take precedence over those set through + // `__asan_default_options`. + InitializeDefaultFlags(); ProcessFlags(); - - // TODO: Update other globals and data structures that may need to change - // after initialization due to new flags potentially being set changing after - // `__asan_default_options` is registered. - // See GH issue 'https://github.com/llvm/llvm-project/issues/117925' for - // details. - SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); + ApplyFlags(); }); # if CAN_SANITIZE_UB diff --git a/system/lib/compiler-rt/lib/asan/asan_flags.h b/system/lib/compiler-rt/lib/asan/asan_flags.h index b55c81f07d4bd..6f38a62a25d82 100644 --- a/system/lib/compiler-rt/lib/asan/asan_flags.h +++ b/system/lib/compiler-rt/lib/asan/asan_flags.h @@ -19,12 +19,12 @@ // ASan flag values can be defined in four ways: // 1) initialized with default values at startup. -// 2) overriden during compilation of ASan runtime by providing +// 2) overridden during compilation of ASan runtime by providing // compile definition ASAN_DEFAULT_OPTIONS. -// 3) overriden from string returned by user-specified function +// 3) overridden from string returned by user-specified function // __asan_default_options(). -// 4) overriden from env variable ASAN_OPTIONS. -// 5) overriden during ASan activation (for now used on Android only). +// 4) overridden from env variable ASAN_OPTIONS. +// 5) overridden during ASan activation (for now used on Android only). namespace __asan { diff --git a/system/lib/compiler-rt/lib/asan/asan_flags.inc b/system/lib/compiler-rt/lib/asan/asan_flags.inc index fad1577d912a5..32e6d3405533d 100644 --- a/system/lib/compiler-rt/lib/asan/asan_flags.inc +++ b/system/lib/compiler-rt/lib/asan/asan_flags.inc @@ -116,6 +116,9 @@ ASAN_FLAG(bool, poison_partial, true, "stack buffers.") ASAN_FLAG(bool, poison_array_cookie, true, "Poison (or not) the array cookie after operator new[].") +ASAN_FLAG(int, poison_history_size, 0, + "[EXPERIMENTAL] Number of most recent memory poisoning calls for " + "which the stack traces will be recorded.") // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. // https://github.com/google/sanitizers/issues/131 diff --git a/system/lib/compiler-rt/lib/asan/asan_fuchsia.cpp b/system/lib/compiler-rt/lib/asan/asan_fuchsia.cpp index 96c41e9d42ba6..6876be1dca535 100644 --- a/system/lib/compiler-rt/lib/asan/asan_fuchsia.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_fuchsia.cpp @@ -25,6 +25,11 @@ # include "asan_thread.h" # include "lsan/lsan_common.h" +namespace __sanitizer { +// ASan doesn't need to do anything else special in the startup hook. +void EarlySanitizerInit() {} +} // namespace __sanitizer + namespace __asan { // The system already set up the shadow memory for us. diff --git a/system/lib/compiler-rt/lib/asan/asan_interceptors.cpp b/system/lib/compiler-rt/lib/asan/asan_interceptors.cpp index a610afbef06dc..996ac13de4bd5 100644 --- a/system/lib/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_interceptors.cpp @@ -826,7 +826,7 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(__isoc23_strtoll); # endif - // Intecept jump-related functions. + // Intercept jump-related functions. ASAN_INTERCEPT_FUNC(longjmp); # if ASAN_INTERCEPT_SWAPCONTEXT diff --git a/system/lib/compiler-rt/lib/asan/asan_internal.h b/system/lib/compiler-rt/lib/asan/asan_internal.h index 06dfc4b177339..35c887eaf851c 100644 --- a/system/lib/compiler-rt/lib/asan/asan_internal.h +++ b/system/lib/compiler-rt/lib/asan/asan_internal.h @@ -61,6 +61,7 @@ using __sanitizer::StackTrace; void AsanInitFromRtl(); bool TryAsanInitFromRtl(); +void ApplyFlags(); // asan_win.cpp void InitializePlatformExceptionHandlers(); @@ -82,6 +83,7 @@ void ReplaceSystemMalloc(); uptr FindDynamicShadowStart(); void AsanCheckDynamicRTPrereqs(); void AsanCheckIncompatibleRT(); +void TryReExecWithoutASLR(); // Unpoisons platform-specific stacks. // Returns true if all stacks have been unpoisoned. diff --git a/system/lib/compiler-rt/lib/asan/asan_linux.cpp b/system/lib/compiler-rt/lib/asan/asan_linux.cpp index 4cabca388ca9a..d2c2a394b06c2 100644 --- a/system/lib/compiler-rt/lib/asan/asan_linux.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_linux.cpp @@ -13,7 +13,11 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS + SANITIZER_SOLARIS || SANITIZER_HAIKU + +# if SANITIZER_HAIKU +# define _DEFAULT_SOURCE +# endif # include # include @@ -22,7 +26,9 @@ # include # include # include -# include +# if !SANITIZER_HAIKU +# include +# endif # include # include # include @@ -37,10 +43,14 @@ # include "sanitizer_common/sanitizer_libc.h" # include "sanitizer_common/sanitizer_procmaps.h" -# if SANITIZER_FREEBSD +# if SANITIZER_FREEBSD || SANITIZER_HAIKU # include # endif +# if SANITIZER_LINUX +# include +# endif + # if SANITIZER_SOLARIS # include # endif @@ -50,6 +60,8 @@ # elif SANITIZER_NETBSD # include # include +# elif SANITIZER_HAIKU +extern "C" void *_DYNAMIC; # else # include # include @@ -107,6 +119,39 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); } +void TryReExecWithoutASLR() { +# if SANITIZER_LINUX + // ASLR personality check. + // Caution: 'personality' is sometimes forbidden by sandboxes, so only call + // this function as a last resort (when the memory mapping is incompatible + // and ASan would fail anyway). + int old_personality = personality(0xffffffff); + if (old_personality == -1) { + VReport(1, "WARNING: unable to run personality check.\n"); + return; + } + + bool aslr_on = (old_personality & ADDR_NO_RANDOMIZE) == 0; + + if (aslr_on) { + // Disable ASLR if the memory layout was incompatible. + // Alternatively, we could just keep re-execing until we get lucky + // with a compatible randomized layout, but the risk is that if it's + // not an ASLR-related issue, we will be stuck in an infinite loop of + // re-execing (unless we change ReExec to pass a parameter of the + // number of retries allowed.) + VReport(1, + "WARNING: AddressSanitizer: memory layout is incompatible, " + "possibly due to high-entropy ASLR.\n" + "Re-execing with fixed virtual address space.\n" + "N.B. reducing ASLR entropy is preferable.\n"); + CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); + + ReExec(); + } +# endif +} + # if SANITIZER_ANDROID // FIXME: should we do anything for Android? void AsanCheckDynamicRTPrereqs() {} @@ -125,6 +170,12 @@ static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size, return 0; } +# if SANITIZER_HAIKU + if (!info->dlpi_name[0] || + internal_strncmp(info->dlpi_name, "/boot/system/runtime_loader", + sizeof("/boot/system/runtime_loader") - 1) == 0) + return 0; +# endif # if SANITIZER_LINUX // Ignore vDSO. glibc versions earlier than 2.15 (and some patched // by distributors) return an empty name for the vDSO entry, so @@ -237,4 +288,4 @@ bool HandleDlopenInit() { } // namespace __asan #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || - // SANITIZER_SOLARIS + // SANITIZER_SOLARIS || SANITIZER_HAIKU diff --git a/system/lib/compiler-rt/lib/asan/asan_mac.cpp b/system/lib/compiler-rt/lib/asan/asan_mac.cpp index bfc349223258b..be513a03ed5cd 100644 --- a/system/lib/compiler-rt/lib/asan/asan_mac.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_mac.cpp @@ -55,6 +55,9 @@ uptr FindDynamicShadowStart() { GetMmapGranularity()); } +// Not used. +void TryReExecWithoutASLR() {} + // No-op. Mac does not support static linkage anyway. void AsanCheckDynamicRTPrereqs() {} diff --git a/system/lib/compiler-rt/lib/asan/asan_malloc_linux.cpp b/system/lib/compiler-rt/lib/asan/asan_malloc_linux.cpp index 836231b653e15..5a81ed3b8435e 100644 --- a/system/lib/compiler-rt/lib/asan/asan_malloc_linux.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_malloc_linux.cpp @@ -15,7 +15,8 @@ #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || \ - SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN + SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU || \ + SANITIZER_EMSCRIPTEN # include "asan_allocator.h" # include "asan_interceptors.h" @@ -217,4 +218,5 @@ void ReplaceSystemMalloc() { #endif // SANITIZER_ANDROID #endif // SANITIZER_FREEBSD || SANITIZER_FUCHSIA || SANITIZER_LINUX || - // SANITIZER_NETBSD || SANITIZER_SOLARIS + // SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU || + // SANITIZER_EMSCRIPTEN diff --git a/system/lib/compiler-rt/lib/asan/asan_new_delete.cpp b/system/lib/compiler-rt/lib/asan/asan_new_delete.cpp index b5b1ced8ac5ed..99c7c9938dfb3 100644 --- a/system/lib/compiler-rt/lib/asan/asan_new_delete.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_new_delete.cpp @@ -60,18 +60,42 @@ enum class align_val_t: size_t {}; // TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM. // For local pool allocation, align to SHADOW_GRANULARITY to match asan // allocator behavior. -#define OPERATOR_NEW_BODY(type, nothrow) \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign(0, size, &stack, type); \ - if (!nothrow && UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ - return res; -#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \ - GET_STACK_TRACE_MALLOC; \ - void *res = asan_memalign((uptr)align, size, &stack, type); \ - if (!nothrow && UNLIKELY(!res)) \ - ReportOutOfMemory(size, &stack); \ - return res; +#define OPERATOR_NEW_BODY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_memalign(0, size, &stack, FROM_NEW); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res +#define OPERATOR_NEW_BODY_NOTHROW \ + GET_STACK_TRACE_MALLOC; \ + return asan_memalign(0, size, &stack, FROM_NEW) +#define OPERATOR_NEW_BODY_ARRAY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_memalign(0, size, &stack, FROM_NEW_BR); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res +#define OPERATOR_NEW_BODY_ARRAY_NOTHROW \ + GET_STACK_TRACE_MALLOC; \ + return asan_memalign(0, size, &stack, FROM_NEW_BR) +#define OPERATOR_NEW_BODY_ALIGN \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res +#define OPERATOR_NEW_BODY_ALIGN_NOTHROW \ + GET_STACK_TRACE_MALLOC; \ + return asan_memalign((uptr)align, size, &stack, FROM_NEW) +#define OPERATOR_NEW_BODY_ALIGN_ARRAY \ + GET_STACK_TRACE_MALLOC; \ + void *res = asan_memalign((uptr)align, size, &stack, FROM_NEW_BR); \ + if (UNLIKELY(!res)) \ + ReportOutOfMemory(size, &stack); \ + return res +#define OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW \ + GET_STACK_TRACE_MALLOC; \ + return asan_memalign((uptr)align, size, &stack, FROM_NEW_BR) // On OS X it's not enough to just provide our own 'operator new' and // 'operator delete' implementations, because they're going to be in the @@ -82,106 +106,128 @@ enum class align_val_t: size_t {}; // OS X we need to intercept them using their mangled names. #if !SANITIZER_APPLE CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size) -{ OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); } +void *operator new(size_t size) { OPERATOR_NEW_BODY; } CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size) -{ OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); } +void *operator new[](size_t size) { OPERATOR_NEW_BODY_ARRAY; } CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size, std::nothrow_t const&) -{ OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); } +void *operator new(size_t size, std::nothrow_t const &) { + OPERATOR_NEW_BODY_NOTHROW; +} CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size, std::nothrow_t const&) -{ OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); } +void *operator new[](size_t size, std::nothrow_t const &) { + OPERATOR_NEW_BODY_ARRAY_NOTHROW; +} CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size, std::align_val_t align) -{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); } +void *operator new(size_t size, std::align_val_t align) { + OPERATOR_NEW_BODY_ALIGN; +} CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size, std::align_val_t align) -{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); } +void *operator new[](size_t size, std::align_val_t align) { + OPERATOR_NEW_BODY_ALIGN_ARRAY; +} CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) -{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); } +void *operator new(size_t size, std::align_val_t align, + std::nothrow_t const &) { + OPERATOR_NEW_BODY_ALIGN_NOTHROW; +} CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) -{ OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); } +void *operator new[](size_t size, std::align_val_t align, + std::nothrow_t const &) { + OPERATOR_NEW_BODY_ALIGN_ARRAY_NOTHROW; +} #else // SANITIZER_APPLE -INTERCEPTOR(void *, _Znwm, size_t size) { - OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); -} -INTERCEPTOR(void *, _Znam, size_t size) { - OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); -} +INTERCEPTOR(void *, _Znwm, size_t size) { OPERATOR_NEW_BODY; } +INTERCEPTOR(void *, _Znam, size_t size) { OPERATOR_NEW_BODY_ARRAY; } INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { - OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); + OPERATOR_NEW_BODY_NOTHROW; } INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { - OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); + OPERATOR_NEW_BODY_ARRAY_NOTHROW; } #endif // !SANITIZER_APPLE -#define OPERATOR_DELETE_BODY(type) \ +#define OPERATOR_DELETE_BODY \ + GET_STACK_TRACE_FREE; \ + asan_delete(ptr, 0, 0, &stack, FROM_NEW) +#define OPERATOR_DELETE_BODY_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, 0, &stack, type); - -#define OPERATOR_DELETE_BODY_SIZE(type) \ - GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, 0, &stack, type); - -#define OPERATOR_DELETE_BODY_ALIGN(type) \ + asan_delete(ptr, 0, 0, &stack, FROM_NEW_BR) +#define OPERATOR_DELETE_BODY_ALIGN \ + GET_STACK_TRACE_FREE; \ + asan_delete(ptr, 0, static_cast(align), &stack, FROM_NEW) +#define OPERATOR_DELETE_BODY_ALIGN_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, 0, static_cast(align), &stack, type); - -#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \ + asan_delete(ptr, 0, static_cast(align), &stack, FROM_NEW_BR) +#define OPERATOR_DELETE_BODY_SIZE \ + GET_STACK_TRACE_FREE; \ + asan_delete(ptr, size, 0, &stack, FROM_NEW) +#define OPERATOR_DELETE_BODY_SIZE_ARRAY \ + GET_STACK_TRACE_FREE; \ + asan_delete(ptr, size, 0, &stack, FROM_NEW_BR) +#define OPERATOR_DELETE_BODY_SIZE_ALIGN \ + GET_STACK_TRACE_FREE; \ + asan_delete(ptr, size, static_cast(align), &stack, FROM_NEW) +#define OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY \ GET_STACK_TRACE_FREE; \ - asan_delete(ptr, size, static_cast(align), &stack, type); + asan_delete(ptr, size, static_cast(align), &stack, FROM_NEW_BR) #if !SANITIZER_APPLE CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr) NOEXCEPT -{ OPERATOR_DELETE_BODY(FROM_NEW); } +void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr) NOEXCEPT -{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } +void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY_ARRAY; } CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY(FROM_NEW); } +void operator delete(void *ptr, std::nothrow_t const &) { + OPERATOR_DELETE_BODY; +} CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } +void operator delete[](void *ptr, std::nothrow_t const &) { + OPERATOR_DELETE_BODY_ARRAY; +} CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, size_t size) NOEXCEPT -{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW); } +void operator delete(void *ptr, size_t size) NOEXCEPT { + OPERATOR_DELETE_BODY_SIZE; +} CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, size_t size) NOEXCEPT -{ OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); } +void operator delete[](void *ptr, size_t size) NOEXCEPT { + OPERATOR_DELETE_BODY_SIZE_ARRAY; +} CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, std::align_val_t align) NOEXCEPT -{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); } +void operator delete(void *ptr, std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY_ALIGN; +} CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT -{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); } +void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY_ALIGN_ARRAY; +} CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); } +void operator delete(void *ptr, std::align_val_t align, + std::nothrow_t const &) { + OPERATOR_DELETE_BODY_ALIGN; +} CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); } +void operator delete[](void *ptr, std::align_val_t align, + std::nothrow_t const &) { + OPERATOR_DELETE_BODY_ALIGN_ARRAY; +} CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT -{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); } +void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY_SIZE_ALIGN; +} CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT -{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); } +void operator delete[](void *ptr, size_t size, + std::align_val_t align) NOEXCEPT { + OPERATOR_DELETE_BODY_SIZE_ALIGN_ARRAY; +} #else // SANITIZER_APPLE -INTERCEPTOR(void, _ZdlPv, void *ptr) -{ OPERATOR_DELETE_BODY(FROM_NEW); } -INTERCEPTOR(void, _ZdaPv, void *ptr) -{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } -INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY(FROM_NEW); } -INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) -{ OPERATOR_DELETE_BODY(FROM_NEW_BR); } +INTERCEPTOR(void, _ZdlPv, void *ptr) { OPERATOR_DELETE_BODY; } +INTERCEPTOR(void, _ZdaPv, void *ptr) { OPERATOR_DELETE_BODY_ARRAY; } +INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) { + OPERATOR_DELETE_BODY; +} +INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const &) { + OPERATOR_DELETE_BODY_ARRAY; +} #endif // !SANITIZER_APPLE diff --git a/system/lib/compiler-rt/lib/asan/asan_poisoning.cpp b/system/lib/compiler-rt/lib/asan/asan_poisoning.cpp index 07bc58b724cb6..ca062751bb802 100644 --- a/system/lib/compiler-rt/lib/asan/asan_poisoning.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_poisoning.cpp @@ -20,11 +20,58 @@ #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_interface_internal.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_ring_buffer.h" +#include "sanitizer_common/sanitizer_stackdepot.h" namespace __asan { +using PoisonRecordRingBuffer = RingBuffer; + static atomic_uint8_t can_poison_memory; +static Mutex poison_records_mutex; +static PoisonRecordRingBuffer *poison_records + SANITIZER_GUARDED_BY(poison_records_mutex) = nullptr; + +void AddPoisonRecord(const PoisonRecord &new_record) { + if (flags()->poison_history_size <= 0) + return; + + GenericScopedLock l(&poison_records_mutex); + + if (poison_records == nullptr) + poison_records = PoisonRecordRingBuffer::New(flags()->poison_history_size); + + poison_records->push(new_record); +} + +bool FindPoisonRecord(uptr addr, PoisonRecord &match) { + if (flags()->poison_history_size <= 0) + return false; + + GenericScopedLock l(&poison_records_mutex); + + if (poison_records) { + for (unsigned int i = 0; i < poison_records->size(); i++) { + PoisonRecord record = (*poison_records)[i]; + if (record.begin <= addr && addr < record.end) { + internal_memcpy(&match, &record, sizeof(record)); + return true; + } + } + } + + return false; +} + +void SANITIZER_ACQUIRE(poison_records_mutex) AcquirePoisonRecords() { + poison_records_mutex.Lock(); +} + +void SANITIZER_RELEASE(poison_records_mutex) ReleasePoisonRecords() { + poison_records_mutex.Unlock(); +} + void SetCanPoisonMemory(bool value) { atomic_store(&can_poison_memory, value, memory_order_release); } @@ -107,6 +154,21 @@ void __asan_poison_memory_region(void const volatile *addr, uptr size) { uptr end_addr = beg_addr + size; VPrintf(3, "Trying to poison memory region [%p, %p)\n", (void *)beg_addr, (void *)end_addr); + + if (flags()->poison_history_size > 0) { + GET_STACK_TRACE(/*max_size=*/16, /*fast=*/false); + u32 current_tid = GetCurrentTidOrInvalid(); + + u32 stack_id = StackDepotPut(stack); + + PoisonRecord record; + record.stack_id = stack_id; + record.thread_id = current_tid; + record.begin = beg_addr; + record.end = end_addr; + AddPoisonRecord(record); + } + ShadowSegmentEndpoint beg(beg_addr); ShadowSegmentEndpoint end(end_addr); if (beg.chunk == end.chunk) { @@ -147,6 +209,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, uptr size) { uptr end_addr = beg_addr + size; VPrintf(3, "Trying to unpoison memory region [%p, %p)\n", (void *)beg_addr, (void *)end_addr); + + // Note: we don't need to update the poison tracking here. Since the shadow + // memory will be unpoisoned, the poison tracking ring buffer entries will be + // ignored. + ShadowSegmentEndpoint beg(beg_addr); ShadowSegmentEndpoint end(end_addr); if (beg.chunk == end.chunk) { diff --git a/system/lib/compiler-rt/lib/asan/asan_poisoning.h b/system/lib/compiler-rt/lib/asan/asan_poisoning.h index e34de6c09dd5a..a9ef26fe2b968 100644 --- a/system/lib/compiler-rt/lib/asan/asan_poisoning.h +++ b/system/lib/compiler-rt/lib/asan/asan_poisoning.h @@ -11,6 +11,9 @@ // Shadow memory poisoning by ASan RTL and by user application. //===----------------------------------------------------------------------===// +#ifndef ASAN_POISONING_H +#define ASAN_POISONING_H + #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_mapping.h" @@ -19,6 +22,19 @@ namespace __asan { +struct PoisonRecord { + u32 stack_id; + u32 thread_id; + uptr begin; + uptr end; +}; + +void AddPoisonRecord(const PoisonRecord& new_record); +bool FindPoisonRecord(uptr addr, PoisonRecord& match); + +void AcquirePoisonRecords(); +void ReleasePoisonRecords(); + // Enable/disable memory poisoning. void SetCanPoisonMemory(bool value); bool CanPoisonMemory(); @@ -100,3 +116,5 @@ ALWAYS_INLINE void FastPoisonShadowPartialRightRedzone( void FlushUnneededASanShadowMemory(uptr p, uptr size); } // namespace __asan + +#endif // ASAN_POISONING_H diff --git a/system/lib/compiler-rt/lib/asan/asan_posix.cpp b/system/lib/compiler-rt/lib/asan/asan_posix.cpp index 921c597fef83b..ca691059cfae1 100644 --- a/system/lib/compiler-rt/lib/asan/asan_posix.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_posix.cpp @@ -161,11 +161,17 @@ static void BeforeFork() { // stuff we need. __lsan::LockThreads(); __lsan::LockAllocator(); + + AcquirePoisonRecords(); + StackDepotLockBeforeFork(); } static void AfterFork(bool fork_child) { StackDepotUnlockAfterFork(fork_child); + + ReleasePoisonRecords(); + // `_lsan` functions defined regardless of `CAN_SANITIZE_LEAKS` and unlock // the stuff we need. __lsan::UnlockAllocator(); @@ -178,7 +184,7 @@ static void AfterFork(bool fork_child) { void InstallAtForkHandler() { # if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE || \ - (SANITIZER_LINUX && SANITIZER_SPARC) + (SANITIZER_LINUX && SANITIZER_SPARC) || SANITIZER_HAIKU // While other Linux targets use clone in internal_fork which doesn't // trigger pthread_atfork handlers, Linux/sparc64 uses __fork, causing a // hang. diff --git a/system/lib/compiler-rt/lib/asan/asan_report.cpp b/system/lib/compiler-rt/lib/asan/asan_report.cpp index 45aa607dcda07..e049a21e4e16d 100644 --- a/system/lib/compiler-rt/lib/asan/asan_report.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_report.cpp @@ -21,6 +21,7 @@ #include "asan_scariness_score.h" #include "asan_stack.h" #include "asan_thread.h" +#include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_interface_internal.h" @@ -126,6 +127,33 @@ class ScopedInErrorReport { public: explicit ScopedInErrorReport(bool fatal = false) : halt_on_error_(fatal || flags()->halt_on_error) { + // Deadlock Prevention Between ASan and LSan + // + // Background: + // - The `dl_iterate_phdr` function requires holding libdl's internal lock + // (Lock A). + // - LSan acquires the ASan thread registry lock (Lock B) *after* calling + // `dl_iterate_phdr`. + // + // Problem Scenario: + // When ASan attempts to call `dl_iterate_phdr` while holding Lock B (e.g., + // during error reporting via `ErrorDescription::Print`), a circular lock + // dependency may occur: + // 1. Thread 1: Holds Lock B → Requests Lock A (via dl_iterate_phdr) + // 2. Thread 2: Holds Lock A → Requests Lock B (via LSan operations) + // + // Solution: + // Proactively load all required modules before acquiring Lock B. + // This ensures: + // 1. Any `dl_iterate_phdr` calls during module loading complete before + // locking. + // 2. Subsequent error reporting avoids nested lock acquisition patterns. + // 3. Eliminates the lock order inversion risk between libdl and ASan's + // thread registry. +#if CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD) + Symbolizer::GetOrInit()->GetRefreshedListOfModules(); +#endif + // Make sure the registry and sanitizer report mutexes are locked while // we're printing an error report. // We can lock them only here to avoid self-deadlock in case of @@ -592,5 +620,5 @@ void __sanitizer_ptr_cmp(void *a, void *b) { } // extern "C" // Provide default implementation of __asan_on_error that does nothing -// and may be overriden by user. +// and may be overridden by user. SANITIZER_INTERFACE_WEAK_DEF(void, __asan_on_error, void) {} diff --git a/system/lib/compiler-rt/lib/asan/asan_rtl.cpp b/system/lib/compiler-rt/lib/asan/asan_rtl.cpp index 659645b0b9976..f96ee2c47ce69 100644 --- a/system/lib/compiler-rt/lib/asan/asan_rtl.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_rtl.cpp @@ -394,6 +394,39 @@ void PrintAddressSpaceLayout() { kHighShadowBeg > kMidMemEnd); } +// Apply most options specified either through the ASAN_OPTIONS +// environment variable, or through the `__asan_default_options` user function. +// +// This function may be called multiple times, once per weak reference callback +// on Windows, so it needs to be idempotent. +// +// Context: +// For maximum compatibility on Windows, it is necessary for ASan options to be +// configured/registered/applied inside this method (instead of in +// ASanInitInternal, for example). That's because, on Windows, the user-provided +// definition for `__asan_default_opts` may not be bound when `ASanInitInternal` +// is invoked (it is bound later). +// +// To work around the late binding on windows, `ApplyOptions` will be called, +// again, after binding to the user-provided `__asan_default_opts` function. +// Therefore, any flags not configured here are not guaranteed to be +// configurable through `__asan_default_opts` on Windows. +// +// +// For more details on this issue, see: +// https://github.com/llvm/llvm-project/issues/117925 +void ApplyFlags() { + SetCanPoisonMemory(flags()->poison_heap); + SetMallocContextSize(common_flags()->malloc_context_size); + + __asan_option_detect_stack_use_after_return = + flags()->detect_stack_use_after_return; + + AllocatorOptions allocator_options; + allocator_options.SetFrom(flags(), common_flags()); + ApplyAllocatorOptions(allocator_options); +} + static bool AsanInitInternal() { if (LIKELY(AsanInited())) return true; @@ -401,8 +434,9 @@ static bool AsanInitInternal() { CacheBinaryName(); - // Initialize flags. This must be done early, because most of the - // initialization steps look at flags(). + // Initialize flags. On Windows it also also register weak function callbacks. + // This must be done early, because most of the initialization steps look at + // flags(). InitializeFlags(); WaitForDebugger(flags()->sleep_before_init, "before init"); @@ -420,9 +454,6 @@ static bool AsanInitInternal() { AsanCheckDynamicRTPrereqs(); AvoidCVE_2016_2143(); - SetCanPoisonMemory(flags()->poison_heap); - SetMallocContextSize(common_flags()->malloc_context_size); - InitializePlatformExceptionHandlers(); InitializeHighMemEnd(); @@ -433,10 +464,6 @@ static bool AsanInitInternal() { SetPrintfAndReportCallback(AppendToErrorMessageBuffer); __sanitizer_set_report_path(common_flags()->log_path); - - __asan_option_detect_stack_use_after_return = - flags()->detect_stack_use_after_return; - __sanitizer::InitializePlatformEarly(); // Setup internal allocator callback. @@ -455,7 +482,19 @@ static bool AsanInitInternal() { #if !SANITIZER_EMSCRIPTEN DisableCoreDumperIfNecessary(); -#endif + +#if SANITIZER_POSIX + if (StackSizeIsUnlimited()) { + VPrintf(1, + "WARNING: Unlimited stack size detected. This may affect " + "compatibility with the shadow mappings.\n"); + // MSan and TSan re-exec with a fixed size stack. We don't do that because + // it may break the program. InitializeShadowMemory() will, if needed, + // re-exec without ASLR, which solves most shadow mapping compatibility + // issues. + } +#endif // SANITIZER_POSIX +#endif // !SANITIZER_EMSCRIPTEN InitializeShadowMemory(); @@ -468,6 +507,13 @@ static bool AsanInitInternal() { allocator_options.SetFrom(flags(), common_flags()); InitializeAllocator(allocator_options); + // Apply ASan flags. + // NOTE: In order for options specified through `__asan_default_options` to be + // honored on Windows, it is necessary for those options to be configured + // inside the `ApplyOptions` method. See the function-level comment for + // `ApplyFlags` for more details. + ApplyFlags(); + if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL) MaybeStartBackgroudThread(); @@ -490,7 +536,6 @@ static bool AsanInitInternal() { AsanThread *main_thread = CreateMainThread(); CHECK_EQ(0, main_thread->tid()); force_interface_symbols(); // no-op. - SanitizerInitializeUnwinder(); if (CAN_SANITIZE_LEAKS) { __lsan::InitCommonLsan(); diff --git a/system/lib/compiler-rt/lib/asan/asan_shadow_setup.cpp b/system/lib/compiler-rt/lib/asan/asan_shadow_setup.cpp index 83f1906aaebf7..8084530e53499 100644 --- a/system/lib/compiler-rt/lib/asan/asan_shadow_setup.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_shadow_setup.cpp @@ -110,6 +110,15 @@ void InitializeShadowMemory() { ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); } else { + // ASan's mappings can usually shadow the entire address space, even with + // maximum ASLR entropy. However: + // - On 32-bit systems, the maximum ASLR entropy (currently up to 16-bits + // == 256MB) is a significant chunk of the address space; reclaiming it + // by disabling ASLR might allow chonky binaries to run. + // - On 64-bit systems, some settings (e.g., for Linux, unlimited stack + // size plus 31+ bits of entropy) can lead to an incompatible layout. + TryReExecWithoutASLR(); + Report( "Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); diff --git a/system/lib/compiler-rt/lib/asan/asan_win.cpp b/system/lib/compiler-rt/lib/asan/asan_win.cpp index 09a13b11cff1f..845408ac38abc 100644 --- a/system/lib/compiler-rt/lib/asan/asan_win.cpp +++ b/system/lib/compiler-rt/lib/asan/asan_win.cpp @@ -145,7 +145,6 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { t->GetStartData(params); auto res = (*params.start_routine)(params.arg); - t->Destroy(); // POSIX calls this from TSD destructor. return res; } @@ -166,6 +165,13 @@ INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security, thr_flags, tid); } +INTERCEPTOR_WINAPI(void, ExitThread, DWORD dwExitCode) { + AsanThread *t = (AsanThread *)__asan::GetCurrentThread(); + if (t) + t->Destroy(); + REAL(ExitThread)(dwExitCode); +} + // }}} namespace __asan { @@ -181,6 +187,7 @@ void InitializePlatformInterceptors() { (LPCWSTR)&InitializePlatformInterceptors, &pinned)); ASAN_INTERCEPT_FUNC(CreateThread); + ASAN_INTERCEPT_FUNC(ExitThread); ASAN_INTERCEPT_FUNC(SetUnhandledExceptionFilter); #ifdef _WIN64 @@ -272,6 +279,9 @@ uptr FindDynamicShadowStart() { GetMmapGranularity()); } +// Not used +void TryReExecWithoutASLR() {} + void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} diff --git a/system/lib/compiler-rt/lib/builtins/assembly.h b/system/lib/compiler-rt/lib/builtins/assembly.h index 34c71241524dc..d7db7d8189457 100644 --- a/system/lib/compiler-rt/lib/builtins/assembly.h +++ b/system/lib/compiler-rt/lib/builtins/assembly.h @@ -61,7 +61,7 @@ #define LOCAL_LABEL(name) .L ## name #define FILE_LEVEL_DIRECTIVE #define SYMBOL_IS_FUNC(name) \ - .def name SEPARATOR \ + .def FUNC_SYMBOL(name) SEPARATOR \ .scl 2 SEPARATOR \ .type 32 SEPARATOR \ .endef @@ -71,7 +71,7 @@ #endif -#if defined(__arm__) || defined(__aarch64__) +#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__) #define FUNC_ALIGN \ .text SEPARATOR \ .balign 16 SEPARATOR @@ -79,11 +79,12 @@ #define FUNC_ALIGN #endif -// BTI and PAC gnu property note +// BTI, PAC, and GCS gnu property note #define NT_GNU_PROPERTY_TYPE_0 5 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1 #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2 +#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4 #if defined(__ARM_FEATURE_BTI_DEFAULT) #define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI @@ -97,6 +98,12 @@ #define PAC_FLAG 0 #endif +#if defined(__ARM_FEATURE_GCS_DEFAULT) +#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS +#else +#define GCS_FLAG 0 +#endif + #define GNU_PROPERTY(type, value) \ .pushsection .note.gnu.property, "a" SEPARATOR \ .p2align 3 SEPARATOR \ @@ -118,11 +125,12 @@ #define BTI_J #endif -#if (BTI_FLAG | PAC_FLAG) != 0 -#define GNU_PROPERTY_BTI_PAC \ - GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG) +#if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0 +#define GNU_PROPERTY_BTI_PAC_GCS \ + GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \ + BTI_FLAG | PAC_FLAG | GCS_FLAG) #else -#define GNU_PROPERTY_BTI_PAC +#define GNU_PROPERTY_BTI_PAC_GCS #endif #if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM) @@ -194,6 +202,23 @@ #else #define WIDE(op) op #endif + +#if defined(__ARM_FEATURE_PAC_DEFAULT) && defined(__ARM_FEATURE_BTI_DEFAULT) +#define PACBTI_LANDING pacbti r12, lr, sp +#elif defined(__ARM_FEATURE_PAC_DEFAULT) +#define PACBTI_LANDING pac r12, lr, sp +#elif defined(__ARM_FEATURE_BTI_DEFAULT) +#define PACBTI_LANDING bti +#else +#define PACBTI_LANDING +#endif + +#if defined(__ARM_FEATURE_PAUTH) +#define PAC_RETURN bxaut r12, lr, sp +#else +#define PAC_RETURN aut r12, lr, sp SEPARATOR bx lr +#endif + #else // !defined(__arm) #define DECLARE_FUNC_ENCODING #define DEFINE_CODE_STATE @@ -208,6 +233,16 @@ #define GLUE4(a, b, c, d) GLUE4_(a, b, c, d) #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) +#ifndef __arm64ec__ +#define FUNC_SYMBOL(name) name +#else +// On ARM64EC, function names and calls (but not address-taking or data symbol +// references) use symbols prefixed with "#". +#define QUOTE(a) #a +#define STR(a) QUOTE(a) +#define HASH # +#define FUNC_SYMBOL(name) STR(GLUE2(HASH, name)) +#endif #ifdef VISIBILITY_HIDDEN #define DECLARE_SYMBOL_VISIBILITY(name) \ @@ -222,54 +257,54 @@ #define DEFINE_COMPILERRT_FUNCTION(name) \ DEFINE_CODE_STATE \ FILE_LEVEL_DIRECTIVE SEPARATOR \ - .globl SYMBOL_NAME(name) SEPARATOR \ + .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_SYMBOL_VISIBILITY(name) \ DECLARE_FUNC_ENCODING \ - SYMBOL_NAME(name): + FUNC_SYMBOL(SYMBOL_NAME(name)): #define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \ DEFINE_CODE_STATE \ FILE_LEVEL_DIRECTIVE SEPARATOR \ - .globl SYMBOL_NAME(name) SEPARATOR \ + .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ .thumb_func SEPARATOR \ - SYMBOL_NAME(name): + FUNC_SYMBOL(SYMBOL_NAME(name)): #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \ DEFINE_CODE_STATE \ FILE_LEVEL_DIRECTIVE SEPARATOR \ - .globl SYMBOL_NAME(name) SEPARATOR \ + .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ HIDDEN(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_FUNC_ENCODING \ - SYMBOL_NAME(name): + FUNC_SYMBOL(SYMBOL_NAME(name)): #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \ DEFINE_CODE_STATE \ - .globl name SEPARATOR \ + .globl FUNC_SYMBOL(name) SEPARATOR \ SYMBOL_IS_FUNC(name) SEPARATOR \ HIDDEN(name) SEPARATOR \ DECLARE_FUNC_ENCODING \ - name: + FUNC_SYMBOL(name): #define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \ DEFINE_CODE_STATE \ FUNC_ALIGN \ - .globl name SEPARATOR \ + .globl FUNC_SYMBOL(name) SEPARATOR \ SYMBOL_IS_FUNC(name) SEPARATOR \ - DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name)) SEPARATOR \ DECLARE_FUNC_ENCODING \ - name: \ + FUNC_SYMBOL(name): \ SEPARATOR CFI_START \ SEPARATOR BTI_C #define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \ - .globl SYMBOL_NAME(name) SEPARATOR \ + .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ - .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR + .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(target) SEPARATOR #if defined(__ARM_EABI__) #define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \ diff --git a/system/lib/compiler-rt/lib/builtins/clear_cache.c b/system/lib/compiler-rt/lib/builtins/clear_cache.c index 2ac99b25c243f..eb58452d624ee 100644 --- a/system/lib/compiler-rt/lib/builtins/clear_cache.c +++ b/system/lib/compiler-rt/lib/builtins/clear_cache.c @@ -59,11 +59,14 @@ uintptr_t GetCurrentProcess(void); // specified range. void __clear_cache(void *start, void *end) { -#if __i386__ || __x86_64__ || defined(_M_IX86) || defined(_M_X64) +#if defined(_WIN32) && \ + (defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)) + FlushInstructionCache(GetCurrentProcess(), start, end - start); +#elif __i386__ || __x86_64__ || defined(_M_IX86) || defined(_M_X64) // Intel processors have a unified instruction and data cache // so there is nothing to do -#elif defined(_WIN32) && (defined(__arm__) || defined(__aarch64__)) - FlushInstructionCache(GetCurrentProcess(), start, end - start); +#elif defined(__s390__) +// no-op #elif defined(__arm__) && !defined(__APPLE__) #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) struct arm_sync_icache_args arg; diff --git a/system/lib/compiler-rt/lib/builtins/clzdi2.c b/system/lib/compiler-rt/lib/builtins/clzdi2.c index 12c17982a5cb1..c0ea6da05a24f 100644 --- a/system/lib/compiler-rt/lib/builtins/clzdi2.c +++ b/system/lib/compiler-rt/lib/builtins/clzdi2.c @@ -14,12 +14,12 @@ // Returns: the number of leading 0-bits -#if !defined(__clang__) && \ - ((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \ +#if ((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \ (defined(__riscv) && __SIZEOF_POINTER__ >= 8)) // On 64-bit architectures with neither a native clz instruction nor a native -// ctz instruction, gcc resolves __builtin_clz to __clzdi2 rather than -// __clzsi2, leading to infinite recursion. +// ctz instruction, `__builtin_clz` resolves to `__clzdi2` rather than +// __clzsi2 as libgcc does not ship with `__clzsi2`, leading to infinite +// recursion. #define __builtin_clz(a) __clzsi2(a) extern int __clzsi2(si_int); #endif diff --git a/system/lib/compiler-rt/lib/builtins/crtbegin.c b/system/lib/compiler-rt/lib/builtins/crtbegin.c index d5f7756308b09..447474bd0b692 100644 --- a/system/lib/compiler-rt/lib/builtins/crtbegin.c +++ b/system/lib/compiler-rt/lib/builtins/crtbegin.c @@ -54,22 +54,33 @@ static void __attribute__((used)) __do_init(void) { } #ifdef CRT_HAS_INITFINI_ARRAY -#if __has_feature(ptrauth_init_fini) +# if __has_feature(ptrauth_init_fini) // TODO: use __ptrauth-qualified pointers when they are supported on clang side -#if __has_feature(ptrauth_init_fini_address_discrimination) +# if __has_feature(ptrauth_init_fini_address_discrimination) __attribute__((section(".init_array"), used)) static void *__init = ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, ptrauth_blend_discriminator( &__init, __ptrauth_init_fini_discriminator)); -#else +# else __attribute__((section(".init_array"), used)) static void *__init = ptrauth_sign_constant(&__do_init, ptrauth_key_init_fini_pointer, __ptrauth_init_fini_discriminator); -#endif -#else +# endif +# elif __has_feature(ptrauth_calls) +# ifdef __aarch64__ +// If ptrauth_init_fini feature is not present, compiler emits raw unsigned +// pointers in .init_array. Use inline assembly to avoid implicit signing of +// __do_init function pointer with ptrauth_calls enabled. +__asm__(".pushsection .init_array,\"aw\",@init_array\n\t" + ".xword __do_init\n\t" + ".popsection"); +# else +# error "ptrauth_calls is only supported for AArch64" +# endif +# else __attribute__((section(".init_array"), used)) static void (*__init)(void) = __do_init; -#endif +# endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .init,\"ax\",@progbits\n\t" "call __do_init\n\t" @@ -125,22 +136,33 @@ static void __attribute__((used)) __do_fini(void) { } #ifdef CRT_HAS_INITFINI_ARRAY -#if __has_feature(ptrauth_init_fini) +# if __has_feature(ptrauth_init_fini) // TODO: use __ptrauth-qualified pointers when they are supported on clang side -#if __has_feature(ptrauth_init_fini_address_discrimination) +# if __has_feature(ptrauth_init_fini_address_discrimination) __attribute__((section(".fini_array"), used)) static void *__fini = ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, ptrauth_blend_discriminator( &__fini, __ptrauth_init_fini_discriminator)); -#else +# else __attribute__((section(".fini_array"), used)) static void *__fini = ptrauth_sign_constant(&__do_fini, ptrauth_key_init_fini_pointer, __ptrauth_init_fini_discriminator); -#endif -#else +# endif +# elif __has_feature(ptrauth_calls) +# ifdef __aarch64__ +// If ptrauth_init_fini feature is not present, compiler emits raw unsigned +// pointers in .fini_array. Use inline assembly to avoid implicit signing of +// __do_fini function pointer with ptrauth_calls enabled. +__asm__(".pushsection .fini_array,\"aw\",@fini_array\n\t" + ".xword __do_fini\n\t" + ".popsection"); +# else +# error "ptrauth_calls is only supported for AArch64" +# endif +# else __attribute__((section(".fini_array"), used)) static void (*__fini)(void) = __do_fini; -#endif +# endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .fini,\"ax\",@progbits\n\t" "call __do_fini\n\t" diff --git a/system/lib/compiler-rt/lib/builtins/extendhfdf2.c b/system/lib/compiler-rt/lib/builtins/extendhfdf2.c new file mode 100644 index 0000000000000..1cfbdb82730ad --- /dev/null +++ b/system/lib/compiler-rt/lib/builtins/extendhfdf2.c @@ -0,0 +1,15 @@ +//===-- lib/extendhfdf2.c - half -> single conversion -------------*- C -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#define SRC_HALF +#define DST_DOUBLE +#include "fp_extend_impl.inc" + +COMPILER_RT_ABI NOINLINE dst_t __extendhfdf2(src_t a) { + return __extendXfYf2__(a); +} diff --git a/system/lib/compiler-rt/lib/builtins/extendhfsf2.c b/system/lib/compiler-rt/lib/builtins/extendhfsf2.c index 0159ab09d3ebb..c0f25cdadcd4f 100644 --- a/system/lib/compiler-rt/lib/builtins/extendhfsf2.c +++ b/system/lib/compiler-rt/lib/builtins/extendhfsf2.c @@ -16,12 +16,14 @@ COMPILER_RT_ABI NOINLINE float __extendhfsf2(src_t a) { return __extendXfYf2__(a); } -COMPILER_RT_ABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); } - #if defined(__ARM_EABI__) #if defined(COMPILER_RT_ARMHF_TARGET) +AEABI_RTABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); } AEABI_RTABI float __aeabi_h2f(src_t a) { return __extendhfsf2(a); } #else +COMPILER_RT_ALIAS(__extendhfsf2, __gnu_h2f_ieee) COMPILER_RT_ALIAS(__extendhfsf2, __aeabi_h2f) #endif +#else +COMPILER_RT_ABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); } #endif diff --git a/system/lib/compiler-rt/lib/builtins/fp_compare_impl.inc b/system/lib/compiler-rt/lib/builtins/fp_compare_impl.inc index 83bdea46a45da..fa1629fc1a07a 100644 --- a/system/lib/compiler-rt/lib/builtins/fp_compare_impl.inc +++ b/system/lib/compiler-rt/lib/builtins/fp_compare_impl.inc @@ -12,7 +12,7 @@ // functions. We need to ensure that the return value is sign-extended in the // same way as GCC expects (since otherwise GCC-generated __builtin_isinf // returns true for finite 128-bit floating-point numbers). -#if defined(__aarch64__) || defined(__wasm__) +#if defined(__aarch64__) || defined(__arm64ec__) || defined(__wasm__) // AArch64 GCC overrides libgcc_cmp_return to use int instead of long. typedef int CMP_RESULT; #elif __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 4 diff --git a/system/lib/compiler-rt/lib/builtins/fp_lib.h b/system/lib/compiler-rt/lib/builtins/fp_lib.h index fae58497a8f80..95b24aac1ff1d 100644 --- a/system/lib/compiler-rt/lib/builtins/fp_lib.h +++ b/system/lib/compiler-rt/lib/builtins/fp_lib.h @@ -359,7 +359,7 @@ static __inline fp_t __compiler_rt_scalbn(fp_t x, int y) { return __compiler_rt_scalbnX(x, y); } static __inline fp_t __compiler_rt_fmax(fp_t x, fp_t y) { -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(__arm64ec__) // Use __builtin_fmax which turns into an fmaxnm instruction on AArch64. return __builtin_fmax(x, y); #else diff --git a/system/lib/compiler-rt/lib/builtins/int_lib.h b/system/lib/compiler-rt/lib/builtins/int_lib.h index f6c1b7cff4b99..943430de259d8 100644 --- a/system/lib/compiler-rt/lib/builtins/int_lib.h +++ b/system/lib/compiler-rt/lib/builtins/int_lib.h @@ -49,7 +49,7 @@ #define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name #if defined(__ELF__) || defined(__MINGW32__) || defined(__wasm__) || \ - defined(_AIX) || defined(__CYGWIN__) + defined(_AIX) || defined(__CYGWIN__) #define COMPILER_RT_ALIAS(name, aliasname) \ COMPILER_RT_ABI __typeof(name) aliasname __attribute__((__alias__(#name))); #elif defined(__APPLE__) @@ -64,7 +64,7 @@ COMPILER_RT_ALIAS_VISIBILITY(aliasname) \ __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ COMPILER_RT_ABI __typeof(name) aliasname; -#elif defined(_WIN32) +#elif defined(_WIN32) || defined(__UEFI__) #define COMPILER_RT_ALIAS(name, aliasname) #else #error Unsupported target diff --git a/system/lib/compiler-rt/lib/builtins/int_types.h b/system/lib/compiler-rt/lib/builtins/int_types.h index 48862f3642175..7c7f8cb64aa9a 100644 --- a/system/lib/compiler-rt/lib/builtins/int_types.h +++ b/system/lib/compiler-rt/lib/builtins/int_types.h @@ -223,7 +223,7 @@ typedef union { #define CRT_HAS_TF_MODE #endif -#if __STDC_VERSION__ >= 199901L +#if __STDC_VERSION__ >= 199901L && !defined(_MSC_VER) typedef float _Complex Fcomplex; typedef double _Complex Dcomplex; typedef long double _Complex Lcomplex; diff --git a/system/lib/compiler-rt/lib/builtins/trampoline_setup.c b/system/lib/compiler-rt/lib/builtins/trampoline_setup.c index 830e25e4c0303..844eb27944142 100644 --- a/system/lib/compiler-rt/lib/builtins/trampoline_setup.c +++ b/system/lib/compiler-rt/lib/builtins/trampoline_setup.c @@ -41,45 +41,3 @@ COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack, __clear_cache(trampOnStack, &trampOnStack[10]); } #endif // __powerpc__ && !defined(__powerpc64__) - -// The AArch64 compiler generates calls to __trampoline_setup() when creating -// trampoline functions on the stack for use with nested functions. -// This function creates a custom 36-byte trampoline function on the stack -// which loads x18 with a pointer to the outer function's locals -// and then jumps to the target nested function. -// Note: x18 is a reserved platform register on Windows and macOS. - -#if defined(__aarch64__) && defined(__ELF__) -COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack, - int trampSizeAllocated, - const void *realFunc, void *localsPtr) { - // This should never happen, but if compiler did not allocate - // enough space on stack for the trampoline, abort. - if (trampSizeAllocated < 36) - compilerrt_abort(); - - // create trampoline - // Load realFunc into x17. mov/movk 16 bits at a time. - trampOnStack[0] = - 0xd2800000u | ((((uint64_t)realFunc >> 0) & 0xffffu) << 5) | 0x11; - trampOnStack[1] = - 0xf2a00000u | ((((uint64_t)realFunc >> 16) & 0xffffu) << 5) | 0x11; - trampOnStack[2] = - 0xf2c00000u | ((((uint64_t)realFunc >> 32) & 0xffffu) << 5) | 0x11; - trampOnStack[3] = - 0xf2e00000u | ((((uint64_t)realFunc >> 48) & 0xffffu) << 5) | 0x11; - // Load localsPtr into x18 - trampOnStack[4] = - 0xd2800000u | ((((uint64_t)localsPtr >> 0) & 0xffffu) << 5) | 0x12; - trampOnStack[5] = - 0xf2a00000u | ((((uint64_t)localsPtr >> 16) & 0xffffu) << 5) | 0x12; - trampOnStack[6] = - 0xf2c00000u | ((((uint64_t)localsPtr >> 32) & 0xffffu) << 5) | 0x12; - trampOnStack[7] = - 0xf2e00000u | ((((uint64_t)localsPtr >> 48) & 0xffffu) << 5) | 0x12; - trampOnStack[8] = 0xd61f0220; // br x17 - - // Clear instruction cache. - __clear_cache(trampOnStack, &trampOnStack[9]); -} -#endif // defined(__aarch64__) && !defined(__APPLE__) && !defined(_WIN64) diff --git a/system/lib/compiler-rt/lib/builtins/truncsfhf2.c b/system/lib/compiler-rt/lib/builtins/truncsfhf2.c index 379e7cb6f7845..6ad8621b8bb02 100644 --- a/system/lib/compiler-rt/lib/builtins/truncsfhf2.c +++ b/system/lib/compiler-rt/lib/builtins/truncsfhf2.c @@ -16,12 +16,14 @@ COMPILER_RT_ABI NOINLINE dst_t __truncsfhf2(float a) { return __truncXfYf2__(a); } -COMPILER_RT_ABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); } - #if defined(__ARM_EABI__) #if defined(COMPILER_RT_ARMHF_TARGET) +AEABI_RTABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); } AEABI_RTABI dst_t __aeabi_f2h(float a) { return __truncsfhf2(a); } #else +COMPILER_RT_ALIAS(__truncsfhf2, __gnu_f2h_ieee) COMPILER_RT_ALIAS(__truncsfhf2, __aeabi_f2h) #endif +#else +COMPILER_RT_ABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); } #endif diff --git a/system/lib/compiler-rt/lib/builtins/udivmodti4.c b/system/lib/compiler-rt/lib/builtins/udivmodti4.c index 55def37c9e1fe..6ce213fd5f2a4 100644 --- a/system/lib/compiler-rt/lib/builtins/udivmodti4.c +++ b/system/lib/compiler-rt/lib/builtins/udivmodti4.c @@ -83,7 +83,7 @@ static inline du_int udiv128by64to64default(du_int u1, du_int u0, du_int v, static inline du_int udiv128by64to64(du_int u1, du_int u0, du_int v, du_int *r) { -#if defined(__x86_64__) +#if defined(__x86_64__) && !defined(__arm64ec__) du_int result; __asm__("divq %[v]" : "=a"(result), "=d"(*r) diff --git a/system/lib/compiler-rt/lib/interception/interception.h b/system/lib/compiler-rt/lib/interception/interception.h index dc1922ac8f0a6..b33d38effc9ac 100644 --- a/system/lib/compiler-rt/lib/interception/interception.h +++ b/system/lib/compiler-rt/lib/interception/interception.h @@ -19,7 +19,8 @@ #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \ !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \ - !SANITIZER_SOLARIS && !SANITIZER_EMSCRIPTEN + !SANITIZER_SOLARIS && !SANITIZER_HAIKU && !SANITIZER_AIX && \ + !SANITIZER_EMSCRIPTEN # error "Interception doesn't work on this operating system." #endif @@ -168,6 +169,16 @@ const interpose_substitution substitution_##func_name[] \ extern "C" ret_type func(__VA_ARGS__); # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \ extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__); +#elif SANITIZER_AIX +# define WRAP(x) __interceptor_##x +# define TRAMPOLINE(x) WRAP(x) +// # define WRAPPER_NAME(x) "__interceptor_" #x +# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) +// AIX's linker will not select the weak symbol, so don't use weak for the +// interceptors. +# define DECLARE_WRAPPER(ret_type, func, ...) \ + extern "C" ret_type func(__VA_ARGS__) \ + __attribute__((alias("__interceptor_" #func), visibility("default"))); #elif SANITIZER_EMSCRIPTEN # define WRAP(x) x # define INTERCEPTOR_ATTRIBUTE @@ -378,12 +389,17 @@ inline void DoesNotSupportStaticLinking() {} #define INCLUDED_FROM_INTERCEPTION_LIB -#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN +#if SANITIZER_AIX +# include "interception_aix.h" +# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_AIX(func) +# define INTERCEPT_FUNCTION_VER(func, symver) INTERCEPT_FUNCTION_AIX(func) -# include "interception_linux.h" -# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) -# define INTERCEPT_FUNCTION_VER(func, symver) \ +#elif SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ + SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN + +# include "interception_linux.h" +# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) +# define INTERCEPT_FUNCTION_VER(func, symver) \ INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) #elif SANITIZER_APPLE # include "interception_mac.h" diff --git a/system/lib/compiler-rt/lib/interception/interception_aix.cpp b/system/lib/compiler-rt/lib/interception/interception_aix.cpp new file mode 100644 index 0000000000000..953bbad96eb47 --- /dev/null +++ b/system/lib/compiler-rt/lib/interception/interception_aix.cpp @@ -0,0 +1,45 @@ +//===-- interception_aix.cpp ------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// AIX-specific interception methods. +//===----------------------------------------------------------------------===// + +#include "interception.h" +#include "sanitizer_common/sanitizer_common.h" + +#if SANITIZER_AIX + +# include // for dlsym() + +namespace __interception { + +static void *GetFuncAddr(const char *name, uptr wrapper_addr) { + // AIX dlsym can only defect the functions that are exported, so + // on AIX, we can not intercept some basic functions like memcpy. + // FIXME: if we are going to ship dynamic asan library, we may need to search + // all the loaded modules with RTLD_DEFAULT if RTLD_NEXT failed. + void *addr = dlsym(RTLD_NEXT, name); + + // In case `name' is not loaded, dlsym ends up finding the actual wrapper. + // We don't want to intercept the wrapper and have it point to itself. + if ((uptr)addr == wrapper_addr) + addr = nullptr; + return addr; +} + +bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, + uptr wrapper) { + void *addr = GetFuncAddr(name, wrapper); + *ptr_to_real = (uptr)addr; + return addr && (func == wrapper); +} + +} // namespace __interception +#endif // SANITIZER_AIX diff --git a/system/lib/compiler-rt/lib/interception/interception_aix.h b/system/lib/compiler-rt/lib/interception/interception_aix.h new file mode 100644 index 0000000000000..b86ae89f50461 --- /dev/null +++ b/system/lib/compiler-rt/lib/interception/interception_aix.h @@ -0,0 +1,36 @@ +//===-- interception_aix.h --------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// AIX-specific interception methods. +//===----------------------------------------------------------------------===// + +#if SANITIZER_AIX + +# if !defined(INCLUDED_FROM_INTERCEPTION_LIB) +# error \ + "interception_aix.h should be included from interception library only" +# endif + +# ifndef INTERCEPTION_AIX_H +# define INTERCEPTION_AIX_H + +namespace __interception { +bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, + uptr wrapper); +} // namespace __interception + +# define INTERCEPT_FUNCTION_AIX(func) \ + ::__interception::InterceptFunction( \ + #func, (::__interception::uptr *)&REAL(func), \ + (::__interception::uptr) & (func), \ + (::__interception::uptr) & WRAP(func)) + +# endif // INTERCEPTION_AIX_H +#endif // SANITIZER_AIX diff --git a/system/lib/compiler-rt/lib/interception/interception_linux.cpp b/system/lib/compiler-rt/lib/interception/interception_linux.cpp index ef8136eb4fc70..f900ae6a593bd 100644 --- a/system/lib/compiler-rt/lib/interception/interception_linux.cpp +++ b/system/lib/compiler-rt/lib/interception/interception_linux.cpp @@ -14,7 +14,7 @@ #include "interception.h" #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS + SANITIZER_SOLARIS || SANITIZER_HAIKU #include // for dlsym() and dlvsym() @@ -80,4 +80,4 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, } // namespace __interception #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || - // SANITIZER_SOLARIS + // SANITIZER_SOLARIS || SANITIZER_HAIKU diff --git a/system/lib/compiler-rt/lib/interception/interception_linux.h b/system/lib/compiler-rt/lib/interception/interception_linux.h index 557e18269898f..9a6b3ba567e00 100644 --- a/system/lib/compiler-rt/lib/interception/interception_linux.h +++ b/system/lib/compiler-rt/lib/interception/interception_linux.h @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN + SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN #if !defined(INCLUDED_FROM_INTERCEPTION_LIB) # error interception_linux.h should be included from interception library only @@ -52,4 +52,4 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, #endif // INTERCEPTION_LINUX_H #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || - // SANITIZER_SOLARIS + // SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN diff --git a/system/lib/compiler-rt/lib/interception/interception_win.cpp b/system/lib/compiler-rt/lib/interception/interception_win.cpp index 002b37468a200..246a22c56c31a 100644 --- a/system/lib/compiler-rt/lib/interception/interception_win.cpp +++ b/system/lib/compiler-rt/lib/interception/interception_win.cpp @@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xC033: // 33 C0 : xor eax, eax case 0xC933: // 33 C9 : xor ecx, ecx case 0xD233: // 33 D2 : xor edx, edx + case 0x9066: // 66 90 : xchg %ax,%ax (Two-byte NOP) case 0xDB84: // 84 DB : test bl,bl case 0xC084: // 84 C0 : test al,al case 0xC984: // 84 C9 : test cl,cl @@ -726,7 +727,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x5541: // push r13 case 0x5641: // push r14 case 0x5741: // push r15 - case 0x9066: // Two-byte NOP case 0xc084: // test al, al case 0x018a: // mov al, byte ptr [rcx] return 2; @@ -743,6 +743,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX] if (rel_offset) *rel_offset = 2; + FALLTHROUGH; case 0xB841: // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX return 6; @@ -753,6 +754,12 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x7B81: // 81 7B YY XX XX XX XX cmp DWORD PTR [rbx+YY], XX XX XX XX case 0x7981: // 81 79 YY XX XX XX XX cmp dword ptr [rcx+YY], XX XX XX XX return 7; + + case 0xb848: // 48 b8 XX XX XX XX XX XX XX XX : + // movabsq XX XX XX XX XX XX XX XX, rax + case 0xba48: // 48 ba XX XX XX XX XX XX XX XX : + // movabsq XX XX XX XX XX XX XX XX, rdx + return 10; } switch (0x00FFFFFF & *(u32 *)address) { diff --git a/system/lib/compiler-rt/lib/lsan/lsan_allocator.cpp b/system/lib/compiler-rt/lib/lsan/lsan_allocator.cpp index 2507d7f45f38a..e14bee6b69b08 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_allocator.cpp +++ b/system/lib/compiler-rt/lib/lsan/lsan_allocator.cpp @@ -220,6 +220,10 @@ void lsan_free(void *p) { Deallocate(p); } +void lsan_free_sized(void *p, uptr) { Deallocate(p); } + +void lsan_free_aligned_sized(void *p, uptr, uptr) { Deallocate(p); } + void *lsan_realloc(void *p, uptr size, const StackTrace &stack) { return SetErrnoOnNull(Reallocate(stack, p, size, 1)); } diff --git a/system/lib/compiler-rt/lib/lsan/lsan_allocator.h b/system/lib/compiler-rt/lib/lsan/lsan_allocator.h index 5eed0cbdb309b..556b9f56a4a4a 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_allocator.h +++ b/system/lib/compiler-rt/lib/lsan/lsan_allocator.h @@ -53,7 +53,7 @@ struct ChunkMetadata { #if !SANITIZER_CAN_USE_ALLOCATOR64 template struct AP32 { - static const uptr kSpaceBeg = 0; + static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN; static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kMetadataSize = sizeof(ChunkMetadata); typedef __sanitizer::CompactSizeClassMap SizeClassMap; @@ -127,6 +127,8 @@ void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack); void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack); void *lsan_malloc(uptr size, const StackTrace &stack); void lsan_free(void *p); +void lsan_free_sized(void *p, uptr size); +void lsan_free_aligned_sized(void *p, uptr alignment, uptr size); void *lsan_realloc(void *p, uptr size, const StackTrace &stack); void *lsan_reallocarray(void *p, uptr nmemb, uptr size, const StackTrace &stack); diff --git a/system/lib/compiler-rt/lib/lsan/lsan_common.cpp b/system/lib/compiler-rt/lib/lsan/lsan_common.cpp index 8c6d1e9183a88..b24e140417320 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_common.cpp +++ b/system/lib/compiler-rt/lib/lsan/lsan_common.cpp @@ -129,7 +129,8 @@ static const char kStdSuppressions[] = # endif // TLS leak in some glibc versions, described in // https://sourceware.org/bugzilla/show_bug.cgi?id=12650. - "leak:*tls_get_addr*\n"; + "leak:*tls_get_addr*\n" + "leak:*dlerror*\n"; void InitializeSuppressions() { CHECK_EQ(nullptr, suppression_ctx); diff --git a/system/lib/compiler-rt/lib/lsan/lsan_fuchsia.cpp b/system/lib/compiler-rt/lib/lsan/lsan_fuchsia.cpp index ba59bc9b71e33..bb5de89b56729 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_fuchsia.cpp +++ b/system/lib/compiler-rt/lib/lsan/lsan_fuchsia.cpp @@ -21,6 +21,11 @@ using namespace __lsan; +namespace __sanitizer { +// LSan doesn't need to do anything else special in the startup hook. +void EarlySanitizerInit() {} +} // namespace __sanitizer + namespace __lsan { void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {} diff --git a/system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp b/system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp index 39440768c83c1..f0b8bb6f28412 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp +++ b/system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -96,6 +96,35 @@ INTERCEPTOR(void, free, void *p) { lsan_free(p); } +# if SANITIZER_INTERCEPT_FREE_SIZED +INTERCEPTOR(void, free_sized, void *p, uptr size) { + if (UNLIKELY(!p)) + return; + if (DlsymAlloc::PointerIsMine(p)) + return DlsymAlloc::Free(p); + ENSURE_LSAN_INITED; + lsan_free_sized(p, size); +} +# define LSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized) +# else +# define LSAN_MAYBE_INTERCEPT_FREE_SIZED +# endif + +# if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED +INTERCEPTOR(void, free_aligned_sized, void *p, uptr alignment, uptr size) { + if (UNLIKELY(!p)) + return; + if (DlsymAlloc::PointerIsMine(p)) + return DlsymAlloc::Free(p); + ENSURE_LSAN_INITED; + lsan_free_aligned_sized(p, alignment, size); +} +# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \ + INTERCEPT_FUNCTION(free_aligned_sized) +# else +# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED +# endif + INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { if (DlsymAlloc::Use()) return DlsymAlloc::Callocate(nmemb, size); @@ -129,6 +158,9 @@ INTERCEPTOR(void*, valloc, uptr size) { GET_STACK_TRACE_MALLOC; return lsan_valloc(size, stack); } +#else +# define LSAN_MAYBE_INTERCEPT_FREE_SIZED +# define LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED #endif // !SANITIZER_APPLE #if SANITIZER_INTERCEPT_MEMALIGN @@ -568,6 +600,8 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(malloc); INTERCEPT_FUNCTION(free); + LSAN_MAYBE_INTERCEPT_FREE_SIZED; + LSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED; LSAN_MAYBE_INTERCEPT_CFREE; INTERCEPT_FUNCTION(calloc); INTERCEPT_FUNCTION(realloc); diff --git a/system/lib/compiler-rt/lib/lsan/lsan_malloc_mac.cpp b/system/lib/compiler-rt/lib/lsan/lsan_malloc_mac.cpp index 525c30272ccca..8a16c053da238 100644 --- a/system/lib/compiler-rt/lib/lsan/lsan_malloc_mac.cpp +++ b/system/lib/compiler-rt/lib/lsan/lsan_malloc_mac.cpp @@ -44,16 +44,19 @@ using namespace __lsan; void *p = lsan_valloc(size, stack) #define COMMON_MALLOC_FREE(ptr) \ lsan_free(ptr) -#define COMMON_MALLOC_SIZE(ptr) \ - uptr size = lsan_mz_size(ptr) -#define COMMON_MALLOC_FILL_STATS(zone, stats) -#define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ - (void)zone_name; \ - Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", ptr); -#define COMMON_MALLOC_NAMESPACE __lsan -#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0 -#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0 +# define COMMON_MALLOC_FREE_SIZED(ptr, size) lsan_free_sized(ptr, size) +# define COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size) \ + lsan_free_aligned_sized(ptr, alignment, size) +# define COMMON_MALLOC_SIZE(ptr) uptr size = lsan_mz_size(ptr) +# define COMMON_MALLOC_FILL_STATS(zone, stats) +# define COMMON_MALLOC_REPORT_UNKNOWN_REALLOC(ptr, zone_ptr, zone_name) \ + (void)zone_name; \ + Report("mz_realloc(%p) -- attempting to realloc unallocated memory.\n", \ + ptr); +# define COMMON_MALLOC_NAMESPACE __lsan +# define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0 +# define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 0 -#include "sanitizer_common/sanitizer_malloc_mac.inc" +# include "sanitizer_common/sanitizer_malloc_mac.inc" #endif // SANITIZER_APPLE diff --git a/system/lib/compiler-rt/lib/profile/InstrProfiling.h b/system/lib/compiler-rt/lib/profile/InstrProfiling.h index 7f0c0c194dc91..8791d5aa5dd70 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfiling.h +++ b/system/lib/compiler-rt/lib/profile/InstrProfiling.h @@ -124,7 +124,6 @@ ValueProfNode *__llvm_profile_begin_vnodes(void); ValueProfNode *__llvm_profile_end_vnodes(void); const VTableProfData *__llvm_profile_begin_vtables(void); const VTableProfData *__llvm_profile_end_vtables(void); -uint32_t *__llvm_profile_begin_orderfile(void); /*! * \brief Merge profile data from buffer. @@ -175,8 +174,6 @@ void __llvm_profile_instrument_target_value(uint64_t TargetValue, void *Data, */ int __llvm_profile_write_file(void); -int __llvm_orderfile_write_file(void); - /*! * \brief Set the FILE object for writing instrumentation data. Return 0 if set * successfully or return 1 if failed. @@ -280,7 +277,7 @@ uint64_t __llvm_profile_get_vtable_section_size(const VTableProfData *Begin, /* ! \brief Given the sizes of the data and counter information, computes the * number of padding bytes before and after the counter section, as well as the - * number of padding bytes after other setions in the raw profile. + * number of padding bytes after other sections in the raw profile. * Returns -1 upon errors and 0 upon success. Output parameters should be used * iff return value is 0. * @@ -304,6 +301,18 @@ int __llvm_profile_get_padding_sizes_for_counters( */ void __llvm_profile_set_dumped(void); +/*! + * \brief Write custom target-specific profiling data to a separate file. + * Used by offload PGO. + */ +int __llvm_write_custom_profile(const char *Target, + const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd, + const char *CountersBegin, + const char *CountersEnd, const char *NamesBegin, + const char *NamesEnd, + const uint64_t *VersionOverride); + /*! * This variable is defined in InstrProfilingRuntime.cpp as a hidden * symbol. Its main purpose is to enable profile runtime user to diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingBuffer.c b/system/lib/compiler-rt/lib/profile/InstrProfilingBuffer.c index 1c451d7ec7563..b406e8db74f3f 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingBuffer.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingBuffer.c @@ -252,5 +252,6 @@ COMPILER_RT_VISIBILITY int __llvm_profile_write_buffer_internal( &BufferWriter, DataBegin, DataEnd, CountersBegin, CountersEnd, BitmapBegin, BitmapEnd, /*VPDataReader=*/0, NamesBegin, NamesEnd, /*VTableBegin=*/NULL, /*VTableEnd=*/NULL, /*VNamesBegin=*/NULL, - /*VNamesEnd=*/NULL, /*SkipNameDataWrite=*/0); + /*VNamesEnd=*/NULL, /*SkipNameDataWrite=*/0, + __llvm_profile_get_version()); } diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingFile.c b/system/lib/compiler-rt/lib/profile/InstrProfilingFile.c index bad4cc71801ec..354f21b786151 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingFile.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingFile.c @@ -77,6 +77,7 @@ typedef struct lprofFilename { char Hostname[COMPILER_RT_MAX_HOSTLEN]; unsigned NumPids; unsigned NumHosts; + unsigned NumBinaryIds; /* When in-process merging is enabled, this parameter specifies * the total number of profile data files shared by all the processes * spawned from the same binary. By default the value is 1. If merging @@ -88,8 +89,8 @@ typedef struct lprofFilename { ProfileNameSpecifier PNS; } lprofFilename; -static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL, - {0}, 0, 0, 0, PNS_unknown}; +static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL, {0}, + 0, 0, 0, 0, PNS_unknown}; static int ProfileMergeRequested = 0; static int getProfileFileSizeForMerging(FILE *ProfileFile, @@ -233,7 +234,7 @@ COMPILER_RT_VISIBILITY extern int64_t INSTR_PROF_PROFILE_BITMAP_BIAS_VAR #endif static const int ContinuousModeSupported = 1; static const int UseBiasVar = 1; -/* TODO: If there are two DSOs, the second DSO initilization will truncate the +/* TODO: If there are two DSOs, the second DSO initialization will truncate the * first profile file. */ static const char *FileOpenMode = "w+b"; /* This symbol is defined by the compiler when runtime counter relocation is @@ -356,15 +357,6 @@ static uint32_t fileWriter(ProfDataWriter *This, ProfDataIOVec *IOVecs, return 0; } -/* TODO: make buffer size controllable by an internal option, and compiler can pass the size - to runtime via a variable. */ -static uint32_t orderFileWriter(FILE *File, const uint32_t *DataStart) { - if (fwrite(DataStart, sizeof(uint32_t), INSTR_ORDER_FILE_BUFFER_SIZE, File) != - INSTR_ORDER_FILE_BUFFER_SIZE) - return 1; - return 0; -} - static void initFileWriter(ProfDataWriter *This, FILE *File) { This->Write = fileWriter; This->WriterCtx = File; @@ -427,17 +419,17 @@ static int getProfileFileSizeForMerging(FILE *ProfileFile, * \p ProfileBuffer. Returns -1 on failure. On success, the caller is * responsible for unmapping the mmap'd buffer in \p ProfileBuffer. */ static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize, - char **ProfileBuffer) { - *ProfileBuffer = mmap(NULL, ProfileFileSize, PROT_READ, MAP_SHARED | MAP_FILE, - fileno(ProfileFile), 0); - if (*ProfileBuffer == MAP_FAILED) { - PROF_ERR("Unable to merge profile data, mmap failed: %s\n", - strerror(errno)); + ManagedMemory *ProfileBuffer) { + lprofGetFileContentBuffer(ProfileFile, ProfileFileSize, ProfileBuffer); + + if (ProfileBuffer->Status == MS_INVALID) { + PROF_ERR("Unable to merge profile data: %s\n", "reading file failed"); return -1; } - if (__llvm_profile_check_compatibility(*ProfileBuffer, ProfileFileSize)) { - (void)munmap(*ProfileBuffer, ProfileFileSize); + if (__llvm_profile_check_compatibility(ProfileBuffer->Addr, + ProfileFileSize)) { + (void)lprofReleaseBuffer(ProfileBuffer, ProfileFileSize); PROF_WARN("Unable to merge profile data: %s\n", "source profile file is not compatible."); return -1; @@ -446,13 +438,13 @@ static int mmapProfileForMerging(FILE *ProfileFile, uint64_t ProfileFileSize, } /* Read profile data in \c ProfileFile and merge with in-memory - profile counters. Returns -1 if there is fatal error, otheriwse + profile counters. Returns -1 if there is fatal error, otherwise 0 is returned. Returning 0 does not mean merge is actually performed. If merge is actually done, *MergeDone is set to 1. */ static int doProfileMerging(FILE *ProfileFile, int *MergeDone) { uint64_t ProfileFileSize; - char *ProfileBuffer; + ManagedMemory ProfileBuffer; /* Get the size of the profile on disk. */ if (getProfileFileSizeForMerging(ProfileFile, &ProfileFileSize) == -1) @@ -468,9 +460,9 @@ static int doProfileMerging(FILE *ProfileFile, int *MergeDone) { return -1; /* Now start merging */ - if (__llvm_profile_merge_from_buffer(ProfileBuffer, ProfileFileSize)) { + if (__llvm_profile_merge_from_buffer(ProfileBuffer.Addr, ProfileFileSize)) { PROF_ERR("%s\n", "Invalid profile data to merge"); - (void)munmap(ProfileBuffer, ProfileFileSize); + (void)lprofReleaseBuffer(&ProfileBuffer, ProfileFileSize); return -1; } @@ -479,7 +471,7 @@ static int doProfileMerging(FILE *ProfileFile, int *MergeDone) { (void)COMPILER_RT_FTRUNCATE(ProfileFile, __llvm_profile_get_size_for_buffer()); - (void)munmap(ProfileBuffer, ProfileFileSize); + (void)lprofReleaseBuffer(&ProfileBuffer, ProfileFileSize); *MergeDone = 1; return 0; @@ -502,7 +494,7 @@ static void createProfileDir(const char *Filename) { * the original profile data is truncated and gets ready for the profile * dumper. With profile merging enabled, each executable as well as any of * its instrumented shared libraries dump profile data into their own data file. -*/ + */ static FILE *openFileForMerging(const char *ProfileFileName, int *MergeDone) { FILE *ProfileFile = getProfileFile(); int rc; @@ -540,6 +532,17 @@ static FILE *getFileObject(const char *OutputName) { return fopen(OutputName, "ab"); } +static void closeFileObject(FILE *OutputFile) { + if (OutputFile == getProfileFile()) { + fflush(OutputFile); + if (doMerging() && !__llvm_profile_is_continuous_mode_enabled()) { + lprofUnlockFileHandle(OutputFile); + } + } else { + fclose(OutputFile); + } +} + /* Write profile data to file \c OutputName. */ static int writeFile(const char *OutputName) { int RetVal; @@ -561,36 +564,7 @@ static int writeFile(const char *OutputName) { initFileWriter(&fileWriter, OutputFile); RetVal = lprofWriteData(&fileWriter, lprofGetVPDataReader(), MergeDone); - if (OutputFile == getProfileFile()) { - fflush(OutputFile); - if (doMerging() && !__llvm_profile_is_continuous_mode_enabled()) { - lprofUnlockFileHandle(OutputFile); - } - } else { - fclose(OutputFile); - } - - return RetVal; -} - -/* Write order data to file \c OutputName. */ -static int writeOrderFile(const char *OutputName) { - int RetVal; - FILE *OutputFile; - - OutputFile = fopen(OutputName, "w"); - - if (!OutputFile) { - PROF_WARN("can't open file with mode ab: %s\n", OutputName); - return -1; - } - - FreeHook = &free; - setupIOBuffer(); - const uint32_t *DataBegin = __llvm_profile_begin_orderfile(); - RetVal = orderFileWriter(OutputFile, DataBegin); - - fclose(OutputFile); + closeFileObject(OutputFile); return RetVal; } @@ -698,13 +672,13 @@ static void initializeProfileForContinuousMode(void) { } else { /* The merged profile has a non-zero length. Check that it is compatible * with the data in this process. */ - char *ProfileBuffer; + ManagedMemory ProfileBuffer; if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) { lprofUnlockFileHandle(File); fclose(File); return; } - (void)munmap(ProfileBuffer, ProfileFileSize); + (void)lprofReleaseBuffer(&ProfileBuffer, ProfileFileSize); } } else { File = fopen(Filename, FileOpenMode); @@ -790,7 +764,7 @@ static int checkBounds(int Idx, int Strlen) { * lprofcurFilename structure. */ static int parseFilenamePattern(const char *FilenamePat, unsigned CopyFilenamePat) { - int NumPids = 0, NumHosts = 0, I; + int NumPids = 0, NumHosts = 0, NumBinaryIds = 0, I; char *PidChars = &lprofCurFilename.PidChars[0]; char *Hostname = &lprofCurFilename.Hostname[0]; int MergingEnabled = 0; @@ -855,6 +829,16 @@ static int parseFilenamePattern(const char *FilenamePat, FilenamePat); return -1; } + } else if (FilenamePat[I] == 'b') { + if (!NumBinaryIds++) { + /* Check if binary ID does not exist or if its size is 0. */ + if (__llvm_write_binary_ids(NULL) <= 0) { + PROF_WARN("Unable to get binary ID for filename pattern %s. Using " + "the default name.", + FilenamePat); + return -1; + } + } } else if (FilenamePat[I] == 'c') { if (__llvm_profile_is_continuous_mode_enabled()) { PROF_WARN("%%c specifier can only be specified once in %s.\n", @@ -866,8 +850,9 @@ static int parseFilenamePattern(const char *FilenamePat, __llvm_profile_set_page_size(getpagesize()); __llvm_profile_enable_continuous_mode(); #else - PROF_WARN("%s", "Continous mode is currently only supported for Mach-O," - " ELF and COFF formats."); + PROF_WARN("%s", + "Continuous mode is currently only supported for Mach-O," + " ELF and COFF formats."); return -1; #endif } else { @@ -887,6 +872,7 @@ static int parseFilenamePattern(const char *FilenamePat, lprofCurFilename.NumPids = NumPids; lprofCurFilename.NumHosts = NumHosts; + lprofCurFilename.NumBinaryIds = NumBinaryIds; return 0; } @@ -934,24 +920,53 @@ static void parseAndSetFilename(const char *FilenamePat, * filename with PID and hostname substitutions. */ /* The length to hold uint64_t followed by 3 digits pool id including '_' */ #define SIGLEN 24 +/* The length to hold 160-bit hash in hexadecimal form */ +#define BINARY_ID_LEN 40 static int getCurFilenameLength(void) { int Len; if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0]) return 0; if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts || - lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize)) + lprofCurFilename.NumBinaryIds || lprofCurFilename.TmpDir || + lprofCurFilename.MergePoolSize)) return strlen(lprofCurFilename.FilenamePat); Len = strlen(lprofCurFilename.FilenamePat) + lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) + lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) + + lprofCurFilename.NumBinaryIds * BINARY_ID_LEN + (lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0); if (lprofCurFilename.MergePoolSize) Len += SIGLEN; return Len; } +typedef struct lprofBinaryIdsBuffer { + char String[BINARY_ID_LEN + 1]; + int Length; +} lprofBinaryIdsBuffer; + +/* Reads binary ID length and then its data, writes it into lprofBinaryIdsBuffer + * in hexadecimal form. */ +static uint32_t binaryIdsStringWriter(ProfDataWriter *This, + ProfDataIOVec *IOVecs, + uint32_t NumIOVecs) { + if (NumIOVecs < 2 || IOVecs[0].ElmSize != sizeof(uint64_t)) + return -1; + uint64_t BinaryIdLen = *(const uint64_t *)IOVecs[0].Data; + if (IOVecs[1].ElmSize != sizeof(uint8_t) || IOVecs[1].NumElm != BinaryIdLen) + return -1; + const uint8_t *BinaryIdData = (const uint8_t *)IOVecs[1].Data; + lprofBinaryIdsBuffer *Data = (lprofBinaryIdsBuffer *)This->WriterCtx; + for (uint64_t I = 0; I < BinaryIdLen; I++) { + Data->Length += + snprintf(Data->String + Data->Length, BINARY_ID_LEN + 1 - Data->Length, + "%02hhx", BinaryIdData[I]); + } + return 0; +} + /* Return the pointer to the current profile file name (after substituting * PIDs and Hostnames in filename pattern. \p FilenameBuf is the buffer * to store the resulting filename. If no substitution is needed, the @@ -965,7 +980,8 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) { return 0; if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts || - lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize || + lprofCurFilename.NumBinaryIds || lprofCurFilename.TmpDir || + lprofCurFilename.MergePoolSize || __llvm_profile_is_continuous_mode_enabled())) { if (!ForceUseBuf) return lprofCurFilename.FilenamePat; @@ -992,6 +1008,12 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) { memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength); FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR; J += TmpDirLength + 1; + } else if (FilenamePat[I] == 'b') { + lprofBinaryIdsBuffer Data = {{0}, 0}; + ProfDataWriter Writer = {binaryIdsStringWriter, &Data}; + __llvm_write_binary_ids(&Writer); + memcpy(FilenameBuf + J, Data.String, Data.Length); + J += Data.Length; } else { if (!getMergePoolSize(FilenamePat, &I)) continue; @@ -1066,8 +1088,10 @@ const char *__llvm_profile_get_filename(void) { return "\0"; } Filename = getCurFilename(FilenameBuf, 1); - if (!Filename) + if (!Filename) { + free(FilenameBuf); return "\0"; + } return FilenameBuf; } @@ -1188,65 +1212,6 @@ int __llvm_profile_dump(void) { return rc; } -/* Order file data will be saved in a file with suffx .order. */ -static const char *OrderFileSuffix = ".order"; - -COMPILER_RT_VISIBILITY -int __llvm_orderfile_write_file(void) { - int rc, Length, LengthBeforeAppend, SuffixLength; - const char *Filename; - char *FilenameBuf; - - // Temporarily suspend getting SIGKILL when the parent exits. - int PDeathSig = lprofSuspendSigKill(); - - SuffixLength = strlen(OrderFileSuffix); - Length = getCurFilenameLength() + SuffixLength; - FilenameBuf = (char *)COMPILER_RT_ALLOCA(Length + 1); - Filename = getCurFilename(FilenameBuf, 1); - - /* Check the filename. */ - if (!Filename) { - PROF_ERR("Failed to write file : %s\n", "Filename not set"); - if (PDeathSig == 1) - lprofRestoreSigKill(); - return -1; - } - - /* Append order file suffix */ - LengthBeforeAppend = strlen(Filename); - memcpy(FilenameBuf + LengthBeforeAppend, OrderFileSuffix, SuffixLength); - FilenameBuf[LengthBeforeAppend + SuffixLength] = '\0'; - - /* Check if there is llvm/runtime version mismatch. */ - if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) { - PROF_ERR("Runtime and instrumentation version mismatch : " - "expected %d, but get %d\n", - INSTR_PROF_RAW_VERSION, - (int)GET_VERSION(__llvm_profile_get_version())); - if (PDeathSig == 1) - lprofRestoreSigKill(); - return -1; - } - - /* Write order data to the file. */ - rc = writeOrderFile(Filename); - if (rc) - PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno)); - - // Restore SIGKILL. - if (PDeathSig == 1) - lprofRestoreSigKill(); - - return rc; -} - -COMPILER_RT_VISIBILITY -int __llvm_orderfile_dump(void) { - int rc = __llvm_orderfile_write_file(); - return rc; -} - static void writeFileWithoutReturn(void) { __llvm_profile_write_file(); } COMPILER_RT_VISIBILITY @@ -1295,12 +1260,12 @@ COMPILER_RT_VISIBILITY int __llvm_profile_set_file_object(FILE *File, } else { /* The merged profile has a non-zero length. Check that it is compatible * with the data in this process. */ - char *ProfileBuffer; + ManagedMemory ProfileBuffer; if (mmapProfileForMerging(File, ProfileFileSize, &ProfileBuffer) == -1) { lprofUnlockFileHandle(File); return 1; } - (void)munmap(ProfileBuffer, ProfileFileSize); + (void)lprofReleaseBuffer(&ProfileBuffer, ProfileFileSize); } mmapForContinuousMode(0, File); lprofUnlockFileHandle(File); @@ -1311,4 +1276,115 @@ COMPILER_RT_VISIBILITY int __llvm_profile_set_file_object(FILE *File, return 0; } +#ifndef __APPLE__ +int __llvm_write_custom_profile(const char *Target, + const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd, + const char *CountersBegin, + const char *CountersEnd, const char *NamesBegin, + const char *NamesEnd, + const uint64_t *VersionOverride) { + int ReturnValue = 0, FilenameLength, TargetLength; + char *FilenameBuf, *TargetFilename; + const char *Filename; + + /* Save old profile data */ + FILE *oldFile = getProfileFile(); + + // Temporarily suspend getting SIGKILL when the parent exits. + int PDeathSig = lprofSuspendSigKill(); + + if (lprofProfileDumped() || __llvm_profile_is_continuous_mode_enabled()) { + PROF_NOTE("Profile data not written to file: %s.\n", "already written"); + if (PDeathSig == 1) + lprofRestoreSigKill(); + return 0; + } + + /* Check if there is llvm/runtime version mismatch. */ + if (GET_VERSION(__llvm_profile_get_version()) != INSTR_PROF_RAW_VERSION) { + PROF_ERR("Runtime and instrumentation version mismatch : " + "expected %d, but get %d\n", + INSTR_PROF_RAW_VERSION, + (int)GET_VERSION(__llvm_profile_get_version())); + if (PDeathSig == 1) + lprofRestoreSigKill(); + return -1; + } + + /* Get current filename */ + FilenameLength = getCurFilenameLength(); + FilenameBuf = (char *)COMPILER_RT_ALLOCA(FilenameLength + 1); + Filename = getCurFilename(FilenameBuf, 0); + + /* Check the filename. */ + if (!Filename) { + PROF_ERR("Failed to write file : %s\n", "Filename not set"); + if (PDeathSig == 1) + lprofRestoreSigKill(); + return -1; + } + + /* Allocate new space for our target-specific PGO filename */ + TargetLength = strlen(Target); + TargetFilename = + (char *)COMPILER_RT_ALLOCA(FilenameLength + TargetLength + 2); + + /* Find file basename and path sizes */ + int32_t DirEnd = FilenameLength - 1; + while (DirEnd >= 0 && !IS_DIR_SEPARATOR(Filename[DirEnd])) { + DirEnd--; + } + uint32_t DirSize = DirEnd + 1, BaseSize = FilenameLength - DirSize; + + /* Prepend "TARGET." to current filename */ + if (DirSize > 0) { + memcpy(TargetFilename, Filename, DirSize); + } + memcpy(TargetFilename + DirSize, Target, TargetLength); + TargetFilename[TargetLength + DirSize] = '.'; + memcpy(TargetFilename + DirSize + 1 + TargetLength, Filename + DirSize, + BaseSize); + TargetFilename[FilenameLength + 1 + TargetLength] = 0; + + /* Open and truncate target-specific PGO file */ + FILE *OutputFile = fopen(TargetFilename, "w"); + setProfileFile(OutputFile); + + if (!OutputFile) { + PROF_ERR("Failed to open file : %s\n", TargetFilename); + if (PDeathSig == 1) + lprofRestoreSigKill(); + return -1; + } + + FreeHook = &free; + setupIOBuffer(); + + /* Write custom data */ + ProfDataWriter fileWriter; + initFileWriter(&fileWriter, OutputFile); + + uint64_t Version = __llvm_profile_get_version(); + if (VersionOverride) + Version = *VersionOverride; + + /* Write custom data to the file */ + ReturnValue = + lprofWriteDataImpl(&fileWriter, DataBegin, DataEnd, CountersBegin, + CountersEnd, NULL, NULL, lprofGetVPDataReader(), NULL, + NULL, NULL, NULL, NamesBegin, NamesEnd, 0, Version); + closeFileObject(OutputFile); + + // Restore SIGKILL. + if (PDeathSig == 1) + lprofRestoreSigKill(); + + /* Restore old profiling file */ + setProfileFile(oldFile); + + return ReturnValue; +} +#endif + #endif diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingInternal.h b/system/lib/compiler-rt/lib/profile/InstrProfilingInternal.h index b100343ca04f9..5647782527eb7 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingInternal.h +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingInternal.h @@ -128,7 +128,7 @@ typedef struct VPDataReaderType { uint8_t *SiteCountArray[]); /* Function pointer to getValueProfRecordHeader method. */ uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites); - /* Function pointer to getFristValueProfRecord method. */ + /* Function pointer to getFirstValueProfRecord method. */ struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *); /* Return the number of value data for site \p Site. */ uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site); @@ -160,7 +160,8 @@ int lprofWriteDataImpl(ProfDataWriter *Writer, VPDataReaderType *VPDataReader, const char *NamesBegin, const char *NamesEnd, const VTableProfData *VTableBegin, const VTableProfData *VTableEnd, const char *VNamesBegin, - const char *VNamesEnd, int SkipNameDataWrite); + const char *VNamesEnd, int SkipNameDataWrite, + uint64_t Version); /* Merge value profile data pointed to by SrcValueProfData into * in-memory profile counters pointed by to DstData. */ diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c index 651f8785d0b94..9cb313bc7a1fc 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c @@ -196,8 +196,6 @@ static const int dummy_name[0] COMPILER_RT_SECTION( COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME); static int dummy_vnds[0] COMPILER_RT_SECTION( COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME); -static int dummy_orderfile[0] COMPILER_RT_SECTION( - COMPILER_RT_SEG INSTR_PROF_ORDERFILE_SECT_NAME); static int dummy_vname[0] COMPILER_RT_SECTION( COMPILER_RT_SEG INSTR_PROF_VNAME_SECT_NAME); static int dummy_vtab[0] COMPILER_RT_SECTION( @@ -213,11 +211,10 @@ static int dummy_covinit_funcs[0] COMPILER_RT_SECTION( #pragma GCC diagnostic ignored "-Wcast-qual" #endif COMPILER_RT_VISIBILITY -void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_bits, - (void *)&dummy_data, (void *)&dummy_name, - (void *)&dummy_vnds, (void *)&dummy_orderfile, - (void *)&dummy_vname, (void *)&dummy_vtab, - (void *)&dummy_covinit_funcs}; +void *__llvm_profile_keep[] = { + (void *)&dummy_cnts, (void *)&dummy_bits, (void *)&dummy_data, + (void *)&dummy_name, (void *)&dummy_vnds, (void *)&dummy_vname, + (void *)&dummy_vtab, (void *)&dummy_covinit_funcs}; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c index 6adc7f328cbf7..8c682ae118358 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformDarwin.c @@ -47,8 +47,6 @@ extern char COMPILER_RT_VISIBILITY extern char VNameEnd __asm("section$end$__DATA$" INSTR_PROF_VNAME_SECT_NAME); COMPILER_RT_VISIBILITY -extern uint32_t - OrderFileStart __asm("section$start$__DATA$" INSTR_PROF_ORDERFILE_SECT_NAME); COMPILER_RT_VISIBILITY extern ValueProfNode @@ -87,8 +85,6 @@ COMPILER_RT_VISIBILITY const char *__llvm_profile_begin_vtabnames(void) { return &VNameStart; } COMPILER_RT_VISIBILITY const char *__llvm_profile_end_vtabnames(void) { return &VNameEnd; } -COMPILER_RT_VISIBILITY -uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; } COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_begin_vnodes(void) { diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index 5b230c1b20062..558b7fc8cad62 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -32,7 +32,6 @@ #define PROF_VTABLE_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VTAB_COMMON) #define PROF_BITS_START INSTR_PROF_SECT_START(INSTR_PROF_BITS_COMMON) #define PROF_BITS_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_BITS_COMMON) -#define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON) #define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON) #define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON) #define PROF_COVINIT_START INSTR_PROF_SECT_START(INSTR_PROF_COVINIT_COMMON) @@ -53,7 +52,6 @@ extern char PROF_VNAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_VNAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_BITS_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_BITS_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; -extern uint32_t PROF_ORDERFILE_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; @@ -102,9 +100,6 @@ COMPILER_RT_VISIBILITY char *__llvm_profile_begin_bitmap(void) { COMPILER_RT_VISIBILITY char *__llvm_profile_end_bitmap(void) { return &PROF_BITS_STOP; } -COMPILER_RT_VISIBILITY uint32_t *__llvm_profile_begin_orderfile(void) { - return &PROF_ORDERFILE_START; -} COMPILER_RT_VISIBILITY ValueProfNode * __llvm_profile_begin_vnodes(void) { diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformOther.c index 29e570b9fba92..19414ab78b3be 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformOther.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformOther.c @@ -27,7 +27,6 @@ static const char *VNamesFirst = NULL; static const char *VNamesLast = NULL; static char *CountersFirst = NULL; static char *CountersLast = NULL; -static uint32_t *OrderFileFirst = NULL; static const void *getMinAddr(const void *A1, const void *A2) { return A1 < A2 ? A1 : A2; @@ -108,9 +107,6 @@ COMPILER_RT_VISIBILITY char *__llvm_profile_begin_bitmap(void) { return BitmapFirst; } COMPILER_RT_VISIBILITY char *__llvm_profile_end_bitmap(void) { return BitmapLast; } -/* TODO: correctly set up OrderFileFirst. */ -COMPILER_RT_VISIBILITY -uint32_t *__llvm_profile_begin_orderfile(void) { return OrderFileFirst; } COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_begin_vnodes(void) { diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c index 741b01faada4e..d1b347e861411 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c @@ -36,7 +36,6 @@ #pragma section(".lprfc$Z", read, write) #pragma section(".lprfb$A", read, write) #pragma section(".lprfb$Z", read, write) -#pragma section(".lorderfile$A", read, write) #pragma section(".lprfnd$A", read, write) #pragma section(".lprfnd$Z", read, write) #endif @@ -51,7 +50,6 @@ char COMPILER_RT_SECTION(".lprfc$A") CountersStart; char COMPILER_RT_SECTION(".lprfc$Z") CountersEnd; char COMPILER_RT_SECTION(".lprfb$A") BitmapStart; char COMPILER_RT_SECTION(".lprfb$Z") BitmapEnd; -uint32_t COMPILER_RT_SECTION(".lorderfile$A") OrderFileStart; ValueProfNode COMPILER_RT_SECTION(".lprfnd$A") VNodesStart; ValueProfNode COMPILER_RT_SECTION(".lprfnd$Z") VNodesEnd; @@ -85,7 +83,6 @@ char *__llvm_profile_begin_counters(void) { return &CountersStart + 1; } char *__llvm_profile_end_counters(void) { return &CountersEnd; } char *__llvm_profile_begin_bitmap(void) { return &BitmapStart + 1; } char *__llvm_profile_end_bitmap(void) { return &BitmapEnd; } -uint32_t *__llvm_profile_begin_orderfile(void) { return &OrderFileStart; } ValueProfNode *__llvm_profile_begin_vnodes(void) { return &VNodesStart + 1; } ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; } diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.c b/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.c index c637b9d0b893c..0fae91cfb8950 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.c @@ -21,6 +21,15 @@ #include #endif +#ifdef _AIX +#include +// depends on `uint` to be a typedef from to +// `uint_t`; however, does not always declare `uint`. We provide +// the typedef prior to including to work around this issue. +typedef uint_t uint; +#include +#endif + #ifdef COMPILER_RT_HAS_UNAME #include #endif @@ -258,6 +267,121 @@ COMPILER_RT_VISIBILITY FILE *lprofOpenFileEx(const char *ProfileName) { return f; } +#if defined(_AIX) +// Return 1 (true) if the file descriptor Fd represents a file that is on a +// local filesystem, otherwise return 0. +static int isLocalFilesystem(int Fd) { + struct statfs Vfs; + if (fstatfs(Fd, &Vfs) != 0) { + PROF_ERR("%s: fstatfs(%d) failed: %s\n", __func__, Fd, strerror(errno)); + return 0; + } + + int Ret; + size_t BufSize = 2048u; + char *Buf; + int Tries = 3; + while (Tries--) { + Buf = malloc(BufSize); + // mntctl returns -1 if `Buf` is `NULL`. + Ret = mntctl(MCTL_QUERY, BufSize, Buf); + if (Ret != 0) + break; + BufSize = *(unsigned int *)Buf; + free(Buf); + } + + if (Ret != -1) { + // Look for the correct vmount entry. + char *CurObjPtr = Buf; + while (Ret--) { + struct vmount *Vp = (struct vmount *)CurObjPtr; + _Static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), + "fsid length mismatch"); + if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) { + int Answer = (Vp->vmt_flags & MNT_REMOTE) == 0; + free(Buf); + return Answer; + } + CurObjPtr += Vp->vmt_length; + } + } + + free(Buf); + // There was an error in mntctl or vmount entry not found; "remote" is the + // conservative answer. + return 0; +} +#endif + +static int isMmapSafe(int Fd) { + if (getenv("LLVM_PROFILE_NO_MMAP")) // For testing purposes. + return 0; +#ifdef _AIX + return isLocalFilesystem(Fd); +#else + return 1; +#endif +} + +COMPILER_RT_VISIBILITY void lprofGetFileContentBuffer(FILE *F, uint64_t Length, + ManagedMemory *Buf) { + Buf->Status = MS_INVALID; + if (isMmapSafe(fileno(F))) { + Buf->Addr = + mmap(NULL, Length, PROT_READ, MAP_SHARED | MAP_FILE, fileno(F), 0); + if (Buf->Addr == MAP_FAILED) + PROF_ERR("%s: mmap failed: %s\n", __func__, strerror(errno)) + else + Buf->Status = MS_MMAP; + return; + } + + if (getenv("LLVM_PROFILE_VERBOSE")) + PROF_NOTE("%s\n", "could not use mmap; using fread instead"); + + void *Buffer = malloc(Length); + if (!Buffer) { + PROF_ERR("%s: malloc failed: %s\n", __func__, strerror(errno)); + return; + } + if (ftell(F) != 0) { + PROF_ERR("%s: expecting ftell to return zero\n", __func__); + free(Buffer); + return; + } + + // Read the entire file into memory. + size_t BytesRead = fread(Buffer, 1, Length, F); + if (BytesRead != (size_t)Length) { + PROF_ERR("%s: fread failed%s\n", __func__, + feof(F) ? ": end of file reached" : ""); + free(Buffer); + return; + } + + // Reading was successful, record the result in the Buf parameter. + Buf->Addr = Buffer; + Buf->Status = MS_MALLOC; +} + +COMPILER_RT_VISIBILITY +void lprofReleaseBuffer(ManagedMemory *Buf, size_t Length) { + switch (Buf->Status) { + case MS_MALLOC: + free(Buf->Addr); + break; + case MS_MMAP: + (void)munmap(Buf->Addr, Length); + break; + default: + PROF_ERR("%s: Buffer has invalid state: %d\n", __func__, Buf->Status); + break; + } + Buf->Addr = NULL; + Buf->Status = MS_INVALID; +} + COMPILER_RT_VISIBILITY const char *lprofGetPathPrefix(int *PrefixStrip, size_t *PrefixLen) { const char *Prefix = getenv("GCOV_PREFIX"); diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.h b/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.h index 227c2aa0a7cae..234cf26cc0af7 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.h +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingUtil.h @@ -31,6 +31,25 @@ int lprofUnlockFileHandle(FILE *F); * lock for exclusive access. The caller will block * if the lock is already held by another process. */ FILE *lprofOpenFileEx(const char *Filename); + +enum MemoryStatus { + MS_INVALID, // Addr is not a valid address + MS_MMAP, // Addr was mmap'ed + MS_MALLOC // Addr was malloc'ed +}; +typedef struct { + void *Addr; + enum MemoryStatus Status; +} ManagedMemory; + +/* Read the content of a file using mmap or fread into a buffer. + * Certain files (e.g. NFS mounted) cannot be opened reliably with mmap, + * so we use fread in those cases. The corresponding lprofReleaseBuffer + * will free/munmap the buffer. + */ +void lprofGetFileContentBuffer(FILE *F, uint64_t FileSize, ManagedMemory *Buf); +void lprofReleaseBuffer(ManagedMemory *FileBuffer, size_t Length); + /* PS4 doesn't have setenv/getenv/fork. Define a shim. */ #if __ORBIS__ #include diff --git a/system/lib/compiler-rt/lib/profile/InstrProfilingWriter.c b/system/lib/compiler-rt/lib/profile/InstrProfilingWriter.c index 8816a71155511..633fdb9661162 100644 --- a/system/lib/compiler-rt/lib/profile/InstrProfilingWriter.c +++ b/system/lib/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -254,21 +254,21 @@ COMPILER_RT_VISIBILITY int lprofWriteData(ProfDataWriter *Writer, const VTableProfData *VTableEnd = __llvm_profile_end_vtables(); const char *VNamesBegin = __llvm_profile_begin_vtabnames(); const char *VNamesEnd = __llvm_profile_end_vtabnames(); + uint64_t Version = __llvm_profile_get_version(); return lprofWriteDataImpl(Writer, DataBegin, DataEnd, CountersBegin, CountersEnd, BitmapBegin, BitmapEnd, VPDataReader, NamesBegin, NamesEnd, VTableBegin, VTableEnd, - VNamesBegin, VNamesEnd, SkipNameDataWrite); + VNamesBegin, VNamesEnd, SkipNameDataWrite, Version); } -COMPILER_RT_VISIBILITY int -lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin, - const __llvm_profile_data *DataEnd, - const char *CountersBegin, const char *CountersEnd, - const char *BitmapBegin, const char *BitmapEnd, - VPDataReaderType *VPDataReader, const char *NamesBegin, - const char *NamesEnd, const VTableProfData *VTableBegin, - const VTableProfData *VTableEnd, const char *VNamesBegin, - const char *VNamesEnd, int SkipNameDataWrite) { +COMPILER_RT_VISIBILITY int lprofWriteDataImpl( + ProfDataWriter *Writer, const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd, const char *CountersBegin, + const char *CountersEnd, const char *BitmapBegin, const char *BitmapEnd, + VPDataReaderType *VPDataReader, const char *NamesBegin, + const char *NamesEnd, const VTableProfData *VTableBegin, + const VTableProfData *VTableEnd, const char *VNamesBegin, + const char *VNamesEnd, int SkipNameDataWrite, uint64_t Version) { /* Calculate size of sections. */ const uint64_t DataSectionSize = __llvm_profile_get_data_size(DataBegin, DataEnd); @@ -308,6 +308,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin, #define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init; #include "profile/InstrProfData.inc" } + Header.Version = Version; /* On WIN64, label differences are truncated 32-bit values. Truncate * CountersDelta to match. */ diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h index 62523c7ae187c..6c2020e6373c0 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h @@ -23,7 +23,7 @@ namespace __sanitizer { typedef CompactSizeClassMap InternalSizeClassMap; struct AP32 { - static const uptr kSpaceBeg = 0; + static const uptr kSpaceBeg = SANITIZER_MMAP_BEGIN; static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kMetadataSize = 0; typedef InternalSizeClassMap SizeClassMap; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h index e495c56f03775..6e54c4852fbb6 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h @@ -166,7 +166,7 @@ struct SizeClassAllocator32LocalCache { DCHECK_GT(c->count, 0); } void *res = c->batch[--c->count]; - PREFETCH(c->batch[c->count - 1]); + PREFETCH(c->batch[c->count > 0 ? c->count - 1 : 0]); stats_.Add(AllocatorStatAllocated, c->class_size); return res; } diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h index 1414092e38d7e..fded66546f810 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang.h @@ -14,6 +14,18 @@ #ifndef SANITIZER_ATOMIC_CLANG_H #define SANITIZER_ATOMIC_CLANG_H +// Helper to suppress warnings related to 8-byte atomic accesses when the target +// is 32-bit AIX (where such accesses use libatomic). +#if defined(_AIX) && !defined(__powerpc64__) && defined(__clang__) +# define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Watomic-alignment\"") +# define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END _Pragma("clang diagnostic pop") +#else +# define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN +# define SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END +#endif + namespace __sanitizer { // We use the compiler builtin atomic operations for loads and stores, which @@ -35,6 +47,7 @@ inline void proc_yield(int cnt) { #endif } +SANITIZER_IGNORE_ATOMIC_ALIGNMENT_BEGIN template inline typename T::Type atomic_load(const volatile T *a, memory_order mo) { DCHECK(mo == memory_order_relaxed || mo == memory_order_consume || @@ -92,6 +105,8 @@ inline bool atomic_compare_exchange_weak(volatile T *a, typename T::Type *cmp, return atomic_compare_exchange_strong(a, cmp, xchg, mo); } +SANITIZER_IGNORE_ATOMIC_ALIGNMENT_END + } // namespace __sanitizer #undef ATOMIC_ORDER diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common.h index d9e7ded593feb..120c2861c1ac0 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -166,7 +166,7 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, // Used to check if we can map shadow memory to a fixed location. bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); -// Releases memory pages entirely within the [beg, end] address range. Noop if +// Releases memory pages entirely within the [beg, end) address range. Noop if // the provided range does not contain at least one entire page. void ReleaseMemoryPagesToOS(uptr beg, uptr end); void IncreaseTotalMmap(uptr size); @@ -925,12 +925,6 @@ class ListOfModules { // Callback type for iterating over a set of memory ranges. typedef void (*RangeIteratorCallback)(uptr begin, uptr end, void *arg); -enum AndroidApiLevel { - ANDROID_NOT_ANDROID = 0, - ANDROID_LOLLIPOP_MR1 = 22, - ANDROID_POST_LOLLIPOP = 23 -}; - void WriteToSyslog(const char *buffer); #if defined(SANITIZER_WINDOWS) && defined(_MSC_VER) && !defined(__clang__) @@ -963,19 +957,8 @@ inline void AndroidLogInit() {} inline void SetAbortMessage(const char *) {} #endif -#if SANITIZER_ANDROID -void SanitizerInitializeUnwinder(); -AndroidApiLevel AndroidGetApiLevel(); -#else -inline void AndroidLogWrite(const char *buffer_unused) {} -inline void SanitizerInitializeUnwinder() {} -inline AndroidApiLevel AndroidGetApiLevel() { return ANDROID_NOT_ANDROID; } -#endif - inline uptr GetPthreadDestructorIterations() { -#if SANITIZER_ANDROID - return (AndroidGetApiLevel() == ANDROID_LOLLIPOP_MR1) ? 8 : 4; -#elif SANITIZER_POSIX +#if SANITIZER_POSIX return 4; #else // Unused on Windows. diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 24a8a2d4dc55b..2d6cf7fc3282f 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -481,7 +481,8 @@ INTERCEPTOR(char*, textdomain, const char *domainname) { #endif #if SANITIZER_INTERCEPT_STRCMP || SANITIZER_INTERCEPT_MEMCMP -static inline int CharCmpX(unsigned char c1, unsigned char c2) { +[[maybe_unused]] static inline int CharCmpX(unsigned char c1, + unsigned char c2) { return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; } #endif @@ -953,7 +954,7 @@ INTERCEPTOR(double, frexp, double x, int *exp) { #define INIT_FREXP #endif // SANITIZER_INTERCEPT_FREXP -#if SANITIZER_INTERCEPT_FREXPF_FREXPL +#if SANITIZER_INTERCEPT_FREXPF INTERCEPTOR(float, frexpf, float x, int *exp) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp); @@ -963,6 +964,12 @@ INTERCEPTOR(float, frexpf, float x, int *exp) { return res; } +# define INIT_FREXPF COMMON_INTERCEPT_FUNCTION(frexpf); +#else +# define INIT_FREXPF +#endif + +#if SANITIZER_INTERCEPT_FREXPL INTERCEPTOR(long double, frexpl, long double x, int *exp) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp); @@ -972,12 +979,10 @@ INTERCEPTOR(long double, frexpl, long double x, int *exp) { return res; } -#define INIT_FREXPF_FREXPL \ - COMMON_INTERCEPT_FUNCTION(frexpf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(frexpl) +# define INIT_FREXPL COMMON_INTERCEPT_FUNCTION_LDBL(frexpl) #else -#define INIT_FREXPF_FREXPL -#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL +# define INIT_FREXPL +#endif #if SI_POSIX static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec, @@ -1346,7 +1351,8 @@ INTERCEPTOR(unsigned long, time, unsigned long *t) { #if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS static void unpoison_tm(void *ctx, __sanitizer_tm *tm) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm)); -#if !SANITIZER_SOLARIS +// AIX tm struct does not have tm_zone field. +# if !SANITIZER_SOLARIS && !SANITIZER_AIX if (tm->tm_zone) { // Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone // can point to shared memory and tsan would report a data race. @@ -1731,10 +1737,12 @@ INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to, VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap) #endif +# if SANITIZER_INTERCEPT_VASPRINTF INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap) +# endif -#if SANITIZER_INTERCEPT_ISOC99_PRINTF +# if SANITIZER_INTERCEPT_ISOC99_PRINTF INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap) VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap) @@ -1783,10 +1791,12 @@ INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag, FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) #endif +# if SANITIZER_INTERCEPT_ASPRINTF INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format) +# endif -#if SANITIZER_INTERCEPT_ISOC99_PRINTF +# if SANITIZER_INTERCEPT_ISOC99_PRINTF INTERCEPTOR(int, __isoc99_printf, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format) @@ -1807,17 +1817,24 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size, #endif // SANITIZER_INTERCEPT_PRINTF #if SANITIZER_INTERCEPT_PRINTF -#define INIT_PRINTF \ - COMMON_INTERCEPT_FUNCTION_LDBL(printf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \ - COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf); +# define INIT_PRINTF_COMMON \ + COMMON_INTERCEPT_FUNCTION_LDBL(printf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf); +# if !SANITIZER_AIX +// AIX does not have [v]asprintf. +# define INIT_PRINTF_EXTRA \ + COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \ + COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); +# else +# define INIT_PRINTF_EXTRA +# endif +# define INIT_PRINTF INIT_PRINTF_COMMON INIT_PRINTF_EXTRA #else #define INIT_PRINTF #endif @@ -1855,6 +1872,22 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size, #define INIT_ISOC99_PRINTF #endif +#if SANITIZER_INTERCEPT_SETPROCTITLE +INTERCEPTOR(void, setproctitle, const char *fmt, ...) { + void *ctx; + va_list ap; + va_start(ap, fmt); + COMMON_INTERCEPTOR_ENTER(ctx, setproctitle, fmt, ap); + if (common_flags()->check_printf) + printf_common(ctx, fmt, ap); + REAL(setproctitle)(fmt, ap); + va_end(ap); +} +# define INIT_SETPROCTITLE COMMON_INTERCEPT_FUNCTION(setproctitle); +#else +# define INIT_SETPROCTITLE +#endif + #if SANITIZER_INTERCEPT_IOCTL #include "sanitizer_common_interceptors_ioctl.inc" #include "sanitizer_interceptors_ioctl_netbsd.inc" @@ -3901,7 +3934,7 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) { if (res != ((SIZE_T)-1)) { CHECK_LE(res, sizeof(local_dest)); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); - REAL(memcpy)(dest, local_dest, res); + internal_memcpy(dest, local_dest, res); } return res; } @@ -3923,7 +3956,7 @@ INTERCEPTOR(int, wctomb, char *dest, wchar_t src) { if (res != -1) { CHECK_LE(res, sizeof(local_dest)); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); - REAL(memcpy)(dest, local_dest, res); + internal_memcpy(dest, local_dest, res); } return res; } @@ -10263,6 +10296,71 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) { # define INIT_FREADLINK #endif +#if SANITIZER_INTERCEPT_GETSERVENT_R || SANITIZER_INTERCEPT_GETSERVBYNAME_R || \ + SANITIZER_INTERCEPT_GETSERVBYPORT_R + +UNUSED static void HandleGetServentReentrantResult( + void *ctx, int res, struct __sanitizer_servent *result_buf, char *buf, + SIZE_T buflen, struct __sanitizer_servent **result) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)result, sizeof(void *)); + if (res) + return; + if (*result) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)*result, + sizeof(__sanitizer_servent)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); + } +} + +#endif + +#if SANITIZER_INTERCEPT_GETSERVENT_R +INTERCEPTOR(int, getservent_r, struct __sanitizer_servent *result_buf, + char *buf, SIZE_T buflen, struct __sanitizer_servent **result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getservent_r, result_buf, buf, buflen, result); + int res = REAL(getservent_r)(result_buf, buf, buflen, result); + HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result); + return res; +} +# define INIT_GETSERVENT_R COMMON_INTERCEPT_FUNCTION(getservent_r) +#else +# define INIT_GETSERVENT_R +#endif + +#if SANITIZER_INTERCEPT_GETSERVBYNAME_R +INTERCEPTOR(int, getservbyname_r, const char *name, const char *proto, + struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen, + struct __sanitizer_servent **result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getservbyname_r, name, proto, result_buf, buf, + buflen, result); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, internal_strlen(name)); + int res = REAL(getservbyname_r)(name, proto, result_buf, buf, buflen, result); + HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result); + return res; +} +# define INIT_GETSERVBYNAME_R COMMON_INTERCEPT_FUNCTION(getservbyname_r) +#else +# define INIT_GETSERVBYNAME_R +#endif + +#if SANITIZER_INTERCEPT_GETSERVBYPORT_R +INTERCEPTOR(int, getservbyport_r, int port, const char *proto, + struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen, + struct __sanitizer_servent **result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getservbyport_r, port, proto, result_buf, buf, + buflen, result); + int res = REAL(getservbyport_r)(port, proto, result_buf, buf, buflen, result); + HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result); + return res; +} +# define INIT_GETSERVBYPORT_R COMMON_INTERCEPT_FUNCTION(getservbyport_r) +#else +# define INIT_GETSERVBYPORT_R +#endif + #include "sanitizer_common_interceptors_netbsd_compat.inc" namespace __sanitizer { @@ -10328,8 +10426,10 @@ static void InitializeCommonInterceptors() { INIT_PRINTF; INIT_PRINTF_L; INIT_ISOC99_PRINTF; + INIT_SETPROCTITLE; INIT_FREXP; - INIT_FREXPF_FREXPL; + INIT_FREXPF; + INIT_FREXPL; INIT_GETPWNAM_AND_FRIENDS; INIT_GETPWNAM_R_AND_FRIENDS; INIT_GETPWENT; @@ -10587,4 +10687,7 @@ static void InitializeCommonInterceptors() { INIT_FREADLINK; INIT___PRINTF_CHK; + INIT_GETSERVENT_R; + INIT_GETSERVBYNAME_R; + INIT_GETSERVBYPORT_R; } diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc index 24e5dc0fb22f5..dd4dab07b3c69 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_format.inc @@ -67,6 +67,10 @@ static const char *maybe_parse_length_modifier(const char *p, char ll[2]) { // Returns true if the character is an integer conversion specifier. static bool format_is_integer_conv(char c) { +#if SANITIZER_GLIBC + if (char_is_one_of(c, "bB")) + return true; +#endif return char_is_one_of(c, "diouxXn"); } diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index dda11daa77f49..673f284b6a043 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc @@ -48,35 +48,41 @@ static void ioctl_table_fill() { ++ioctl_table_size; \ } + _(FIONBIO, READ, sizeof(int)); +#if !SANITIZER_HAIKU _(FIOASYNC, READ, sizeof(int)); _(FIOCLEX, NONE, 0); _(FIOGETOWN, WRITE, sizeof(int)); - _(FIONBIO, READ, sizeof(int)); _(FIONCLEX, NONE, 0); _(FIOSETOWN, READ, sizeof(int)); +#endif _(SIOCATMARK, WRITE, sizeof(int)); _(SIOCGIFCONF, CUSTOM, 0); _(SIOCGPGRP, WRITE, sizeof(int)); _(SIOCSPGRP, READ, sizeof(int)); -#if !SANITIZER_SOLARIS +#if !SANITIZER_SOLARIS && !SANITIZER_HAIKU _(TIOCCONS, NONE, 0); #endif - _(TIOCEXCL, NONE, 0); +#if !SANITIZER_HAIKU _(TIOCGETD, WRITE, sizeof(int)); + _(TIOCNOTTY, NONE, 0); + _(TIOCPKT, READ, sizeof(int)); + _(TIOCSETD, READ, sizeof(int)); + _(TIOCSTI, READ, sizeof(char)); +#endif + _(TIOCEXCL, NONE, 0); _(TIOCGPGRP, WRITE, pid_t_sz); _(TIOCGWINSZ, WRITE, struct_winsize_sz); _(TIOCMBIC, READ, sizeof(int)); _(TIOCMBIS, READ, sizeof(int)); _(TIOCMGET, WRITE, sizeof(int)); _(TIOCMSET, READ, sizeof(int)); - _(TIOCNOTTY, NONE, 0); _(TIOCNXCL, NONE, 0); _(TIOCOUTQ, WRITE, sizeof(int)); - _(TIOCPKT, READ, sizeof(int)); +# if !SANITIZER_AIX _(TIOCSCTTY, NONE, 0); - _(TIOCSETD, READ, sizeof(int)); +# endif _(TIOCSPGRP, READ, pid_t_sz); - _(TIOCSTI, READ, sizeof(char)); _(TIOCSWINSZ, READ, struct_winsize_sz); #if !SANITIZER_IOS @@ -338,12 +344,16 @@ static void ioctl_table_fill() { _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int)); _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int)); _(TCFLSH, NONE, 0); +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS _(TCGETS, WRITE, struct_termios_sz); +# endif _(TCSBRK, NONE, 0); _(TCSBRKP, NONE, 0); +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS _(TCSETS, READ, struct_termios_sz); _(TCSETSF, READ, struct_termios_sz); _(TCSETSW, READ, struct_termios_sz); +# endif _(TCXONC, NONE, 0); _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz); _(TIOCGSOFTCAR, WRITE, sizeof(int)); diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc index 1565a494140f6..0b6731c89950b 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @@ -33,11 +33,13 @@ // Platform-specific options. #if SANITIZER_APPLE -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 #elif SANITIZER_WINDOWS64 -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 +#elif SANITIZER_AIX +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 0 #else -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 +# define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 #endif // SANITIZER_APPLE #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index 29fe4721ba40d..521fc116f2888 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -3205,6 +3205,28 @@ POST_SYSCALL(futex) COMMON_SYSCALL_BLOCKING_END(); } +PRE_SYSCALL(copy_file_range) +(int fdin, __sanitizer___kernel_off_t *offin, int fdout, + __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) { + if (offin != nullptr) { + PRE_READ(offin, sizeof(*offin)); + } + if (offout != nullptr) { + PRE_READ(offout, sizeof(*offout)); + } +} + +POST_SYSCALL(copy_file_range) +(SSIZE_T, int fdin, __sanitizer___kernel_off_t *offin, int fdout, + __sanitizer___kernel_off_t *offout, SIZE_T size, unsigned int flags) { + if (offin != nullptr) { + POST_WRITE(offin, sizeof(*offin)); + } + if (offout != nullptr) { + POST_WRITE(offout, sizeof(*offout)); + } +} + } // extern "C" # undef PRE_SYSCALL diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno.h index 46c85364cef56..76919da57d942 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno.h @@ -29,6 +29,8 @@ # define __errno_location ___errno #elif SANITIZER_WINDOWS # define __errno_location _errno +#elif SANITIZER_HAIKU +# define __errno_location _errnop #endif extern "C" int *__errno_location(); diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h index b51cb7e0d625f..d92194fdced29 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_errno_codes.h @@ -24,12 +24,21 @@ namespace __sanitizer { -#define errno_ENOMEM __WASI_ERRNO_NOMEM -#define errno_EBUSY __WASI_ERRNO_BUSY -#define errno_EINVAL __WASI_ERRNO_INVAL -#define errno_ERANGE __WASI_ERRNO_RANGE -#define errno_ENAMETOOLONG __WASI_ERRNO_NAMETOOLONG -#define errno_ENOSYS __WASI_ERRNO_NOSYS +#ifdef __HAIKU__ +# define errno_ENOMEM (0x80000000) +# define errno_EBUSY (0x80000000 + 14) +# define errno_EINVAL (0x80000000 + 5) +# define errno_ERANGE (0x80007000 + 17) +# define errno_ENAMETOOLONG (0x80000000 + 0x6004) +# define errno_ENOSYS (0x80007009) +#else +# define errno_ENOMEM __WASI_ERRNO_NOMEM +# define errno_EBUSY __WASI_ERRNO_BUSY +# define errno_EINVAL __WASI_ERRNO_INVAL +# define errno_ERANGE __WASI_ERRNO_RANGE +# define errno_ENAMETOOLONG __WASI_ERRNO_NAMETOOLONG +# define errno_ENOSYS __WASI_ERRNO_NOSYS +#endif // Those might not present or their value differ on different platforms. extern const int errno_EOWNERDEAD; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp index 96af270f9d8b5..9236a458cdb0e 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp @@ -96,12 +96,76 @@ static void RecursiveCreateParentDirs(char *path) { } } +/// Parse the report path \p pattern and copy the parsed path to \p dest. +/// +/// * `%%` becomes `%` +/// * `%H` expands to the environment variable `HOME` +/// * `%t` expands to the environment variable `TMPDIR` +/// * `%p` expands to the process ID (PID) +static void ParseAndSetPath(const char *pattern, char *dest, + const uptr dest_size) { + CHECK(pattern); + CHECK(dest); + CHECK_GE(dest_size, 1); + dest[0] = '\0'; + uptr next_substr_start_idx = 0; + for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) { + if (pattern[i] != '%') + continue; + int bytes_to_copy = i - next_substr_start_idx; + // Copy over previous substring. + CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx, + internal_strlen(dest) + bytes_to_copy + 1), + dest_size); + const char *str_to_concat; + switch (pattern[++i]) { + case '%': + str_to_concat = "%"; + break; + case 'H': + str_to_concat = GetEnv("HOME"); + break; + case 't': + str_to_concat = GetEnv("TMPDIR"); + break; + case 'p': { + // Use printf directly to write the PID since it's not a static string. + int remaining_capacity = dest_size - internal_strlen(dest); + int bytes_copied = + internal_snprintf(dest + internal_strlen(dest), remaining_capacity, + "%ld", internal_getpid()); + CHECK_GT(bytes_copied, 0); + CHECK_LT(bytes_copied, remaining_capacity); + str_to_concat = ""; + break; + } + default: { + // Invalid pattern: fallback to original pattern. + const char *message = "ERROR: Unexpected pattern: "; + WriteToFile(kStderrFd, message, internal_strlen(message)); + WriteToFile(kStderrFd, pattern, internal_strlen(pattern)); + WriteToFile(kStderrFd, "\n", internal_strlen("\n")); + CHECK_LT(internal_strlcpy(dest, pattern, dest_size), dest_size); + return; + } + } + CHECK(str_to_concat); + CHECK_LT(internal_strlcat(dest, str_to_concat, dest_size), dest_size); + next_substr_start_idx = i + 1; + } + CHECK_LT(internal_strlcat(dest, pattern + next_substr_start_idx, dest_size), + dest_size); +} + void ReportFile::SetReportPath(const char *path) { if (path) { uptr len = internal_strlen(path); if (len > sizeof(path_prefix) - 100) { - Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1], - path[2], path[3], path[4], path[5], path[6], path[7]); + const char *message = "ERROR: Path is too long: "; + WriteToFile(kStderrFd, message, internal_strlen(message)); + WriteToFile(kStderrFd, path, 8); + message = "...\n"; + WriteToFile(kStderrFd, message, internal_strlen(message)); Die(); } } @@ -115,7 +179,7 @@ void ReportFile::SetReportPath(const char *path) { } else if (internal_strcmp(path, "stdout") == 0) { fd = kStdoutFd; } else { - internal_snprintf(path_prefix, kMaxPathLength, "%s", path); + ParseAndSetPath(path, path_prefix, kMaxPathLength); RecursiveCreateParentDirs(path_prefix); } } diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index acbf3ebfc95c0..1ca50eb186a34 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -547,6 +547,8 @@ void __sanitizer_startup_hook(int argc, char **argv, char **envp, __sanitizer::StoredEnviron = envp; __sanitizer::MainThreadStackBase = reinterpret_cast(stack_base); __sanitizer::MainThreadStackSize = stack_size; + + EarlySanitizerInit(); } void __sanitizer_set_report_path(const char *path) { diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.h index 26c1deab9e5fe..47e7537c1bdf1 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.h @@ -32,6 +32,13 @@ struct MemoryMappingLayoutData { void InitShadowBounds(); +// Individual sanitizers can define this to explicitly run something at the end +// of `__sanitizer_startup_hook`. This can be useful if a sanitizer needs to do +// extra work after the common startup hook code is called and before module +// ctors are invoked. For example, hwasan can explicitly call its initializing +// function here so it can be set up before libc extensions are initialized. +void EarlySanitizerInit(); + } // namespace __sanitizer #endif // SANITIZER_FUCHSIA diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp new file mode 100644 index 0000000000000..7cf2437d5b755 --- /dev/null +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_haiku.cpp @@ -0,0 +1,361 @@ +//===-- sanitizer_haiku.cpp -----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file is shared between Sanitizer run-time libraries and implements +// Haiku-specific functions from sanitizer_libc.h. +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" + +#if SANITIZER_HAIKU + +# include "sanitizer_common.h" +# include "sanitizer_flags.h" +# include "sanitizer_getauxval.h" +# include "sanitizer_internal_defs.h" +# include "sanitizer_libc.h" +# include "sanitizer_linux.h" +# include "sanitizer_mutex.h" +# include "sanitizer_placement_new.h" +# include "sanitizer_procmaps.h" + +# include +# include + +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include "system/vm_defs.h" +# include "system/syscalls.h" +# include "shared/syscall_utils.h" + +namespace __sanitizer { + +static void *GetRealLibcAddress(const char *symbol) { + void *real = dlsym(RTLD_NEXT, symbol); + if (!real) + real = dlsym(RTLD_DEFAULT, symbol); + if (!real) { + Printf("GetRealLibcAddress failed for symbol=%s", symbol); + Die(); + } + return real; +} + +# define _REAL(func, ...) real##_##func(__VA_ARGS__) +# define DEFINE__REAL(ret_type, func, ...) \ + static ret_type (*real_##func)(__VA_ARGS__) = NULL; \ + if (!real_##func) { \ + real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \ + } \ + CHECK(real_##func); + +// --------------- sanitizer_libc.h +uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, + u64 offset) { + if ((flags & MAP_ANONYMOUS) != 0) + fd = -1; + + int mapping = + (flags & MAP_SHARED) != 0 ? REGION_NO_PRIVATE_MAP : REGION_PRIVATE_MAP; + + uint32 addressSpec; + if ((flags & MAP_FIXED) != 0) + addressSpec = B_EXACT_ADDRESS; + else if (addr != NULL) + addressSpec = B_BASE_ADDRESS; + else + addressSpec = B_RANDOMIZED_ANY_ADDRESS; + + uint32 areaProtection = 0; + if ((prot & PROT_READ) != 0) + areaProtection |= B_READ_AREA; + if ((prot & PROT_WRITE) != 0) + areaProtection |= B_WRITE_AREA; + if ((prot & PROT_EXEC) != 0) + areaProtection |= B_EXECUTE_AREA; + + if ((flags & MAP_NORESERVE) != 0) + areaProtection |= B_OVERCOMMITTING_AREA; + + area_id area = _kern_map_file("sanitizer mmap", &addr, addressSpec, length, + areaProtection, mapping, true, fd, offset); + if (area < 0) + RETURN_AND_SET_ERRNO(area); + return (uptr)addr; +} + +uptr internal_munmap(void *addr, uptr length) { + DEFINE__REAL(int, munmap, void *a, uptr b); + return _REAL(munmap, addr, length); +} + +uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, + void *new_address) { + CHECK(false && "internal_mremap is unimplemented on Haiku"); + return 0; +} + +int internal_mprotect(void *addr, uptr length, int prot) { + DEFINE__REAL(int, mprotect, void *a, uptr b, int c); + return _REAL(mprotect, addr, length, prot); +} + +int internal_madvise(uptr addr, uptr length, int advice) { + DEFINE__REAL(int, madvise, void *a, uptr b, int c); + return _REAL(madvise, (void *)addr, length, advice); +} + +uptr internal_close(fd_t fd) { + CHECK(&_kern_close); + RETURN_AND_SET_ERRNO(_kern_close(fd)); +} + +uptr internal_open(const char *filename, int flags) { + CHECK(&_kern_open); + RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, 0)); +} + +uptr internal_open(const char *filename, int flags, u32 mode) { + CHECK(&_kern_open); + RETURN_AND_SET_ERRNO(_kern_open(-1, filename, flags, mode)); +} + +uptr internal_read(fd_t fd, void *buf, uptr count) { + sptr res; + CHECK(&_kern_read); + HANDLE_EINTR(res, (sptr)_kern_read(fd, -1, buf, (size_t)count)); + RETURN_AND_SET_ERRNO(res); + return res; +} + +uptr internal_write(fd_t fd, const void *buf, uptr count) { + sptr res; + CHECK(&_kern_write); + HANDLE_EINTR(res, (sptr)_kern_write(fd, -1, buf, count)); + RETURN_AND_SET_ERRNO(res); + return res; +} + +uptr internal_ftruncate(fd_t fd, uptr size) { + sptr res; + DEFINE__REAL(int, ftruncate, int, off_t); + return _REAL(ftruncate, fd, size); + return res; +} + +uptr internal_stat(const char *path, void *buf) { + DEFINE__REAL(int, _stat_current, const char *a, void *b); + return _REAL(_stat_current, path, buf); +} + +uptr internal_lstat(const char *path, void *buf) { + DEFINE__REAL(int, _lstat_current, const char *a, void *b); + return _REAL(_lstat_current, path, buf); +} + +uptr internal_fstat(fd_t fd, void *buf) { + DEFINE__REAL(int, _fstat_current, int a, void *b); + return _REAL(_fstat_current, fd, buf); +} + +uptr internal_filesize(fd_t fd) { + struct stat st; + if (internal_fstat(fd, &st)) + return -1; + return (uptr)st.st_size; +} + +uptr internal_dup(int oldfd) { + DEFINE__REAL(int, dup, int a); + return _REAL(dup, oldfd); +} + +uptr internal_dup2(int oldfd, int newfd) { + DEFINE__REAL(int, dup2, int a, int b); + return _REAL(dup2, oldfd, newfd); +} + +uptr internal_readlink(const char *path, char *buf, uptr bufsize) { + CHECK(&_kern_read_link); + RETURN_AND_SET_ERRNO(_kern_read_link(-1, path, buf, &bufsize)); +} + +uptr internal_unlink(const char *path) { + DEFINE__REAL(int, unlink, const char *a); + return _REAL(unlink, path); +} + +uptr internal_rename(const char *oldpath, const char *newpath) { + DEFINE__REAL(int, rename, const char *a, const char *b); + return _REAL(rename, oldpath, newpath); +} + +uptr internal_sched_yield() { + CHECK(&_kern_thread_yield); + _kern_thread_yield(); + return 0; +} + +void internal__exit(int exitcode) { + DEFINE__REAL(void, _exit, int a); + _REAL(_exit, exitcode); + Die(); // Unreachable. +} + +void internal_usleep(u64 useconds) { + _kern_snooze_etc(useconds, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT, NULL); +} + +uptr internal_execve(const char *filename, char *const argv[], + char *const envp[]) { + DEFINE__REAL(int, execve, const char *, char *const[], char *const[]); + return _REAL(execve, filename, argv, envp); +} + +# if 0 +tid_t GetTid() { + DEFINE__REAL(int, _lwp_self); + return _REAL(_lwp_self); +} + +int TgKill(pid_t pid, tid_t tid, int sig) { + DEFINE__REAL(int, _lwp_kill, int a, int b); + (void)pid; + return _REAL(_lwp_kill, tid, sig); +} + +u64 NanoTime() { + timeval tv; + DEFINE__REAL(int, __gettimeofday50, void *a, void *b); + internal_memset(&tv, 0, sizeof(tv)); + _REAL(__gettimeofday50, &tv, 0); + return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000; +} +# endif + +uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { + DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b); + return _REAL(__clock_gettime50, clk_id, tp); +} + +uptr internal_ptrace(int request, int pid, void *addr, int data) { + DEFINE__REAL(int, ptrace, int a, int b, void *c, int d); + return _REAL(ptrace, request, pid, addr, data); +} + +uptr internal_waitpid(int pid, int *status, int options) { + DEFINE__REAL(int, waitpid, pid_t, int *, int); + return _REAL(waitpid, pid, status, options); +} + +uptr internal_getpid() { + DEFINE__REAL(int, getpid); + return _REAL(getpid); +} + +uptr internal_getppid() { + DEFINE__REAL(int, getppid); + return _REAL(getppid); +} + +int internal_dlinfo(void *handle, int request, void *p) { + DEFINE__REAL(int, dlinfo, void *a, int b, void *c); + return _REAL(dlinfo, handle, request, p); +} + +uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) { + DEFINE__REAL(int, __getdents30, int a, void *b, size_t c); + return _REAL(__getdents30, fd, dirp, count); +} + +uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { + CHECK(&_kern_seek); + off_t result = _kern_seek(fd, offset, whence); + if (result < 0) { + errno = result; + return -1; + } + return result; +} + +uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { + Printf("internal_prctl not implemented for Haiku"); + Die(); + return 0; +} + +uptr internal_sigaltstack(const void *ss, void *oss) { + DEFINE__REAL(int, __sigaltstack14, const void *a, void *b); + return _REAL(__sigaltstack14, ss, oss); +} + +int internal_fork() { + DEFINE__REAL(int, fork); + return _REAL(fork); +} + +# if 0 +int internal_sysctl(const int *name, unsigned int namelen, void *oldp, + uptr *oldlenp, const void *newp, uptr newlen) { + CHECK(&__sysctl); + return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen); +} +# endif + +int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, + const void *newp, uptr newlen) { + DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c, + const void *d, size_t e); + return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp, + (size_t)newlen); +} + +uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset) { + CHECK(&_kern_set_signal_mask); + return _kern_set_signal_mask(how, set, oldset); +} + +void internal_sigfillset(__sanitizer_sigset_t *set) { + DEFINE__REAL(int, __sigfillset14, const void *a); + (void)_REAL(__sigfillset14, set); +} + +void internal_sigemptyset(__sanitizer_sigset_t *set) { + DEFINE__REAL(int, __sigemptyset14, const void *a); + (void)_REAL(__sigemptyset14, set); +} + +void internal_sigdelset(__sanitizer_sigset_t *set, int signo) { + DEFINE__REAL(int, __sigdelset14, const void *a, int b); + (void)_REAL(__sigdelset14, set, signo); +} + +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, + void *arg) { + DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e); + + return _REAL(clone, fn, child_stack, flags, arg); +} + +} // namespace __sanitizer + +#endif diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 72256519132ff..741f0924614a9 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -14,7 +14,7 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN + SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN # include "sanitizer_common.h" # include "sanitizer_flags.h" @@ -63,15 +63,17 @@ # include # include # include -# if !SANITIZER_SOLARIS && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_SOLARIS && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN # include # endif # include # include -# include +# if !SANITIZER_HAIKU +# include +# include +# endif # include # include -# include # include # if SANITIZER_LINUX @@ -82,6 +84,12 @@ # include # endif +# if SANITIZER_ANDROID && __ANDROID_API__ < 35 +// The weak `strerrorname_np` (introduced in API level 35) definition, +// allows for checking the API level at runtime. +extern "C" SANITIZER_WEAK_ATTRIBUTE const char *strerrorname_np(int); +# endif + # if SANITIZER_LINUX && defined(__loongarch__) # include # endif @@ -118,6 +126,13 @@ extern struct ps_strings *__ps_strings; # define environ _environ # endif +# if SANITIZER_HAIKU +# include +# include +# include +extern "C" char **__libc_argv; +# endif + # if SANITIZER_EMSCRIPTEN # include // For INFINITY # include // For emscripten_futex_wait @@ -251,7 +266,8 @@ ScopedBlockSignals::~ScopedBlockSignals() { SetSigProcMask(&saved_, nullptr); } # endif // --------------- sanitizer_libc.h -# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU && \ + !SANITIZER_EMSCRIPTEN # if !SANITIZER_S390 uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, u64 offset) { @@ -597,9 +613,10 @@ uptr internal_execve(const char *filename, char *const argv[], return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv, (uptr)envp); } -# endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU && + // !SANITIZER_EMSCRIPTEN -# if !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_NETBSD && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN void internal__exit(int exitcode) { # if SANITIZER_FREEBSD || SANITIZER_SOLARIS internal_syscall(SYSCALL(exit), exitcode); @@ -608,7 +625,7 @@ void internal__exit(int exitcode) { # endif Die(); // Unreachable. } -# endif // !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# endif // !SANITIZER_NETBSD && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN // ----------------- sanitizer_common.h bool FileExists(const char *filename) { @@ -636,6 +653,8 @@ tid_t GetTid() { return Tid; # elif SANITIZER_SOLARIS return thr_self(); +# elif SANITIZER_HAIKU + return find_thread(NULL); # else return internal_syscall(SYSCALL(gettid)); # endif @@ -652,6 +671,8 @@ int TgKill(pid_t pid, tid_t tid, int sig) { errno = thr_kill(tid, sig); // TgKill is expected to return -1 on error, not an errno. return errno != 0 ? -1 : 0; +# elif SANITIZER_HAIKU + return kill_thread(tid); # endif } # endif @@ -681,7 +702,7 @@ u64 NanoTime() { // should be called first inside __asan_init. const char *GetEnv(const char *name) { # if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_SOLARIS || \ - SANITIZER_EMSCRIPTEN + SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN if (::environ != 0) { uptr NameLen = internal_strlen(name); for (char **Env = ::environ; *Env != 0; Env++) { @@ -719,13 +740,15 @@ const char *GetEnv(const char *name) { # endif } -# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_GO +# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \ + !SANITIZER_GO extern "C" { SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; } # endif -# if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_HAIKU && !SANITIZER_FREEBSD && !SANITIZER_NETBSD && \ + !SANITIZER_EMSCRIPTEN static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -753,7 +776,10 @@ static void ReadNullSepFileToArray(const char *path, char ***arr, # if !SANITIZER_EMSCRIPTEN static void GetArgsAndEnv(char ***argv, char ***envp) { -# if SANITIZER_FREEBSD +# if SANITIZER_HAIKU + *argv = __libc_argv; + *envp = environ; +# elif SANITIZER_FREEBSD // On FreeBSD, retrieving the argument and environment arrays is done via the // kern.ps_strings sysctl, which returns a pointer to a structure containing // this information. See also . @@ -814,7 +840,7 @@ char **GetEnviron() { void FutexWait(atomic_uint32_t *p, u32 cmp) { # if SANITIZER_FREEBSD _umtx_op(p, UMTX_OP_WAIT_UINT, cmp, 0, 0); -# elif SANITIZER_NETBSD +# elif SANITIZER_NETBSD || SANITIZER_HAIKU sched_yield(); /* No userspace futex-like synchronization */ # elif SANITIZER_EMSCRIPTEN emscripten_futex_wait(p, cmp, INFINITY); @@ -826,7 +852,7 @@ void FutexWait(atomic_uint32_t *p, u32 cmp) { void FutexWake(atomic_uint32_t *p, u32 count) { # if SANITIZER_FREEBSD _umtx_op(p, UMTX_OP_WAKE, count, 0, 0); -# elif SANITIZER_NETBSD +# elif SANITIZER_NETBSD || SANITIZER_HAIKU /* No userspace futex-like synchronization */ # elif SANITIZER_EMSCRIPTEN emscripten_futex_wake(p, count); @@ -860,7 +886,8 @@ struct linux_dirent { }; # endif -# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_HAIKU && \ + !SANITIZER_EMSCRIPTEN // Syscall wrappers. uptr internal_ptrace(int request, int pid, void *addr, void *data) { return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr, @@ -1074,7 +1101,7 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { # endif # endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN -# if !SANITIZER_NETBSD && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_NETBSD && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN // ThreadLister implementation. ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) { task_path_.AppendF("/proc/%d/task", pid); @@ -1260,6 +1287,16 @@ uptr GetPageSize() { CHECK_EQ(rv, 0); return (uptr)pz; # elif SANITIZER_USE_GETAUXVAL +# if SANITIZER_ANDROID && __ANDROID_API__ < 35 + // The 16 KB page size was introduced in Android 15 (API level 35), while + // earlier versions of Android always used a 4 KB page size. + // We are checking the weak definition of `strerrorname_np` (introduced in API + // level 35) because some earlier API levels crashed when + // `getauxval(AT_PAGESZ)` was called from the `.preinit_array`. + if (!strerrorname_np) + return 4096; +# endif + return getauxval(AT_PAGESZ); # else return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. @@ -1272,7 +1309,19 @@ extern "C" void _emscripten_get_progname(char *buf, int buf_len); # endif uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) { -# if SANITIZER_SOLARIS +# if SANITIZER_HAIKU + int32_t cookie = 0; + image_info info; + const char *argv0 = ""; + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { + if (info.type != B_APP_IMAGE) + continue; + argv0 = info.name; + break; + } + internal_strncpy(buf, argv0, buf_len); + return internal_strlen(buf); +# elif SANITIZER_SOLARIS const char *default_module_name = getexecname(); CHECK_NE(default_module_name, NULL); return internal_snprintf(buf, buf_len, "%s", default_module_name); @@ -1341,11 +1390,11 @@ bool LibraryNameIs(const char *full_name, const char *base_name) { return (name[base_name_length] == '-' || name[base_name_length] == '.'); } -# if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID && !SANITIZER_HAIKU // Call cb for each region mapped by map. void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { CHECK_NE(map, nullptr); -# if !SANITIZER_FREEBSD +# if !SANITIZER_FREEBSD && !SANITIZER_HAIKU typedef ElfW(Phdr) Elf_Phdr; typedef ElfW(Ehdr) Elf_Ehdr; # endif // !SANITIZER_FREEBSD @@ -1878,54 +1927,6 @@ int internal_uname(struct utsname *buf) { } # endif -# if SANITIZER_ANDROID -static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, - void *data) { - // Any name starting with "lib" indicates a bug in L where library base names - // are returned instead of paths. - if (info->dlpi_name && info->dlpi_name[0] == 'l' && - info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') { - *(bool *)data = true; - return 1; - } - return 0; -} - -static atomic_uint32_t android_api_level; - -static AndroidApiLevel AndroidDetectApiLevelStatic() { -# if __ANDROID_API__ <= 22 - return ANDROID_LOLLIPOP_MR1; -# else - return ANDROID_POST_LOLLIPOP; -# endif -} - -static AndroidApiLevel AndroidDetectApiLevel() { - bool base_name_seen = false; - dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen); - if (base_name_seen) - return ANDROID_LOLLIPOP_MR1; // L MR1 - return ANDROID_POST_LOLLIPOP; // post-L - // Plain L (API level 21) is completely broken wrt ASan and not very - // interesting to detect. -} - -extern "C" __attribute__((weak)) void *_DYNAMIC; - -AndroidApiLevel AndroidGetApiLevel() { - AndroidApiLevel level = - (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed); - if (level) - return level; - level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic() - : AndroidDetectApiLevel(); - atomic_store(&android_api_level, level, memory_order_relaxed); - return level; -} - -# endif - static HandleSignalMode GetHandleSignalModeImpl(int signum) { switch (signum) { case SIGABRT: @@ -2004,11 +2005,18 @@ using Context = ucontext_t; SignalContext::WriteFlag SignalContext::GetWriteFlag() const { Context *ucontext = (Context *)context; # if defined(__x86_64__) || defined(__i386__) +# if !SANITIZER_HAIKU static const uptr PF_WRITE = 1U << 1; +# endif # if SANITIZER_FREEBSD uptr err = ucontext->uc_mcontext.mc_err; # elif SANITIZER_NETBSD uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR]; +# elif SANITIZER_HAIKU + uptr err = 0; // FIXME: ucontext->uc_mcontext.r13; + // The err register was added on the main branch and not + // available with the current release. To be reverted later. + // https://github.com/haiku/haiku/commit/11adda21aa4e6b24f71a496868a44d7607bc3764 # elif SANITIZER_SOLARIS && defined(__i386__) const int Err = 13; uptr err = ucontext->uc_mcontext.gregs[Err]; @@ -2621,6 +2629,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.mc_rip; *bp = ucontext->uc_mcontext.mc_rbp; *sp = ucontext->uc_mcontext.mc_rsp; +# elif SANITIZER_HAIKU + ucontext_t *ucontext = (ucontext_t *)context; + *pc = ucontext->uc_mcontext.rip; + *bp = ucontext->uc_mcontext.rbp; + *sp = ucontext->uc_mcontext.rsp; # else ucontext_t *ucontext = (ucontext_t *)context; *pc = ucontext->uc_mcontext.gregs[REG_RIP]; @@ -2633,6 +2646,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.mc_eip; *bp = ucontext->uc_mcontext.mc_ebp; *sp = ucontext->uc_mcontext.mc_esp; +# elif SANITIZER_HAIKU + ucontext_t *ucontext = (ucontext_t *)context; + *pc = ucontext->uc_mcontext.eip; + *bp = ucontext->uc_mcontext.ebp; + *sp = ucontext->uc_mcontext.esp; # else ucontext_t *ucontext = (ucontext_t *)context; # if SANITIZER_SOLARIS diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index 087f5bc1265b0..27a3ef3ac7113 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -14,7 +14,7 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN + SANITIZER_SOLARIS || SANITIZER_HAIKU || SANITIZER_EMSCRIPTEN # include "sanitizer_common.h" # include "sanitizer_internal_defs.h" # include "sanitizer_platform_limits_freebsd.h" @@ -31,6 +31,11 @@ namespace __sanitizer { // the one in , which is used by readdir(). struct linux_dirent; +# if SANITIZER_HAIKU +struct MemoryMappingLayoutData { + long signed int cookie; +}; +# else struct ProcSelfMapsBuff { char *data; uptr mmaped_size; @@ -43,6 +48,7 @@ struct MemoryMappingLayoutData { }; void ReadProcMaps(ProcSelfMapsBuff *proc_maps); +# endif // SANITIZER_HAIKU // Syscall wrappers. uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); @@ -124,7 +130,7 @@ bool LibraryNameIs(const char *full_name, const char *base_name); // Call cb for each region mapped by map. void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)); -// Releases memory pages entirely within the [beg, end] address range. +// Releases memory pages entirely within the [beg, end) address range. // The pages no longer count toward RSS; reads are guaranteed to return 0. // Requires (but does not verify!) that pages are MAP_PRIVATE. inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index 57706f74fa7f5..6ee31595372ca 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -14,7 +14,7 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS + SANITIZER_SOLARIS || SANITIZER_HAIKU # include "sanitizer_allocator_internal.h" # include "sanitizer_atomic.h" @@ -28,8 +28,20 @@ # include "sanitizer_procmaps.h" # include "sanitizer_solaris.h" +# if SANITIZER_HAIKU +# define _GNU_SOURCE +# define _DEFAULT_SOURCE +# endif + # if SANITIZER_NETBSD -# define _RTLD_SOURCE // for __lwp_gettcb_fast() / __lwp_getprivate_fast() +# // for __lwp_gettcb_fast() / __lwp_getprivate_fast() +# define _RTLD_SOURCE +# include +# undef _RTLD_SOURCE +# include +# if __NetBSD_Version__ >= 1099001200 +# include +# endif # endif # include // for dlsym() @@ -74,18 +86,9 @@ extern "C" int __sys_sigaction(int signum, const struct sigaction *act, # include # endif -# if SANITIZER_ANDROID -# include -# if !defined(CPU_COUNT) && !defined(__aarch64__) -# include -# include -struct __sanitizer::linux_dirent { - long d_ino; - off_t d_off; - unsigned short d_reclen; - char d_name[]; -}; -# endif +# if SANITIZER_HAIKU +# include +# include # endif # if !SANITIZER_ANDROID @@ -651,6 +654,7 @@ static void GetTls(uptr *addr, uptr *size) { *addr = (uptr)tcb->tcb_dtv[1]; } } +# elif SANITIZER_HAIKU # else # error "Unknown OS" # endif @@ -721,8 +725,13 @@ static int AddModuleSegments(const char *module_name, dl_phdr_info *info, if (phdr->p_type == PT_LOAD) { uptr cur_beg = info->dlpi_addr + phdr->p_vaddr; uptr cur_end = cur_beg + phdr->p_memsz; +# if SANITIZER_HAIKU + bool executable = phdr->p_flags & PF_EXECUTE; + bool writable = phdr->p_flags & PF_WRITE; +# else bool executable = phdr->p_flags & PF_X; bool writable = phdr->p_flags & PF_W; +# endif cur_module.addAddressRange(cur_beg, cur_end, executable, writable); } else if (phdr->p_type == PT_NOTE) { # ifdef NT_GNU_BUILD_ID @@ -774,42 +783,13 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; } -static bool requiresProcmaps() { -# if SANITIZER_ANDROID && __ANDROID_API__ <= 22 - // Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken. - // The runtime check allows the same library to work with - // both K and L (and future) Android releases. - return AndroidGetApiLevel() <= ANDROID_LOLLIPOP_MR1; -# else - return false; -# endif -} - -static void procmapsInit(InternalMmapVectorNoCtor *modules) { - MemoryMappingLayout memory_mapping(/*cache_enabled*/ true); - memory_mapping.DumpListOfModules(modules); -} - void ListOfModules::init() { clearOrInit(); - if (requiresProcmaps()) { - procmapsInit(&modules_); - } else { - DlIteratePhdrData data = {&modules_, true}; - dl_iterate_phdr(dl_iterate_phdr_cb, &data); - } + DlIteratePhdrData data = {&modules_, true}; + dl_iterate_phdr(dl_iterate_phdr_cb, &data); } -// When a custom loader is used, dl_iterate_phdr may not contain the full -// list of modules. Allow callers to fall back to using procmaps. -void ListOfModules::fallbackInit() { - if (!requiresProcmaps()) { - clearOrInit(); - procmapsInit(&modules_); - } else { - clear(); - } -} +void ListOfModules::fallbackInit() { clear(); } // getrusage does not give us the current RSS, only the max RSS. // Still, this is better than nothing if /proc/self/statm is not available @@ -855,45 +835,17 @@ u32 GetNumberOfCPUs() { int req[2]; uptr len = sizeof(ncpu); req[0] = CTL_HW; +# ifdef HW_NCPUONLINE + req[1] = HW_NCPUONLINE; +# else req[1] = HW_NCPU; +# endif CHECK_EQ(internal_sysctl(req, 2, &ncpu, &len, NULL, 0), 0); return ncpu; -# elif SANITIZER_ANDROID && !defined(CPU_COUNT) && !defined(__aarch64__) - // Fall back to /sys/devices/system/cpu on Android when cpu_set_t doesn't - // exist in sched.h. That is the case for toolchains generated with older - // NDKs. - // This code doesn't work on AArch64 because internal_getdents makes use of - // the 64bit getdents syscall, but cpu_set_t seems to always exist on AArch64. - uptr fd = internal_open("/sys/devices/system/cpu", O_RDONLY | O_DIRECTORY); - if (internal_iserror(fd)) - return 0; - InternalMmapVector buffer(4096); - uptr bytes_read = buffer.size(); - uptr n_cpus = 0; - u8 *d_type; - struct linux_dirent *entry = (struct linux_dirent *)&buffer[bytes_read]; - while (true) { - if ((u8 *)entry >= &buffer[bytes_read]) { - bytes_read = internal_getdents(fd, (struct linux_dirent *)buffer.data(), - buffer.size()); - if (internal_iserror(bytes_read) || !bytes_read) - break; - entry = (struct linux_dirent *)buffer.data(); - } - d_type = (u8 *)entry + entry->d_reclen - 1; - if (d_type >= &buffer[bytes_read] || - (u8 *)&entry->d_name[3] >= &buffer[bytes_read]) - break; - if (entry->d_ino != 0 && *d_type == DT_DIR) { - if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' && - entry->d_name[2] == 'u' && entry->d_name[3] >= '0' && - entry->d_name[3] <= '9') - n_cpus++; - } - entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen); - } - internal_close(fd); - return n_cpus; +# elif SANITIZER_HAIKU + system_info info; + get_system_info(&info); + return info.cpu_count; # elif SANITIZER_SOLARIS return sysconf(_SC_NPROCESSORS_ONLN); # else diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp index d15f30c61b586..bb71af5ad8b6a 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp @@ -38,13 +38,6 @@ extern char **environ; # endif -# if defined(__has_include) && __has_include() -# define SANITIZER_OS_TRACE 1 -# include -# else -# define SANITIZER_OS_TRACE 0 -# endif - // Integrate with CrashReporter library if available # if defined(__has_include) && __has_include() # define HAVE_CRASHREPORTERCLIENT_H 1 @@ -843,31 +836,23 @@ void LogMessageOnPrintf(const char *str) { } void LogFullErrorReport(const char *buffer) { -#if !SANITIZER_GO - // Log with os_trace. This will make it into the crash log. -#if SANITIZER_OS_TRACE -#pragma clang diagnostic push -// os_trace is deprecated. -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if (GetMacosAlignedVersion() >= MacosVersion(10, 10)) { - // os_trace requires the message (format parameter) to be a string literal. - if (internal_strncmp(SanitizerToolName, "AddressSanitizer", - sizeof("AddressSanitizer") - 1) == 0) - os_trace("Address Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", - sizeof("UndefinedBehaviorSanitizer") - 1) == 0) - os_trace("Undefined Behavior Sanitizer reported a failure."); - else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", - sizeof("ThreadSanitizer") - 1) == 0) - os_trace("Thread Sanitizer reported a failure."); - else - os_trace("Sanitizer tool reported a failure."); - - if (common_flags()->log_to_syslog) - os_trace("Consult syslog for more information."); - } -#pragma clang diagnostic pop -#endif +# if !SANITIZER_GO + // Log with os_log_error. This will make it into the crash log. + if (internal_strncmp(SanitizerToolName, "AddressSanitizer", + sizeof("AddressSanitizer") - 1) == 0) + os_log_error(OS_LOG_DEFAULT, "Address Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer", + sizeof("UndefinedBehaviorSanitizer") - 1) == 0) + os_log_error(OS_LOG_DEFAULT, + "Undefined Behavior Sanitizer reported a failure."); + else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer", + sizeof("ThreadSanitizer") - 1) == 0) + os_log_error(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure."); + else + os_log_error(OS_LOG_DEFAULT, "Sanitizer tool reported a failure."); + + if (common_flags()->log_to_syslog) + os_log_error(OS_LOG_DEFAULT, "Consult syslog for more information."); // Log to syslog. // The logging on OS X may call pthread_create so we need the threading @@ -881,7 +866,7 @@ void LogFullErrorReport(const char *buffer) { WriteToSyslog(buffer); // The report is added to CrashLog as part of logging all of Printf output. -#endif +# endif // !SANITIZER_GO } SignalContext::WriteFlag SignalContext::GetWriteFlag() const { @@ -1203,13 +1188,14 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, const uptr left_padding = Max(granularity, 1ULL << min_shadow_base_alignment); - uptr space_size = shadow_size_bytes + left_padding; + uptr space_size = shadow_size_bytes; uptr largest_gap_found = 0; uptr max_occupied_addr = 0; + VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size); uptr shadow_start = - FindAvailableMemoryRange(space_size, alignment, granularity, + FindAvailableMemoryRange(space_size, alignment, left_padding, &largest_gap_found, &max_occupied_addr); // If the shadow doesn't fit, restrict the address space to make it fit. if (shadow_start == 0) { @@ -1229,9 +1215,9 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale, } RestrictMemoryToMaxAddress(new_max_vm); high_mem_end = new_max_vm - 1; - space_size = (high_mem_end >> shadow_scale) + left_padding; + space_size = (high_mem_end >> shadow_scale); VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size); - shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity, + shadow_start = FindAvailableMemoryRange(space_size, alignment, left_padding, nullptr, nullptr); if (shadow_start == 0) { Report("Unable to find a memory range after restricting VM.\n"); @@ -1272,10 +1258,15 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, mach_msg_type_number_t count = kRegionInfoSize; kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth, (vm_region_info_t)&vminfo, &count); - if (kr == KERN_INVALID_ADDRESS) { + + // There are cases where going beyond the processes' max vm does + // not return KERN_INVALID_ADDRESS so we check for going beyond that + // max address as well. + if (kr == KERN_INVALID_ADDRESS || address > max_vm_address) { // No more regions beyond "address", consider the gap at the end of VM. address = max_vm_address; vmsize = 0; + kr = -1; // break after this iteration. } else { if (max_occupied_addr) *max_occupied_addr = address + vmsize; } diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.h index f0a97d098eea0..b0e4ac7f40745 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_mac.h @@ -37,9 +37,6 @@ struct VersionBase { VersionBase(u16 major, u16 minor) : major(major), minor(minor) {} - bool operator==(const VersionType &other) const { - return major == other.major && minor == other.minor; - } bool operator>=(const VersionType &other) const { return major > other.major || (major == other.major && minor >= other.minor); @@ -47,6 +44,12 @@ struct VersionBase { bool operator<(const VersionType &other) const { return !(*this >= other); } }; +template +bool operator==(const VersionBase &self, + const VersionBase &other) { + return self.major == other.major && self.minor == other.minor; +} + struct MacosVersion : VersionBase { MacosVersion(u16 major, u16 minor) : VersionBase(major, minor) {} }; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc index 6343eb284afbf..be27584f20535 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_malloc_mac.inc @@ -144,6 +144,22 @@ INTERCEPTOR(void, free, void *ptr) { COMMON_MALLOC_FREE(ptr); } +#if SANITIZER_INTERCEPT_FREE_SIZED && defined(COMMON_MALLOC_FREE_SIZED) +INTERCEPTOR(void, free_sized, void *ptr, size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_FREE_SIZED(ptr, size); +} +#endif + +#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED && \ + defined(COMMON_MALLOC_FREE_ALIGNED_SIZED) +INTERCEPTOR(void, free_aligned_sized, void *ptr, size_t alignment, + size_t size) { + COMMON_MALLOC_ENTER(); + COMMON_MALLOC_FREE_ALIGNED_SIZED(ptr, alignment, size); +} +#endif + INTERCEPTOR(void *, realloc, void *ptr, size_t size) { COMMON_MALLOC_ENTER(); COMMON_MALLOC_REALLOC(ptr, size); diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 9bf5dddac58f6..a54e9b8e90843 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -55,6 +55,18 @@ # define SANITIZER_SOLARIS 0 #endif +#if defined(__HAIKU__) +# define SANITIZER_HAIKU 1 +#else +# define SANITIZER_HAIKU 0 +#endif + +#if defined(__wasi__) +# define SANITIZER_WASI 1 +#else +# define SANITIZER_WASI 0 +#endif + // - SANITIZER_APPLE: all Apple code // - TARGET_OS_OSX: macOS // - SANITIZER_IOS: devices (iOS and iOS-like) @@ -142,9 +154,10 @@ # define SANITIZER_EMSCRIPTEN 0 #endif -#define SANITIZER_POSIX \ - (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \ - SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_EMSCRIPTEN) +#define SANITIZER_POSIX \ + (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_APPLE || \ + SANITIZER_NETBSD || SANITIZER_SOLARIS || SANITIZER_HAIKU || \ + SANITIZER_EMSCRIPTEN) #if __LP64__ || defined(_WIN64) # define SANITIZER_WORDSIZE 64 @@ -311,6 +324,9 @@ # endif #endif +// The first address that can be returned by mmap. +#define SANITIZER_MMAP_BEGIN 0 + // The range of addresses which can be returned my mmap. // FIXME: this value should be different on different platforms. Larger values // will still work but will consume more memory for TwoLevelByteMap. @@ -416,7 +432,8 @@ # define SANITIZER_SUPPRESS_LEAK_ON_PTHREAD_EXIT 0 #endif -#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || SANITIZER_SOLARIS +#if SANITIZER_FREEBSD || SANITIZER_APPLE || SANITIZER_NETBSD || \ + SANITIZER_SOLARIS || SANITIZER_HAIKU # define SANITIZER_MADVISE_DONTNEED MADV_FREE #else # define SANITIZER_MADVISE_DONTNEED MADV_DONTNEED @@ -471,4 +488,19 @@ # define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0 #endif +#if SANITIZER_LINUX +# if SANITIZER_GLIBC +// Workaround for +// glibc/commit/3d3572f59059e2b19b8541ea648a6172136ec42e +// Linux: Keep termios ioctl constants strictly internal +# if __GLIBC_PREREQ(2, 41) +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 0 +# else +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1 +# endif +# else +# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1 +# endif +#endif + #endif // SANITIZER_PLATFORM_H diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 3cc84b995c62f..489a79158bc59 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -129,8 +129,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #if SANITIZER_FUCHSIA #define SI_NOT_FUCHSIA 0 +#define SI_FUCHSIA 1 #else #define SI_NOT_FUCHSIA 1 +#define SI_FUCHSIA 0 #endif #if SANITIZER_SOLARIS @@ -139,6 +141,12 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SI_SOLARIS 0 #endif +#if SANITIZER_AIX +# define SI_NOT_AIX 0 +#else +# define SI_NOT_AIX 1 +#endif + #if SANITIZER_SOLARIS32 #define SI_SOLARIS32 1 #else @@ -171,20 +179,20 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA) -#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA +#define SANITIZER_INTERCEPT_STRCMP (SI_NOT_FUCHSIA && SI_NOT_AIX) #define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA -#define SANITIZER_INTERCEPT_STRCASESTR SI_POSIX +#define SANITIZER_INTERCEPT_STRCASESTR (SI_POSIX && SI_NOT_AIX) #define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_STRCHR SI_NOT_FUCHSIA -#define SANITIZER_INTERCEPT_STRCHRNUL SI_POSIX_NOT_MAC +#define SANITIZER_INTERCEPT_STRCHRNUL (SI_POSIX_NOT_MAC && SI_NOT_AIX) #define SANITIZER_INTERCEPT_STRRCHR SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_STRSPN SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_STRPBRK SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX #define SANITIZER_INTERCEPT_MEMSET 1 -#define SANITIZER_INTERCEPT_MEMMOVE 1 -#define SANITIZER_INTERCEPT_MEMCPY 1 +#define SANITIZER_INTERCEPT_MEMMOVE SI_NOT_AIX +#define SANITIZER_INTERCEPT_MEMCPY SI_NOT_AIX #define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA #define SANITIZER_INTERCEPT_BCMP \ SANITIZER_INTERCEPT_MEMCMP && \ @@ -243,16 +251,22 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_ISOC99_SCANF SI_GLIBC #ifndef SANITIZER_INTERCEPT_PRINTF -#define SANITIZER_INTERCEPT_PRINTF SI_POSIX -#define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD) -#define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC +# define SANITIZER_INTERCEPT_ASPRINTF SI_NOT_AIX +# define SANITIZER_INTERCEPT_VASPRINTF SI_NOT_AIX +# define SANITIZER_INTERCEPT_PRINTF SI_POSIX +# define SANITIZER_INTERCEPT_PRINTF_L (SI_FREEBSD || SI_NETBSD) +# define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_GLIBC #endif +#define SANITIZER_INTERCEPT_SETPROCTITLE (SI_FREEBSD || SI_NETBSD) + #define SANITIZER_INTERCEPT___PRINTF_CHK \ (SANITIZER_INTERCEPT_PRINTF && SI_GLIBC) -#define SANITIZER_INTERCEPT_FREXP SI_NOT_FUCHSIA -#define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_POSIX +// AIX libc does not export FREXP and FREXPF. +#define SANITIZER_INTERCEPT_FREXP (SI_NOT_FUCHSIA && SI_NOT_AIX) +#define SANITIZER_INTERCEPT_FREXPF (SI_POSIX && SI_NOT_AIX) +#define SANITIZER_INTERCEPT_FREXPL SI_POSIX #define SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS SI_POSIX #define SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS \ @@ -301,7 +315,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_ACCEPT4 \ (SI_LINUX_NOT_ANDROID || SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_PACCEPT SI_NETBSD -#define SANITIZER_INTERCEPT_MODF SI_POSIX +#define SANITIZER_INTERCEPT_MODF (SI_POSIX && SI_NOT_AIX) #define SANITIZER_INTERCEPT_RECVMSG SI_POSIX #define SANITIZER_INTERCEPT_SENDMSG SI_POSIX #define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX @@ -336,8 +350,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT___WCSXFRM_L SI_LINUX #define SANITIZER_INTERCEPT_WCSNRTOMBS \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) -#define SANITIZER_INTERCEPT_WCRTOMB \ - (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) +#define SANITIZER_INTERCEPT_WCRTOMB \ + (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS || \ + !SI_NOT_AIX) #define SANITIZER_INTERCEPT_WCTOMB \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS @@ -377,7 +392,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_GETMNTENT_R SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_STATFS \ (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) -#define SANITIZER_INTERCEPT_STATFS64 SI_GLIBC && SANITIZER_HAS_STATFS64 +#define SANITIZER_INTERCEPT_STATFS64 \ + ((SI_GLIBC || !SI_NOT_AIX) && SANITIZER_HAS_STATFS64) #define SANITIZER_INTERCEPT_STATVFS \ (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID) #define SANITIZER_INTERCEPT_STATVFS64 SI_GLIBC @@ -426,10 +442,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_TTYNAME_R SI_POSIX #define SANITIZER_INTERCEPT_TEMPNAM SI_POSIX #define SANITIZER_INTERCEPT_SINCOS SI_LINUX || SI_SOLARIS -#define SANITIZER_INTERCEPT_REMQUO SI_POSIX -#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD) -#define SANITIZER_INTERCEPT_LGAMMA SI_POSIX -#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD) +#define SANITIZER_INTERCEPT_REMQUO (SI_POSIX && SI_NOT_AIX) +#define SANITIZER_INTERCEPT_REMQUOL (SI_POSIX && !SI_NETBSD && SI_NOT_AIX) +#define SANITIZER_INTERCEPT_LGAMMA (SI_POSIX && SI_NOT_AIX) +#define SANITIZER_INTERCEPT_LGAMMAL (SI_POSIX && !SI_NETBSD && SI_NOT_AIX) #define SANITIZER_INTERCEPT_LGAMMA_R (SI_FREEBSD || SI_LINUX || SI_SOLARIS) #define SANITIZER_INTERCEPT_LGAMMAL_R SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_DRAND48_R SI_GLIBC @@ -512,11 +528,13 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE (SI_LINUX || SI_FREEBSD) #define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33)) -#define SANITIZER_INTERCEPT_STAT \ - (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \ - SI_STAT_LINUX) -#define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64 -#define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX) +#define SANITIZER_INTERCEPT_STAT \ + (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \ + SI_STAT_LINUX || !SI_NOT_AIX) +#define SANITIZER_INTERCEPT_STAT64 \ + ((SI_STAT_LINUX || !SI_NOT_AIX) && SANITIZER_HAS_STAT64) +#define SANITIZER_INTERCEPT_LSTAT \ + (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX || !SI_NOT_AIX) #define SANITIZER_INTERCEPT___XSTAT \ ((!SANITIZER_INTERCEPT_STAT && SI_POSIX) || SI_STAT_LINUX) #define SANITIZER_INTERCEPT___XSTAT64 SI_GLIBC @@ -533,7 +551,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_MMAP SI_POSIX #define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID || SI_SOLARIS -#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID || SI_EMSCRIPTEN) +#define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO \ + (SI_GLIBC || SI_ANDROID || SI_FUCHSIA || SI_EMSCRIPTEN) #define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD) #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC #define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID) @@ -584,7 +603,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_PROTOENT_R SI_GLIBC #define SANITIZER_INTERCEPT_NETENT (SI_LINUX || SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_SETVBUF \ - (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC) + (SI_NETBSD || SI_FREEBSD || SI_LINUX || SI_MAC || !SI_NOT_AIX) #define SANITIZER_INTERCEPT_GETMNTINFO (SI_NETBSD || SI_FREEBSD || SI_MAC) #define SANITIZER_INTERCEPT_MI_VECTOR_HASH SI_NETBSD #define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD @@ -652,6 +671,21 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, # define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0 #endif #define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00) +#define SANITIZER_INTERCEPT_GETSERVENT_R SI_GLIBC +#define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC +#define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC + +// Until free_sized and free_aligned_sized are more generally available, +// we can only unconditionally intercept on ELF-based platforms where it +// is okay to have undefined weak symbols. +#ifdef __ELF__ +# define SANITIZER_INTERCEPT_FREE_SIZED 1 +# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 1 +#else +# define SANITIZER_INTERCEPT_FREE_SIZED 0 +# define SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED 0 +#endif + // This macro gives a way for downstream users to override the above // interceptor macros irrespective of the platform they are on. They have // to do two things: diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp index 4940062eeae47..c4fa1e3c1f6fa 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -70,14 +71,8 @@ #include #include #include -#include -#include -#include -#include -#include #include #include -#include #include #include #include @@ -87,10 +82,6 @@ #include #include -#define _KERNEL // to declare 'shminfo' structure -#include -#undef _KERNEL - #undef IOC_DIRMASK // Include these after system headers to avoid name clashes and ambiguities. @@ -141,8 +132,6 @@ unsigned struct_timeb_sz = sizeof(struct timeb); unsigned struct_msqid_ds_sz = sizeof(struct msqid_ds); unsigned struct_mq_attr_sz = sizeof(struct mq_attr); unsigned struct_statvfs_sz = sizeof(struct statvfs); -unsigned struct_shminfo_sz = sizeof(struct shminfo); -unsigned struct_shm_info_sz = sizeof(struct shm_info); unsigned struct_regmatch_sz = sizeof(regmatch_t); unsigned struct_regex_sz = sizeof(regex_t); unsigned struct_fstab_sz = sizeof(struct fstab); @@ -156,9 +145,6 @@ const uptr sig_err = (uptr)SIG_ERR; const uptr sa_siginfo = (uptr)SA_SIGINFO; int shmctl_ipc_stat = (int)IPC_STAT; -int shmctl_ipc_info = (int)IPC_INFO; -int shmctl_shm_info = (int)SHM_INFO; -int shmctl_shm_stat = (int)SHM_STAT; unsigned struct_utmpx_sz = sizeof(struct utmpx); int map_fixed = MAP_FIXED; @@ -378,22 +364,6 @@ const int si_SEGV_MAPERR = SEGV_MAPERR; const int si_SEGV_ACCERR = SEGV_ACCERR; const int unvis_valid = UNVIS_VALID; const int unvis_validpush = UNVIS_VALIDPUSH; - -const unsigned MD5_CTX_sz = sizeof(MD5_CTX); -const unsigned MD5_return_length = MD5_DIGEST_STRING_LENGTH; - -#define SHA2_CONST(LEN) \ - const unsigned SHA##LEN##_CTX_sz = sizeof(SHA##LEN##_CTX); \ - const unsigned SHA##LEN##_return_length = SHA##LEN##_DIGEST_STRING_LENGTH; \ - const unsigned SHA##LEN##_block_length = SHA##LEN##_BLOCK_LENGTH; \ - const unsigned SHA##LEN##_digest_length = SHA##LEN##_DIGEST_LENGTH - -SHA2_CONST(224); -SHA2_CONST(256); -SHA2_CONST(384); -SHA2_CONST(512); - -#undef SHA2_CONST } // namespace __sanitizer using namespace __sanitizer; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h index 8ce73f206fd88..1cbb40e0b2ffc 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h @@ -419,12 +419,14 @@ struct __sanitizer_wordexp_t { typedef void __sanitizer_FILE; -extern unsigned struct_shminfo_sz; -extern unsigned struct_shm_info_sz; extern int shmctl_ipc_stat; -extern int shmctl_ipc_info; -extern int shmctl_shm_info; -extern int shmctl_shm_stat; + +// This simplifies generic code +#define struct_shminfo_sz -1 +#define struct_shm_info_sz -1 +#define shmctl_shm_stat -1 +#define shmctl_ipc_info -1 +#define shmctl_shm_info -1 extern unsigned struct_utmpx_sz; @@ -708,22 +710,6 @@ extern unsigned IOCTL_KDSKBMODE; extern const int si_SEGV_MAPERR; extern const int si_SEGV_ACCERR; -extern const unsigned MD5_CTX_sz; -extern const unsigned MD5_return_length; - -#define SHA2_EXTERN(LEN) \ - extern const unsigned SHA##LEN##_CTX_sz; \ - extern const unsigned SHA##LEN##_return_length; \ - extern const unsigned SHA##LEN##_block_length; \ - extern const unsigned SHA##LEN##_digest_length - -SHA2_EXTERN(224); -SHA2_EXTERN(256); -SHA2_EXTERN(384); -SHA2_EXTERN(512); - -#undef SHA2_EXTERN - struct __sanitizer_cap_rights { u64 cr_rights[2]; }; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp index aacd28c55ceaa..435f3b2861dc9 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp @@ -498,7 +498,6 @@ struct urio_command { #include #include #include -#include #include #include #include @@ -515,7 +514,7 @@ struct urio_command { #include #if defined(__x86_64__) -#include +#include #endif // clang-format on diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index d994d39913dd8..8824d136e2fdb 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -24,7 +24,8 @@ // Must go after undef _FILE_OFFSET_BITS. #include "sanitizer_platform.h" -#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_EMSCRIPTEN +#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU || \ + SANITIZER_EMSCRIPTEN // Must go after undef _FILE_OFFSET_BITS. #include "sanitizer_glibc_version.h" @@ -52,7 +53,7 @@ #include #include #include -#if !SANITIZER_APPLE +#if !SANITIZER_APPLE && !SANITIZER_HAIKU #include #endif @@ -61,7 +62,9 @@ #endif #if !SANITIZER_ANDROID && !SANITIZER_EMSCRIPTEN +#if !SANITIZER_HAIKU #include +#endif #include #include #endif @@ -111,9 +114,11 @@ typedef struct user_fpregs elf_fpregset_t; #if !SANITIZER_ANDROID #include +#if !SANITIZER_HAIKU #include #include #endif +#endif #if SANITIZER_LINUX #if SANITIZER_GLIBC @@ -163,7 +168,7 @@ typedef struct user_fpregs elf_fpregset_t; #include #include #include -#elif !SANITIZER_EMSCRIPTEN +#elif !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN #include #endif // SANITIZER_LINUX @@ -173,6 +178,11 @@ typedef struct user_fpregs elf_fpregset_t; #include #endif +#if SANITIZER_HAIKU +#include +#include +#endif + // Include these after system headers to avoid name clashes and ambiguities. # include "sanitizer_common.h" # include "sanitizer_internal_defs.h" @@ -217,7 +227,7 @@ namespace __sanitizer { unsigned struct_fstab_sz = sizeof(struct fstab); #endif // SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD || // SANITIZER_APPLE -#if !SANITIZER_ANDROID && !SANITIZER_EMSCRIPTEN +#if !SANITIZER_ANDROID && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN unsigned struct_statfs_sz = sizeof(struct statfs); unsigned struct_sockaddr_sz = sizeof(struct sockaddr); @@ -324,7 +334,7 @@ namespace __sanitizer { int shmctl_shm_stat = (int)SHM_STAT; #endif -#if !SANITIZER_APPLE && !SANITIZER_FREEBSD +#if !SANITIZER_APPLE && !SANITIZER_FREEBSD && !SANITIZER_HAIKU unsigned struct_utmp_sz = sizeof(struct utmp); #endif #if !SANITIZER_ANDROID @@ -356,9 +366,9 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); int glob_altdirfunc = GLOB_ALTDIRFUNC; #endif -# if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID && !SANITIZER_HAIKU const int wordexp_wrde_dooffs = WRDE_DOOFFS; -# endif // !SANITIZER_ANDROID +# endif // !SANITIZER_ANDROID && !SANITIZER_HAIKU # if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ @@ -540,7 +550,8 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_sock_fprog_sz = sizeof(struct sock_fprog); # endif // SANITIZER_GLIBC -# if !SANITIZER_ANDROID && !SANITIZER_APPLE && !SANITIZER_EMSCRIPTEN +# if !SANITIZER_ANDROID && !SANITIZER_APPLE && !SANITIZER_HAIKU && \ + !SANITIZER_EMSCRIPTEN unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req); unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req); #endif @@ -554,12 +565,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); const unsigned IOCTL_NOT_PRESENT = 0; #if !SANITIZER_EMSCRIPTEN + unsigned IOCTL_FIONBIO = FIONBIO; +#if !SANITIZER_HAIKU unsigned IOCTL_FIOASYNC = FIOASYNC; unsigned IOCTL_FIOCLEX = FIOCLEX; unsigned IOCTL_FIOGETOWN = FIOGETOWN; - unsigned IOCTL_FIONBIO = FIONBIO; unsigned IOCTL_FIONCLEX = FIONCLEX; unsigned IOCTL_FIOSETOWN = FIOSETOWN; +#endif unsigned IOCTL_SIOCADDMULTI = SIOCADDMULTI; unsigned IOCTL_SIOCATMARK = SIOCATMARK; unsigned IOCTL_SIOCDELMULTI = SIOCDELMULTI; @@ -580,23 +593,27 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_SIOCSIFMTU = SIOCSIFMTU; unsigned IOCTL_SIOCSIFNETMASK = SIOCSIFNETMASK; unsigned IOCTL_SIOCSPGRP = SIOCSPGRP; + +#if !SANITIZER_HAIKU unsigned IOCTL_TIOCCONS = TIOCCONS; - unsigned IOCTL_TIOCEXCL = TIOCEXCL; unsigned IOCTL_TIOCGETD = TIOCGETD; + unsigned IOCTL_TIOCNOTTY = TIOCNOTTY; + unsigned IOCTL_TIOCPKT = TIOCPKT; + unsigned IOCTL_TIOCSETD = TIOCSETD; + unsigned IOCTL_TIOCSTI = TIOCSTI; +#endif + + unsigned IOCTL_TIOCEXCL = TIOCEXCL; unsigned IOCTL_TIOCGPGRP = TIOCGPGRP; unsigned IOCTL_TIOCGWINSZ = TIOCGWINSZ; unsigned IOCTL_TIOCMBIC = TIOCMBIC; unsigned IOCTL_TIOCMBIS = TIOCMBIS; unsigned IOCTL_TIOCMGET = TIOCMGET; unsigned IOCTL_TIOCMSET = TIOCMSET; - unsigned IOCTL_TIOCNOTTY = TIOCNOTTY; unsigned IOCTL_TIOCNXCL = TIOCNXCL; unsigned IOCTL_TIOCOUTQ = TIOCOUTQ; - unsigned IOCTL_TIOCPKT = TIOCPKT; unsigned IOCTL_TIOCSCTTY = TIOCSCTTY; - unsigned IOCTL_TIOCSETD = TIOCSETD; unsigned IOCTL_TIOCSPGRP = TIOCSPGRP; - unsigned IOCTL_TIOCSTI = TIOCSTI; unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ; #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT; @@ -771,16 +788,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER; #endif // SOUND_VERSION unsigned IOCTL_TCFLSH = TCFLSH; - unsigned IOCTL_TCGETA = TCGETA; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS unsigned IOCTL_TCGETS = TCGETS; +# endif unsigned IOCTL_TCSBRK = TCSBRK; unsigned IOCTL_TCSBRKP = TCSBRKP; - unsigned IOCTL_TCSETA = TCSETA; - unsigned IOCTL_TCSETAF = TCSETAF; - unsigned IOCTL_TCSETAW = TCSETAW; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS unsigned IOCTL_TCSETS = TCSETS; unsigned IOCTL_TCSETSF = TCSETSF; unsigned IOCTL_TCSETSW = TCSETSW; +# endif unsigned IOCTL_TCXONC = TCXONC; unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS; unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR; @@ -1108,7 +1125,7 @@ COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent)); CHECK_SIZE_AND_OFFSET(dirent, d_ino); #if SANITIZER_APPLE CHECK_SIZE_AND_OFFSET(dirent, d_seekoff); -#elif SANITIZER_FREEBSD +#elif SANITIZER_FREEBSD || SANITIZER_HAIKU // There is no 'd_off' field on FreeBSD. #else CHECK_SIZE_AND_OFFSET(dirent, d_off); @@ -1125,7 +1142,9 @@ CHECK_SIZE_AND_OFFSET(dirent64, d_reclen); CHECK_TYPE_SIZE(ifconf); CHECK_SIZE_AND_OFFSET(ifconf, ifc_len); +#if !SANITIZER_HAIKU CHECK_SIZE_AND_OFFSET(ifconf, ifc_ifcu); +#endif CHECK_TYPE_SIZE(pollfd); CHECK_SIZE_AND_OFFSET(pollfd, fd); @@ -1182,7 +1201,7 @@ CHECK_TYPE_SIZE(__kernel_loff_t); CHECK_TYPE_SIZE(__kernel_fd_set); #endif -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_HAIKU CHECK_TYPE_SIZE(wordexp_t); CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordc); CHECK_SIZE_AND_OFFSET(wordexp_t, we_wordv); @@ -1212,7 +1231,7 @@ CHECK_SIZE_AND_OFFSET(mntent, mnt_freq); CHECK_SIZE_AND_OFFSET(mntent, mnt_passno); #endif -#if !SANITIZER_EMSCRIPTEN +#if !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN CHECK_TYPE_SIZE(ether_addr); #endif @@ -1252,7 +1271,7 @@ CHECK_TYPE_SIZE(clock_t); CHECK_TYPE_SIZE(clockid_t); #endif -#if !SANITIZER_ANDROID && !SANITIZER_EMSCRIPTEN +#if !SANITIZER_ANDROID && !SANITIZER_HAIKU && !SANITIZER_EMSCRIPTEN CHECK_TYPE_SIZE(ifaddrs); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name); diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 15a20cf3f5ad4..1b600798c79fc 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -14,48 +14,49 @@ #ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H #define SANITIZER_PLATFORM_LIMITS_POSIX_H -#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_EMSCRIPTEN - -#include "sanitizer_internal_defs.h" -#include "sanitizer_platform.h" -#include "sanitizer_mallinfo.h" - -#if SANITIZER_APPLE -#include -#if !__DARWIN_ONLY_64_BIT_INO_T -#define SANITIZER_HAS_STAT64 1 -#define SANITIZER_HAS_STATFS64 1 -#else -#define SANITIZER_HAS_STAT64 0 -#define SANITIZER_HAS_STATFS64 0 -#endif -#elif SANITIZER_EMSCRIPTEN -#define SANITIZER_HAS_STAT64 0 -#define SANITIZER_HAS_STATFS64 0 -#else +#if SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU || \ + SANITIZER_EMSCRIPTEN + +# include "sanitizer_internal_defs.h" +# include "sanitizer_mallinfo.h" +# include "sanitizer_platform.h" + +# if SANITIZER_APPLE +# include +# if !__DARWIN_ONLY_64_BIT_INO_T +# define SANITIZER_HAS_STAT64 1 +# define SANITIZER_HAS_STATFS64 1 +# else +# define SANITIZER_HAS_STAT64 0 +# define SANITIZER_HAS_STATFS64 0 +# endif +# elif SANITIZER_EMSCRIPTEN +# define SANITIZER_HAS_STAT64 0 +# define SANITIZER_HAS_STATFS64 0 +# else // Must be SANITIZER_LINUX then -#define SANITIZER_HAS_STAT64 1 -#define SANITIZER_HAS_STATFS64 1 -#endif +# define SANITIZER_HAS_STAT64 1 +# define SANITIZER_HAS_STATFS64 1 +# endif -#if SANITIZER_EMSCRIPTEN -#include // For sigset_t -#include // For clock_t and clockid_t -#endif +# if SANITIZER_EMSCRIPTEN +# include // For sigset_t +# include // For clock_t and clockid_t +# endif -#if defined(__sparc__) +# if defined(__sparc__) // FIXME: This can't be included from tsan which does not support sparc yet. -#include "sanitizer_glibc_version.h" -#endif +# include "sanitizer_glibc_version.h" +# endif -# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map*)(handle)) +# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) ((link_map *)(handle)) namespace __sanitizer { extern unsigned struct_utsname_sz; extern unsigned struct_stat_sz; -#if SANITIZER_HAS_STAT64 +# if SANITIZER_HAS_STAT64 extern unsigned struct_stat64_sz; -#endif +# endif extern unsigned struct_rusage_sz; extern unsigned siginfo_t_sz; extern unsigned struct_itimerval_sz; @@ -73,13 +74,13 @@ extern unsigned struct_itimerspec_sz; extern unsigned struct_sigevent_sz; extern unsigned struct_stack_t_sz; extern unsigned struct_sched_param_sz; -#if SANITIZER_HAS_STATFS64 +# if SANITIZER_HAS_STATFS64 extern unsigned struct_statfs64_sz; -#endif +# endif extern unsigned struct_regex_sz; extern unsigned struct_regmatch_sz; -#if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID extern unsigned struct_fstab_sz; extern unsigned struct_statfs_sz; extern unsigned struct_sockaddr_sz; @@ -91,45 +92,47 @@ unsigned ucontext_t_sz(void *uctx); # if defined(__x86_64__) const unsigned struct_kernel_stat_sz = 144; const unsigned struct_kernel_stat64_sz = 0; -#elif defined(__i386__) +# elif defined(__i386__) const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 96; -#elif defined(__arm__) +# elif defined(__arm__) const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__aarch64__) +# elif defined(__aarch64__) const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__powerpc__) && !defined(__powerpc64__) +# elif defined(__powerpc__) && !defined(__powerpc64__) const unsigned struct_kernel_stat_sz = 72; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__powerpc64__) +# elif defined(__powerpc64__) const unsigned struct_kernel_stat_sz = 144; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__mips__) +# elif defined(__mips__) const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) # if defined(_ABIN32) && _MIPS_SIM == _ABIN32 : FIRST_32_SECOND_64(176, 216); +# elif SANITIZER_MUSL + : FIRST_32_SECOND_64(160, 208); # else : FIRST_32_SECOND_64(160, 216); # endif const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__s390__) && !defined(__s390x__) +# elif defined(__s390__) && !defined(__s390x__) const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__s390x__) +# elif defined(__s390x__) const unsigned struct_kernel_stat_sz = 144; const unsigned struct_kernel_stat64_sz = 0; -#elif defined(__sparc__) && defined(__arch64__) +# elif defined(__sparc__) && defined(__arch64__) const unsigned struct___old_kernel_stat_sz = 0; const unsigned struct_kernel_stat_sz = 104; const unsigned struct_kernel_stat64_sz = 144; -#elif defined(__sparc__) && !defined(__arch64__) +# elif defined(__sparc__) && !defined(__arch64__) const unsigned struct___old_kernel_stat_sz = 0; const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 104; -#elif SANITIZER_RISCV64 +# elif SANITIZER_RISCV64 const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64 # elif defined(__hexagon__) @@ -154,15 +157,15 @@ extern unsigned struct_old_utsname_sz; extern unsigned struct_oldold_utsname_sz; const unsigned struct_kexec_segment_sz = 4 * sizeof(unsigned long); -#endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -#if SANITIZER_LINUX +# if SANITIZER_LINUX -#if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__) +# if defined(__powerpc64__) || defined(__s390__) || defined(__loongarch__) const unsigned struct___old_kernel_stat_sz = 0; -#elif !defined(__sparc__) +# elif !defined(__sparc__) const unsigned struct___old_kernel_stat_sz = 32; -#endif +# endif extern unsigned struct_rlimit_sz; extern unsigned struct_utimbuf_sz; @@ -207,17 +210,17 @@ struct __sanitizer___sysctl_args { const unsigned old_sigset_t_sz = sizeof(unsigned long); struct __sanitizer_sem_t { -#if SANITIZER_ANDROID && defined(_LP64) +# if SANITIZER_ANDROID && defined(_LP64) int data[4]; -#elif SANITIZER_ANDROID && !defined(_LP64) +# elif SANITIZER_ANDROID && !defined(_LP64) int data; -#elif SANITIZER_LINUX +# elif SANITIZER_LINUX uptr data[4]; -#endif +# endif }; -#endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned struct_ustat_sz; extern unsigned struct_rlimit64_sz; extern unsigned struct_statvfs64_sz; @@ -228,45 +231,45 @@ struct __sanitizer_ipc_perm { int gid; int cuid; int cgid; -#ifdef __powerpc__ +# ifdef __powerpc__ unsigned mode; unsigned __seq; u64 __unused1; u64 __unused2; -#elif defined(__sparc__) +# elif defined(__sparc__) unsigned mode; unsigned short __pad2; unsigned short __seq; unsigned long long __unused1; unsigned long long __unused2; -#else +# else unsigned int mode; unsigned short __seq; unsigned short __pad2; -#if defined(__x86_64__) && !defined(_LP64) +# if defined(__x86_64__) && !defined(_LP64) u64 __unused1; u64 __unused2; -#else +# else unsigned long __unused1; unsigned long __unused2; -#endif -#endif +# endif +# endif }; struct __sanitizer_shmid_ds { __sanitizer_ipc_perm shm_perm; -#if defined(__sparc__) -#if !defined(__arch64__) +# if defined(__sparc__) +# if !defined(__arch64__) u32 __pad1; -#endif +# endif long shm_atime; -#if !defined(__arch64__) +# if !defined(__arch64__) u32 __pad2; -#endif +# endif long shm_dtime; -#if !defined(__arch64__) +# if !defined(__arch64__) u32 __pad3; -#endif +# endif long shm_ctime; uptr shm_segsz; int shm_cpid; @@ -274,61 +277,61 @@ struct __sanitizer_shmid_ds { unsigned long shm_nattch; unsigned long __glibc_reserved1; unsigned long __glibc_reserved2; -#else -#ifndef __powerpc__ +# else +# ifndef __powerpc__ uptr shm_segsz; -#elif !defined(__powerpc64__) +# elif !defined(__powerpc64__) uptr __unused0; -#endif -#if defined(__x86_64__) && !defined(_LP64) +# endif +# if defined(__x86_64__) && !defined(_LP64) u64 shm_atime; u64 shm_dtime; u64 shm_ctime; -#else +# else uptr shm_atime; -#if !defined(_LP64) && !defined(__mips__) +# if !defined(_LP64) && !defined(__mips__) uptr __unused1; -#endif +# endif uptr shm_dtime; -#if !defined(_LP64) && !defined(__mips__) +# if !defined(_LP64) && !defined(__mips__) uptr __unused2; -#endif +# endif uptr shm_ctime; -#if !defined(_LP64) && !defined(__mips__) +# if !defined(_LP64) && !defined(__mips__) uptr __unused3; -#endif -#endif -#ifdef __powerpc__ +# endif +# endif +# ifdef __powerpc__ uptr shm_segsz; -#endif +# endif int shm_cpid; int shm_lpid; -#if defined(__x86_64__) && !defined(_LP64) +# if defined(__x86_64__) && !defined(_LP64) u64 shm_nattch; u64 __unused4; u64 __unused5; -#else +# else uptr shm_nattch; uptr __unused4; uptr __unused5; -#endif -#endif +# endif +# endif }; -#endif +# endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned struct_msqid_ds_sz; extern unsigned struct_mq_attr_sz; extern unsigned struct_timex_sz; extern unsigned struct_statvfs_sz; -#endif // SANITIZER_LINUX && !SANITIZER_ANDROID +# endif // SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer_iovec { void *iov_base; usize iov_len; }; -#if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID struct __sanitizer_ifaddrs { struct __sanitizer_ifaddrs *ifa_next; char *ifa_name; @@ -336,21 +339,21 @@ struct __sanitizer_ifaddrs { void *ifa_addr; // (struct sockaddr *) void *ifa_netmask; // (struct sockaddr *) // This is a union on Linux. -# ifdef ifa_dstaddr -# undef ifa_dstaddr -# endif +# ifdef ifa_dstaddr +# undef ifa_dstaddr +# endif void *ifa_dstaddr; // (struct sockaddr *) void *ifa_data; }; -#endif // !SANITIZER_ANDROID +# endif // !SANITIZER_ANDROID -#if SANITIZER_APPLE +# if SANITIZER_APPLE typedef unsigned long __sanitizer_pthread_key_t; -#else +# else typedef unsigned __sanitizer_pthread_key_t; -#endif +# endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer_XDR { int x_op; @@ -364,25 +367,28 @@ struct __sanitizer_XDR { const int __sanitizer_XDR_ENCODE = 0; const int __sanitizer_XDR_DECODE = 1; const int __sanitizer_XDR_FREE = 2; -#endif +# endif struct __sanitizer_passwd { char *pw_name; char *pw_passwd; int pw_uid; int pw_gid; -#if SANITIZER_APPLE +# if SANITIZER_APPLE long pw_change; char *pw_class; -#endif -#if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)) +# endif +# if !(SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32)) && !SANITIZER_HAIKU char *pw_gecos; -#endif +# endif char *pw_dir; char *pw_shell; -#if SANITIZER_APPLE +# if SANITIZER_APPLE long pw_expire; -#endif +# endif +# if SANITIZER_HAIKU + char *pw_gecos; +# endif }; struct __sanitizer_group { @@ -395,9 +401,9 @@ struct __sanitizer_group { # if (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \ (defined(__x86_64__) && !defined(_LP64)) || defined(__hexagon__) typedef long long __sanitizer_time_t; -#else +# else typedef long __sanitizer_time_t; -#endif +# endif typedef long __sanitizer_suseconds_t; @@ -442,11 +448,15 @@ struct __sanitizer_tm { int tm_wday; int tm_yday; int tm_isdst; +# if SANITIZER_HAIKU + int tm_gmtoff; +# else long int tm_gmtoff; +# endif const char *tm_zone; }; -#if SANITIZER_LINUX +# if SANITIZER_LINUX struct __sanitizer_mntent { char *mnt_fsname; char *mnt_dir; @@ -461,9 +471,9 @@ struct __sanitizer_file_handle { int handle_type; unsigned char f_handle[1]; // variable sized }; -#endif +# endif -#if SANITIZER_APPLE +# if SANITIZER_APPLE || SANITIZER_HAIKU struct __sanitizer_msghdr { void *msg_name; unsigned msg_namelen; @@ -478,7 +488,31 @@ struct __sanitizer_cmsghdr { int cmsg_level; int cmsg_type; }; -#else +# elif SANITIZER_MUSL +struct __sanitizer_msghdr { + void *msg_name; + unsigned msg_namelen; + struct __sanitizer_iovec *msg_iov; + int msg_iovlen; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + void *msg_control; + unsigned msg_controllen; +# if SANITIZER_WORDSIZE == 64 + int __pad2; +# endif + int msg_flags; +}; +struct __sanitizer_cmsghdr { + unsigned cmsg_len; +# if SANITIZER_WORDSIZE == 64 + int __pad1; +# endif + int cmsg_level; + int cmsg_type; +}; +# else // In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but // many implementations don't conform to the standard. struct __sanitizer_msghdr { @@ -495,22 +529,31 @@ struct __sanitizer_cmsghdr { int cmsg_level; int cmsg_type; }; -#endif +# endif -#if SANITIZER_LINUX +# if SANITIZER_LINUX struct __sanitizer_mmsghdr { __sanitizer_msghdr msg_hdr; unsigned int msg_len; }; -#endif +# endif -#if SANITIZER_APPLE +# if SANITIZER_APPLE struct __sanitizer_dirent { unsigned long long d_ino; unsigned long long d_seekoff; unsigned short d_reclen; // more fields that we don't care about }; +# elif SANITIZER_HAIKU +struct __sanitizer_dirent { + int d_dev; + int d_pdev; + unsigned long long d_ino; + unsigned long long d_pino; + unsigned short d_reclen; + // more fields that we don't care about +}; # elif (SANITIZER_LINUX && !SANITIZER_GLIBC) || defined(__x86_64__) || \ defined(__hexagon__) struct __sanitizer_dirent { @@ -536,52 +579,54 @@ struct __sanitizer_dirent64 { // more fields that we don't care about }; extern unsigned struct_sock_fprog_sz; -#endif +# endif -#if SANITIZER_EMSCRIPTEN +# if SANITIZER_EMSCRIPTEN typedef clock_t __sanitizer_clock_t; -#elif defined(__x86_64__) && !defined(_LP64) +# elif SANITIZER_HAIKU +typedef int __sanitizer_clock_t; +# elif defined(__x86_64__) && !defined(_LP64) typedef long long __sanitizer_clock_t; -#else +# else typedef long __sanitizer_clock_t; -#endif +# endif -#if SANITIZER_LINUX +# if SANITIZER_LINUX || SANITIZER_HAIKU typedef int __sanitizer_clockid_t; typedef unsigned long long __sanitizer_eventfd_t; -#elif SANITIZER_EMSCRIPTEN +# elif SANITIZER_EMSCRIPTEN typedef clockid_t __sanitizer_clockid_t; // eventfd is Unix-specific. -#endif +# endif -#if SANITIZER_LINUX +# if SANITIZER_LINUX # if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \ defined(__mips__) || defined(__hexagon__) typedef unsigned __sanitizer___kernel_uid_t; typedef unsigned __sanitizer___kernel_gid_t; -#else +# else typedef unsigned short __sanitizer___kernel_uid_t; typedef unsigned short __sanitizer___kernel_gid_t; -#endif -#if defined(__x86_64__) && !defined(_LP64) +# endif +# if defined(__x86_64__) && !defined(_LP64) typedef long long __sanitizer___kernel_off_t; -#else +# else typedef long __sanitizer___kernel_off_t; -#endif +# endif -#if defined(__powerpc__) || defined(__mips__) +# if defined(__powerpc__) || defined(__mips__) typedef unsigned int __sanitizer___kernel_old_uid_t; typedef unsigned int __sanitizer___kernel_old_gid_t; -#else +# else typedef unsigned short __sanitizer___kernel_old_uid_t; typedef unsigned short __sanitizer___kernel_old_gid_t; -#endif +# endif typedef long long __sanitizer___kernel_loff_t; typedef struct { unsigned long fds_bits[1024 / (8 * sizeof(long))]; } __sanitizer___kernel_fd_set; -#endif +# endif // This thing depends on the platform. We are only interested in the upper // limit. Verified with a compiler assert in .cpp. @@ -590,52 +635,54 @@ union __sanitizer_pthread_attr_t { void *align; }; -#if SANITIZER_ANDROID -# if SANITIZER_MIPS +# if SANITIZER_ANDROID +# if SANITIZER_MIPS typedef unsigned long __sanitizer_sigset_t[16 / sizeof(unsigned long)]; -# else +# else typedef unsigned long __sanitizer_sigset_t; -# endif -#elif SANITIZER_APPLE +# endif +# elif SANITIZER_APPLE typedef unsigned __sanitizer_sigset_t; -#elif SANITIZER_LINUX +# elif SANITIZER_HAIKU +typedef unsigned long long __sanitizer_sigset_t; +# elif SANITIZER_LINUX struct __sanitizer_sigset_t { // The size is determined by looking at sizeof of real sigset_t on linux. uptr val[128 / sizeof(uptr)]; }; -#elif SANITIZER_EMSCRIPTEN +# elif SANITIZER_EMSCRIPTEN typedef sigset_t __sanitizer_sigset_t; -#endif +# endif struct __sanitizer_siginfo_pad { -#if SANITIZER_X32 +# if SANITIZER_X32 // x32 siginfo_t is aligned to 8 bytes. u64 pad[128 / sizeof(u64)]; -#else +# else // Require uptr, because siginfo_t is always pointer-size aligned on Linux. uptr pad[128 / sizeof(uptr)]; -#endif +# endif }; -#if SANITIZER_LINUX -# define SANITIZER_HAS_SIGINFO 1 +# if SANITIZER_LINUX +# define SANITIZER_HAS_SIGINFO 1 union __sanitizer_siginfo { __extension__ struct { int si_signo; -# if SANITIZER_MIPS +# if SANITIZER_MIPS int si_code; int si_errno; -# else +# else int si_errno; int si_code; -# endif +# endif }; __sanitizer_siginfo_pad pad; }; -#else -# define SANITIZER_HAS_SIGINFO 0 +# else +# define SANITIZER_HAS_SIGINFO 0 typedef __sanitizer_siginfo_pad __sanitizer_siginfo; -#endif +# endif using __sanitizer_sighandler_ptr = void (*)(int sig); using __sanitizer_sigactionhandler_ptr = void (*)(int sig, @@ -643,7 +690,7 @@ using __sanitizer_sigactionhandler_ptr = void (*)(int sig, void *uctx); // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros. -#if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64) +# if SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64) struct __sanitizer_sigaction { unsigned sa_flags; union { @@ -653,7 +700,8 @@ struct __sanitizer_sigaction { __sanitizer_sigset_t sa_mask; void (*sa_restorer)(); }; -#elif SANITIZER_ANDROID && SANITIZER_MIPS32 // check this before WORDSIZE == 32 +# elif SANITIZER_ANDROID && \ + SANITIZER_MIPS32 // check this before WORDSIZE == 32 struct __sanitizer_sigaction { unsigned sa_flags; union { @@ -662,7 +710,7 @@ struct __sanitizer_sigaction { }; __sanitizer_sigset_t sa_mask; }; -#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32) +# elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32) struct __sanitizer_sigaction { union { __sanitizer_sigactionhandler_ptr sigaction; @@ -672,66 +720,66 @@ struct __sanitizer_sigaction { uptr sa_flags; void (*sa_restorer)(); }; -#else // !SANITIZER_ANDROID +# else // !SANITIZER_ANDROID struct __sanitizer_sigaction { -#if defined(__mips__) && !SANITIZER_FREEBSD +# if defined(__mips__) && !SANITIZER_FREEBSD && !SANITIZER_MUSL unsigned int sa_flags; -#endif +# endif union { __sanitizer_sigactionhandler_ptr sigaction; __sanitizer_sighandler_ptr handler; }; -#if SANITIZER_FREEBSD +# if SANITIZER_FREEBSD int sa_flags; __sanitizer_sigset_t sa_mask; -#else -#if defined(__s390x__) +# else +# if defined(__s390x__) int sa_resv; -#else +# else __sanitizer_sigset_t sa_mask; -#endif -#ifndef __mips__ -#if defined(__sparc__) -#if __GLIBC_PREREQ (2, 20) +# endif +# if !defined(__mips__) || SANITIZER_MUSL +# if defined(__sparc__) +# if __GLIBC_PREREQ(2, 20) // On sparc glibc 2.19 and earlier sa_flags was unsigned long. -#if defined(__arch64__) +# if defined(__arch64__) // To maintain ABI compatibility on sparc64 when switching to an int, // __glibc_reserved0 was added. int __glibc_reserved0; -#endif +# endif int sa_flags; -#else +# else unsigned long sa_flags; -#endif -#else +# endif +# else int sa_flags; -#endif -#endif -#endif -#if SANITIZER_LINUX +# endif +# endif +# endif +# if SANITIZER_LINUX || SANITIZER_HAIKU void (*sa_restorer)(); -#endif -#if defined(__mips__) && (SANITIZER_WORDSIZE == 32) +# endif +# if defined(__mips__) && (SANITIZER_WORDSIZE == 32) && !SANITIZER_MUSL int sa_resv[1]; -#endif -#if defined(__s390x__) +# endif +# if defined(__s390x__) __sanitizer_sigset_t sa_mask; -#endif +# endif }; -#endif // !SANITIZER_ANDROID +# endif // !SANITIZER_ANDROID -#if defined(__mips__) -#define __SANITIZER_KERNEL_NSIG 128 -#else -#define __SANITIZER_KERNEL_NSIG 64 -#endif +# if defined(__mips__) +# define __SANITIZER_KERNEL_NSIG 128 +# else +# define __SANITIZER_KERNEL_NSIG 64 +# endif struct __sanitizer_kernel_sigset_t { uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)]; }; // Linux system headers define the 'sa_handler' and 'sa_sigaction' macros. -#if SANITIZER_MIPS +# if SANITIZER_MIPS struct __sanitizer_kernel_sigaction_t { unsigned int sa_flags; union { @@ -741,7 +789,7 @@ struct __sanitizer_kernel_sigaction_t { __sanitizer_kernel_sigset_t sa_mask; void (*sa_restorer)(void); }; -#else +# else struct __sanitizer_kernel_sigaction_t { union { void (*handler)(int signo); @@ -751,22 +799,22 @@ struct __sanitizer_kernel_sigaction_t { void (*sa_restorer)(void); __sanitizer_kernel_sigset_t sa_mask; }; -#endif +# endif extern const uptr sig_ign; extern const uptr sig_dfl; extern const uptr sig_err; extern const uptr sa_siginfo; -#if SANITIZER_LINUX +# if SANITIZER_LINUX extern int e_tabsz; -#endif +# endif extern int af_inet; extern int af_inet6; uptr __sanitizer_in_addr_sz(int af); -#if SANITIZER_LINUX +# if SANITIZER_LINUX struct __sanitizer_dl_phdr_info { uptr dlpi_addr; const char *dlpi_name; @@ -775,7 +823,7 @@ struct __sanitizer_dl_phdr_info { }; extern unsigned struct_ElfW_Phdr_sz; -#endif +# endif struct __sanitizer_protoent { char *p_name; @@ -795,15 +843,15 @@ struct __sanitizer_addrinfo { int ai_family; int ai_socktype; int ai_protocol; -#if SANITIZER_ANDROID || SANITIZER_APPLE +# if SANITIZER_ANDROID || SANITIZER_APPLE || SANITIZER_HAIKU unsigned ai_addrlen; char *ai_canonname; void *ai_addr; -#else // LINUX +# else // LINUX unsigned ai_addrlen; void *ai_addr; char *ai_canonname; -#endif +# endif struct __sanitizer_addrinfo *ai_next; }; @@ -821,14 +869,14 @@ struct __sanitizer_pollfd { short revents; }; -#if SANITIZER_ANDROID || SANITIZER_APPLE +# if SANITIZER_ANDROID || SANITIZER_APPLE typedef unsigned __sanitizer_nfds_t; -#else +# else typedef unsigned long __sanitizer_nfds_t; -#endif +# endif -#if !SANITIZER_ANDROID -# if SANITIZER_LINUX +# if !SANITIZER_ANDROID +# if SANITIZER_LINUX struct __sanitizer_glob_t { uptr gl_pathc; char **gl_pathv; @@ -841,13 +889,13 @@ struct __sanitizer_glob_t { int (*gl_lstat)(const char *, void *); int (*gl_stat)(const char *, void *); }; -# endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -# if SANITIZER_LINUX +# if SANITIZER_LINUX extern int glob_nomatch; extern int glob_altdirfunc; -# endif -#endif // !SANITIZER_ANDROID +# endif +# endif // !SANITIZER_ANDROID extern unsigned path_max; @@ -861,7 +909,7 @@ struct __sanitizer_wordexp_t { uptr we_offs; }; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer_FILE { int _flags; char *_IO_read_ptr; @@ -879,11 +927,11 @@ struct __sanitizer_FILE { __sanitizer_FILE *_chain; int _fileno; }; -# define SANITIZER_HAS_STRUCT_FILE 1 -#else +# define SANITIZER_HAS_STRUCT_FILE 1 +# else typedef void __sanitizer_FILE; -# define SANITIZER_HAS_STRUCT_FILE 0 -#endif +# define SANITIZER_HAS_STRUCT_FILE 0 +# endif # if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ @@ -935,14 +983,14 @@ extern int shmctl_ipc_stat; extern int shmctl_ipc_info; extern int shmctl_shm_info; extern int shmctl_shm_stat; -#endif +# endif -#if !SANITIZER_APPLE && !SANITIZER_FREEBSD +# if !SANITIZER_APPLE && !SANITIZER_FREEBSD extern unsigned struct_utmp_sz; -#endif -#if !SANITIZER_ANDROID +# endif +# if !SANITIZER_ANDROID extern unsigned struct_utmpx_sz; -#endif +# endif extern int map_fixed; @@ -952,13 +1000,13 @@ struct __sanitizer_ifconf { union { void *ifcu_req; } ifc_ifcu; -#if SANITIZER_APPLE +# if SANITIZER_APPLE } __attribute__((packed)); -#else +# else }; -#endif +# endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID struct __sanitizer__obstack_chunk { char *limit; struct __sanitizer__obstack_chunk *prev; @@ -985,57 +1033,57 @@ struct __sanitizer_cookie_io_functions_t { __sanitizer_cookie_io_seek seek; __sanitizer_cookie_io_close close; }; -#endif +# endif -#define IOC_NRBITS 8 -#define IOC_TYPEBITS 8 -#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \ - defined(__sparc__) -#define IOC_SIZEBITS 13 -#define IOC_DIRBITS 3 -#define IOC_NONE 1U -#define IOC_WRITE 4U -#define IOC_READ 2U -#else -#define IOC_SIZEBITS 14 -#define IOC_DIRBITS 2 -#define IOC_NONE 0U -#define IOC_WRITE 1U -#define IOC_READ 2U -#endif -#define IOC_NRMASK ((1 << IOC_NRBITS) - 1) -#define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1) -#define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1) -#if defined(IOC_DIRMASK) -#undef IOC_DIRMASK -#endif -#define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1) -#define IOC_NRSHIFT 0 -#define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS) -#define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS) -#define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS) -#define EVIOC_EV_MAX 0x1f -#define EVIOC_ABS_MAX 0x3f - -#define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK) -#define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK) -#define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK) - -#if defined(__sparc__) +# define IOC_NRBITS 8 +# define IOC_TYPEBITS 8 +# if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \ + defined(__sparc__) +# define IOC_SIZEBITS 13 +# define IOC_DIRBITS 3 +# define IOC_NONE 1U +# define IOC_WRITE 4U +# define IOC_READ 2U +# else +# define IOC_SIZEBITS 14 +# define IOC_DIRBITS 2 +# define IOC_NONE 0U +# define IOC_WRITE 1U +# define IOC_READ 2U +# endif +# define IOC_NRMASK ((1 << IOC_NRBITS) - 1) +# define IOC_TYPEMASK ((1 << IOC_TYPEBITS) - 1) +# define IOC_SIZEMASK ((1 << IOC_SIZEBITS) - 1) +# if defined(IOC_DIRMASK) +# undef IOC_DIRMASK +# endif +# define IOC_DIRMASK ((1 << IOC_DIRBITS) - 1) +# define IOC_NRSHIFT 0 +# define IOC_TYPESHIFT (IOC_NRSHIFT + IOC_NRBITS) +# define IOC_SIZESHIFT (IOC_TYPESHIFT + IOC_TYPEBITS) +# define IOC_DIRSHIFT (IOC_SIZESHIFT + IOC_SIZEBITS) +# define EVIOC_EV_MAX 0x1f +# define EVIOC_ABS_MAX 0x3f + +# define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK) +# define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK) +# define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK) + +# if defined(__sparc__) // In sparc the 14 bits SIZE field overlaps with the // least significant bit of DIR, so either IOC_READ or // IOC_WRITE shall be 1 in order to get a non-zero SIZE. -#define IOC_SIZE(nr) \ - ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff)) -#else -#define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK) -#endif +# define IOC_SIZE(nr) \ + ((((((nr) >> 29) & 0x7) & (4U | 2U)) == 0) ? 0 : (((nr) >> 16) & 0x3fff)) +# else +# define IOC_SIZE(nr) (((nr) >> IOC_SIZESHIFT) & IOC_SIZEMASK) +# endif extern unsigned struct_ifreq_sz; extern unsigned struct_termios_sz; extern unsigned struct_winsize_sz; -#if SANITIZER_LINUX +# if SANITIZER_LINUX extern unsigned struct_arpreq_sz; extern unsigned struct_cdrom_msf_sz; extern unsigned struct_cdrom_multisession_sz; @@ -1062,9 +1110,9 @@ extern unsigned struct_mtpos_sz; extern unsigned struct_vt_consize_sz; extern unsigned struct_vt_sizes_sz; extern unsigned struct_vt_stat_sz; -#endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -#if SANITIZER_LINUX +# if SANITIZER_LINUX extern unsigned struct_copr_buffer_sz; extern unsigned struct_copr_debug_buf_sz; extern unsigned struct_copr_msg_sz; @@ -1076,9 +1124,9 @@ extern unsigned struct_sbi_instrument_sz; extern unsigned struct_seq_event_rec_sz; extern unsigned struct_synth_info_sz; extern unsigned struct_vt_mode_sz; -#endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned struct_ax25_parms_struct_sz; extern unsigned struct_input_keymap_entry_sz; extern unsigned struct_ipx_config_data_sz; @@ -1099,15 +1147,15 @@ extern unsigned struct_unimapinit_sz; extern const unsigned long __sanitizer_bufsiz; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned struct_audio_buf_info_sz; extern unsigned struct_ppp_stats_sz; -#endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID +# endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -#if !SANITIZER_ANDROID && !SANITIZER_APPLE +# if !SANITIZER_ANDROID && !SANITIZER_APPLE extern unsigned struct_sioc_sg_req_sz; extern unsigned struct_sioc_vif_req_sz; -#endif +# endif extern unsigned fpos_t_sz; @@ -1143,29 +1191,31 @@ extern unsigned IOCTL_SIOCSIFMETRIC; extern unsigned IOCTL_SIOCSIFMTU; extern unsigned IOCTL_SIOCSIFNETMASK; extern unsigned IOCTL_SIOCSPGRP; +# if !SANITIZER_HAIKU extern unsigned IOCTL_TIOCCONS; -extern unsigned IOCTL_TIOCEXCL; extern unsigned IOCTL_TIOCGETD; +extern unsigned IOCTL_TIOCNOTTY; +extern unsigned IOCTL_TIOCPKT; +extern unsigned IOCTL_TIOCSETD; +extern unsigned IOCTL_TIOCSTI; +# endif +extern unsigned IOCTL_TIOCEXCL; extern unsigned IOCTL_TIOCGPGRP; extern unsigned IOCTL_TIOCGWINSZ; extern unsigned IOCTL_TIOCMBIC; extern unsigned IOCTL_TIOCMBIS; extern unsigned IOCTL_TIOCMGET; extern unsigned IOCTL_TIOCMSET; -extern unsigned IOCTL_TIOCNOTTY; extern unsigned IOCTL_TIOCNXCL; extern unsigned IOCTL_TIOCOUTQ; -extern unsigned IOCTL_TIOCPKT; extern unsigned IOCTL_TIOCSCTTY; -extern unsigned IOCTL_TIOCSETD; extern unsigned IOCTL_TIOCSPGRP; -extern unsigned IOCTL_TIOCSTI; extern unsigned IOCTL_TIOCSWINSZ; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned IOCTL_SIOCGETSGCNT; extern unsigned IOCTL_SIOCGETVIFCNT; -#endif -#if SANITIZER_LINUX +# endif +# if SANITIZER_LINUX extern unsigned IOCTL_EVIOCGABS; extern unsigned IOCTL_EVIOCGBIT; extern unsigned IOCTL_EVIOCGEFFECTS; @@ -1305,16 +1355,14 @@ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG; extern unsigned IOCTL_SNDCTL_COPR_WCODE; extern unsigned IOCTL_SNDCTL_COPR_WDATA; extern unsigned IOCTL_TCFLSH; -extern unsigned IOCTL_TCGETA; -extern unsigned IOCTL_TCGETS; extern unsigned IOCTL_TCSBRK; extern unsigned IOCTL_TCSBRKP; -extern unsigned IOCTL_TCSETA; -extern unsigned IOCTL_TCSETAF; -extern unsigned IOCTL_TCSETAW; +# if SANITIZER_TERMIOS_IOCTL_CONSTANTS +extern unsigned IOCTL_TCGETS; extern unsigned IOCTL_TCSETS; extern unsigned IOCTL_TCSETSF; extern unsigned IOCTL_TCSETSW; +# endif extern unsigned IOCTL_TCXONC; extern unsigned IOCTL_TIOCGLCKTRMIOS; extern unsigned IOCTL_TIOCGSOFTCAR; @@ -1431,9 +1479,9 @@ extern unsigned IOCTL_VT_OPENQRY; extern unsigned IOCTL_VT_RELDISP; extern unsigned IOCTL_VT_SETMODE; extern unsigned IOCTL_VT_WAITACTIVE; -#endif // SANITIZER_LINUX +# endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID extern unsigned IOCTL_EQL_EMANCIPATE; extern unsigned IOCTL_EQL_ENSLAVE; extern unsigned IOCTL_EQL_GETMASTRCFG; @@ -1522,35 +1570,45 @@ extern unsigned IOCTL_KDSETMODE; extern unsigned IOCTL_KDSKBMODE; extern unsigned IOCTL_KIOCSOUND; extern unsigned IOCTL_PIO_SCRNMAP; -#endif +# endif + +# if SANITIZER_GLIBC +struct __sanitizer_servent { + char *s_name; + char **s_aliases; + int s_port; + char *s_proto; +}; +# endif extern const int si_SEGV_MAPERR; extern const int si_SEGV_ACCERR; } // namespace __sanitizer -#define CHECK_TYPE_SIZE(TYPE) \ - COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE)) +# define CHECK_TYPE_SIZE(TYPE) \ + COMPILER_CHECK(sizeof(__sanitizer_##TYPE) == sizeof(TYPE)) -#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ - COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \ - sizeof(((CLASS *)NULL)->MEMBER)); \ - COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \ - offsetof(CLASS, MEMBER)) +# define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ + COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) == \ + sizeof(((CLASS *)NULL)->MEMBER)); \ + COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) == \ + offsetof(CLASS, MEMBER)) // For sigaction, which is a function and struct at the same time, // and thus requires explicit "struct" in sizeof() expression. -#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \ - COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \ - sizeof(((struct CLASS *)NULL)->MEMBER)); \ - COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \ - offsetof(struct CLASS, MEMBER)) +# define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, MEMBER) \ + COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS *)NULL)->MEMBER) == \ + sizeof(((struct CLASS *)NULL)->MEMBER)); \ + COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) == \ + offsetof(struct CLASS, MEMBER)) -#define SIGACTION_SYMNAME sigaction +# define SIGACTION_SYMNAME sigaction # if SANITIZER_LINUX typedef void *__sanitizer_timer_t; # endif -#endif // SANITIZER_LINUX || SANITIZER_APPLE +#endif // SANITIZER_LINUX || SANITIZER_APPLE || SANITIZER_HAIKU || + // SANITIZER_EMSCRIPTEN #endif diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h index bf3c2c28e32e3..d713ddf847dfb 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h @@ -16,7 +16,7 @@ #include "sanitizer_platform.h" #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ - SANITIZER_APPLE || SANITIZER_SOLARIS || \ + SANITIZER_APPLE || SANITIZER_SOLARIS || SANITIZER_HAIKU || \ SANITIZER_FUCHSIA #include "sanitizer_common.h" diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp new file mode 100644 index 0000000000000..7a6062a571ba5 --- /dev/null +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_haiku.cpp @@ -0,0 +1,94 @@ +//===-- sanitizer_procmaps_haiku.cpp --------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Information about the process mappings +// (Haiku-specific parts). +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" +#if SANITIZER_HAIKU +# include "sanitizer_common.h" +# include "sanitizer_procmaps.h" + +# include + +namespace __sanitizer { + +void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) { + // data_ should be unused on this platform + CHECK(!data_); + module->addAddressRange(start, end, IsExecutable(), IsWritable()); +} + +MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); } + +void MemoryMappingLayout::Reset() { data_.cookie = 0; } + +MemoryMappingLayout::~MemoryMappingLayout() {} + +// static +void MemoryMappingLayout::CacheMemoryMappings() {} + +bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { + area_info info; + if (get_next_area_info(B_CURRENT_TEAM, &data_.cookie, &info) != B_OK) + return false; + + segment->start = (uptr)info.address; + segment->end = (uptr)info.address + info.size; + segment->offset = 0; + segment->protection = 0; + if (info.protection & B_READ_AREA) + segment->protection |= kProtectionRead; + if (info.protection & B_WRITE_AREA) + segment->protection |= kProtectionWrite; + if (info.protection & B_EXECUTE_AREA) + segment->protection |= kProtectionExecute; + if (segment->filename) { + uptr len = Min((uptr)B_OS_NAME_LENGTH, segment->filename_size - 1); + internal_strncpy(segment->filename, info.name, len); + segment->filename[len] = 0; + } + return true; +} + +bool MemoryMappingLayout::Error() const { return false; } + +void MemoryMappingLayout::DumpListOfModules( + InternalMmapVectorNoCtor *modules) { + Reset(); + InternalMmapVector module_name(kMaxPathLength); + MemoryMappedSegment segment(module_name.data(), module_name.size()); + for (uptr i = 0; Next(&segment); i++) { + const char *cur_name = segment.filename; + if (cur_name[0] == '\0') + continue; + // Don't subtract 'cur_beg' from the first entry: + // * If a binary is compiled w/o -pie, then the first entry in + // process maps is likely the binary itself (all dynamic libs + // are mapped higher in address space). For such a binary, + // instruction offset in binary coincides with the actual + // instruction address in virtual memory (as code section + // is mapped to a fixed memory range). + // * If a binary is compiled with -pie, all the modules are + // mapped high at address space (in particular, higher than + // shadow memory of the tool), so the module can't be the + // first entry. + uptr base_address = (i ? segment.start : 0) - segment.offset; + LoadedModule cur_module; + cur_module.set(cur_name, base_address); + segment.AddAddressRanges(&cur_module); + modules->push_back(cur_module); + } +} + +void GetMemoryProfile(fill_profile_f cb, uptr *stats) {} + +} // namespace __sanitizer + +#endif diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp index 5ff8d1832556f..a9533d6fc04ca 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_mac.cpp @@ -334,9 +334,22 @@ static const load_command *NextCommand(const load_command *lc) { return (const load_command *)((const char *)lc + lc->cmdsize); } -static void FindUUID(const load_command *first_lc, u8 *uuid_output) { - for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) { - if (lc->cmd != LC_UUID) continue; +# ifdef MH_MAGIC_64 +static constexpr size_t header_size = sizeof(mach_header_64); +# else +static constexpr size_t header_size = sizeof(mach_header); +# endif + +static void FindUUID(const load_command *first_lc, const mach_header *hdr, + u8 *uuid_output) { + uint32_t curcmd = 0; + for (const load_command *lc = first_lc; curcmd < hdr->ncmds; + curcmd++, lc = NextCommand(lc)) { + CHECK_LT((const char *)lc, + (const char *)hdr + header_size + hdr->sizeofcmds); + + if (lc->cmd != LC_UUID) + continue; const uuid_command *uuid_lc = (const uuid_command *)lc; const uint8_t *uuid = &uuid_lc->uuid[0]; @@ -345,9 +358,16 @@ static void FindUUID(const load_command *first_lc, u8 *uuid_output) { } } -static bool IsModuleInstrumented(const load_command *first_lc) { - for (const load_command *lc = first_lc; lc->cmd != 0; lc = NextCommand(lc)) { - if (lc->cmd != LC_LOAD_DYLIB) continue; +static bool IsModuleInstrumented(const load_command *first_lc, + const mach_header *hdr) { + uint32_t curcmd = 0; + for (const load_command *lc = first_lc; curcmd < hdr->ncmds; + curcmd++, lc = NextCommand(lc)) { + CHECK_LT((const char *)lc, + (const char *)hdr + header_size + hdr->sizeofcmds); + + if (lc->cmd != LC_LOAD_DYLIB) + continue; const dylib_command *dylib_lc = (const dylib_command *)lc; uint32_t dylib_name_offset = dylib_lc->dylib.name.offset; @@ -393,10 +413,10 @@ bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { continue; } } - FindUUID((const load_command *)data_.current_load_cmd_addr, + FindUUID((const load_command *)data_.current_load_cmd_addr, hdr, data_.current_uuid); data_.current_instrumented = IsModuleInstrumented( - (const load_command *)data_.current_load_cmd_addr); + (const load_command *)data_.current_load_cmd_addr, hdr); } while (data_.current_load_cmd_count > 0) { diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp index 80b8158f43db9..452b30308be91 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_solaris.cpp @@ -9,9 +9,6 @@ // Information about the process mappings (Solaris-specific parts). //===----------------------------------------------------------------------===// -// Before Solaris 11.4, doesn't work in a largefile environment. -#undef _FILE_OFFSET_BITS - // Avoid conflict between `_TIME_BITS` defined vs. `_FILE_OFFSET_BITS` // undefined in some Linux configurations. #undef _TIME_BITS diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_redefine_builtins.h b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_redefine_builtins.h index b087871c586c3..9000a3e5e45dd 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_redefine_builtins.h +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_redefine_builtins.h @@ -16,7 +16,7 @@ // The asm hack only works with GCC and Clang. // XXX Emscripten This does not work in Wasm. -# if !defined(_WIN32) && !defined(__wasm__) +# if !defined(_WIN32) && !defined(_AIX) && !defined(__wasm__) asm(R"( .set memcpy, __sanitizer_internal_memcpy diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp index 58d17d90c343a..24929b8c4bd7c 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp @@ -38,25 +38,28 @@ # include #endif #include // for user_regs_struct -#if SANITIZER_ANDROID && SANITIZER_MIPS -# include // for mips SP register in sys/user.h -#endif -#include // for signal-related stuff - -#ifdef sa_handler -# undef sa_handler -#endif - -#ifdef sa_sigaction -# undef sa_sigaction -#endif - -#include "sanitizer_common.h" -#include "sanitizer_flags.h" -#include "sanitizer_libc.h" -#include "sanitizer_linux.h" -#include "sanitizer_mutex.h" -#include "sanitizer_placement_new.h" +# if SANITIZER_MIPS +// clang-format off +# include // must be included before +# include // for mips SP register +// clang-format on +# endif +# include // for signal-related stuff + +# ifdef sa_handler +# undef sa_handler +# endif + +# ifdef sa_sigaction +# undef sa_sigaction +# endif + +# include "sanitizer_common.h" +# include "sanitizer_flags.h" +# include "sanitizer_libc.h" +# include "sanitizer_linux.h" +# include "sanitizer_mutex.h" +# include "sanitizer_placement_new.h" // Sufficiently old kernel headers don't provide this value, but we can still // call prctl with it. If the runtime kernel is new enough, the prctl call will @@ -511,11 +514,7 @@ typedef pt_regs regs_struct; #elif defined(__mips__) typedef struct user regs_struct; -# if SANITIZER_ANDROID -# define REG_SP regs[EF_R29] -# else -# define REG_SP regs[EF_REG29] -# endif +# define REG_SP regs[EF_R29] #elif defined(__aarch64__) typedef struct user_pt_regs regs_struct; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp index f114acea79c9c..fa15f8a9f06a9 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp @@ -49,6 +49,8 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList { # define SP_REG Esp # elif SANITIZER_ARM | SANITIZER_ARM64 # define SP_REG Sp +# elif SANITIZER_MIPS32 +# define SP_REG IntSp # else # error Architecture not supported! # endif diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp index 710360520e3cd..70036f25d8b37 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp @@ -31,11 +31,12 @@ Symbolizer *Symbolizer::GetOrInit() { const char *ExtractToken(const char *str, const char *delims, char **result) { uptr prefix_len = internal_strcspn(str, delims); - *result = (char*)InternalAlloc(prefix_len + 1); + *result = (char *)InternalAlloc(prefix_len + 1); internal_memcpy(*result, str, prefix_len); (*result)[prefix_len] = '\0'; const char *prefix_end = str + prefix_len; - if (*prefix_end != '\0') prefix_end++; + if (*prefix_end != '\0') + prefix_end++; return prefix_end; } @@ -78,7 +79,8 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, internal_memcpy(*result, str, prefix_len); (*result)[prefix_len] = '\0'; const char *prefix_end = str + prefix_len; - if (*prefix_end != '\0') prefix_end += internal_strlen(delimiter); + if (*prefix_end != '\0') + prefix_end += internal_strlen(delimiter); return prefix_end; } @@ -215,18 +217,20 @@ const LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { modules_were_reloaded = true; } const LoadedModule *module = SearchForModule(modules_, address); - if (module) return module; + if (module) + return module; // dlopen/dlclose interceptors invalidate the module list, but when // interception is disabled, we need to retry if the lookup fails in // case the module list changed. -#if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE +# if !SANITIZER_INTERCEPT_DLOPEN_DLCLOSE if (!modules_were_reloaded) { RefreshModules(); module = SearchForModule(modules_, address); - if (module) return module; + if (module) + return module; } -#endif +# endif if (fallback_modules_.size()) { module = SearchForModule(fallback_modules_, address); @@ -261,31 +265,31 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess { // script/asan_symbolize.py and sanitizer_common.h. void GetArgV(const char *path_to_binary, const char *(&argv)[kArgVMax]) const override { -#if defined(__x86_64h__) - const char* const kSymbolizerArch = "--default-arch=x86_64h"; -#elif defined(__x86_64__) - const char* const kSymbolizerArch = "--default-arch=x86_64"; -#elif defined(__i386__) - const char* const kSymbolizerArch = "--default-arch=i386"; -#elif SANITIZER_LOONGARCH64 +# if defined(__x86_64h__) + const char *const kSymbolizerArch = "--default-arch=x86_64h"; +# elif defined(__x86_64__) + const char *const kSymbolizerArch = "--default-arch=x86_64"; +# elif defined(__i386__) + const char *const kSymbolizerArch = "--default-arch=i386"; +# elif SANITIZER_LOONGARCH64 const char *const kSymbolizerArch = "--default-arch=loongarch64"; -#elif SANITIZER_RISCV64 +# elif SANITIZER_RISCV64 const char *const kSymbolizerArch = "--default-arch=riscv64"; -#elif defined(__aarch64__) - const char* const kSymbolizerArch = "--default-arch=arm64"; -#elif defined(__arm__) - const char* const kSymbolizerArch = "--default-arch=arm"; -#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - const char* const kSymbolizerArch = "--default-arch=powerpc64"; -#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - const char* const kSymbolizerArch = "--default-arch=powerpc64le"; -#elif defined(__s390x__) - const char* const kSymbolizerArch = "--default-arch=s390x"; -#elif defined(__s390__) - const char* const kSymbolizerArch = "--default-arch=s390"; -#else - const char* const kSymbolizerArch = "--default-arch=unknown"; -#endif +# elif defined(__aarch64__) + const char *const kSymbolizerArch = "--default-arch=arm64"; +# elif defined(__arm__) + const char *const kSymbolizerArch = "--default-arch=arm"; +# elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + const char *const kSymbolizerArch = "--default-arch=powerpc64"; +# elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + const char *const kSymbolizerArch = "--default-arch=powerpc64le"; +# elif defined(__s390x__) + const char *const kSymbolizerArch = "--default-arch=s390x"; +# elif defined(__s390__) + const char *const kSymbolizerArch = "--default-arch=s390"; +# else + const char *const kSymbolizerArch = "--default-arch=unknown"; +# endif const char *const demangle_flag = common_flags()->demangle ? "--demangle" : "--no-demangle"; @@ -316,7 +320,8 @@ static const char *ParseFileLineInfo(AddressInfo *info, const char *str) { char *back = file_line_info + size - 1; for (int i = 0; i < 2; ++i) { while (back > file_line_info && IsDigit(*back)) --back; - if (*back != ':' || !IsDigit(back[1])) break; + if (*back != ':' || !IsDigit(back[1])) + break; info->column = info->line; info->line = internal_atoll(back + 1); // Truncate the string at the colon to keep only filename. @@ -437,7 +442,7 @@ bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { if (!buf) return false; ParseSymbolizeDataOutput(buf, info); - info->start += (addr - info->module_offset); // Add the base address. + info->start += (addr - info->module_offset); // Add the base address. return true; } @@ -460,10 +465,9 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix, size_needed = internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n", command_prefix, module_name, module_offset); else - size_needed = internal_snprintf(buffer_, kBufferSize, - "%s \"%s:%s\" 0x%zx\n", command_prefix, - module_name, ModuleArchToString(arch), - module_offset); + size_needed = internal_snprintf( + buffer_, kBufferSize, "%s \"%s:%s\" 0x%zx\n", command_prefix, + module_name, ModuleArchToString(arch), module_offset); if (size_needed >= static_cast(kBufferSize)) { Report("WARNING: Command buffer too small"); @@ -485,9 +489,9 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn) CHECK_NE(path_[0], '\0'); } -static bool IsSameModule(const char* path) { - if (const char* ProcessName = GetProcessName()) { - if (const char* SymbolizerName = StripModuleName(path)) { +static bool IsSameModule(const char *path) { + if (const char *ProcessName = GetProcessName()) { + if (const char *SymbolizerName = StripModuleName(path)) { return !internal_strcmp(ProcessName, SymbolizerName); } } @@ -517,9 +521,9 @@ const char *SymbolizerProcess::SendCommand(const char *command) { const char *SymbolizerProcess::SendCommandImpl(const char *command) { if (input_fd_ == kInvalidFd || output_fd_ == kInvalidFd) - return nullptr; + return nullptr; if (!WriteToSymbolizer(command, internal_strlen(command))) - return nullptr; + return nullptr; if (!ReadFromSymbolizer()) return nullptr; return buffer_.data(); diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp index caff915c2b7b6..4475a095f786f 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp @@ -38,9 +38,10 @@ // because we do not require a C++ ABI library to be linked to a program // using sanitizers; if it's not present, we'll just use the mangled name. namespace __cxxabiv1 { - extern "C" SANITIZER_WEAK_ATTRIBUTE - char *__cxa_demangle(const char *mangled, char *buffer, - size_t *length, int *status); +extern "C" SANITIZER_WEAK_ATTRIBUTE char *__cxa_demangle(const char *mangled, + char *buffer, + size_t *length, + int *status); } namespace __sanitizer { @@ -53,8 +54,7 @@ const char *DemangleCXXABI(const char *name) { // it does not allocate). For now, we just call it anyway, and we leak // the returned value. if (&__cxxabiv1::__cxa_demangle) - if (const char *demangled_name = - __cxxabiv1::__cxa_demangle(name, 0, 0, 0)) + if (const char *demangled_name = __cxxabiv1::__cxa_demangle(name, 0, 0, 0)) return demangled_name; return nullptr; @@ -85,7 +85,8 @@ const char *DemangleSwift(const char *name) { } const char *DemangleSwiftAndCXX(const char *name) { - if (!name) return nullptr; + if (!name) + return nullptr; if (const char *swift_demangled_name = DemangleSwift(name)) return swift_demangled_name; return DemangleCXXABI(name); @@ -114,7 +115,8 @@ static bool CreateTwoHighNumberedPipes(int *infd_, int *outfd_) { } else { outfd = sock_pair[i]; for (int j = 0; j < i; j++) { - if (sock_pair[j] == infd) continue; + if (sock_pair[j] == infd) + continue; internal_close(sock_pair[j][0]); internal_close(sock_pair[j][1]); } @@ -155,7 +157,7 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { } if (use_posix_spawn_) { -#if SANITIZER_APPLE +# if SANITIZER_APPLE fd_t fd = internal_spawn(argv, const_cast(GetEnvP()), &pid); if (fd == kInvalidFd) { Report("WARNING: failed to spawn external symbolizer (errno: %d)\n", @@ -165,14 +167,16 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() { input_fd_ = fd; output_fd_ = fd; -#else // SANITIZER_APPLE +# else // SANITIZER_APPLE UNIMPLEMENTED(); -#endif // SANITIZER_APPLE +# endif // SANITIZER_APPLE } else { fd_t infd[2] = {}, outfd[2] = {}; if (!CreateTwoHighNumberedPipes(infd, outfd)) { - Report("WARNING: Can't create a socket pair to start " - "external symbolizer (errno: %d)\n", errno); + Report( + "WARNING: Can't create a socket pair to start " + "external symbolizer (errno: %d)\n", + errno); return false; } @@ -261,10 +265,11 @@ bool Addr2LineProcess::ReachedEndOfOutput(const char *buffer, // 1. First one, corresponding to given offset to be symbolized // (may be equal to output_terminator_, if offset is not valid). // 2. Second one for output_terminator_, itself to mark the end of output. - if (length <= kTerminatorLen) return false; + if (length <= kTerminatorLen) + return false; // Addr2Line output should end up with output_terminator_. - return !internal_memcmp(buffer + length - kTerminatorLen, - output_terminator_, kTerminatorLen); + return !internal_memcmp(buffer + length - kTerminatorLen, output_terminator_, + kTerminatorLen); } class Addr2LinePool final : public SymbolizerTool { @@ -284,9 +289,7 @@ class Addr2LinePool final : public SymbolizerTool { return false; } - bool SymbolizeData(uptr addr, DataInfo *info) override { - return false; - } + bool SymbolizeData(uptr addr, DataInfo *info) override { return false; } private: const char *SendCommand(const char *module_name, uptr module_offset) { @@ -300,22 +303,21 @@ class Addr2LinePool final : public SymbolizerTool { } if (!addr2line) { addr2line = - new(*allocator_) Addr2LineProcess(addr2line_path_, module_name); + new (*allocator_) Addr2LineProcess(addr2line_path_, module_name); addr2line_pool_.push_back(addr2line); } CHECK_EQ(0, internal_strcmp(module_name, addr2line->module_name())); char buffer[kBufferSize]; - internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n", - module_offset, dummy_address_); + internal_snprintf(buffer, kBufferSize, "0x%zx\n0x%zx\n", module_offset, + dummy_address_); return addr2line->SendCommand(buffer); } static const uptr kBufferSize = 64; const char *addr2line_path_; LowLevelAllocator *allocator_; - InternalMmapVector addr2line_pool_; - static const uptr dummy_address_ = - FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX); + InternalMmapVector addr2line_pool_; + static const uptr dummy_address_ = FIRST_32_SECOND_64(UINT32_MAX, UINT64_MAX); }; #endif @@ -354,8 +356,9 @@ class InternalSymbolizer final : public SymbolizerTool { } bool SymbolizePC(uptr addr, SymbolizedStack *stack) override { - bool result = __sanitizer_symbolize_code( - stack->info.module, stack->info.module_offset, buffer_, sizeof(buffer_)); + bool result = __sanitizer_symbolize_code(stack->info.module, + stack->info.module_offset, buffer_, + sizeof(buffer_)); if (result) ParseSymbolizePCOutput(buffer_, stack); return result; @@ -425,44 +428,53 @@ static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) { } else if (!internal_strncmp(binary_name, kLLVMSymbolizerPrefix, internal_strlen(kLLVMSymbolizerPrefix))) { VReport(2, "Using llvm-symbolizer at user-specified path: %s\n", path); - return new(*allocator) LLVMSymbolizer(path, allocator); + return new (*allocator) LLVMSymbolizer(path, allocator); } else if (!internal_strcmp(binary_name, "atos")) { -#if SANITIZER_APPLE +# if SANITIZER_APPLE VReport(2, "Using atos at user-specified path: %s\n", path); - return new(*allocator) AtosSymbolizer(path, allocator); -#else // SANITIZER_APPLE + return new (*allocator) AtosSymbolizer(path, allocator); +# else // SANITIZER_APPLE Report("ERROR: Using `atos` is only supported on Darwin.\n"); Die(); -#endif // SANITIZER_APPLE +# endif // SANITIZER_APPLE } else if (!internal_strcmp(binary_name, "addr2line")) { VReport(2, "Using addr2line at user-specified path: %s\n", path); - return new(*allocator) Addr2LinePool(path, allocator); + return new (*allocator) Addr2LinePool(path, allocator); } else if (path) { - Report("ERROR: External symbolizer path is set to '%s' which isn't " - "a known symbolizer. Please set the path to the llvm-symbolizer " - "binary or other known tool.\n", path); + Report( + "ERROR: External symbolizer path is set to '%s' which isn't " + "a known symbolizer. Please set the path to the llvm-symbolizer " + "binary or other known tool.\n", + path); Die(); } // Otherwise symbolizer program is unknown, let's search $PATH +# ifdef SANITIZER_DISABLE_SYMBOLIZER_PATH_SEARCH + VReport(2, + "Symbolizer path search is disabled in the runtime " + "build configuration.\n"); + return nullptr; +# else CHECK(path == nullptr); -#if SANITIZER_APPLE +# if SANITIZER_APPLE if (const char *found_path = FindPathToBinary("atos")) { VReport(2, "Using atos found at: %s\n", found_path); - return new(*allocator) AtosSymbolizer(found_path, allocator); + return new (*allocator) AtosSymbolizer(found_path, allocator); } -#endif // SANITIZER_APPLE +# endif // SANITIZER_APPLE if (const char *found_path = FindPathToBinary("llvm-symbolizer")) { VReport(2, "Using llvm-symbolizer found at: %s\n", found_path); - return new(*allocator) LLVMSymbolizer(found_path, allocator); + return new (*allocator) LLVMSymbolizer(found_path, allocator); } if (common_flags()->allow_addr2line) { if (const char *found_path = FindPathToBinary("addr2line")) { VReport(2, "Using addr2line found at: %s\n", found_path); - return new(*allocator) Addr2LinePool(found_path, allocator); + return new (*allocator) Addr2LinePool(found_path, allocator); } } return nullptr; +# endif // SANITIZER_DISABLE_SYMBOLIZER_PATH_SEARCH } static void ChooseSymbolizerTools(IntrusiveList *list, @@ -494,17 +506,17 @@ static void ChooseSymbolizerTools(IntrusiveList *list, list->push_back(tool); } -#if SANITIZER_APPLE +# if SANITIZER_APPLE VReport(2, "Using dladdr symbolizer.\n"); - list->push_back(new(*allocator) DlAddrSymbolizer()); -#endif // SANITIZER_APPLE + list->push_back(new (*allocator) DlAddrSymbolizer()); +# endif // SANITIZER_APPLE } Symbolizer *Symbolizer::PlatformInit() { IntrusiveList list; list.clear(); ChooseSymbolizerTools(&list, &symbolizer_allocator_); - return new(symbolizer_allocator_) Symbolizer(list); + return new (symbolizer_allocator_) Symbolizer(list); } void Symbolizer::LateInitialize() { diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp index 6a8e82e2e213c..4f1538eeb9c55 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp @@ -12,7 +12,7 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ - SANITIZER_SOLARIS + SANITIZER_SOLARIS || SANITIZER_HAIKU #include "sanitizer_common.h" #include "sanitizer_stacktrace.h" @@ -91,38 +91,6 @@ _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) { } // namespace -#if SANITIZER_ANDROID -void SanitizerInitializeUnwinder() { - if (AndroidGetApiLevel() >= ANDROID_LOLLIPOP_MR1) return; - - // Pre-lollipop Android can not unwind through signal handler frames with - // libgcc unwinder, but it has a libcorkscrew.so library with the necessary - // workarounds. - void *p = dlopen("libcorkscrew.so", RTLD_LAZY); - if (!p) { - VReport(1, - "Failed to open libcorkscrew.so. You may see broken stack traces " - "in SEGV reports."); - return; - } - acquire_my_map_info_list = - (acquire_my_map_info_list_func)(uptr)dlsym(p, "acquire_my_map_info_list"); - release_my_map_info_list = - (release_my_map_info_list_func)(uptr)dlsym(p, "release_my_map_info_list"); - unwind_backtrace_signal_arch = (unwind_backtrace_signal_arch_func)(uptr)dlsym( - p, "unwind_backtrace_signal_arch"); - if (!acquire_my_map_info_list || !release_my_map_info_list || - !unwind_backtrace_signal_arch) { - VReport(1, - "Failed to find one of the required symbols in libcorkscrew.so. " - "You may see broken stack traces in SEGV reports."); - acquire_my_map_info_list = 0; - unwind_backtrace_signal_arch = 0; - release_my_map_info_list = 0; - } -} -#endif - void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { CHECK_GE(max_depth, 2); size = 0; @@ -171,4 +139,4 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { } // namespace __sanitizer #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || - // SANITIZER_SOLARIS + // SANITIZER_SOLARIS || SANITIZER_HAIKU diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp index 6fc18396ca63b..30ba812afc4b0 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_unwind_win.cpp @@ -75,6 +75,11 @@ void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { stack_frame.AddrPC.Offset = ctx.Pc; stack_frame.AddrFrame.Offset = ctx.R11; stack_frame.AddrStack.Offset = ctx.Sp; +# elif SANITIZER_MIPS32 + int machine_type = IMAGE_FILE_MACHINE_R4000; + stack_frame.AddrPC.Offset = ctx.Fir; + stack_frame.AddrFrame.Offset = ctx.IntS8; + stack_frame.AddrStack.Offset = ctx.IntSp; # else int machine_type = IMAGE_FILE_MACHINE_I386; stack_frame.AddrPC.Offset = ctx.Eip; diff --git a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp index fd0f989ee392b..48ebe78c4031e 100644 --- a/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/system/lib/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -1011,6 +1011,9 @@ void SignalContext::InitPcSpBp() { # if SANITIZER_ARM bp = (uptr)context_record->R11; sp = (uptr)context_record->Sp; +# elif SANITIZER_MIPS32 + bp = (uptr)context_record->IntS8; + sp = (uptr)context_record->IntSp; # else bp = (uptr)context_record->Ebp; sp = (uptr)context_record->Esp; diff --git a/system/lib/compiler-rt/lib/ubsan/ubsan_init_standalone.cpp b/system/lib/compiler-rt/lib/ubsan/ubsan_init_standalone.cpp index 91c3f57b424b9..5083246b8b7f3 100644 --- a/system/lib/compiler-rt/lib/ubsan/ubsan_init_standalone.cpp +++ b/system/lib/compiler-rt/lib/ubsan/ubsan_init_standalone.cpp @@ -19,6 +19,13 @@ #include "ubsan_init.h" #include "ubsan_signals_standalone.h" +#if SANITIZER_FUCHSIA +namespace __sanitizer { +// UBSan doesn't need to do anything else special in the startup hook. +void EarlySanitizerInit() {} +} // namespace __sanitizer +#endif // SANITIZER_FUCHSIA + namespace __ubsan { class UbsanStandaloneInitializer { diff --git a/system/lib/compiler-rt/lib/ubsan/ubsan_platform.h b/system/lib/compiler-rt/lib/ubsan/ubsan_platform.h index 252536f26a80f..357d9524d06de 100644 --- a/system/lib/compiler-rt/lib/ubsan/ubsan_platform.h +++ b/system/lib/compiler-rt/lib/ubsan/ubsan_platform.h @@ -16,7 +16,7 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ defined(__NetBSD__) || defined(__DragonFly__) || \ (defined(__sun__) && defined(__svr4__)) || defined(_WIN32) || \ - defined(__Fuchsia__) || defined(__EMSCRIPTEN__) + defined(__Fuchsia__) || defined(__HAIKU__) || defined(__EMSCRIPTEN__) #define CAN_SANITIZE_UB 1 #else # define CAN_SANITIZE_UB 0 diff --git a/system/lib/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/system/lib/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp index c3ffd41bcacc0..ebc36a8583e05 100644 --- a/system/lib/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp +++ b/system/lib/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp @@ -1,7 +1,7 @@ #include "sanitizer_common/sanitizer_atomic.h" -#include #include +#include #include #include @@ -9,9 +9,7 @@ extern "C" void ubsan_message(const char *msg); static void message(const char *msg) { ubsan_message(msg); } #else -static void message(const char *msg) { - (void)write(2, msg, strlen(msg)); -} +static void message(const char *msg) { (void)write(2, msg, strlen(msg)); } #endif static const int kMaxCallerPcs = 20; @@ -62,16 +60,18 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind, uintptr_t p; for (unsigned i = 0; i < sz; ++i) { p = __sanitizer::atomic_load_relaxed(&caller_pcs[i]); - if (p == 0) break; // Concurrent update. + if (p == 0) + break; // Concurrent update. if (p == caller) return; } - if (p == 0) continue; // FIXME: yield? + if (p == 0) + continue; // FIXME: yield? } if (!__sanitizer::atomic_compare_exchange_strong( &caller_pcs_sz, &sz, sz + 1, __sanitizer::memory_order_seq_cst)) - continue; // Concurrent update! Try again from the start. + continue; // Concurrent update! Try again from the start. if (sz == kMaxCallerPcs) { message("ubsan: too many errors\n"); @@ -85,6 +85,12 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind, } } +SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind, + uintptr_t caller) { + // Use another handlers, in case it's already overriden. + __ubsan_report_error(kind, caller); +} + #if defined(__ANDROID__) extern "C" __attribute__((weak)) void android_set_abort_message(const char *); static void abort_with_message(const char *kind, uintptr_t caller) { @@ -121,7 +127,7 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) { #define HANDLER_NORECOVER(name, kind) \ INTERFACE void __ubsan_handle_##name##_minimal_abort() { \ uintptr_t caller = GET_CALLER_PC(); \ - __ubsan_report_error(kind, caller); \ + __ubsan_report_error_fatal(kind, caller); \ abort_with_message(kind, caller); \ } diff --git a/system/lib/compiler-rt/readme.txt b/system/lib/compiler-rt/readme.txt index b8d907f7d8998..8f2fe7cbebeb6 100644 --- a/system/lib/compiler-rt/readme.txt +++ b/system/lib/compiler-rt/readme.txt @@ -1,14 +1,14 @@ LLVM's compiler-rt ------------------ -These files are from the llvm-project based on release 20.1.8. +These files are from the llvm-project based on release 21.1.8. We maintain a local fork of llvm-project that contains any Emscripten specific patches: https://github.com/emscripten-core/llvm-project -The current patch is based on the emscripten-libs-20 branch. +The current patch is based on the emscripten-libs-21 branch. Update Instructions ------------------- @@ -20,4 +20,4 @@ Modifications For a list of changes from upstream see the compiler-rt files that are part of: -https://github.com/llvm/llvm-project/compare/llvmorg-20.1.8...emscripten-core:emscripten-libs-20 +https://github.com/llvm/llvm-project/compare/llvmorg-21.1.8...emscripten-core:emscripten-libs-21 diff --git a/test/codesize/test_codesize_hello_dylink_all.json b/test/codesize/test_codesize_hello_dylink_all.json index f7aff3b76c4e2..0ba509a1d7f0c 100644 --- a/test/codesize/test_codesize_hello_dylink_all.json +++ b/test/codesize/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { "a.out.js": 244848, - "a.out.nodebug.wasm": 574227, - "total": 819075, + "a.out.nodebug.wasm": 577782, + "total": 822630, "sent": [ "IMG_Init", "IMG_Load", @@ -1629,6 +1629,7 @@ "__eqtf2", "__errno_location", "__extenddftf2", + "__extendhfdf2", "__extendhfsf2", "__extendsfdf2", "__extendsftf2", @@ -1764,6 +1765,7 @@ "__libc_free", "__libc_malloc", "__libc_realloc", + "__llvm_write_custom_profile", "__lock", "__lshrdi3", "__lshrti3", @@ -3485,6 +3487,7 @@ "$__expo2", "$__expo2f", "$__extenddftf2", + "$__extendhfdf2", "$__extendhfsf2", "$__extendsfdf2", "$__extendsftf2", @@ -3616,6 +3619,7 @@ "$__libc_current_sigrtmax", "$__libc_current_sigrtmin", "$__llvm_profile_get_num_counters", + "$__llvm_write_custom_profile", "$__localtime_r", "$__lookup_ipliteral", "$__lseek", @@ -3886,6 +3890,7 @@ "$basename", "$bcmp", "$bcopy", + "$binaryIdsStringWriter", "$bind", "$bind_textdomain_codeset", "$bindtextdomain", @@ -4443,9 +4448,12 @@ "$login_tty", "$logl", "$lookup", + "$lprofBufferIOWrite", "$lprofBufferWriter", "$lprofLockFileHandle", "$lprofMergeValueProfData", + "$lprofReleaseBuffer", + "$lprofWriteDataImpl", "$lrand48", "$lrint", "$lrintf",