head 1.4; access; symbols netbsd-11-0-RC4:1.3 netbsd-11-0-RC3:1.3 netbsd-11-0-RC2:1.3 netbsd-11-0-RC1:1.3 gcc-14-3-0:1.1.1.3 perseant-exfatfs-base-20250801:1.3 netbsd-11:1.3.0.4 netbsd-11-base:1.3 gcc-12-5-0:1.1.1.2 perseant-exfatfs-base-20240630:1.3 gcc-12-4-0:1.1.1.2 perseant-exfatfs:1.3.0.2 perseant-exfatfs-base:1.3 gcc-12-3-0:1.1.1.2 gcc-10-5-0:1.1.1.1 gcc-10-4-0:1.1.1.1 cjep_sun2x:1.2.0.4 cjep_sun2x-base:1.2 cjep_staticlib_x-base1:1.2 cjep_staticlib_x:1.2.0.2 cjep_staticlib_x-base:1.2 gcc-10-3-0:1.1.1.1 FSF:1.1.1; locks; strict; comment @// @; 1.4 date 2025.09.14.00.08.58; author mrg; state Exp; branches; next 1.3; commitid x9D5QEnvbeMI4CaG; 1.3 date 2023.07.31.01.44.57; author mrg; state Exp; branches; next 1.2; commitid q79F5Opf0FLsyTyE; 1.2 date 2021.04.11.23.54.28; author mrg; state dead; branches; next 1.1; commitid wJn7ggfUTEMOWVOC; 1.1 date 2021.04.10.22.09.22; author mrg; state Exp; branches 1.1.1.1; next ; commitid eC4g0MRpqTvEkNOC; 1.1.1.1 date 2021.04.10.22.09.22; author mrg; state Exp; branches; next 1.1.1.2; commitid eC4g0MRpqTvEkNOC; 1.1.1.2 date 2023.07.30.05.20.41; author mrg; state Exp; branches; next 1.1.1.3; commitid tk6nV4mbc9nVEMyE; 1.1.1.3 date 2025.09.13.23.45.04; author mrg; state Exp; branches; next ; commitid KwhwN4krNWa6XBaG; desc @@ 1.4 log @merge GCC 14.3.0. @ text @//===-- tsan_debugging.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 a part of ThreadSanitizer (TSan), a race detector. // // TSan debugging API implementation. //===----------------------------------------------------------------------===// #include "tsan_interface.h" #include "tsan_report.h" #include "tsan_rtl.h" #include "sanitizer_common/sanitizer_stackdepot.h" using namespace __tsan; static const char *ReportTypeDescription(ReportType typ) { switch (typ) { case ReportTypeRace: return "data-race"; case ReportTypeVptrRace: return "data-race-vptr"; case ReportTypeUseAfterFree: return "heap-use-after-free"; case ReportTypeVptrUseAfterFree: return "heap-use-after-free-vptr"; case ReportTypeExternalRace: return "external-race"; case ReportTypeThreadLeak: return "thread-leak"; case ReportTypeMutexDestroyLocked: return "locked-mutex-destroy"; case ReportTypeMutexDoubleLock: return "mutex-double-lock"; case ReportTypeMutexInvalidAccess: return "mutex-invalid-access"; case ReportTypeMutexBadUnlock: return "mutex-bad-unlock"; case ReportTypeMutexBadReadLock: return "mutex-bad-read-lock"; case ReportTypeMutexBadReadUnlock: return "mutex-bad-read-unlock"; case ReportTypeSignalUnsafe: return "signal-unsafe-call"; case ReportTypeErrnoInSignal: return "errno-in-signal-handler"; case ReportTypeDeadlock: return "lock-order-inversion"; case ReportTypeMutexHeldWrongContext: return "mutex-held-in-wrong-context"; // No default case so compiler warns us if we miss one } UNREACHABLE("missing case"); } static const char *ReportLocationTypeDescription(ReportLocationType typ) { switch (typ) { case ReportLocationGlobal: return "global"; case ReportLocationHeap: return "heap"; case ReportLocationStack: return "stack"; case ReportLocationTLS: return "tls"; case ReportLocationFD: return "fd"; // No default case so compiler warns us if we miss one } UNREACHABLE("missing case"); } static void CopyTrace(SymbolizedStack *first_frame, void **trace, uptr trace_size) { uptr i = 0; for (SymbolizedStack *frame = first_frame; frame != nullptr; frame = frame->next) { trace[i++] = (void *)frame->info.address; if (i >= trace_size) break; } } // Meant to be called by the debugger. SANITIZER_INTERFACE_ATTRIBUTE void *__tsan_get_current_report() { return const_cast(cur_thread()->current_report); } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_data(void *report, const char **description, int *count, int *stack_count, int *mop_count, int *loc_count, int *mutex_count, int *thread_count, int *unique_tid_count, void **sleep_trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; *description = ReportTypeDescription(rep->typ); *count = rep->count; *stack_count = rep->stacks.Size(); *mop_count = rep->mops.Size(); *loc_count = rep->locs.Size(); *mutex_count = rep->mutexes.Size(); *thread_count = rep->threads.Size(); *unique_tid_count = rep->unique_tids.Size(); if (rep->sleep) CopyTrace(rep->sleep->frames, sleep_trace, trace_size); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_tag(void *report, uptr *tag) { const ReportDesc *rep = (ReportDesc *)report; *tag = rep->tag; return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_stack(void *report, uptr idx, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->stacks.Size()); ReportStack *stack = rep->stacks[idx]; if (stack) CopyTrace(stack->frames, trace, trace_size); return stack ? 1 : 0; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_mop(void *report, uptr idx, int *tid, void **addr, int *size, int *write, int *atomic, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->mops.Size()); ReportMop *mop = rep->mops[idx]; *tid = mop->tid; *addr = (void *)mop->addr; *size = mop->size; *write = mop->write ? 1 : 0; *atomic = mop->atomic ? 1 : 0; if (mop->stack) CopyTrace(mop->stack->frames, trace, trace_size); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_loc(void *report, uptr idx, const char **type, void **addr, uptr *start, uptr *size, int *tid, int *fd, int *suppressable, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->locs.Size()); ReportLocation *loc = rep->locs[idx]; *type = ReportLocationTypeDescription(loc->type); *addr = (void *)loc->global.start; *start = loc->heap_chunk_start; *size = loc->heap_chunk_size; *tid = loc->tid; *fd = loc->fd; *suppressable = loc->suppressable; if (loc->stack) CopyTrace(loc->stack->frames, trace, trace_size); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_loc_object_type(void *report, uptr idx, const char **object_type) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->locs.Size()); ReportLocation *loc = rep->locs[idx]; *object_type = GetObjectTypeFromTag(loc->external_tag); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr, int *destroyed, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->mutexes.Size()); ReportMutex *mutex = rep->mutexes[idx]; *mutex_id = mutex->id; *addr = (void *)mutex->addr; *destroyed = false; if (mutex->stack) CopyTrace(mutex->stack->frames, trace, trace_size); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id, int *running, const char **name, int *parent_tid, void **trace, uptr trace_size) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->threads.Size()); ReportThread *thread = rep->threads[idx]; *tid = thread->id; *os_id = thread->os_id; *running = thread->running; *name = thread->name; *parent_tid = thread->parent_tid; if (thread->stack) CopyTrace(thread->stack->frames, trace, trace_size); return 1; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_report_unique_tid(void *report, uptr idx, int *tid) { const ReportDesc *rep = (ReportDesc *)report; CHECK_LT(idx, rep->unique_tids.Size()); *tid = rep->unique_tids[idx]; return 1; } SANITIZER_INTERFACE_ATTRIBUTE const char *__tsan_locate_address(uptr addr, char *name, uptr name_size, uptr *region_address_ptr, uptr *region_size_ptr) { uptr region_address = 0; uptr region_size = 0; const char *region_kind = nullptr; if (name && name_size > 0) name[0] = 0; if (IsMetaMem(reinterpret_cast(addr))) { region_kind = "meta shadow"; } else if (IsShadowMem(reinterpret_cast(addr))) { region_kind = "shadow"; } else { bool is_stack = false; MBlock *b = 0; Allocator *a = allocator(); if (a->PointerIsMine((void *)addr)) { void *block_begin = a->GetBlockBegin((void *)addr); if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin); } if (b != 0) { region_address = (uptr)allocator()->GetBlockBegin((void *)addr); region_size = b->siz; region_kind = "heap"; } else { // TODO(kuba.brecka): We should not lock. This is supposed to be called // from within the debugger when other threads are stopped. ctx->thread_registry.Lock(); ThreadContext *tctx = IsThreadStackOrTls(addr, &is_stack); ctx->thread_registry.Unlock(); if (tctx) { region_kind = is_stack ? "stack" : "tls"; } else { region_kind = "global"; DataInfo info; if (Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) { internal_strncpy(name, info.name, name_size); region_address = info.start; region_size = info.size; } } } } CHECK(region_kind); if (region_address_ptr) *region_address_ptr = region_address; if (region_size_ptr) *region_size_ptr = region_size; return region_kind; } SANITIZER_INTERFACE_ATTRIBUTE int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id, tid_t *os_id) { MBlock *b = 0; Allocator *a = allocator(); if (a->PointerIsMine((void *)addr)) { void *block_begin = a->GetBlockBegin((void *)addr); if (block_begin) b = ctx->metamap.GetBlock((uptr)block_begin); } if (b == 0) return 0; *thread_id = b->tid; // No locking. This is supposed to be called from within the debugger when // other threads are stopped. ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid); *os_id = tctx->os_id; StackTrace stack = StackDepotGet(b->stk); size = Min(size, (uptr)stack.size); for (uptr i = 0; i < size; i++) trace[i] = stack.trace[stack.size - i - 1]; return size; } @ 1.3 log @make this actually be GCC 12.3.0's libsanitizer. the libsanitizer we used with GCC 9 and GCC 10 was significantly ahead of the GCC 9 and GCC 10 provided versions. @ text @d38 3 a40 1 // No default case so compiler warns us if we miss one d162 1 a162 1 *destroyed = mutex->destroyed; @ 1.2 log @revert sanitizer back to the version we were using with GCC 9, since that one was already newer than the GCC 10 version. @ text @d198 1 a198 1 if (IsMetaMem(addr)) { d200 1 a200 1 } else if (IsShadowMem(addr)) { d218 1 a218 1 ctx->thread_registry->Lock(); d220 1 a220 1 ctx->thread_registry->Unlock(); d255 1 a255 1 ThreadContextBase *tctx = ctx->thread_registry->GetThreadLocked(b->tid); @ 1.1 log @Initial revision @ text @@ 1.1.1.1 log @initial import of GCC 10.3.0. main changes include: caveats: - ABI issue between c++14 and c++17 fixed - profile mode is removed from libstdc++ - -fno-common is now the default new features: - new flags -fallocation-dce, -fprofile-partial-training, -fprofile-reproducible, -fprofile-prefix-path, and -fanalyzer - many new compile and link time optimisations - enhanced drive optimisations - openacc 2.6 support - openmp 5.0 features - new warnings: -Wstring-compare and -Wzero-length-bounds - extended warnings: -Warray-bounds, -Wformat-overflow, -Wrestrict, -Wreturn-local-addr, -Wstringop-overflow, -Warith-conversion, -Wmismatched-tags, and -Wredundant-tags - some likely C2X features implemented - more C++20 implemented - many new arm & intel CPUs known hundreds of reported bugs are fixed. full list of changes can be found at: https://gcc.gnu.org/gcc-10/changes.html @ text @@ 1.1.1.2 log @initial import of GCC 12.3.0. major changes in GCC 11 included: - The default mode for C++ is now -std=gnu++17 instead of -std=gnu++14. - When building GCC itself, the host compiler must now support C++11, rather than C++98. - Some short options of the gcov tool have been renamed: -i to -j and -j to -H. - ThreadSanitizer improvements. - Introduce Hardware-assisted AddressSanitizer support. - For targets that produce DWARF debugging information GCC now defaults to DWARF version 5. This can produce up to 25% more compact debug information compared to earlier versions. - Many optimisations. - The existing malloc attribute has been extended so that it can be used to identify allocator/deallocator API pairs. A pair of new -Wmismatched-dealloc and -Wmismatched-new-delete warnings are added. - Other new warnings: -Wsizeof-array-div, enabled by -Wall, warns about divisions of two sizeof operators when the first one is applied to an array and the divisor does not equal the size of the array element. -Wstringop-overread, enabled by default, warns about calls to string functions reading past the end of the arrays passed to them as arguments. -Wtsan, enabled by default, warns about unsupported features in ThreadSanitizer (currently std::atomic_thread_fence). - Enchanced warnings: -Wfree-nonheap-object detects many more instances of calls to deallocation functions with pointers not returned from a dynamic memory allocation function. -Wmaybe-uninitialized diagnoses passing pointers or references to uninitialized memory to functions taking const-qualified arguments. -Wuninitialized detects reads from uninitialized dynamically allocated memory. -Warray-parameter warns about functions with inconsistent array forms. -Wvla-parameter warns about functions with inconsistent VLA forms. - Several new features from the upcoming C2X revision of the ISO C standard are supported with -std=c2x and -std=gnu2x. - Several C++20 features have been implemented. - The C++ front end has experimental support for some of the upcoming C++23 draft. - Several new C++ warnings. - Enhanced Arm, AArch64, x86, and RISC-V CPU support. - The implementation of how program state is tracked within -fanalyzer has been completely rewritten with many enhancements. see https://gcc.gnu.org/gcc-11/changes.html for a full list. major changes in GCC 12 include: - An ABI incompatibility between C and C++ when passing or returning by value certain aggregates containing zero width bit-fields has been discovered on various targets. x86-64, ARM and AArch64 will always ignore them (so there is a C ABI incompatibility between GCC 11 and earlier with GCC 12 or later), PowerPC64 ELFv2 always take them into account (so there is a C++ ABI incompatibility, GCC 4.4 and earlier compatible with GCC 12 or later, incompatible with GCC 4.5 through GCC 11). RISC-V has changed the handling of these already starting with GCC 10. As the ABI requires, MIPS takes them into account handling function return values so there is a C++ ABI incompatibility with GCC 4.5 through 11. - STABS: Support for emitting the STABS debugging format is deprecated and will be removed in the next release. All ports now default to emit DWARF (version 2 or later) debugging info or are obsoleted. - Vectorization is enabled at -O2 which is now equivalent to the original -O2 -ftree-vectorize -fvect-cost-model=very-cheap. - GCC now supports the ShadowCallStack sanitizer. - Support for __builtin_shufflevector compatible with the clang language extension was added. - Support for attribute unavailable was added. - Support for __builtin_dynamic_object_size compatible with the clang language extension was added. - New warnings: -Wbidi-chars warns about potentially misleading UTF-8 bidirectional control characters. -Warray-compare warns about comparisons between two operands of array type. - Some new features from the upcoming C2X revision of the ISO C standard are supported with -std=c2x and -std=gnu2x. - Several C++23 features have been implemented. - Many C++ enhancements across warnings and -f options. see https://gcc.gnu.org/gcc-12/changes.html for a full list. @ text @d198 1 a198 1 if (IsMetaMem(reinterpret_cast(addr))) { d200 1 a200 1 } else if (IsShadowMem(reinterpret_cast(addr))) { d218 1 a218 1 ctx->thread_registry.Lock(); d220 1 a220 1 ctx->thread_registry.Unlock(); d255 1 a255 1 ThreadContextBase *tctx = ctx->thread_registry.GetThreadLocked(b->tid); @ 1.1.1.3 log @initial import of GCC 14.3.0. major changes in GCC 13: - improved sanitizer - zstd debug info compression - LTO improvements - SARIF based diagnostic support - new warnings: -Wxor-used-as-pow, -Wenum-int-mismatch, -Wself-move, -Wdangling-reference - many new -Wanalyzer* specific warnings - enhanced warnings: -Wpessimizing-move, -Wredundant-move - new attributes to mark file descriptors, c++23 "assume" - several C23 features added - several C++23 features added - many new features for Arm, x86, RISC-V major changes in GCC 14: - more strict C99 or newer support - ia64* marked deprecated (but seemingly still in GCC 15.) - several new hardening features - support for "hardbool", which can have user supplied values of true/false - explicit support for stack scrubbing upon function exit - better auto-vectorisation support - added clang-compatible __has_feature and __has_extension - more C23, including -std=c23 - several C++26 features added - better diagnostics in C++ templates - new warnings: -Wnrvo, Welaborated-enum-base - many new features for Arm, x86, RISC-V - possible ABI breaking change for SPARC64 and small structures with arrays of floats. @ text @d38 1 a38 3 case ReportTypeMutexHeldWrongContext: return "mutex-held-in-wrong-context"; // No default case so compiler warns us if we miss one d160 1 a160 1 *destroyed = false; @