15ffd83dbSDimitry Andric //=-- lsan_posix.cpp -----------------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===---------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // This file is a part of LeakSanitizer. 105ffd83dbSDimitry Andric // Standalone LSan RTL code common to POSIX-like systems. 115ffd83dbSDimitry Andric // 125ffd83dbSDimitry Andric //===---------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #include "sanitizer_common/sanitizer_platform.h" 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric #if SANITIZER_POSIX 175ffd83dbSDimitry Andric #include "lsan.h" 185ffd83dbSDimitry Andric #include "lsan_allocator.h" 19*bdd1243dSDimitry Andric #include "lsan_thread.h" 205ffd83dbSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h" 215ffd83dbSDimitry Andric #include "sanitizer_common/sanitizer_tls_get_addr.h" 225ffd83dbSDimitry Andric 235ffd83dbSDimitry Andric namespace __lsan { 245ffd83dbSDimitry Andric 255ffd83dbSDimitry Andric ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {} 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric struct OnStartedArgs { 285ffd83dbSDimitry Andric uptr stack_begin; 295ffd83dbSDimitry Andric uptr stack_end; 305ffd83dbSDimitry Andric uptr cache_begin; 315ffd83dbSDimitry Andric uptr cache_end; 325ffd83dbSDimitry Andric uptr tls_begin; 335ffd83dbSDimitry Andric uptr tls_end; 345ffd83dbSDimitry Andric DTLS *dtls; 355ffd83dbSDimitry Andric }; 365ffd83dbSDimitry Andric 375ffd83dbSDimitry Andric void ThreadContext::OnStarted(void *arg) { 385ffd83dbSDimitry Andric auto args = reinterpret_cast<const OnStartedArgs *>(arg); 395ffd83dbSDimitry Andric stack_begin_ = args->stack_begin; 405ffd83dbSDimitry Andric stack_end_ = args->stack_end; 415ffd83dbSDimitry Andric tls_begin_ = args->tls_begin; 425ffd83dbSDimitry Andric tls_end_ = args->tls_end; 435ffd83dbSDimitry Andric cache_begin_ = args->cache_begin; 445ffd83dbSDimitry Andric cache_end_ = args->cache_end; 455ffd83dbSDimitry Andric dtls_ = args->dtls; 465ffd83dbSDimitry Andric } 475ffd83dbSDimitry Andric 485ffd83dbSDimitry Andric void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { 495ffd83dbSDimitry Andric OnStartedArgs args; 505ffd83dbSDimitry Andric uptr stack_size = 0; 515ffd83dbSDimitry Andric uptr tls_size = 0; 52fe6060f1SDimitry Andric GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size, 535ffd83dbSDimitry Andric &args.tls_begin, &tls_size); 545ffd83dbSDimitry Andric args.stack_end = args.stack_begin + stack_size; 555ffd83dbSDimitry Andric args.tls_end = args.tls_begin + tls_size; 565ffd83dbSDimitry Andric GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); 575ffd83dbSDimitry Andric args.dtls = DTLS_Get(); 585ffd83dbSDimitry Andric ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args); 595ffd83dbSDimitry Andric } 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, 625ffd83dbSDimitry Andric uptr *tls_begin, uptr *tls_end, uptr *cache_begin, 635ffd83dbSDimitry Andric uptr *cache_end, DTLS **dtls) { 645ffd83dbSDimitry Andric ThreadContext *context = static_cast<ThreadContext *>( 65*bdd1243dSDimitry Andric GetLsanThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id)); 665ffd83dbSDimitry Andric if (!context) 675ffd83dbSDimitry Andric return false; 685ffd83dbSDimitry Andric *stack_begin = context->stack_begin(); 695ffd83dbSDimitry Andric *stack_end = context->stack_end(); 705ffd83dbSDimitry Andric *tls_begin = context->tls_begin(); 715ffd83dbSDimitry Andric *tls_end = context->tls_end(); 725ffd83dbSDimitry Andric *cache_begin = context->cache_begin(); 735ffd83dbSDimitry Andric *cache_end = context->cache_end(); 745ffd83dbSDimitry Andric *dtls = context->dtls(); 755ffd83dbSDimitry Andric return true; 765ffd83dbSDimitry Andric } 775ffd83dbSDimitry Andric 785ffd83dbSDimitry Andric void InitializeMainThread() { 79349cc55cSDimitry Andric u32 tid = ThreadCreate(kMainTid, true); 80fe6060f1SDimitry Andric CHECK_EQ(tid, kMainTid); 815ffd83dbSDimitry Andric ThreadStart(tid, GetTid()); 825ffd83dbSDimitry Andric } 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric static void OnStackUnwind(const SignalContext &sig, const void *, 855ffd83dbSDimitry Andric BufferedStackTrace *stack) { 865ffd83dbSDimitry Andric stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 875ffd83dbSDimitry Andric common_flags()->fast_unwind_on_fatal); 885ffd83dbSDimitry Andric } 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric void LsanOnDeadlySignal(int signo, void *siginfo, void *context) { 915ffd83dbSDimitry Andric HandleDeadlySignal(siginfo, context, GetCurrentThread(), &OnStackUnwind, 925ffd83dbSDimitry Andric nullptr); 935ffd83dbSDimitry Andric } 945ffd83dbSDimitry Andric 9581ad6265SDimitry Andric void InstallAtExitCheckLeaks() { 9681ad6265SDimitry Andric if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) 9781ad6265SDimitry Andric Atexit(DoLeakCheck); 9881ad6265SDimitry Andric } 9981ad6265SDimitry Andric 1005ffd83dbSDimitry Andric } // namespace __lsan 1015ffd83dbSDimitry Andric 1025ffd83dbSDimitry Andric #endif // SANITIZER_POSIX 103