From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 438453857C59 for ; Mon, 19 Oct 2020 07:04:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 438453857C59 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=Tobias_Burnus@mentor.com IronPort-SDR: n9OT77ZzKeJs8+K0dypJDQHHVvgmQ/k6FC7USAV2gTboSZiDg6bs0mSbpYWsFXg6XjEl/3gxzT gCHtav3IfFtTE8ccPWCzgw6nNqCmrG/VJYkZyuzXeYXK10/QOA6CwCYapjBnlBoCPQCGYm7C19 PlCkauGxbKYGGX9fToE2v2Gi4OC2gAhlDwEZ7Xt+KaYpu33xMGpIB47I/O0YplbrfA3yrHNJ2W YFwiJzDntZ4FNfh8oiabfYq9Tb/G0wJ6GiegcLjdUS+azdpofTraMQaxXAbNrZysNPp3flRicG IGs= X-IronPort-AV: E=Sophos;i="5.77,393,1596528000"; d="scan'208";a="54083272" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 18 Oct 2020 23:04:34 -0800 IronPort-SDR: k2pONseUMlyg+lChWJTZKryu7R9x3qd3/d0pxuwgMydUeJNAny8xlG0iHWNys9HqVQUdRkl3y6 NJG/PzJQxKt3Hdk4E4x1HTldNNQYW5HoBmhsCoCpoJIJJQ8CoDNlVTYdLIVX3S9IncgnvUnLjJ W6heJzMxivMDNyrSyzJbCxmM9C71blChrXF9q4B4HzyzTOlKCZnUIgC7dsRNlCMa0AmTMY0RcC QvJngojaTLABxGkh8YHfD92UJyLUuhUUEemfK6LR0DjC/zaZf9OGfQc0VUmCr0OZAU2qvDSDmM htk= Subject: Re: [PATCH] Libsanitizer: merge from master. To: =?UTF-8?Q?Martin_Li=c5=a1ka?= , References: <3c1342f6-d11c-d510-025c-c208e48c465e@suse.cz> <9195f09f-69a2-9038-3667-db06c8c4327f@suse.cz> From: Tobias Burnus Message-ID: <79bd1d9d-c276-caa5-bfeb-85832c2d21fc@codesourcery.com> Date: Mon, 19 Oct 2020 09:04:24 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.3.2 MIME-Version: 1.0 In-Reply-To: <9195f09f-69a2-9038-3667-db06c8c4327f@suse.cz> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: quoted-printable Content-Language: en-US X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-07.mgc.mentorg.com (139.181.222.7) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, BODY_8BITS, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_ASCII_DIVIDERS, KAM_DMARC_STATUS, KAM_SHORT, NICE_REPLY_A, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Oct 2020 07:04:55 -0000 Hi Martin, this patch caused here a build fail: gcc-mainline/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_lib= cdep.cpp:490:39: error: 'NT_X86_XSTATE' was not declared in this scope It turned out that the used GLIBC of the cross build is 2.11.1. And that one does not contain this #define in 'elf.h'. I wonder whether we should do something like the following =96 what do you = think? --- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cp= p +++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cp= p @@ -490 +490,5 @@ typedef user_regs_struct regs_struct; -static constexpr uptr kExtraRegs[] =3D {NT_X86_XSTATE, NT_FPREGSET}; +static constexpr uptr kExtraRegs[] =3D { +#ifdef NT_X86_XSTATE + NT_X86_XSTATE, +#endif + DNT_FPREGSET}; Tobias On 10/16/20 10:59 AM, Martin Li=9Aka wrote: > On 6/2/20 8:00 AM, Martin Li=9Aka wrote: >> Merged from revision b638b63b99d66786cb37336292604a2ae3490cfd. > > Hello. > > I'm going to install one more merge from master. > >> >> The patch successfully bootstraps on x86_64-linux-gnu and >> ppc64le-linux-gnu. I also tested ppc64-linux-gnu that exposed: >> https://reviews.llvm.org/D80864 (which is fixed on master). > > Again I tested the patch on x86_64-linux-gnu and ppc64le-linux-gnu. > >> >> Abidiff looks happy and I made UBSAN and ASAN bootstrap on >> x86_64-linux-gnu. > > It's fine also now. > >> >> I'm planning to do merge from master twice a year, once now and >> next time short before stage1 closes. >> >> I am going to install the patches as merge from master is obvious >> and I haven't made anything special. >> >> libsanitizer/ChangeLog: >> >> * MERGE: Merge from master. >> --- >> libsanitizer/MERGE |=A0=A0 2 +- >> libsanitizer/asan/asan_globals.cpp |=A0 19 + >> libsanitizer/asan/asan_interceptors.h |=A0=A0 7 +- >> libsanitizer/asan/asan_mapping.h |=A0=A0 2 +- >> libsanitizer/asan/asan_report.cpp |=A0=A0 3 + >> libsanitizer/asan/asan_thread.cpp |=A0=A0 2 + >> .../include/sanitizer/linux_syscall_hooks.h |=A0=A0 8 +- >> .../include/sanitizer/netbsd_syscall_hooks.h |=A0=A0 2 +- >> .../include/sanitizer/tsan_interface.h |=A0 20 +- >> libsanitizer/lsan/lsan.cpp |=A0 17 +- >> libsanitizer/lsan/lsan.h |=A0=A0 6 + >> libsanitizer/lsan/lsan_allocator.h |=A0=A0 5 +- >> libsanitizer/lsan/lsan_common.cpp |=A0 51 +- >> libsanitizer/lsan/lsan_common.h |=A0 17 +- >> libsanitizer/lsan/lsan_common_fuchsia.cpp | 166 +++++ >> libsanitizer/lsan/lsan_common_linux.cpp |=A0=A0 3 +- >> libsanitizer/lsan/lsan_common_mac.cpp |=A0=A0 3 +- >> libsanitizer/lsan/lsan_fuchsia.cpp | 123 ++++ >> libsanitizer/lsan/lsan_fuchsia.h |=A0 35 + >> libsanitizer/lsan/lsan_interceptors.cpp |=A0 19 +- >> libsanitizer/lsan/lsan_linux.cpp |=A0=A0 6 +- >> libsanitizer/lsan/lsan_posix.cpp |=A0 96 +++ >> libsanitizer/lsan/lsan_posix.h |=A0 49 ++ >> libsanitizer/lsan/lsan_thread.cpp |=A0 98 +-- >> libsanitizer/lsan/lsan_thread.h |=A0 35 +- >> .../sanitizer_common/sanitizer_allocator.cpp |=A0=A0 4 +- >> .../sanitizer_allocator_primary64.h |=A0 10 +- >> .../sanitizer_common/sanitizer_common.cpp |=A0=A0 2 + >> .../sanitizer_common/sanitizer_common.h |=A0=A0 5 +- >> .../sanitizer_common_interceptors.inc | 190 +++++- >> ...izer_common_interceptors_netbsd_compat.inc | 128 ++++ >> .../sanitizer_common_libcdep.cpp |=A0 12 +- >> .../sanitizer_common_syscalls.inc |=A0 17 + >> .../sanitizer_coverage_fuchsia.cpp |=A0 25 +- >> .../sanitizer_coverage_interface.inc |=A0=A0 1 + >> .../sanitizer_coverage_libcdep_new.cpp |=A0=A0 1 + >> .../sanitizer_common/sanitizer_file.h |=A0=A0 4 +- >> .../sanitizer_flag_parser.cpp |=A0 11 +- >> .../sanitizer_common/sanitizer_flag_parser.h |=A0 49 ++ >> .../sanitizer_common/sanitizer_flags.cpp |=A0 10 +- >> .../sanitizer_common/sanitizer_freebsd.h |=A0 23 +- >> .../sanitizer_common/sanitizer_fuchsia.cpp |=A0=A0 4 + >> .../sanitizer_common/sanitizer_fuchsia.h |=A0=A0 6 + >> .../sanitizer_interceptors_ioctl_netbsd.inc |=A0 18 +- >> .../sanitizer_interface_internal.h |=A0=A0 6 +- >> .../sanitizer_internal_defs.h |=A0=A0 2 +- >> .../sanitizer_common/sanitizer_libc.h |=A0=A0 2 + >> .../sanitizer_common/sanitizer_linux.cpp | 151 ++++- >> .../sanitizer_common/sanitizer_linux.h |=A0=A0 2 + >> .../sanitizer_linux_libcdep.cpp |=A0 17 +- >> .../sanitizer_common/sanitizer_linux_s390.cpp |=A0 11 +- >> .../sanitizer_common/sanitizer_mac.cpp |=A0 81 ++- >> libsanitizer/sanitizer_common/sanitizer_mac.h |=A0 21 +- >> .../sanitizer_common/sanitizer_malloc_mac.inc |=A0 18 +- >> .../sanitizer_common/sanitizer_netbsd.cpp |=A0=A0 7 +- >> .../sanitizer_platform_interceptors.h |=A0 24 + >> .../sanitizer_platform_limits_freebsd.cpp | 614 +++++++++--------- >> .../sanitizer_platform_limits_freebsd.h |=A0 32 +- >> .../sanitizer_platform_limits_linux.cpp |=A0=A0 7 +- >> .../sanitizer_platform_limits_netbsd.cpp | 191 ++++++ >> .../sanitizer_platform_limits_netbsd.h |=A0 33 +- >> .../sanitizer_platform_limits_openbsd.cpp |=A0=A0 1 + >> .../sanitizer_platform_limits_openbsd.h |=A0=A0 1 + >> .../sanitizer_platform_limits_posix.cpp |=A0=A0 1 + >> .../sanitizer_platform_limits_posix.h |=A0=A0 3 +- >> .../sanitizer_platform_limits_solaris.cpp |=A0=A0 1 + >> .../sanitizer_platform_limits_solaris.h |=A0=A0 1 + >> .../sanitizer_common/sanitizer_posix.cpp |=A0 10 +- >> .../sanitizer_common/sanitizer_posix.h |=A0=A0 4 +- >> .../sanitizer_posix_libcdep.cpp |=A0=A0 6 +- >> .../sanitizer_common/sanitizer_procmaps.h |=A0=A0 7 +- >> .../sanitizer_procmaps_fuchsia.cpp |=A0 80 +++ >> .../sanitizer_common/sanitizer_ptrauth.h |=A0 21 + >> .../sanitizer_common/sanitizer_rtems.cpp |=A0=A0 4 + >> .../sanitizer_common/sanitizer_stacktrace.cpp |=A0 17 +- >> .../sanitizer_stoptheworld_fuchsia.cpp |=A0 42 ++ >> .../sanitizer_stoptheworld_mac.cpp |=A0=A0 9 +- >> .../sanitizer_stoptheworld_netbsd_libcdep.cpp |=A0 12 +- >> .../sanitizer_common/sanitizer_symbolizer.cpp |=A0=A0 6 + >> .../sanitizer_common/sanitizer_symbolizer.h |=A0=A0 3 + >> .../sanitizer_symbolizer_internal.h |=A0=A0 7 + >> .../sanitizer_symbolizer_libcdep.cpp |=A0 89 ++- >> .../sanitizer_symbolizer_mac.cpp |=A0 88 ++- >> .../sanitizer_symbolizer_mac.h |=A0=A0 1 + >> .../sanitizer_symbolizer_markup.cpp |=A0=A0 4 +- >> .../sanitizer_symbolizer_posix_libcdep.cpp |=A0 16 +- >> .../sanitizer_symbolizer_win.cpp |=A0=A0 2 +- >> .../sanitizer_syscalls_netbsd.inc |=A0 22 +- >> .../sanitizer_common/sanitizer_win.cpp |=A0=A0 9 +- >> libsanitizer/tsan/tsan_clock.cpp |=A0 68 +- >> libsanitizer/tsan/tsan_clock.h |=A0 58 ++ >> libsanitizer/tsan/tsan_interceptors_posix.cpp |=A0 21 +- >> libsanitizer/tsan/tsan_platform.h |=A0=A0 1 + >> libsanitizer/tsan/tsan_platform_mac.cpp |=A0 10 +- >> libsanitizer/tsan/tsan_rtl.cpp |=A0 12 +- >> libsanitizer/tsan/tsan_rtl.h |=A0=A0 4 +- >> libsanitizer/tsan/tsan_rtl_mutex.cpp |=A0 25 +- >> libsanitizer/tsan/tsan_rtl_ppc64.S |=A0=A0 1 - >> libsanitizer/tsan/tsan_rtl_thread.cpp |=A0 34 +- >> libsanitizer/tsan/tsan_stat.h |=A0=A0 1 + >> libsanitizer/ubsan/ubsan_checks.inc |=A0=A0 6 + >> libsanitizer/ubsan/ubsan_flags.cpp |=A0=A0 1 - >> libsanitizer/ubsan/ubsan_handlers.cpp |=A0 65 +- >> libsanitizer/ubsan/ubsan_handlers.h |=A0=A0 8 - >> libsanitizer/ubsan/ubsan_init.cpp |=A0=A0 2 + >> libsanitizer/ubsan/ubsan_platform.h |=A0=A0 2 - >> .../ubsan/ubsan_type_hash_itanium.cpp |=A0=A0 2 + >> 107 files changed, 2551 insertions(+), 770 deletions(-) >> create mode 100644 libsanitizer/lsan/lsan_common_fuchsia.cpp >> create mode 100644 libsanitizer/lsan/lsan_fuchsia.cpp >> create mode 100644 libsanitizer/lsan/lsan_fuchsia.h >> create mode 100644 libsanitizer/lsan/lsan_posix.cpp >> create mode 100644 libsanitizer/lsan/lsan_posix.h >> create mode 100644 >> libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_compa= t.inc >> create mode 100644 >> libsanitizer/sanitizer_common/sanitizer_procmaps_fuchsia.cpp >> create mode 100644 libsanitizer/sanitizer_common/sanitizer_ptrauth.h >> create mode 100644 >> libsanitizer/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp >> >> diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE >> index 49ee2c3bab8..e14e830ea7d 100644 >> --- a/libsanitizer/MERGE >> +++ b/libsanitizer/MERGE >> @@ -1,4 +1,4 @@ >> -82588e05cc32bb30807e480abd4e689b0dee132a >> +b638b63b99d66786cb37336292604a2ae3490cfd >> >> The first line of this file holds the git revision number of the >> last merge done from the master library sources. >> diff --git a/libsanitizer/asan/asan_globals.cpp >> b/libsanitizer/asan/asan_globals.cpp >> index e045c31cd1c..9d7dbc6f264 100644 >> --- a/libsanitizer/asan/asan_globals.cpp >> +++ b/libsanitizer/asan/asan_globals.cpp >> @@ -154,6 +154,23 @@ static void CheckODRViolationViaIndicator(const >> Global *g) { >> } >> } >> >> +// Check ODR violation for given global G by checking if it's >> already poisoned. >> +// We use this method in case compiler doesn't use private aliases >> for global >> +// variables. >> +static void CheckODRViolationViaPoisoning(const Global *g) { >> + if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) { >> + // This check may not be enough: if the first global is much larger >> + // the entire redzone of the second global may be within the >> first global. >> + for (ListOfGlobals *l =3D list_of_all_globals; l; l =3D l->next) { >> + if (g->beg =3D=3D l->g->beg && >> + (flags()->detect_odr_violation >=3D 2 || g->size !=3D >> l->g->size) && >> + !IsODRViolationSuppressed(g->name)) >> + ReportODRViolation(g, FindRegistrationSite(g), >> + l->g, FindRegistrationSite(l->g)); >> + } >> + } >> +} >> + >> // Clang provides two different ways for global variables protection: >> // it can poison the global itself or its private alias. In former >> // case we may poison same symbol multiple times, that can help us to >> @@ -199,6 +216,8 @@ static void RegisterGlobal(const Global *g) { >> // where two globals with the same name are defined in >> different modules. >> if (UseODRIndicator(g)) >> CheckODRViolationViaIndicator(g); >> + else >> + CheckODRViolationViaPoisoning(g); >> } >> if (CanPoisonMemory()) >> PoisonRedZones(*g); >> diff --git a/libsanitizer/asan/asan_interceptors.h >> b/libsanitizer/asan/asan_interceptors.h >> index b7a85fedbdf..344a64bd83d 100644 >> --- a/libsanitizer/asan/asan_interceptors.h >> +++ b/libsanitizer/asan/asan_interceptors.h >> @@ -80,12 +80,7 @@ void InitializePlatformInterceptors(); >> #if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS >> && \ >> !SANITIZER_NETBSD >> # define ASAN_INTERCEPT___CXA_THROW 1 >> -# if ! defined(ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION) \ >> - || ASAN_HAS_CXA_RETHROW_PRIMARY_EXCEPTION >> -# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1 >> -# else >> -# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0 >> -# endif >> +# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1 >> # if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && >> defined(__arm__)) >> # define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1 >> # else >> diff --git a/libsanitizer/asan/asan_mapping.h >> b/libsanitizer/asan/asan_mapping.h >> index 09be904270c..41fb49ee46d 100644 >> --- a/libsanitizer/asan/asan_mapping.h >> +++ b/libsanitizer/asan/asan_mapping.h >> @@ -163,7 +163,7 @@ static const u64 kDefaultShort64bitShadowOffset =3D >> static const u64 kAArch64_ShadowOffset64 =3D 1ULL << 36; >> static const u64 kMIPS32_ShadowOffset32 =3D 0x0aaa0000; >> static const u64 kMIPS64_ShadowOffset64 =3D 1ULL << 37; >> -static const u64 kPPC64_ShadowOffset64 =3D 1ULL << 41; >> +static const u64 kPPC64_ShadowOffset64 =3D 1ULL << 44; >> static const u64 kSystemZ_ShadowOffset64 =3D 1ULL << 52; >> static const u64 kSPARC64_ShadowOffset64 =3D 1ULL << 43; // >> 0x80000000000 >> static const u64 kFreeBSD_ShadowOffset32 =3D 1ULL << 30; // 0x40000000 >> diff --git a/libsanitizer/asan/asan_report.cpp >> b/libsanitizer/asan/asan_report.cpp >> index 2e6ce436d03..99e8678aa78 100644 >> --- a/libsanitizer/asan/asan_report.cpp >> +++ b/libsanitizer/asan/asan_report.cpp >> @@ -160,6 +160,9 @@ class ScopedInErrorReport { >> BlockingMutexLock l(&error_message_buf_mutex); >> internal_memcpy(buffer_copy.data(), >> error_message_buffer, kErrorMessageBufferSize); >> + // Clear error_message_buffer so that if we find other errors >> + // we don't re-log this error. >> + error_message_buffer_pos =3D 0; >> } >> >> LogFullErrorReport(buffer_copy.data()); >> diff --git a/libsanitizer/asan/asan_thread.cpp >> b/libsanitizer/asan/asan_thread.cpp >> index 6734d9a1668..f0df8bd4b37 100644 >> --- a/libsanitizer/asan/asan_thread.cpp >> +++ b/libsanitizer/asan/asan_thread.cpp >> @@ -480,6 +480,8 @@ bool GetThreadRangesLocked(tid_t os_id, uptr >> *stack_begin, uptr *stack_end, >> return true; >> } >> >> +void GetAllThreadAllocatorCachesLocked(InternalMmapVector >> *caches) {} >> + >> void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback >> callback, >> void *arg) { >> __asan::AsanThread *t =3D __asan::GetAsanThreadByOsIDLocked(os_id); >> diff --git a/libsanitizer/include/sanitizer/linux_syscall_hooks.h >> b/libsanitizer/include/sanitizer/linux_syscall_hooks.h >> index a1794b71af5..56eae3d40f9 100644 >> --- a/libsanitizer/include/sanitizer/linux_syscall_hooks.h >> +++ b/libsanitizer/include/sanitizer/linux_syscall_hooks.h >> @@ -1845,6 +1845,10 @@ >> #define __sanitizer_syscall_post_rt_sigaction(res, signum, act, >> oldact, sz) \ >> __sanitizer_syscall_post_impl_rt_sigaction(res, (long)signum, >> (long)act, \ >> (long)oldact, (long)sz) >> +#define __sanitizer_syscall_pre_sigaltstack(ss, >> oss) \ >> + __sanitizer_syscall_pre_impl_sigaltstack((long)ss, (long)oss) >> +#define __sanitizer_syscall_post_sigaltstack(res, ss, >> oss) \ >> + __sanitizer_syscall_post_impl_sigaltstack(res, (long)ss, (long)oss) >> >> // And now a few syscalls we don't handle yet. >> #define __sanitizer_syscall_pre_afs_syscall(...) >> @@ -1912,7 +1916,6 @@ >> #define __sanitizer_syscall_pre_setreuid32(...) >> #define __sanitizer_syscall_pre_set_thread_area(...) >> #define __sanitizer_syscall_pre_setuid32(...) >> -#define __sanitizer_syscall_pre_sigaltstack(...) >> #define __sanitizer_syscall_pre_sigreturn(...) >> #define __sanitizer_syscall_pre_sigsuspend(...) >> #define __sanitizer_syscall_pre_stty(...) >> @@ -1992,7 +1995,6 @@ >> #define __sanitizer_syscall_post_setreuid32(res, ...) >> #define __sanitizer_syscall_post_set_thread_area(res, ...) >> #define __sanitizer_syscall_post_setuid32(res, ...) >> -#define __sanitizer_syscall_post_sigaltstack(res, ...) >> #define __sanitizer_syscall_post_sigreturn(res, ...) >> #define __sanitizer_syscall_post_sigsuspend(res, ...) >> #define __sanitizer_syscall_post_stty(res, ...) >> @@ -3075,6 +3077,8 @@ void >> __sanitizer_syscall_pre_impl_rt_sigaction(long signum, long act, >> long oldact, long sz); >> void __sanitizer_syscall_post_impl_rt_sigaction(long res, long >> signum, long act, >> long oldact, long sz); >> +void __sanitizer_syscall_pre_impl_sigaltstack(long ss, long oss); >> +void __sanitizer_syscall_post_impl_sigaltstack(long res, long ss, >> long oss); >> #ifdef __cplusplus >> }=A0 // extern "C" >> #endif >> diff --git a/libsanitizer/include/sanitizer/netbsd_syscall_hooks.h >> b/libsanitizer/include/sanitizer/netbsd_syscall_hooks.h >> index 174b4bf06de..370da0ea72e 100644 >> --- a/libsanitizer/include/sanitizer/netbsd_syscall_hooks.h >> +++ b/libsanitizer/include/sanitizer/netbsd_syscall_hooks.h >> @@ -20,7 +20,7 @@ >> // DO NOT EDIT! THIS FILE HAS BEEN GENERATED! >> // >> // Generated with: generate_netbsd_syscalls.awk >> -// Generated date: 2019-11-01 >> +// Generated date: 2019-12-24 >> // Generated from: syscalls.master,v 1.296 2019/09/22 22:59:39 >> christos Exp >> // >> //=3D=3D=3D-----------------------------------------------------------= -----------=3D=3D=3D// >> >> diff --git a/libsanitizer/include/sanitizer/tsan_interface.h >> b/libsanitizer/include/sanitizer/tsan_interface.h >> index 011b23350ca..96b8ad58541 100644 >> --- a/libsanitizer/include/sanitizer/tsan_interface.h >> +++ b/libsanitizer/include/sanitizer/tsan_interface.h >> @@ -38,34 +38,34 @@ void __tsan_release(void *addr); >> >> // Mutex has static storage duration and no-op constructor and >> destructor. >> // This effectively makes tsan ignore destroy annotation. >> -const unsigned __tsan_mutex_linker_init =3D 1 << 0; >> +static const unsigned __tsan_mutex_linker_init =3D 1 << 0; >> // Mutex is write reentrant. >> -const unsigned __tsan_mutex_write_reentrant =3D 1 << 1; >> +static const unsigned __tsan_mutex_write_reentrant =3D 1 << 1; >> // Mutex is read reentrant. >> -const unsigned __tsan_mutex_read_reentrant =3D 1 << 2; >> +static const unsigned __tsan_mutex_read_reentrant =3D 1 << 2; >> // Mutex does not have static storage duration, and must not be >> used after >> // its destructor runs. The opposite of __tsan_mutex_linker_init. >> // If this flag is passed to __tsan_mutex_destroy, then the >> destruction >> // is ignored unless this flag was previously set on the mutex. >> -const unsigned __tsan_mutex_not_static =3D 1 << 8; >> +static const unsigned __tsan_mutex_not_static =3D 1 << 8; >> >> // Mutex operation flags: >> >> // Denotes read lock operation. >> -const unsigned __tsan_mutex_read_lock =3D 1 << 3; >> +static const unsigned __tsan_mutex_read_lock =3D 1 << 3; >> // Denotes try lock operation. >> -const unsigned __tsan_mutex_try_lock =3D 1 << 4; >> +static const unsigned __tsan_mutex_try_lock =3D 1 << 4; >> // Denotes that a try lock operation has failed to acquire the mutex. >> -const unsigned __tsan_mutex_try_lock_failed =3D 1 << 5; >> +static const unsigned __tsan_mutex_try_lock_failed =3D 1 << 5; >> // Denotes that the lock operation acquires multiple recursion levels. >> // Number of levels is passed in recursion parameter. >> // This is useful for annotation of e.g. Java builtin monitors, >> // for which wait operation releases all recursive acquisitions of >> the mutex. >> -const unsigned __tsan_mutex_recursive_lock =3D 1 << 6; >> +static const unsigned __tsan_mutex_recursive_lock =3D 1 << 6; >> // Denotes that the unlock operation releases all recursion levels. >> // Number of released levels is returned and later must be passed to >> // the corresponding __tsan_mutex_post_lock annotation. >> -const unsigned __tsan_mutex_recursive_unlock =3D 1 << 7; >> +static const unsigned __tsan_mutex_recursive_unlock =3D 1 << 7; >> >> // Annotate creation of a mutex. >> // Supported flags: mutex creation flags. >> @@ -152,7 +152,7 @@ void __tsan_set_fiber_name(void *fiber, const >> char *name); >> >> // Flags for __tsan_switch_to_fiber: >> // Do not establish a happens-before relation between fibers >> -const unsigned __tsan_switch_to_fiber_no_sync =3D 1 << 0; >> +static const unsigned __tsan_switch_to_fiber_no_sync =3D 1 << 0; >> >> #ifdef __cplusplus >> }=A0 // extern "C" >> diff --git a/libsanitizer/lsan/lsan.cpp b/libsanitizer/lsan/lsan.cpp >> index 4ce03046ffb..80a6e2fa701 100644 >> --- a/libsanitizer/lsan/lsan.cpp >> +++ b/libsanitizer/lsan/lsan.cpp >> @@ -15,7 +15,6 @@ >> >> #include "sanitizer_common/sanitizer_flags.h" >> #include "sanitizer_common/sanitizer_flag_parser.h" >> -#include "sanitizer_common/sanitizer_stacktrace.h" >> #include "lsan_allocator.h" >> #include "lsan_common.h" >> #include "lsan_thread.h" >> @@ -87,17 +86,6 @@ static void InitializeFlags() { >> __sanitizer_set_report_path(common_flags()->log_path); >> } >> >> -static void OnStackUnwind(const SignalContext &sig, const void *, >> - BufferedStackTrace *stack) { >> - stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, >> sig.context, >> - common_flags()->fast_unwind_on_fatal); >> -} >> - >> -static void LsanOnDeadlySignal(int signo, void *siginfo, void >> *context) { >> - HandleDeadlySignal(siginfo, context, GetCurrentThread(), >> &OnStackUnwind, >> - nullptr); >> -} >> - >> extern "C" void __lsan_init() { >> CHECK(!lsan_init_is_running); >> if (lsan_inited) >> @@ -114,10 +102,7 @@ extern "C" void __lsan_init() { >> InitializeInterceptors(); >> InitializeThreadRegistry(); >> InstallDeadlySignalHandlers(LsanOnDeadlySignal); >> - u32 tid =3D ThreadCreate(0, 0, true); >> - CHECK_EQ(tid, 0); >> - ThreadStart(tid, GetTid()); >> - SetCurrentThread(tid); >> + InitializeMainThread(); >> >> if (common_flags()->detect_leaks && >> common_flags()->leak_check_at_exit) >> Atexit(DoLeakCheck); >> diff --git a/libsanitizer/lsan/lsan.h b/libsanitizer/lsan/lsan.h >> index 9904ada4bb3..1e82ad72f00 100644 >> --- a/libsanitizer/lsan/lsan.h >> +++ b/libsanitizer/lsan/lsan.h >> @@ -12,6 +12,11 @@ >> //=3D=3D=3D-----------------------------------------------------------= -----------=3D=3D=3D// >> >> >> #include "lsan_thread.h" >> +#if SANITIZER_POSIX >> +#include "lsan_posix.h" >> +#elif SANITIZER_FUCHSIA >> +#include "lsan_fuchsia.h" >> +#endif >> #include "sanitizer_common/sanitizer_flags.h" >> #include "sanitizer_common/sanitizer_stacktrace.h" >> >> @@ -33,6 +38,7 @@ namespace __lsan { >> >> void InitializeInterceptors(); >> void ReplaceSystemMalloc(); >> +void LsanOnDeadlySignal(int signo, void *siginfo, void *context); >> >> #define ENSURE_LSAN_INITED do {=A0=A0 \ >> CHECK(!lsan_init_is_running); \ >> diff --git a/libsanitizer/lsan/lsan_allocator.h >> b/libsanitizer/lsan/lsan_allocator.h >> index e1397099767..bda9d8cdf74 100644 >> --- a/libsanitizer/lsan/lsan_allocator.h >> +++ b/libsanitizer/lsan/lsan_allocator.h >> @@ -66,7 +66,10 @@ template >> using PrimaryAllocatorASVT =3D >> SizeClassAllocator32>; >> using PrimaryAllocator =3D PrimaryAllocatorASVT= ; >> #elif defined(__x86_64__) || defined(__powerpc64__) >> -# if defined(__powerpc64__) >> +# if SANITIZER_FUCHSIA >> +const uptr kAllocatorSpace =3D ~(uptr)0; >> +const uptr kAllocatorSize =3D 0x40000000000ULL; // 4T. >> +# elif defined(__powerpc64__) >> const uptr kAllocatorSpace =3D 0xa0000000000ULL; >> const uptr kAllocatorSize =3D 0x20000000000ULL; // 2T. >> # else >> diff --git a/libsanitizer/lsan/lsan_common.cpp >> b/libsanitizer/lsan/lsan_common.cpp >> index 9ff9f4c5d1c..32ea4e88003 100644 >> --- a/libsanitizer/lsan/lsan_common.cpp >> +++ b/libsanitizer/lsan/lsan_common.cpp >> @@ -211,6 +211,13 @@ void ForEachExtraStackRangeCb(uptr begin, uptr >> end, void* arg) { >> ScanRangeForPointers(begin, end, frontier, "FAKE STACK", >> kReachable); >> } >> >> +#if SANITIZER_FUCHSIA >> + >> +// Fuchsia handles all threads together with its own callback. >> +static void ProcessThreads(SuspendedThreadsList const &, Frontier *) {} >> + >> +#else >> + >> // Scans thread data (stacks and TLS) for heap pointers. >> static void ProcessThreads(SuspendedThreadsList const >> &suspended_threads, >> Frontier *frontier) { >> @@ -308,6 +315,8 @@ static void ProcessThreads(SuspendedThreadsList >> const &suspended_threads, >> } >> } >> >> +#endif // SANITIZER_FUCHSIA >> + >> void ScanRootRegion(Frontier *frontier, const RootRegion &root_region, >> uptr region_begin, uptr region_end, bool >> is_readable) { >> uptr intersection_begin =3D Max(root_region.begin, region_begin); >> @@ -443,25 +452,23 @@ void ProcessPC(Frontier *frontier) { >> } >> >> // Sets the appropriate tag on each chunk. >> -static void ClassifyAllChunks(SuspendedThreadsList const >> &suspended_threads) { >> - // Holds the flood fill frontier. >> - Frontier frontier; >> - >> - ForEachChunk(CollectIgnoredCb, &frontier); >> - ProcessGlobalRegions(&frontier); >> - ProcessThreads(suspended_threads, &frontier); >> - ProcessRootRegions(&frontier); >> - FloodFillTag(&frontier, kReachable); >> +static void ClassifyAllChunks(SuspendedThreadsList const >> &suspended_threads, >> + Frontier *frontier) { >> + ForEachChunk(CollectIgnoredCb, frontier); >> + ProcessGlobalRegions(frontier); >> + ProcessThreads(suspended_threads, frontier); >> + ProcessRootRegions(frontier); >> + FloodFillTag(frontier, kReachable); >> >> - CHECK_EQ(0, frontier.size()); >> - ProcessPC(&frontier); >> + CHECK_EQ(0, frontier->size()); >> + ProcessPC(frontier); >> >> // The check here is relatively expensive, so we do this in a >> separate flood >> // fill. That way we can skip the check for chunks that are >> reachable >> // otherwise. >> LOG_POINTERS("Processing platform-specific allocations.\n"); >> - ProcessPlatformSpecificAllocations(&frontier); >> - FloodFillTag(&frontier, kReachable); >> + ProcessPlatformSpecificAllocations(frontier); >> + FloodFillTag(frontier, kReachable); >> >> // Iterate over leaked chunks and mark those that are reachable >> from other >> // leaked chunks. >> @@ -521,11 +528,6 @@ static void PrintMatchedSuppressions() { >> Printf("%s\n\n", line); >> } >> >> -struct CheckForLeaksParam { >> - bool success; >> - LeakReport leak_report; >> -}; >> - >> static void ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) { >> const InternalMmapVector &suspended_threads =3D >> *(const InternalMmapVector *)arg; >> @@ -538,6 +540,14 @@ static void >> ReportIfNotSuspended(ThreadContextBase *tctx, void *arg) { >> } >> } >> >> +#if SANITIZER_FUCHSIA >> + >> +// Fuchsia provides a libc interface that guarantees all threads are >> +// covered, and SuspendedThreadList is never really used. >> +static void ReportUnsuspendedThreads(const SuspendedThreadsList &) {} >> + >> +#else // !SANITIZER_FUCHSIA >> + >> static void ReportUnsuspendedThreads( >> const SuspendedThreadsList &suspended_threads) { >> InternalMmapVector threads(suspended_threads.ThreadCount()); >> @@ -550,13 +560,15 @@ static void ReportUnsuspendedThreads( >> &ReportIfNotSuspended, &threads); >> } >> >> +#endif // !SANITIZER_FUCHSIA >> + >> static void CheckForLeaksCallback(const SuspendedThreadsList >> &suspended_threads, >> void *arg) { >> CheckForLeaksParam *param =3D reinterpret_cast> *>(arg); >> CHECK(param); >> CHECK(!param->success); >> ReportUnsuspendedThreads(suspended_threads); >> - ClassifyAllChunks(suspended_threads); >> + ClassifyAllChunks(suspended_threads, ¶m->frontier); >> ForEachChunk(CollectLeaksCb, ¶m->leak_report); >> // Clean up for subsequent leak checks. This assumes we did not >> overwrite any >> // kIgnored tags. >> @@ -569,7 +581,6 @@ static bool CheckForLeaks() { >> return false; >> EnsureMainThreadIDIsCorrect(); >> CheckForLeaksParam param; >> - param.success =3D false; >> LockStuffAndStopTheWorld(CheckForLeaksCallback, ¶m); >> >> if (!param.success) { >> diff --git a/libsanitizer/lsan/lsan_common.h >> b/libsanitizer/lsan/lsan_common.h >> index d24abe31b71..6252d52c197 100644 >> --- a/libsanitizer/lsan/lsan_common.h >> +++ b/libsanitizer/lsan/lsan_common.h >> @@ -40,7 +40,7 @@ >> #elif defined(__arm__) && \ >> SANITIZER_LINUX && !SANITIZER_ANDROID >> #define CAN_SANITIZE_LEAKS 1 >> -#elif SANITIZER_NETBSD >> +#elif SANITIZER_NETBSD || SANITIZER_FUCHSIA >> #define CAN_SANITIZE_LEAKS 1 >> #else >> #define CAN_SANITIZE_LEAKS 0 >> @@ -126,12 +126,24 @@ struct RootRegion { >> uptr size; >> }; >> >> +// LockStuffAndStopTheWorld can start to use Scan* calls to collect >> into >> +// this Frontier vector before the StopTheWorldCallback actually runs. >> +// This is used when the OS has a unified callback API for suspending >> +// threads and enumerating roots. >> +struct CheckForLeaksParam { >> + Frontier frontier; >> + LeakReport leak_report; >> + bool success =3D false; >> +}; >> + >> InternalMmapVector const *GetRootRegions(); >> void ScanRootRegion(Frontier *frontier, RootRegion const ®ion, >> uptr region_begin, uptr region_end, bool >> is_readable); >> +void ForEachExtraStackRangeCb(uptr begin, uptr end, void* arg); >> // Run stoptheworld while holding any platform-specific locks, as >> well as the >> // allocator and thread registry locks. >> -void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void* >> argument); >> +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, >> + CheckForLeaksParam* argument); >> >> void ScanRangeForPointers(uptr begin, uptr end, >> Frontier *frontier, >> @@ -211,6 +223,7 @@ ThreadRegistry *GetThreadRegistryLocked(); >> bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr >> *stack_end, >> uptr *tls_begin, uptr *tls_end, uptr >> *cache_begin, >> uptr *cache_end, DTLS **dtls); >> +void GetAllThreadAllocatorCachesLocked(InternalMmapVector >> *caches); >> void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback >> callback, >> void *arg); >> // If called from the main thread, updates the main thread's TID in >> the thread >> diff --git a/libsanitizer/lsan/lsan_common_fuchsia.cpp >> b/libsanitizer/lsan/lsan_common_fuchsia.cpp >> new file mode 100644 >> index 00000000000..caedbf15596 >> --- /dev/null >> +++ b/libsanitizer/lsan/lsan_common_fuchsia.cpp >> @@ -0,0 +1,166 @@ >> +//=3D-- lsan_common_fuchsia.cpp >> --------------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// This file is a part of LeakSanitizer. >> +// Implementation of common leak checking functionality. >> Fuchsia-specific code. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#include "lsan_common.h" >> +#include "sanitizer_common/sanitizer_platform.h" >> + >> +#if CAN_SANITIZE_LEAKS && SANITIZER_FUCHSIA >> +#include >> + >> +#include "lsan_allocator.h" >> +#include "sanitizer_common/sanitizer_flags.h" >> +#include "sanitizer_common/sanitizer_thread_registry.h" >> + >> +// Ensure that the Zircon system ABI is linked in. >> +#pragma comment(lib, "zircon") >> + >> +namespace __lsan { >> + >> +void InitializePlatformSpecificModules() {} >> + >> +LoadedModule *GetLinker() { return nullptr; } >> + >> +__attribute__((tls_model("initial-exec"))) THREADLOCAL int >> disable_counter; >> +bool DisabledInThisThread() { return disable_counter > 0; } >> +void DisableInThisThread() { disable_counter++; } >> +void EnableInThisThread() { >> + if (disable_counter =3D=3D 0) { >> + DisableCounterUnderflow(); >> + } >> + disable_counter--; >> +} >> + >> +// There is nothing left to do after the globals callbacks. >> +void ProcessGlobalRegions(Frontier *frontier) {} >> + >> +// Nothing to do here. >> +void ProcessPlatformSpecificAllocations(Frontier *frontier) {} >> + >> +// On Fuchsia, we can intercept _Exit gracefully, and return a >> failing exit >> +// code if required at that point. Calling Die() here is undefined >> +// behavior and causes rare race conditions. >> +void HandleLeaks() {} >> + >> +int ExitHook(int status) { >> + return status =3D=3D 0 && HasReportedLeaks() ? >> common_flags()->exitcode : status; >> +} >> + >> +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, >> + CheckForLeaksParam *argument) { >> + LockThreadRegistry(); >> + LockAllocator(); >> + >> + struct Params { >> + InternalMmapVector allocator_caches; >> + StopTheWorldCallback callback; >> + CheckForLeaksParam *argument; >> + } params =3D {{}, callback, argument}; >> + >> + // Callback from libc for globals (data/bss modulo relro), when >> enabled. >> + auto globals =3D +[](void *chunk, size_t size, void *data) { >> + auto params =3D static_cast(data); >> + uptr begin =3D reinterpret_cast(chunk); >> + uptr end =3D begin + size; >> + ScanGlobalRange(begin, end, ¶ms->argument->frontier); >> + }; >> + >> + // Callback from libc for thread stacks. >> + auto stacks =3D +[](void *chunk, size_t size, void *data) { >> + auto params =3D static_cast(data); >> + uptr begin =3D reinterpret_cast(chunk); >> + uptr end =3D begin + size; >> + ScanRangeForPointers(begin, end, ¶ms->argument->frontier, >> "STACK", >> + kReachable); >> + }; >> + >> + // Callback from libc for thread registers. >> + auto registers =3D +[](void *chunk, size_t size, void *data) { >> + auto params =3D static_cast(data); >> + uptr begin =3D reinterpret_cast(chunk); >> + uptr end =3D begin + size; >> + ScanRangeForPointers(begin, end, ¶ms->argument->frontier, >> "REGISTERS", >> + kReachable); >> + }; >> + >> + if (flags()->use_tls) { >> + // Collect the allocator cache range from each thread so these >> + // can all be excluded from the reported TLS ranges. >> + GetAllThreadAllocatorCachesLocked(¶ms.allocator_caches); >> + __sanitizer::Sort(params.allocator_caches.data(), >> + params.allocator_caches.size()); >> + } >> + >> + // Callback from libc for TLS regions. This includes thread_local >> + // variables as well as C11 tss_set and POSIX pthread_setspecific. >> + auto tls =3D +[](void *chunk, size_t size, void *data) { >> + auto params =3D static_cast(data); >> + uptr begin =3D reinterpret_cast(chunk); >> + uptr end =3D begin + size; >> + auto i =3D >> __sanitizer::InternalLowerBound(params->allocator_caches, 0, >> + params->allocator_caches.size(), >> + begin, >> CompareLess()); >> + if (i < params->allocator_caches.size() && >> + params->allocator_caches[i] >=3D begin && >> + end - params->allocator_caches[i] <=3D sizeof(AllocatorCache)) = { >> + // Split the range in two and omit the allocator cache within. >> + ScanRangeForPointers(begin, params->allocator_caches[i], >> + ¶ms->argument->frontier, "TLS", kReachable); >> + uptr begin2 =3D params->allocator_caches[i] + >> sizeof(AllocatorCache); >> + ScanRangeForPointers(begin2, end, ¶ms->argument->frontier, >> "TLS", >> + kReachable); >> + } else { >> + ScanRangeForPointers(begin, end, ¶ms->argument->frontier, >> "TLS", >> + kReachable); >> + } >> + }; >> + >> + // This stops the world and then makes callbacks for various >> memory regions. >> + // The final callback is the last thing before the world starts up >> again. >> + __sanitizer_memory_snapshot( >> + flags()->use_globals ? globals : nullptr, >> + flags()->use_stacks ? stacks : nullptr, >> + flags()->use_registers ? registers : nullptr, >> + flags()->use_tls ? tls : nullptr, >> + [](zx_status_t, void *data) { >> + auto params =3D static_cast(data); >> + >> + // We don't use the thread registry at all for enumerating >> the threads >> + // and their stacks, registers, and TLS regions. So use it >> separately >> + // just for the allocator cache, and to call >> ForEachExtraStackRange, >> + // which ASan needs. >> + if (flags()->use_stacks) { >> + GetThreadRegistryLocked()->RunCallbackForEachThreadLocked( >> + [](ThreadContextBase *tctx, void *arg) { >> + ForEachExtraStackRange(tctx->os_id, >> ForEachExtraStackRangeCb, >> + arg); >> + }, >> + ¶ms->argument->frontier); >> + } >> + >> + params->callback({}, params->argument); >> + }, >> + ¶ms); >> + >> + UnlockAllocator(); >> + UnlockThreadRegistry(); >> +} >> + >> +}=A0 // namespace __lsan >> + >> +// This is declared (in extern "C") by . >> +// _Exit calls this directly to intercept and change the status value. >> +int __sanitizer_process_exit_hook(int status) { >> + return __lsan::ExitHook(status); >> +} >> + >> +#endif >> diff --git a/libsanitizer/lsan/lsan_common_linux.cpp >> b/libsanitizer/lsan/lsan_common_linux.cpp >> index ea1a4a2f569..c97ef31593d 100644 >> --- a/libsanitizer/lsan/lsan_common_linux.cpp >> +++ b/libsanitizer/lsan/lsan_common_linux.cpp >> @@ -134,7 +134,8 @@ static int >> LockStuffAndStopTheWorldCallback(struct dl_phdr_info *info, >> // while holding the libdl lock in the parent thread, we can safely >> reenter it >> // in the tracer. The solution is to run stoptheworld from a >> dl_iterate_phdr() >> // callback in the parent thread. >> -void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void >> *argument) { >> +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, >> + CheckForLeaksParam *argument) { >> DoStopTheWorldParam param =3D {callback, argument}; >> dl_iterate_phdr(LockStuffAndStopTheWorldCallback, ¶m); >> } >> diff --git a/libsanitizer/lsan/lsan_common_mac.cpp >> b/libsanitizer/lsan/lsan_common_mac.cpp >> index c1804e93c11..8516a176eb4 100644 >> --- a/libsanitizer/lsan/lsan_common_mac.cpp >> +++ b/libsanitizer/lsan/lsan_common_mac.cpp >> @@ -193,7 +193,8 @@ void ProcessPlatformSpecificAllocations(Frontier >> *frontier) { >> // causes rare race conditions. >> void HandleLeaks() {} >> >> -void LockStuffAndStopTheWorld(StopTheWorldCallback callback, void >> *argument) { >> +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, >> + CheckForLeaksParam *argument) { >> LockThreadRegistry(); >> LockAllocator(); >> StopTheWorld(callback, argument); >> diff --git a/libsanitizer/lsan/lsan_fuchsia.cpp >> b/libsanitizer/lsan/lsan_fuchsia.cpp >> new file mode 100644 >> index 00000000000..40e65c6fb72 >> --- /dev/null >> +++ b/libsanitizer/lsan/lsan_fuchsia.cpp >> @@ -0,0 +1,123 @@ >> +//=3D-- lsan_fuchsia.cpp >> ---------------------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// This file is a part of LeakSanitizer. >> +// Standalone LSan RTL code specific to Fuchsia. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#include "sanitizer_common/sanitizer_platform.h" >> + >> +#if SANITIZER_FUCHSIA >> +#include >> + >> +#include "lsan.h" >> +#include "lsan_allocator.h" >> + >> +using namespace __lsan; >> + >> +namespace __lsan { >> + >> +void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {} >> + >> +ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {} >> + >> +struct OnCreatedArgs { >> + uptr stack_begin, stack_end; >> +}; >> + >> +// On Fuchsia, the stack bounds of a new thread are available before >> +// the thread itself has started running. >> +void ThreadContext::OnCreated(void *arg) { >> + // Stack bounds passed through from >> __sanitizer_before_thread_create_hook >> + // or InitializeMainThread. >> + auto args =3D reinterpret_cast(arg); >> + stack_begin_ =3D args->stack_begin; >> + stack_end_ =3D args->stack_end; >> +} >> + >> +struct OnStartedArgs { >> + uptr cache_begin, cache_end; >> +}; >> + >> +void ThreadContext::OnStarted(void *arg) { >> + auto args =3D reinterpret_cast(arg); >> + cache_begin_ =3D args->cache_begin; >> + cache_end_ =3D args->cache_end; >> +} >> + >> +void ThreadStart(u32 tid) { >> + OnStartedArgs args; >> + GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); >> + CHECK_EQ(args.cache_end - args.cache_begin, sizeof(AllocatorCache)); >> + ThreadContextLsanBase::ThreadStart(tid, GetTid(), >> ThreadType::Regular, &args); >> +} >> + >> +void InitializeMainThread() { >> + OnCreatedArgs args; >> + __sanitizer::GetThreadStackTopAndBottom(true, &args.stack_end, >> + &args.stack_begin); >> + u32 tid =3D ThreadCreate(0, GetThreadSelf(), true, &args); >> + CHECK_EQ(tid, 0); >> + ThreadStart(tid); >> +} >> + >> +void GetAllThreadAllocatorCachesLocked(InternalMmapVector >> *caches) { >> + GetThreadRegistryLocked()->RunCallbackForEachThreadLocked( >> + [](ThreadContextBase *tctx, void *arg) { >> + auto ctx =3D static_cast(tctx); >> + static_cast(arg)->push_back(ctx->cache_begin()); >> + }, >> + caches); >> +} >> + >> +}=A0 // namespace __lsan >> + >> +// These are declared (in extern "C") by . >> +// The system runtime will call our definitions directly. >> + >> +// This is called before each thread creation is attempted. So, in >> +// its first call, the calling thread is the initial and sole thread. >> +void *__sanitizer_before_thread_create_hook(thrd_t thread, bool >> detached, >> + const char *name, void >> *stack_base, >> + size_t stack_size) { >> + uptr user_id =3D reinterpret_cast(thread); >> + ENSURE_LSAN_INITED; >> + EnsureMainThreadIDIsCorrect(); >> + OnCreatedArgs args; >> + args.stack_begin =3D reinterpret_cast(stack_base); >> + args.stack_end =3D args.stack_begin + stack_size; >> + u32 parent_tid =3D GetCurrentThread(); >> + u32 tid =3D ThreadCreate(parent_tid, user_id, detached, &args); >> + return reinterpret_cast(static_cast(tid)); >> +} >> + >> +// This is called after creating a new thread (in the creating thread), >> +// with the pointer returned by >> __sanitizer_before_thread_create_hook (above). >> +void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int >> error) { >> + u32 tid =3D static_cast(reinterpret_cast(hook)); >> + // On success, there is nothing to do here. >> + if (error !=3D thrd_success) { >> + // Clean up the thread registry for the thread creation that >> didn't happen. >> + GetThreadRegistryLocked()->FinishThread(tid); >> + } >> +} >> + >> +// This is called in the newly-created thread before it runs >> anything else, >> +// with the pointer returned by >> __sanitizer_before_thread_create_hook (above). >> +void __sanitizer_thread_start_hook(void *hook, thrd_t self) { >> + u32 tid =3D static_cast(reinterpret_cast(hook)); >> + ThreadStart(tid); >> +} >> + >> +// Each thread runs this just before it exits, >> +// with the pointer returned by BeforeThreadCreateHook (above). >> +// All per-thread destructors have already been called. >> +void __sanitizer_thread_exit_hook(void *hook, thrd_t self) { >> ThreadFinish(); } >> + >> +#endif // SANITIZER_FUCHSIA >> diff --git a/libsanitizer/lsan/lsan_fuchsia.h >> b/libsanitizer/lsan/lsan_fuchsia.h >> new file mode 100644 >> index 00000000000..65d20ea2114 >> --- /dev/null >> +++ b/libsanitizer/lsan/lsan_fuchsia.h >> @@ -0,0 +1,35 @@ >> +//=3D-- lsan_fuchsia.h >> ---------------------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// This file is a part of LeakSanitizer. >> +// Standalone LSan RTL code specific to Fuchsia. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#ifndef LSAN_FUCHSIA_H >> +#define LSAN_FUCHSIA_H >> + >> +#include "lsan_thread.h" >> +#include "sanitizer_common/sanitizer_platform.h" >> + >> +#if !SANITIZER_FUCHSIA >> +#error "lsan_fuchsia.h is used only on Fuchsia systems >> (SANITIZER_FUCHSIA)" >> +#endif >> + >> +namespace __lsan { >> + >> +class ThreadContext : public ThreadContextLsanBase { >> + public: >> + explicit ThreadContext(int tid); >> + void OnCreated(void *arg) override; >> + void OnStarted(void *arg) override; >> +}; >> + >> +}=A0 // namespace __lsan >> + >> +#endif // LSAN_FUCHSIA_H >> diff --git a/libsanitizer/lsan/lsan_interceptors.cpp >> b/libsanitizer/lsan/lsan_interceptors.cpp >> index f642bb807bc..9ce9b78c5a5 100644 >> --- a/libsanitizer/lsan/lsan_interceptors.cpp >> +++ b/libsanitizer/lsan/lsan_interceptors.cpp >> @@ -22,7 +22,9 @@ >> #include "sanitizer_common/sanitizer_platform_interceptors.h" >> #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" >> #include "sanitizer_common/sanitizer_platform_limits_posix.h" >> +#if SANITIZER_POSIX >> #include "sanitizer_common/sanitizer_posix.h" >> +#endif >> #include "sanitizer_common/sanitizer_tls_get_addr.h" >> #include "lsan.h" >> #include "lsan_allocator.h" >> @@ -61,6 +63,9 @@ INTERCEPTOR(void, free, void *p) { >> } >> >> INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { >> + // This hack is not required for Fuchsia because there are no >> dlsym calls >> + // involved in setting up interceptors. >> +#if !SANITIZER_FUCHSIA >> if (lsan_init_is_running) { >> // Hack: dlsym calls calloc before REAL(calloc) is retrieved >> from dlsym. >> const uptr kCallocPoolSize =3D 1024; >> @@ -72,6 +77,7 @@ INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) { >> CHECK(allocated < kCallocPoolSize); >> return mem; >> } >> +#endif // !SANITIZER_FUCHSIA >> ENSURE_LSAN_INITED; >> GET_STACK_TRACE_MALLOC; >> return lsan_calloc(nmemb, size, stack); >> @@ -100,7 +106,7 @@ INTERCEPTOR(void*, valloc, uptr size) { >> GET_STACK_TRACE_MALLOC; >> return lsan_valloc(size, stack); >> } >> -#endif >> +#endif // !SANITIZER_MAC >> >> #if SANITIZER_INTERCEPT_MEMALIGN >> INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { >> @@ -307,7 +313,7 @@ INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void >> *ptr, std::nothrow_t const&) >> >> ///// Thread initialization and finalization. ///// >> >> -#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD >> +#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA >> static unsigned g_thread_finalize_key; >> >> static void thread_finalize(void *v) { >> @@ -394,6 +400,8 @@ INTERCEPTOR(char *, strerror, int errnum) { >> #define LSAN_MAYBE_INTERCEPT_STRERROR >> #endif >> >> +#if SANITIZER_POSIX >> + >> struct ThreadParam { >> void *(*callback)(void *arg); >> void *param; >> @@ -416,7 +424,6 @@ extern "C" void *__lsan_thread_start_func(void >> *arg) { >> int tid =3D 0; >> while ((tid =3D atomic_load(&p->tid, memory_order_acquire)) =3D=3D 0= ) >> internal_sched_yield(); >> - SetCurrentThread(tid); >> ThreadStart(tid, GetTid()); >> atomic_store(&p->tid, 0, memory_order_release); >> return callback(param); >> @@ -477,9 +484,13 @@ INTERCEPTOR(void, _exit, int status) { >> #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) >> #include "sanitizer_common/sanitizer_signal_interceptors.inc" >> >> +#endif // SANITIZER_POSIX >> + >> namespace __lsan { >> >> void InitializeInterceptors() { >> + // Fuchsia doesn't use interceptors that require any setup. >> +#if !SANITIZER_FUCHSIA >> InitializeSignalInterceptors(); >> >> INTERCEPT_FUNCTION(malloc); >> @@ -515,6 +526,8 @@ void InitializeInterceptors() { >> Die(); >> } >> #endif >> + >> +#endif // !SANITIZER_FUCHSIA >> } >> >> } // namespace __lsan >> diff --git a/libsanitizer/lsan/lsan_linux.cpp >> b/libsanitizer/lsan/lsan_linux.cpp >> index 14a42b75d2a..47c2f21b5a6 100644 >> --- a/libsanitizer/lsan/lsan_linux.cpp >> +++ b/libsanitizer/lsan/lsan_linux.cpp >> @@ -6,13 +6,13 @@ >> // >> //=3D=3D=3D-----------------------------------------------------------= -----------=3D=3D=3D// >> >> // >> -// This file is a part of LeakSanitizer. Linux/NetBSD-specific code. >> +// This file is a part of LeakSanitizer. >> Linux/NetBSD/Fuchsia-specific code. >> // >> //=3D=3D=3D-----------------------------------------------------------= -----------=3D=3D=3D// >> >> >> #include "sanitizer_common/sanitizer_platform.h" >> >> -#if SANITIZER_LINUX || SANITIZER_NETBSD >> +#if SANITIZER_LINUX || SANITIZER_NETBSD || SANITIZER_FUCHSIA >> >> #include "lsan_allocator.h" >> >> @@ -29,4 +29,4 @@ void ReplaceSystemMalloc() {} >> >> } // namespace __lsan >> >> -#endif // SANITIZER_LINUX || SANITIZER_NETBSD >> +#endif // SANITIZER_LINUX || SANITIZER_NETBSD || SANITIZER_FUCHSIA >> diff --git a/libsanitizer/lsan/lsan_posix.cpp >> b/libsanitizer/lsan/lsan_posix.cpp >> new file mode 100644 >> index 00000000000..8e05915dd1b >> --- /dev/null >> +++ b/libsanitizer/lsan/lsan_posix.cpp >> @@ -0,0 +1,96 @@ >> +//=3D-- lsan_posix.cpp >> -----------------------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// This file is a part of LeakSanitizer. >> +// Standalone LSan RTL code common to POSIX-like systems. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#include "sanitizer_common/sanitizer_platform.h" >> + >> +#if SANITIZER_POSIX >> +#include "lsan.h" >> +#include "lsan_allocator.h" >> +#include "sanitizer_common/sanitizer_stacktrace.h" >> +#include "sanitizer_common/sanitizer_tls_get_addr.h" >> + >> +namespace __lsan { >> + >> +ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {} >> + >> +struct OnStartedArgs { >> + uptr stack_begin; >> + uptr stack_end; >> + uptr cache_begin; >> + uptr cache_end; >> + uptr tls_begin; >> + uptr tls_end; >> + DTLS *dtls; >> +}; >> + >> +void ThreadContext::OnStarted(void *arg) { >> + auto args =3D reinterpret_cast(arg); >> + stack_begin_ =3D args->stack_begin; >> + stack_end_ =3D args->stack_end; >> + tls_begin_ =3D args->tls_begin; >> + tls_end_ =3D args->tls_end; >> + cache_begin_ =3D args->cache_begin; >> + cache_end_ =3D args->cache_end; >> + dtls_ =3D args->dtls; >> +} >> + >> +void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { >> + OnStartedArgs args; >> + uptr stack_size =3D 0; >> + uptr tls_size =3D 0; >> + GetThreadStackAndTls(tid =3D=3D 0, &args.stack_begin, &stack_size, >> + &args.tls_begin, &tls_size); >> + args.stack_end =3D args.stack_begin + stack_size; >> + args.tls_end =3D args.tls_begin + tls_size; >> + GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); >> + args.dtls =3D DTLS_Get(); >> + ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args); >> +} >> + >> +bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr >> *stack_end, >> + uptr *tls_begin, uptr *tls_end, uptr >> *cache_begin, >> + uptr *cache_end, DTLS **dtls) { >> + ThreadContext *context =3D static_cast( >> + GetThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id)); >> + if (!context) >> + return false; >> + *stack_begin =3D context->stack_begin(); >> + *stack_end =3D context->stack_end(); >> + *tls_begin =3D context->tls_begin(); >> + *tls_end =3D context->tls_end(); >> + *cache_begin =3D context->cache_begin(); >> + *cache_end =3D context->cache_end(); >> + *dtls =3D context->dtls(); >> + return true; >> +} >> + >> +void InitializeMainThread() { >> + u32 tid =3D ThreadCreate(0, 0, true); >> + CHECK_EQ(tid, 0); >> + ThreadStart(tid, GetTid()); >> +} >> + >> +static void OnStackUnwind(const SignalContext &sig, const void *, >> + BufferedStackTrace *stack) { >> + stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, >> sig.context, >> + common_flags()->fast_unwind_on_fatal); >> +} >> + >> +void LsanOnDeadlySignal(int signo, void *siginfo, void *context) { >> + HandleDeadlySignal(siginfo, context, GetCurrentThread(), >> &OnStackUnwind, >> + nullptr); >> +} >> + >> +}=A0 // namespace __lsan >> + >> +#endif // SANITIZER_POSIX >> diff --git a/libsanitizer/lsan/lsan_posix.h >> b/libsanitizer/lsan/lsan_posix.h >> new file mode 100644 >> index 00000000000..840e427c55e >> --- /dev/null >> +++ b/libsanitizer/lsan/lsan_posix.h >> @@ -0,0 +1,49 @@ >> +//=3D-- lsan_posix.h >> -----------------------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// This file is a part of LeakSanitizer. >> +// Standalone LSan RTL code common to POSIX-like systems. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#ifndef LSAN_POSIX_H >> +#define LSAN_POSIX_H >> + >> +#include "lsan_thread.h" >> +#include "sanitizer_common/sanitizer_platform.h" >> + >> +#if !SANITIZER_POSIX >> +#error "lsan_posix.h is used only on POSIX-like systems >> (SANITIZER_POSIX)" >> +#endif >> + >> +namespace __sanitizer { >> +struct DTLS; >> +} >> + >> +namespace __lsan { >> + >> +class ThreadContext : public ThreadContextLsanBase { >> + public: >> + explicit ThreadContext(int tid); >> + void OnStarted(void *arg) override; >> + uptr tls_begin() { return tls_begin_; } >> + uptr tls_end() { return tls_end_; } >> + DTLS *dtls() { return dtls_; } >> + >> + private: >> + uptr tls_begin_ =3D 0; >> + uptr tls_end_ =3D 0; >> + DTLS *dtls_ =3D nullptr; >> +}; >> + >> +void ThreadStart(u32 tid, tid_t os_id, >> + ThreadType thread_type =3D ThreadType::Regular); >> + >> +}=A0 // namespace __lsan >> + >> +#endif // LSAN_POSIX_H >> diff --git a/libsanitizer/lsan/lsan_thread.cpp >> b/libsanitizer/lsan/lsan_thread.cpp >> index 84e7ce61b97..40bdc254bb6 100644 >> --- a/libsanitizer/lsan/lsan_thread.cpp >> +++ b/libsanitizer/lsan/lsan_thread.cpp >> @@ -13,12 +13,13 @@ >> >> #include "lsan_thread.h" >> >> +#include "lsan.h" >> +#include "lsan_allocator.h" >> +#include "lsan_common.h" >> #include "sanitizer_common/sanitizer_common.h" >> #include "sanitizer_common/sanitizer_placement_new.h" >> #include "sanitizer_common/sanitizer_thread_registry.h" >> #include "sanitizer_common/sanitizer_tls_get_addr.h" >> -#include "lsan_allocator.h" >> -#include "lsan_common.h" >> >> namespace __lsan { >> >> @@ -26,7 +27,7 @@ static ThreadRegistry *thread_registry; >> >> static ThreadContextBase *CreateThreadContext(u32 tid) { >> void *mem =3D MmapOrDie(sizeof(ThreadContext), "ThreadContext"); >> - return new(mem) ThreadContext(tid); >> + return new (mem) ThreadContext(tid); >> } >> >> static const uptr kMaxThreads =3D 1 << 13; >> @@ -34,59 +35,26 @@ static const uptr kThreadQuarantineSize =3D 64; >> >> void InitializeThreadRegistry() { >> static ALIGNED(64) char >> thread_registry_placeholder[sizeof(ThreadRegistry)]; >> - thread_registry =3D new(thread_registry_placeholder) >> - ThreadRegistry(CreateThreadContext, kMaxThreads, >> kThreadQuarantineSize); >> + thread_registry =3D new (thread_registry_placeholder) >> + ThreadRegistry(CreateThreadContext, kMaxThreads, >> kThreadQuarantineSize); >> } >> >> -ThreadContext::ThreadContext(int tid) >> - : ThreadContextBase(tid), >> - stack_begin_(0), >> - stack_end_(0), >> - cache_begin_(0), >> - cache_end_(0), >> - tls_begin_(0), >> - tls_end_(0), >> - dtls_(nullptr) {} >> - >> -struct OnStartedArgs { >> - uptr stack_begin, stack_end, >> - cache_begin, cache_end, >> - tls_begin, tls_end; >> - DTLS *dtls; >> -}; >> - >> -void ThreadContext::OnStarted(void *arg) { >> - OnStartedArgs *args =3D reinterpret_cast(arg); >> - stack_begin_ =3D args->stack_begin; >> - stack_end_ =3D args->stack_end; >> - tls_begin_ =3D args->tls_begin; >> - tls_end_ =3D args->tls_end; >> - cache_begin_ =3D args->cache_begin; >> - cache_end_ =3D args->cache_end; >> - dtls_ =3D args->dtls; >> -} >> +ThreadContextLsanBase::ThreadContextLsanBase(int tid) >> + : ThreadContextBase(tid) {} >> >> -void ThreadContext::OnFinished() { >> +void ThreadContextLsanBase::OnFinished() { >> AllocatorThreadFinish(); >> DTLS_Destroy(); >> } >> >> -u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) { >> - return thread_registry->CreateThread(user_id, detached, parent_tid, >> - /* arg */ nullptr); >> +u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached, void >> *arg) { >> + return thread_registry->CreateThread(user_id, detached, >> parent_tid, arg); >> } >> >> -void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { >> - OnStartedArgs args; >> - uptr stack_size =3D 0; >> - uptr tls_size =3D 0; >> - GetThreadStackAndTls(tid =3D=3D 0, &args.stack_begin, &stack_size, >> - &args.tls_begin, &tls_size); >> - args.stack_end =3D args.stack_begin + stack_size; >> - args.tls_end =3D args.tls_begin + tls_size; >> - GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); >> - args.dtls =3D DTLS_Get(); >> - thread_registry->StartThread(tid, os_id, thread_type, &args); >> +void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, >> + ThreadType thread_type, void >> *arg) { >> + thread_registry->StartThread(tid, os_id, thread_type, arg); >> + SetCurrentThread(tid); >> } >> >> void ThreadFinish() { >> @@ -95,7 +63,8 @@ void ThreadFinish() { >> } >> >> ThreadContext *CurrentThreadContext() { >> - if (!thread_registry) return nullptr; >> + if (!thread_registry) >> + return nullptr; >> if (GetCurrentThread() =3D=3D kInvalidTid) >> return nullptr; >> // No lock needed when getting current thread. >> @@ -111,12 +80,12 @@ static bool FindThreadByUid(ThreadContextBase >> *tctx, void *arg) { >> } >> >> u32 ThreadTid(uptr uid) { >> - return thread_registry->FindThread(FindThreadByUid, (void*)uid); >> + return thread_registry->FindThread(FindThreadByUid, (void *)uid); >> } >> >> void ThreadJoin(u32 tid) { >> CHECK_NE(tid, kInvalidTid); >> - thread_registry->JoinThread(tid, /* arg */nullptr); >> + thread_registry->JoinThread(tid, /* arg */ nullptr); >> } >> >> void EnsureMainThreadIDIsCorrect() { >> @@ -126,37 +95,16 @@ void EnsureMainThreadIDIsCorrect() { >> >> ///// Interface to the common LSan module. ///// >> >> -bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr >> *stack_end, >> - uptr *tls_begin, uptr *tls_end, uptr >> *cache_begin, >> - uptr *cache_end, DTLS **dtls) { >> - ThreadContext *context =3D static_cast( >> - thread_registry->FindThreadContextByOsIDLocked(os_id)); >> - if (!context) return false; >> - *stack_begin =3D context->stack_begin(); >> - *stack_end =3D context->stack_end(); >> - *tls_begin =3D context->tls_begin(); >> - *tls_end =3D context->tls_end(); >> - *cache_begin =3D context->cache_begin(); >> - *cache_end =3D context->cache_end(); >> - *dtls =3D context->dtls(); >> - return true; >> -} >> - >> void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback >> callback, >> - void *arg) { >> -} >> + void *arg) {} >> >> -void LockThreadRegistry() { >> - thread_registry->Lock(); >> -} >> +void LockThreadRegistry() { thread_registry->Lock(); } >> >> -void UnlockThreadRegistry() { >> - thread_registry->Unlock(); >> -} >> +void UnlockThreadRegistry() { thread_registry->Unlock(); } >> >> ThreadRegistry *GetThreadRegistryLocked() { >> thread_registry->CheckLocked(); >> return thread_registry; >> } >> >> -} // namespace __lsan >> +}=A0 // namespace __lsan >> diff --git a/libsanitizer/lsan/lsan_thread.h >> b/libsanitizer/lsan/lsan_thread.h >> index b869d066d9d..0ab1582de66 100644 >> --- a/libsanitizer/lsan/lsan_thread.h >> +++ b/libsanitizer/lsan/lsan_thread.h >> @@ -16,38 +16,36 @@ >> >> #include "sanitizer_common/sanitizer_thread_registry.h" >> >> -namespace __sanitizer { >> -struct DTLS; >> -} >> - >> namespace __lsan { >> >> -class ThreadContext : public ThreadContextBase { >> +class ThreadContextLsanBase : public ThreadContextBase { >> public: >> - explicit ThreadContext(int tid); >> - void OnStarted(void *arg) override; >> + explicit ThreadContextLsanBase(int tid); >> void OnFinished() override; >> uptr stack_begin() { return stack_begin_; } >> uptr stack_end() { return stack_end_; } >> - uptr tls_begin() { return tls_begin_; } >> - uptr tls_end() { return tls_end_; } >> uptr cache_begin() { return cache_begin_; } >> uptr cache_end() { return cache_end_; } >> - DTLS *dtls() { return dtls_; } >> >> - private: >> - uptr stack_begin_, stack_end_, >> - cache_begin_, cache_end_, >> - tls_begin_, tls_end_; >> - DTLS *dtls_; >> + // The argument is passed on to the subclass's OnStarted member >> function. >> + static void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type, >> + void *onstarted_arg); >> + >> + protected: >> + uptr stack_begin_ =3D 0; >> + uptr stack_end_ =3D 0; >> + uptr cache_begin_ =3D 0; >> + uptr cache_end_ =3D 0; >> }; >> >> +// This subclass of ThreadContextLsanBase is declared in an >> OS-specific header. >> +class ThreadContext; >> + >> void InitializeThreadRegistry(); >> +void InitializeMainThread(); >> >> -void ThreadStart(u32 tid, tid_t os_id, >> - ThreadType thread_type =3D ThreadType::Regular); >> +u32 ThreadCreate(u32 tid, uptr uid, bool detached, void *arg =3D >> nullptr); >> void ThreadFinish(); >> -u32 ThreadCreate(u32 tid, uptr uid, bool detached); >> void ThreadJoin(u32 tid); >> u32 ThreadTid(uptr uid); >> >> @@ -55,6 +53,7 @@ u32 GetCurrentThread(); >> void SetCurrentThread(u32 tid); >> ThreadContext *CurrentThreadContext(); >> void EnsureMainThreadIDIsCorrect(); >> + >> }=A0 // namespace __lsan >> >> #endif // LSAN_THREAD_H >> diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator.cpp >> b/libsanitizer/sanitizer_common/sanitizer_allocator.cpp >> index 8d07906cca0..ec77b9cbfee 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_allocator.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_allocator.cpp >> @@ -25,7 +25,7 @@ const char *PrimaryAllocatorName =3D >> "SizeClassAllocator"; >> const char *SecondaryAllocatorName =3D "LargeMmapAllocator"; >> >> // ThreadSanitizer for Go uses libc malloc/free. >> -#if SANITIZER_GO || defined(SANITIZER_USE_MALLOC) >> +#if defined(SANITIZER_USE_MALLOC) >> # if SANITIZER_LINUX && !SANITIZER_ANDROID >> extern "C" void *__libc_malloc(uptr size); >> # if !SANITIZER_GO >> @@ -213,7 +213,7 @@ void *LowLevelAllocator::Allocate(uptr size) { >> // Align allocation size. >> size =3D RoundUpTo(size, low_level_alloc_min_alignment); >> if (allocated_end_ - allocated_current_ < (sptr)size) { >> - uptr size_to_allocate =3D Max(size, GetPageSizeCached()); >> + uptr size_to_allocate =3D RoundUpTo(size, GetPageSizeCached()); >> allocated_current_ =3D >> (char*)MmapOrDie(size_to_allocate, __func__); >> allocated_end_ =3D allocated_current_ + size_to_allocate; >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h >> b/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h >> index 90603280e7c..1d9a29c70f3 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_allocator_primary64.h >> @@ -72,11 +72,15 @@ class SizeClassAllocator64 { >> void Init(s32 release_to_os_interval_ms) { >> uptr TotalSpaceSize =3D kSpaceSize + AdditionalSize(); >> if (kUsingConstantSpaceBeg) { >> + CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize)); >> CHECK_EQ(kSpaceBeg, address_range.Init(TotalSpaceSize, >> PrimaryAllocatorName, kSpaceBeg)); >> } else { >> - NonConstSpaceBeg =3D address_range.Init(TotalSpaceSize, >> - PrimaryAllocatorName); >> + // Combined allocator expects that an 2^N allocation is always >> aligned to >> + // 2^N. For this to work, the start of the space needs to be >> aligned as >> + // high as the largest size class (which also needs to be a >> power of 2). >> + NonConstSpaceBeg =3D address_range.InitAligned( >> + TotalSpaceSize, SizeClassMap::kMaxSize, >> PrimaryAllocatorName); >> CHECK_NE(NonConstSpaceBeg, ~(uptr)0); >> } >> SetReleaseToOSIntervalMs(release_to_os_interval_ms); >> @@ -220,7 +224,7 @@ class SizeClassAllocator64 { >> >> // Test-only. >> void TestOnlyUnmap() { >> - UnmapWithCallbackOrDie(SpaceBeg(), kSpaceSize + AdditionalSize()); >> + UnmapWithCallbackOrDie((uptr)address_range.base(), >> address_range.size()); >> } >> >> static void FillMemoryProfile(uptr start, uptr rss, bool file, >> uptr *stats, >> diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cpp >> b/libsanitizer/sanitizer_common/sanitizer_common.cpp >> index f5f9f49d8cf..87efda5bd37 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_common.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_common.cpp >> @@ -274,6 +274,7 @@ uptr ReadBinaryNameCached(/*out*/char *buf, uptr >> buf_len) { >> return name_len; >> } >> >> +#if !SANITIZER_GO >> void PrintCmdline() { >> char **argv =3D GetArgv(); >> if (!argv) return; >> @@ -282,6 +283,7 @@ void PrintCmdline() { >> Printf("%s ", argv[i]); >> Printf("\n\n"); >> } >> +#endif >> >> // Malloc hooks. >> static const int kMaxMallocFreeHooks =3D 5; >> diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h >> b/libsanitizer/sanitizer_common/sanitizer_common.h >> index 87b8f02b5b7..ac16e0e47ef 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_common.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_common.h >> @@ -143,6 +143,7 @@ void RunFreeHooks(const void *ptr); >> class ReservedAddressRange { >> public: >> uptr Init(uptr size, const char *name =3D nullptr, uptr fixed_addr >> =3D 0); >> + uptr InitAligned(uptr size, uptr align, const char *name =3D nullptr)= ; >> uptr Map(uptr fixed_addr, uptr size, const char *name =3D nullptr); >> uptr MapOrDie(uptr fixed_addr, uptr size, const char *name =3D >> nullptr); >> void Unmap(uptr addr, uptr size); >> @@ -552,7 +553,7 @@ bool operator!=3D(const InternalMmapVectorNoCtor >> &lhs, >> template >> class InternalMmapVector : public InternalMmapVectorNoCtor { >> public: >> - InternalMmapVector() { InternalMmapVectorNoCtor::Initialize(1); } >> + InternalMmapVector() { InternalMmapVectorNoCtor::Initialize(0); } >> explicit InternalMmapVector(uptr cnt) { >> InternalMmapVectorNoCtor::Initialize(cnt); >> this->resize(cnt); >> @@ -855,7 +856,7 @@ INLINE uptr GetPthreadDestructorIterations() { >> #endif >> } >> >> -void *internal_start_thread(void(*func)(void*), void *arg); >> +void *internal_start_thread(void *(*func)(void*), void *arg); >> void internal_join_thread(void *th); >> void MaybeStartBackgroudThread(); >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc >> b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc >> index 50e3558b52e..57f8b2d2944 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc >> +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc >> @@ -79,13 +79,15 @@ >> #define devname __devname50 >> #define fgetpos __fgetpos50 >> #define fsetpos __fsetpos50 >> +#define fstatvfs __fstatvfs90 >> +#define fstatvfs1 __fstatvfs190 >> #define fts_children __fts_children60 >> #define fts_close __fts_close60 >> #define fts_open __fts_open60 >> #define fts_read __fts_read60 >> #define fts_set __fts_set60 >> #define getitimer __getitimer50 >> -#define getmntinfo __getmntinfo13 >> +#define getmntinfo __getmntinfo90 >> #define getpwent __getpwent50 >> #define getpwnam __getpwnam50 >> #define getpwnam_r __getpwnam_r50 >> @@ -95,6 +97,7 @@ >> #define getutxent __getutxent50 >> #define getutxid __getutxid50 >> #define getutxline __getutxline50 >> +#define getvfsstat __getvfsstat90 >> #define pututxline __pututxline50 >> #define glob __glob30 >> #define gmtime __gmtime50 >> @@ -110,12 +113,15 @@ >> #define setitimer __setitimer50 >> #define setlocale __setlocale50 >> #define shmctl __shmctl50 >> +#define sigaltstack __sigaltstack14 >> #define sigemptyset __sigemptyset14 >> #define sigfillset __sigfillset14 >> #define sigpending __sigpending14 >> #define sigprocmask __sigprocmask14 >> #define sigtimedwait __sigtimedwait50 >> #define stat __stat50 >> +#define statvfs __statvfs90 >> +#define statvfs1 __statvfs190 >> #define time __time50 >> #define times __times13 >> #define unvis __unvis50 >> @@ -128,11 +134,7 @@ extern const short *_tolower_tab_; >> >> // Platform-specific options. >> #if SANITIZER_MAC >> -namespace __sanitizer { >> -bool PlatformHasDifferentMemcpyAndMemmove(); >> -} >> -#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \ >> - (__sanitizer::PlatformHasDifferentMemcpyAndMemmove()) >> +#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false >> #elif SANITIZER_WINDOWS64 >> #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false >> #else >> @@ -4177,11 +4179,27 @@ INTERCEPTOR(int, pthread_mutex_unlock, void >> *m) { >> >> #if SANITIZER_INTERCEPT___PTHREAD_MUTEX >> INTERCEPTOR(int, __pthread_mutex_lock, void *m) { >> - return WRAP(pthread_mutex_lock)(m); >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m); >> + COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m); >> + int res =3D REAL(__pthread_mutex_lock)(m); >> + if (res =3D=3D errno_EOWNERDEAD) >> + COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m); >> + if (res =3D=3D 0 || res =3D=3D errno_EOWNERDEAD) >> + COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m); >> + if (res =3D=3D errno_EINVAL) >> + COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); >> + return res; >> } >> >> INTERCEPTOR(int, __pthread_mutex_unlock, void *m) { >> - return WRAP(pthread_mutex_unlock)(m); >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m); >> + COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m); >> + int res =3D REAL(__pthread_mutex_unlock)(m); >> + if (res =3D=3D errno_EINVAL) >> + COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); >> + return res; >> } >> >> #define INIT___PTHREAD_MUTEX_LOCK \ >> @@ -6411,12 +6429,11 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void >> *buf, SIZE_T len, int flags, >> if (srcaddr) srcaddr_sz =3D *addrlen; >> (void)srcaddr_sz; // prevent "set but not used" warning >> SSIZE_T res =3D REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen= ); >> - if (res > 0) { >> + if (res > 0) >> COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); >> - if (srcaddr) >> - COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr, >> - Min((SIZE_T)*addrlen, >> srcaddr_sz)); >> - } >> + if (res >=3D 0 && srcaddr) >> + COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr, >> + Min((SIZE_T)*addrlen, >> srcaddr_sz)); >> return res; >> } >> #define INIT_RECV_RECVFROM \ >> @@ -9623,6 +9640,148 @@ INTERCEPTOR(int, getentropy, void *buf, >> SIZE_T buflen) { >> #define INIT_GETENTROPY >> #endif >> >> +#if SANITIZER_INTERCEPT_QSORT >> +// Glibc qsort uses a temporary buffer allocated either on stack or >> on heap. >> +// Poisoned memory from there may get copied into the comparator >> arguments, >> +// where it needs to be dealt with. But even that is not enough - >> the results of >> +// the sort may be copied into the input/output array based on the >> results of >> +// the comparator calls, but directly from the temp memory, >> bypassing the >> +// unpoisoning done in wrapped_qsort_compar. We deal with this by, >> again, >> +// unpoisoning the entire array after the sort is done. >> +// >> +// We can not check that the entire array is initialized at the >> beginning. IMHO, >> +// it's fine for parts of the sorted objects to contain >> uninitialized memory, >> +// ex. as padding in structs. >> +typedef int (*qsort_compar_f)(const void *, const void *); >> +static THREADLOCAL qsort_compar_f qsort_compar; >> +static THREADLOCAL SIZE_T qsort_size; >> +int wrapped_qsort_compar(const void *a, const void *b) { >> + COMMON_INTERCEPTOR_UNPOISON_PARAM(2); >> + COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_size); >> + COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_size); >> + return qsort_compar(a, b); >> +} >> + >> +INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size, >> + qsort_compar_f compar) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar); >> + // Run the comparator over all array elements to detect any memory >> issues. >> + if (nmemb > 1) { >> + for (SIZE_T i =3D 0; i < nmemb - 1; ++i) { >> + void *p =3D (void *)((char *)base + i * size); >> + void *q =3D (void *)((char *)base + (i + 1) * size); >> + COMMON_INTERCEPTOR_UNPOISON_PARAM(2); >> + compar(p, q); >> + } >> + } >> + qsort_compar_f old_compar =3D qsort_compar; >> + qsort_compar =3D compar; >> + SIZE_T old_size =3D qsort_size; >> + qsort_size =3D size; >> + REAL(qsort)(base, nmemb, size, wrapped_qsort_compar); >> + qsort_compar =3D old_compar; >> + qsort_size =3D old_size; >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); >> +} >> +#define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort) >> +#else >> +#define INIT_QSORT >> +#endif >> + >> +#if SANITIZER_INTERCEPT_QSORT_R >> +typedef int (*qsort_r_compar_f)(const void *, const void *, void *); >> +static THREADLOCAL qsort_r_compar_f qsort_r_compar; >> +static THREADLOCAL SIZE_T qsort_r_size; >> +int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) { >> + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); >> + COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size); >> + COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size); >> + return qsort_r_compar(a, b, arg); >> +} >> + >> +INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size, >> + qsort_r_compar_f compar, void *arg) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, >> arg); >> + // Run the comparator over all array elements to detect any memory >> issues. >> + if (nmemb > 1) { >> + for (SIZE_T i =3D 0; i < nmemb - 1; ++i) { >> + void *p =3D (void *)((char *)base + i * size); >> + void *q =3D (void *)((char *)base + (i + 1) * size); >> + COMMON_INTERCEPTOR_UNPOISON_PARAM(3); >> + compar(p, q, arg); >> + } >> + } >> + qsort_r_compar_f old_compar =3D qsort_r_compar; >> + qsort_r_compar =3D compar; >> + SIZE_T old_size =3D qsort_r_size; >> + qsort_r_size =3D size; >> + REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg); >> + qsort_r_compar =3D old_compar; >> + qsort_r_size =3D old_size; >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); >> +} >> +#define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r) >> +#else >> +#define INIT_QSORT_R >> +#endif >> + >> +#if SANITIZER_INTERCEPT_SIGALTSTACK >> +INTERCEPTOR(int, sigaltstack, void *ss, void *oss) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, sigaltstack, ss, oss); >> + int r =3D REAL(sigaltstack)(ss, oss); >> + if (r =3D=3D 0 && oss !=3D nullptr) { >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oss, struct_stack_t_sz); >> + } >> + return r; >> +} >> +#define INIT_SIGALTSTACK COMMON_INTERCEPT_FUNCTION(sigaltstack) >> +#else >> +#define INIT_SIGALTSTACK >> +#endif >> + >> +#if SANITIZER_INTERCEPT_UNAME >> +INTERCEPTOR(int, uname, struct utsname *utsname) { >> +#if SANITIZER_LINUX >> + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) >> + return internal_uname(utsname); >> +#endif >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, uname, utsname); >> + int res =3D REAL(uname)(utsname); >> + if (!res) >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname, >> + __sanitizer::struct_utsname_sz); >> + return res; >> +} >> +#define INIT_UNAME COMMON_INTERCEPT_FUNCTION(uname) >> +#else >> +#define INIT_UNAME >> +#endif >> + >> +#if SANITIZER_INTERCEPT___XUNAME >> +// FreeBSD's define uname() as >> +// static __inline int uname(struct utsname *name) { >> +// return __xuname(SYS_NMLN, (void*)name); >> +// } >> +INTERCEPTOR(int, __xuname, int size, void *utsname) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, __xuname, size, utsname); >> + int res =3D REAL(__xuname)(size, utsname); >> + if (!res) >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, utsname, >> + __sanitizer::struct_utsname_sz); >> + return res; >> +} >> +#define INIT___XUNAME COMMON_INTERCEPT_FUNCTION(__xuname) >> +#else >> +#define INIT___XUNAME >> +#endif >> + >> +#include "sanitizer_common_interceptors_netbsd_compat.inc" >> + >> static void InitializeCommonInterceptors() { >> #if SI_POSIX >> static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; >> @@ -9924,6 +10083,11 @@ static void InitializeCommonInterceptors() { >> INIT_CRYPT; >> INIT_CRYPT_R; >> INIT_GETENTROPY; >> + INIT_QSORT; >> + INIT_QSORT_R; >> + INIT_SIGALTSTACK; >> + INIT_UNAME; >> + INIT___XUNAME; >> >> INIT___PRINTF_CHK; >> } >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_com= pat.inc >> b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_com= pat.inc >> >> new file mode 100644 >> index 00000000000..6aa73ec8c6a >> --- /dev/null >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_common_interceptors_netbsd_com= pat.inc >> @@ -0,0 +1,128 @@ >> +//=3D=3D=3D-- sanitizer_common_interceptors_netbsd_compat.inc ---------= *- >> C++ -*-=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ----------=3D=3D=3D// >> >> +// >> +// Common function interceptors for tools like AddressSanitizer, >> +// ThreadSanitizer, MemorySanitizer, etc. >> +// >> +// Interceptors for NetBSD old function calls that have been versioned. >> +// >> +// NetBSD minimal version supported 9.0. >> +// NetBSD current version supported 9.99.26. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ----------=3D=3D=3D// >> >> + >> +#if SANITIZER_NETBSD >> + >> +// First undef all mangled symbols. >> +// Next, define compat interceptors. >> +// Finally, undef INIT_ and redefine it. >> +// This allows to avoid preprocessor issues. >> + >> +#undef fstatvfs >> +#undef fstatvfs1 >> +#undef getmntinfo >> +#undef getvfsstat >> +#undef statvfs >> +#undef statvfs1 >> + >> +INTERCEPTOR(int, statvfs, char *path, void *buf) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf); >> + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, >> REAL(strlen)(path) + 1); >> + // FIXME: under ASan the call below may write to freed memory and >> corrupt >> + // its metadata. See >> + // https://github.com/google/sanitizers/issues/321. >> + int res =3D REAL(statvfs)(path, buf); >> + if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, >> struct_statvfs90_sz); >> + return res; >> +} >> + >> +INTERCEPTOR(int, fstatvfs, int fd, void *buf) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf); >> + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); >> + // FIXME: under ASan the call below may write to freed memory and >> corrupt >> + // its metadata. See >> + // https://github.com/google/sanitizers/issues/321. >> + int res =3D REAL(fstatvfs)(fd, buf); >> + if (!res) { >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz); >> + if (fd >=3D 0) >> + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); >> + } >> + return res; >> +} >> + >> +#undef INIT_STATVFS >> +#define INIT_STATVFS \ >> + COMMON_INTERCEPT_FUNCTION(statvfs); \ >> + COMMON_INTERCEPT_FUNCTION(fstatvfs); \ >> + COMMON_INTERCEPT_FUNCTION(__statvfs90); \ >> + COMMON_INTERCEPT_FUNCTION(__fstatvfs90) >> + >> +INTERCEPTOR(int, __getmntinfo13, void **mntbufp, int flags) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, __getmntinfo13, mntbufp, flags); >> + int cnt =3D REAL(__getmntinfo13)(mntbufp, flags); >> + if (cnt > 0 && mntbufp) { >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mntbufp, sizeof(void *)); >> + if (*mntbufp) >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *mntbufp, cnt * >> struct_statvfs90_sz); >> + } >> + return cnt; >> +} >> + >> +#undef INIT_GETMNTINFO >> +#define INIT_GETMNTINFO \ >> + COMMON_INTERCEPT_FUNCTION(__getmntinfo13); \ >> + COMMON_INTERCEPT_FUNCTION(__getmntinfo90) >> + >> +INTERCEPTOR(int, getvfsstat, void *buf, SIZE_T bufsize, int flags) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, getvfsstat, buf, bufsize, flags); >> + int ret =3D REAL(getvfsstat)(buf, bufsize, flags); >> + if (buf && ret > 0) >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, ret * >> struct_statvfs90_sz); >> + return ret; >> +} >> + >> +#undef INIT_GETVFSSTAT >> +#define INIT_GETVFSSTAT \ >> + COMMON_INTERCEPT_FUNCTION(getvfsstat); \ >> + COMMON_INTERCEPT_FUNCTION(__getvfsstat90) >> + >> +INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags); >> + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, >> REAL(strlen)(path) + 1); >> + int res =3D REAL(statvfs1)(path, buf, flags); >> + if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, >> struct_statvfs90_sz); >> + return res; >> +} >> + >> +INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) { >> + void *ctx; >> + COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags); >> + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); >> + int res =3D REAL(fstatvfs1)(fd, buf, flags); >> + if (!res) { >> + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs90_sz); >> + if (fd >=3D 0) >> + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); >> + } >> + return res; >> +} >> + >> +#undef INIT_STATVFS1 >> +#define INIT_STATVFS1 \ >> + COMMON_INTERCEPT_FUNCTION(statvfs1); \ >> + COMMON_INTERCEPT_FUNCTION(fstatvfs1); \ >> + COMMON_INTERCEPT_FUNCTION(__statvfs190); \ >> + COMMON_INTERCEPT_FUNCTION(__fstatvfs190) >> + >> +#endif >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp >> b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp >> index 27d6a177760..0c918ebb4a9 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_common_libcdep.cpp >> @@ -30,7 +30,7 @@ SANITIZER_WEAK_ATTRIBUTE StackDepotStats >> *StackDepotGetStats() { >> return nullptr; >> } >> >> -void BackgroundThread(void *arg) { >> +void *BackgroundThread(void *arg) { >> const uptr hard_rss_limit_mb =3D common_flags()->hard_rss_limit_mb; >> const uptr soft_rss_limit_mb =3D common_flags()->soft_rss_limit_mb; >> const bool heap_profile =3D common_flags()->heap_profile; >> @@ -129,6 +129,16 @@ void SetSandboxingCallback(void (*f)()) { >> sandboxing_callback =3D f; >> } >> >> +uptr ReservedAddressRange::InitAligned(uptr size, uptr align, >> + const char *name) { >> + CHECK(IsPowerOfTwo(align)); >> + if (align <=3D GetPageSizeCached()) >> + return Init(size, name); >> + uptr start =3D Init(size + align, name); >> + start +=3D align - (start & (align - 1)); >> + return start; >> +} >> + >> }=A0 // namespace __sanitizer >> >> SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify, >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc >> b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc >> index 31ff48cfd2c..532ac9ead34 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc >> +++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc >> @@ -2885,6 +2885,23 @@ POST_SYSCALL(getrandom)(long res, void *buf, >> uptr count, long flags) { >> POST_WRITE(buf, res); >> } >> } >> + >> +PRE_SYSCALL(sigaltstack)(const void *ss, void *oss) { >> + if (ss !=3D nullptr) { >> + PRE_READ(ss, struct_stack_t_sz); >> + } >> + if (oss !=3D nullptr) { >> + PRE_WRITE(oss, struct_stack_t_sz); >> + } >> +} >> + >> +POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) { >> + if (res =3D=3D 0) { >> + if (oss !=3D nullptr) { >> + POST_WRITE(oss, struct_stack_t_sz); >> + } >> + } >> +} >> }=A0 // extern "C" >> >> #undef PRE_SYSCALL >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp >> b/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp >> index f18cee66b84..a52db08433e 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_coverage_fuchsia.cpp >> @@ -27,15 +27,15 @@ >> >> #include "sanitizer_platform.h" >> #if SANITIZER_FUCHSIA >> +#include >> +#include >> +#include >> + >> #include "sanitizer_atomic.h" >> #include "sanitizer_common.h" >> #include "sanitizer_internal_defs.h" >> #include "sanitizer_symbolizer_fuchsia.h" >> >> -#include >> -#include >> -#include >> - >> using namespace __sanitizer; >> >> namespace __sancov { >> @@ -82,7 +82,8 @@ class TracePcGuardController final { >> void TracePcGuard(u32 *guard, uptr pc) { >> atomic_uint32_t *guard_ptr =3D reinterpret_cast> *>(guard); >> u32 idx =3D atomic_exchange(guard_ptr, 0, memory_order_relaxed); >> - if (idx > 0) array_[idx] =3D pc; >> + if (idx > 0) >> + array_[idx] =3D pc; >> } >> >> void Dump() { >> @@ -140,6 +141,10 @@ class TracePcGuardController final { >> internal_getpid()); >> _zx_object_set_property(vmo_, ZX_PROP_NAME, vmo_name_, >> internal_strlen(vmo_name_)); >> + uint64_t size =3D DataSize(); >> + status =3D _zx_object_set_property(vmo_, >> ZX_PROP_VMO_CONTENT_SIZE, &size, >> + sizeof(size)); >> + CHECK_EQ(status, ZX_OK); >> >> // Map the largest possible view we might need into the VMO. >> Later >> // we might need to increase the VMO's size before we can use >> larger >> @@ -172,6 +177,10 @@ class TracePcGuardController final { >> >> zx_status_t status =3D _zx_vmo_set_size(vmo_, DataSize()); >> CHECK_EQ(status, ZX_OK); >> + uint64_t size =3D DataSize(); >> + status =3D _zx_object_set_property(vmo_, >> ZX_PROP_VMO_CONTENT_SIZE, &size, >> + sizeof(size)); >> + CHECK_EQ(status, ZX_OK); >> >> return first_index; >> } >> @@ -204,13 +213,15 @@ SANITIZER_INTERFACE_ATTRIBUTE void >> __sanitizer_dump_coverage(const uptr *pcs, >> } >> >> SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, >> u32 *guard) { >> - if (!*guard) return; >> + if (!*guard) >> + return; >> __sancov::pc_guard_controller.TracePcGuard(guard, GET_CALLER_PC() >> - 1); >> } >> >> SANITIZER_INTERFACE_WEAK_DEF(void, >> __sanitizer_cov_trace_pc_guard_init, >> u32 *start, u32 *end) { >> - if (start =3D=3D end || *start) return; >> + if (start =3D=3D end || *start) >> + return; >> __sancov::pc_guard_controller.InitTracePcGuard(start, end); >> } >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_coverage_interface.inc >> b/libsanitizer/sanitizer_common/sanitizer_coverage_interface.inc >> index 7beeff7e8af..d7ab0c3d98c 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_coverage_interface.inc >> +++ b/libsanitizer/sanitizer_common/sanitizer_coverage_interface.inc >> @@ -29,4 +29,5 @@ >> INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init) >> INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir) >> INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch) >> INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init) >> +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init) >> INTERFACE_WEAK_FUNCTION(__sanitizer_cov_pcs_init) >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp >> b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp >> index 6a75792f926..73ebeb5fa14 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_coverage_libcdep_new.cpp >> @@ -207,6 +207,7 @@ SANITIZER_INTERFACE_WEAK_DEF(void, >> __sanitizer_cov_trace_div8, void) {} >> SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_gep, void) {} >> SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, >> void) {} >> SANITIZER_INTERFACE_WEAK_DEF(void, >> __sanitizer_cov_8bit_counters_init, void) {} >> +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_bool_flag_init, >> void) {} >> SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} >> }=A0 // extern "C" >> // Weak definition for code instrumented with >> -fsanitize-coverage=3Dstack-depth >> diff --git a/libsanitizer/sanitizer_common/sanitizer_file.h >> b/libsanitizer/sanitizer_common/sanitizer_file.h >> index 4a78a0e0ac8..26681f0493d 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_file.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_file.h >> @@ -87,8 +87,8 @@ bool IsAbsolutePath(const char *path); >> // The child process will close all fds after STDERR_FILENO >> // before passing control to a program. >> pid_t StartSubprocess(const char *filename, const char *const argv[], >> - fd_t stdin_fd =3D kInvalidFd, fd_t stdout_fd =3D >> kInvalidFd, >> - fd_t stderr_fd =3D kInvalidFd); >> + const char *const envp[], fd_t stdin_fd =3D >> kInvalidFd, >> + fd_t stdout_fd =3D kInvalidFd, fd_t stderr_fd =3D >> kInvalidFd); >> // Checks if specified process is still running >> bool IsProcessRunning(pid_t pid); >> // Waits for the process to finish and returns its exit code. >> diff --git a/libsanitizer/sanitizer_common/sanitizer_flag_parser.cpp >> b/libsanitizer/sanitizer_common/sanitizer_flag_parser.cpp >> index 1e2bc665261..9e274268bf2 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_flag_parser.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_flag_parser.cpp >> @@ -56,9 +56,16 @@ char *FlagParser::ll_strndup(const char *s, uptr n) { >> } >> >> void FlagParser::PrintFlagDescriptions() { >> + char buffer[128]; >> + buffer[sizeof(buffer) - 1] =3D '\0'; >> Printf("Available flags for %s:\n", SanitizerToolName); >> - for (int i =3D 0; i < n_flags_; ++i) >> - Printf("\t%s\n\t\t- %s\n", flags_[i].name, flags_[i].desc); >> + for (int i =3D 0; i < n_flags_; ++i) { >> + bool truncated =3D !(flags_[i].handler->Format(buffer, >> sizeof(buffer))); >> + CHECK_EQ(buffer[sizeof(buffer) - 1], '\0'); >> + const char *truncation_str =3D truncated ? " Truncated" : ""; >> + Printf("\t%s\n\t\t- %s (Current Value%s: %s)\n", flags_[i].name, >> + flags_[i].desc, truncation_str, buffer); >> + } >> } >> >> void FlagParser::fatal_error(const char *err) { >> diff --git a/libsanitizer/sanitizer_common/sanitizer_flag_parser.h >> b/libsanitizer/sanitizer_common/sanitizer_flag_parser.h >> index c24ad25626b..fac5dff3463 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_flag_parser.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_flag_parser.h >> @@ -22,9 +22,23 @@ namespace __sanitizer { >> class FlagHandlerBase { >> public: >> virtual bool Parse(const char *value) { return false; } >> + // Write the C string representation of the current value >> (truncated to fit) >> + // into the buffer of size `size`. Returns false if truncation >> occurred and >> + // returns true otherwise. >> + virtual bool Format(char *buffer, uptr size) { >> + if (size > 0) >> + buffer[0] =3D '\0'; >> + return false; >> + } >> >> protected: >> ~FlagHandlerBase() {} >> + >> + inline bool FormatString(char *buffer, uptr size, const char >> *str_to_use) { >> + uptr num_symbols_should_write =3D >> + internal_snprintf(buffer, size, "%s", str_to_use); >> + return num_symbols_should_write < size; >> + } >> }; >> >> template >> @@ -34,6 +48,7 @@ class FlagHandler : public FlagHandlerBase { >> public: >> explicit FlagHandler(T *t) : t_(t) {} >> bool Parse(const char *value) final; >> + bool Format(char *buffer, uptr size) final; >> }; >> >> inline bool ParseBool(const char *value, bool *b) { >> @@ -59,6 +74,11 @@ inline bool FlagHandler::Parse(const char >> *value) { >> return false; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr size) { >> + return FormatString(buffer, size, *t_ ? "true" : "false"); >> +} >> + >> template <> >> inline bool FlagHandler::Parse(const char *value) { >> bool b; >> @@ -75,12 +95,23 @@ inline bool >> FlagHandler::Parse(const char *value) { >> return false; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr >> size) { >> + uptr num_symbols_should_write =3D internal_snprintf(buffer, size, >> "%d", *t_); >> + return num_symbols_should_write < size; >> +} >> + >> template <> >> inline bool FlagHandler::Parse(const char *value) { >> *t_ =3D value; >> return true; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr >> size) { >> + return FormatString(buffer, size, *t_); >> +} >> + >> template <> >> inline bool FlagHandler::Parse(const char *value) { >> const char *value_end; >> @@ -90,6 +121,12 @@ inline bool FlagHandler::Parse(const char >> *value) { >> return ok; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr size) { >> + uptr num_symbols_should_write =3D internal_snprintf(buffer, size, >> "%d", *t_); >> + return num_symbols_should_write < size; >> +} >> + >> template <> >> inline bool FlagHandler::Parse(const char *value) { >> const char *value_end; >> @@ -99,6 +136,12 @@ inline bool FlagHandler::Parse(const char >> *value) { >> return ok; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr size) { >> + uptr num_symbols_should_write =3D internal_snprintf(buffer, size, >> "%p", *t_); >> + return num_symbols_should_write < size; >> +} >> + >> template <> >> inline bool FlagHandler::Parse(const char *value) { >> const char *value_end; >> @@ -108,6 +151,12 @@ inline bool FlagHandler::Parse(const char >> *value) { >> return ok; >> } >> >> +template <> >> +inline bool FlagHandler::Format(char *buffer, uptr size) { >> + uptr num_symbols_should_write =3D internal_snprintf(buffer, size, >> "%lld", *t_); >> + return num_symbols_should_write < size; >> +} >> + >> class FlagParser { >> static const int kMaxFlags =3D 200; >> struct Flag { >> diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cpp >> b/libsanitizer/sanitizer_common/sanitizer_flags.cpp >> index 66a0a5579ed..684ee1e0b99 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_flags.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_flags.cpp >> @@ -75,11 +75,13 @@ void SubstituteForFlagValue(const char *s, char >> *out, uptr out_size) { >> class FlagHandlerInclude : public FlagHandlerBase { >> FlagParser *parser_; >> bool ignore_missing_; >> + const char *original_path_; >> >> public: >> explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) >> - : parser_(parser), ignore_missing_(ignore_missing) {} >> + : parser_(parser), ignore_missing_(ignore_missing), >> original_path_("") {} >> bool Parse(const char *value) final { >> + original_path_ =3D value; >> if (internal_strchr(value, '%')) { >> char *buf =3D (char *)MmapOrDie(kMaxPathLength, >> "FlagHandlerInclude"); >> SubstituteForFlagValue(value, buf, kMaxPathLength); >> @@ -89,6 +91,12 @@ class FlagHandlerInclude : public FlagHandlerBase { >> } >> return parser_->ParseFile(value, ignore_missing_); >> } >> + bool Format(char *buffer, uptr size) { >> + // Note `original_path_` isn't actually what's parsed due to `%` >> + // substitutions. Printing the substituted path would require >> holding onto >> + // mmap'ed memory. >> + return FormatString(buffer, size, original_path_); >> + } >> }; >> >> void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { >> diff --git a/libsanitizer/sanitizer_common/sanitizer_freebsd.h >> b/libsanitizer/sanitizer_common/sanitizer_freebsd.h >> index 64cb21f1c3d..82b227eab6d 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_freebsd.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_freebsd.h >> @@ -19,11 +19,11 @@ >> // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in >> // 32-bit mode. >> #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE =3D=3D 32) >> -# include >> -# if __FreeBSD_version <=3D 902001 // v9.2 >> -# include >> -# include >> -# include >> +#include >> +#if __FreeBSD_version <=3D 902001 // v9.2 >> +#include >> +#include >> +#include >> >> namespace __sanitizer { >> >> @@ -68,8 +68,8 @@ typedef struct __xmcontext { >> } xmcontext_t; >> >> typedef struct __xucontext { >> - sigset_t uc_sigmask; >> - xmcontext_t uc_mcontext; >> + sigset_t uc_sigmask; >> + xmcontext_t uc_mcontext; >> >> struct __ucontext *uc_link; >> stack_t uc_stack; >> @@ -122,15 +122,16 @@ struct xdl_phdr_info { >> void *dlpi_tls_data; >> }; >> >> -typedef int (*__xdl_iterate_hdr_callback)(struct xdl_phdr_info*, >> size_t, void*); >> -typedef int xdl_iterate_phdr_t(__xdl_iterate_hdr_callback, void*); >> +typedef int (*__xdl_iterate_hdr_callback)(struct xdl_phdr_info *, >> size_t, >> + void *); >> +typedef int xdl_iterate_phdr_t(__xdl_iterate_hdr_callback, void *); >> >> #define xdl_iterate_phdr(callback, param) \ >> - (((xdl_iterate_phdr_t*) dl_iterate_phdr)((callback), (param))) >> + (((xdl_iterate_phdr_t *)dl_iterate_phdr)((callback), (param))) >> >> }=A0 // namespace __sanitizer >> >> -# endif // __FreeBSD_version <=3D 902001 >> +#endif // __FreeBSD_version <=3D 902001 >> #endif // SANITIZER_FREEBSD && (SANITIZER_WORDSIZE =3D=3D 32) >> >> #endif // SANITIZER_FREEBSD_H >> diff --git a/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp >> b/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp >> index 6e2c6137f0c..6d1ad794677 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_fuchsia.cpp >> @@ -66,6 +66,10 @@ uptr internal_getpid() { >> return pid; >> } >> >> +int internal_dlinfo(void *handle, int request, void *p) { >> + UNIMPLEMENTED(); >> +} >> + >> uptr GetThreadSelf() { return >> reinterpret_cast(thrd_current()); } >> >> tid_t GetTid() { return GetThreadSelf(); } >> diff --git a/libsanitizer/sanitizer_common/sanitizer_fuchsia.h >> b/libsanitizer/sanitizer_common/sanitizer_fuchsia.h >> index 5a2ad32b411..96f9cde7ef1 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_fuchsia.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_fuchsia.h >> @@ -18,12 +18,18 @@ >> #include "sanitizer_common.h" >> >> #include >> +#include >> >> namespace __sanitizer { >> >> extern uptr MainThreadStackBase, MainThreadStackSize; >> extern sanitizer_shadow_bounds_t ShadowBounds; >> >> +struct MemoryMappingLayoutData { >> + InternalMmapVector data; >> + size_t current; // Current index into the vector. >> +}; >> + >> }=A0 // namespace __sanitizer >> >> #endif // SANITIZER_FUCHSIA >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc >> b/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc >> index 03ef7c1788c..576807ea3a6 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc >> @@ -24,7 +24,7 @@ struct ioctl_desc { >> const char *name; >> }; >> >> -const unsigned ioctl_table_max =3D 1236; >> +const unsigned ioctl_table_max =3D 1238; >> static ioctl_desc ioctl_table[ioctl_table_max]; >> static unsigned ioctl_table_size =3D 0; >> >> @@ -166,9 +166,6 @@ static void ioctl_table_fill() { >> _(FE_ENABLE_HIGH_LNB_VOLTAGE, READ, sizeof(int)); >> _(FE_SET_FRONTEND_TUNE_MODE, READ, sizeof(unsigned int)); >> _(FE_DISHNETWORK_SEND_LEGACY_CMD, READ, sizeof(unsigned long)); >> - /* Entries from file: dev/filemon/filemon.h */ >> - _(FILEMON_SET_FD, READWRITE, sizeof(int)); >> - _(FILEMON_SET_PID, READWRITE, sizeof(int)); >> /* Entries from file: dev/hdaudio/hdaudioio.h */ >> _(HDAUDIO_FGRP_INFO, READWRITE, struct_plistref_sz); >> _(HDAUDIO_FGRP_GETCONFIG, READWRITE, struct_plistref_sz); >> @@ -449,9 +446,6 @@ static void ioctl_table_fill() { >> _(STICIO_STOPQ, NONE, 0); >> /* Entries from file: dev/usb/ukyopon.h */ >> _(UKYOPON_IDENTIFY, WRITE, struct_ukyopon_identify_sz); >> - /* Entries from file: dev/usb/urio.h */ >> - _(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz); >> - _(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz); >> /* Entries from file: dev/usb/usb.h */ >> _(USB_REQUEST, READWRITE, struct_usb_ctl_request_sz); >> _(USB_SETDEBUG, READ, sizeof(int)); >> @@ -653,6 +647,7 @@ static void ioctl_table_fill() { >> _(NVMM_IOC_MACHINE_CONFIGURE, READ, >> struct_nvmm_ioc_machine_configure_sz); >> _(NVMM_IOC_VCPU_CREATE, READ, struct_nvmm_ioc_vcpu_create_sz); >> _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz); >> + _(NVMM_IOC_VCPU_CONFIGURE, READ, struct_nvmm_ioc_vcpu_configure_sz); >> _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz); >> _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz); >> _(NVMM_IOC_VCPU_INJECT, READ, struct_nvmm_ioc_vcpu_inject_sz); >> @@ -735,6 +730,7 @@ static void ioctl_table_fill() { >> _(IOC_NPF_SAVE, WRITE, struct_nvlist_ref_sz); >> _(IOC_NPF_RULE, READWRITE, struct_nvlist_ref_sz); >> _(IOC_NPF_CONN_LOOKUP, READWRITE, struct_nvlist_ref_sz); >> + _(IOC_NPF_TABLE_REPLACE, READWRITE, struct_nvlist_ref_sz); >> /* Entries from file: net/if_pppoe.h */ >> _(PPPOESETPARMS, READ, struct_pppoediscparms_sz); >> _(PPPOEGETPARMS, READWRITE, struct_pppoediscparms_sz); >> @@ -1403,8 +1399,14 @@ static void ioctl_table_fill() { >> _(SNDCTL_DSP_SETRECVOL, READ, sizeof(unsigned int)); >> _(SNDCTL_DSP_SKIP, NONE, 0); >> _(SNDCTL_DSP_SILENCE, NONE, 0); >> + /* Entries from file: dev/filemon/filemon.h (compat <=3D 9.99.26) */ >> + _(FILEMON_SET_FD, READWRITE, sizeof(int)); >> + _(FILEMON_SET_PID, READWRITE, sizeof(int)); >> + /* Entries from file: dev/usb/urio.h (compat <=3D 9.99.43) */ >> + _(URIO_SEND_COMMAND, READWRITE, struct_urio_command_sz); >> + _(URIO_RECV_COMMAND, READWRITE, struct_urio_command_sz); >> #undef _ >> -}=A0 // NOLINT >> +} // NOLINT >> >> static bool ioctl_initialized =3D false; >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h >> b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h >> index c110eff130f..be8023e9e16 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_interface_internal.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_interface_internal.h >> @@ -109,8 +109,10 @@ extern "C" { >> __sanitizer::u32*); >> SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE >> void __sanitizer_cov_8bit_counters_init(); >> - SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE >> - void __sanitizer_cov_pcs_init(); >> + SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void >> + __sanitizer_cov_bool_flag_init(); >> + SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void >> + __sanitizer_cov_pcs_init(); >> } // extern "C" >> >> #endif // SANITIZER_INTERFACE_INTERNAL_H >> diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h >> b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h >> index 00226305e07..d0ffc79b061 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h >> @@ -105,7 +105,7 @@ >> // FIXME: do we have anything like this on Mac? >> #ifndef SANITIZER_CAN_USE_PREINIT_ARRAY >> #if ((SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_OPENBSD || \ >> - SANITIZER_FUCHSIA) && !defined(PIC) >> + SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC) >> #define SANITIZER_CAN_USE_PREINIT_ARRAY 1 >> // Before Solaris 11.4, .preinit_array is fully supported only with >> GNU ld. >> // FIXME: Check for those conditions. >> diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h >> b/libsanitizer/sanitizer_common/sanitizer_libc.h >> index 3d5db35d68b..ec0a6ded009 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_libc.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_libc.h >> @@ -72,6 +72,8 @@ unsigned int internal_sleep(unsigned int seconds); >> uptr internal_getpid(); >> uptr internal_getppid(); >> >> +int internal_dlinfo(void *handle, int request, void *p); >> + >> // Threading >> uptr internal_sched_yield(); >> >> diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cpp >> b/libsanitizer/sanitizer_common/sanitizer_linux.cpp >> index 3807a79b1cd..2168301fd69 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_linux.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cpp >> @@ -26,7 +26,7 @@ >> #include "sanitizer_placement_new.h" >> #include "sanitizer_procmaps.h" >> >> -#if SANITIZER_LINUX >> +#if SANITIZER_LINUX && !SANITIZER_GO >> #include >> #endif >> >> @@ -166,7 +166,7 @@ namespace __sanitizer { >> #if !SANITIZER_SOLARIS && !SANITIZER_NETBSD >> #if !SANITIZER_S390 && !SANITIZER_OPENBSD >> uptr internal_mmap(void *addr, uptr length, int prot, int flags, >> int fd, >> - OFF_T offset) { >> + u64 offset) { >> #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS >> return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, >> flags, fd, >> offset); >> @@ -552,13 +552,14 @@ const char *GetEnv(const char *name) { >> #endif >> } >> >> -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD >> +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD && !SANITIZER_OPENBSD && \ >> + !SANITIZER_GO >> extern "C" { >> SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; >> } >> #endif >> >> -#if !SANITIZER_GO && !SANITIZER_FREEBSD && !SANITIZER_NETBSD >> &&=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 \ >> +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD &&=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 \ >> !SANITIZER_OPENBSD >> static void ReadNullSepFileToArray(const char *path, char ***arr, >> int arr_size) { >> @@ -604,16 +605,21 @@ static void GetArgsAndEnv(char ***argv, char >> ***envp) { >> #else // SANITIZER_FREEBSD >> #if !SANITIZER_GO >> if (&__libc_stack_end) { >> -#endif // !SANITIZER_GO >> uptr* stack_end =3D (uptr*)__libc_stack_end; >> - int argc =3D *stack_end; >> + // Normally argc can be obtained from *stack_end, however, on >> ARM glibc's >> + // _start clobbers it: >> + // >> https://sourceware.org/git/?p=3Dglibc.git;a=3Dblob;f=3Dsysdeps/arm/start= .S;hb=3Drefs/heads/release/2.31/master#l75 >> + // Do not special-case ARM and infer argc from argv everywhere. >> + int argc =3D 0; >> + while (stack_end[argc + 1]) argc++; >> *argv =3D (char**)(stack_end + 1); >> *envp =3D (char**)(stack_end + argc + 2); >> -#if !SANITIZER_GO >> } else { >> +#endif // !SANITIZER_GO >> static const int kMaxArgv =3D 2000, kMaxEnvp =3D 2000; >> ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); >> ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); >> +#if !SANITIZER_GO >> } >> #endif // !SANITIZER_GO >> #endif // SANITIZER_FREEBSD >> @@ -735,6 +741,14 @@ uptr internal_getppid() { >> return internal_syscall(SYSCALL(getppid)); >> } >> >> +int internal_dlinfo(void *handle, int request, void *p) { >> +#if SANITIZER_FREEBSD >> + return dlinfo(handle, request, p); >> +#else >> + UNIMPLEMENTED(); >> +#endif >> +} >> + >> uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned >> int count) { >> #if SANITIZER_FREEBSD >> return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, >> count, NULL); >> @@ -1006,9 +1020,8 @@ static uptr GetKernelAreaSize() { >> // is modified (e.g. under schroot) so check this as well. >> struct utsname uname_info; >> int pers =3D personality(0xffffffffUL); >> - if (!(pers & PER_MASK) >> - && uname(&uname_info) =3D=3D 0 >> - && internal_strstr(uname_info.machine, "64")) >> + if (!(pers & PER_MASK) && internal_uname(&uname_info) =3D=3D 0 && >> + internal_strstr(uname_info.machine, "64")) >> return 0; >> #endif // SANITIZER_ANDROID >> >> @@ -1063,7 +1076,8 @@ uptr GetMaxUserVirtualAddress() { >> >> #if !SANITIZER_ANDROID >> uptr GetPageSize() { >> -#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) >> +#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__)) && \ >> + defined(EXEC_PAGESIZE) >> return EXEC_PAGESIZE; >> #elif SANITIZER_FREEBSD || SANITIZER_NETBSD >> // Use sysctl as sysconf can trigger interceptors internally. >> @@ -1619,6 +1633,12 @@ uptr internal_clone(int (*fn)(void *), void >> *child_stack, int flags, void *arg, >> } >> #endif // defined(__x86_64__) && SANITIZER_LINUX >> >> +#if SANITIZER_LINUX >> +int internal_uname(struct utsname *buf) { >> + return internal_syscall(SYSCALL(uname), buf); >> +} >> +#endif >> + >> #if SANITIZER_ANDROID >> #if __ANDROID_API__ < 21 >> extern "C" __attribute__((weak)) int dl_iterate_phdr( >> @@ -1701,7 +1721,7 @@ HandleSignalMode GetHandleSignalMode(int signum) { >> } >> >> #if !SANITIZER_GO >> -void *internal_start_thread(void(*func)(void *arg), void *arg) { >> +void *internal_start_thread(void *(*func)(void *arg), void *arg) { >> // Start the thread with signals blocked, otherwise it can steal >> user signals. >> __sanitizer_sigset_t set, old; >> internal_sigfillset(&set); >> @@ -1712,7 +1732,7 @@ void *internal_start_thread(void(*func)(void >> *arg), void *arg) { >> #endif >> internal_sigprocmask(SIG_SETMASK, &set, &old); >> void *th; >> - real_pthread_create(&th, nullptr, (void*(*)(void *arg))func, arg); >> + real_pthread_create(&th, nullptr, func, arg); >> internal_sigprocmask(SIG_SETMASK, &old, nullptr); >> return th; >> } >> @@ -1721,7 +1741,7 @@ void internal_join_thread(void *th) { >> real_pthread_join(th, nullptr); >> } >> #else >> -void *internal_start_thread(void (*func)(void *), void *arg) { >> return 0; } >> +void *internal_start_thread(void *(*func)(void *), void *arg) { >> return 0; } >> >> void internal_join_thread(void *th) {} >> #endif >> @@ -1846,6 +1866,105 @@ SignalContext::WriteFlag >> SignalContext::GetWriteFlag() const { >> #endif >> u32 instr =3D *(u32 *)pc; >> return (instr >> 21) & 1 ? WRITE: READ; >> +#elif defined(__riscv) >> + unsigned long pc =3D ucontext->uc_mcontext.__gregs[REG_PC]; >> + unsigned faulty_instruction =3D *(uint16_t *)pc; >> + >> +#if defined(__riscv_compressed) >> + if ((faulty_instruction & 0x3) !=3D 0x3) {=A0 // it's a compressed >> instruction >> + // set op_bits to the instruction bits [1, 0, 15, 14, 13] >> + unsigned op_bits =3D >> + ((faulty_instruction & 0x3) << 3) | (faulty_instruction >> 13); >> + unsigned rd =3D faulty_instruction & 0xF80; // bits 7-11, inclusiv= e >> + switch (op_bits) { >> + case 0b10'010: // c.lwsp (rd !=3D x0) >> +#if __riscv_xlen =3D=3D 64 >> + case 0b10'011: // c.ldsp (rd !=3D x0) >> +#endif >> + return rd ? SignalContext::READ : SignalContext::UNKNOWN; >> + case 0b00'010: // c.lw >> +#if __riscv_flen >=3D 32 && __riscv_xlen =3D=3D 32 >> + case 0b10'011: // c.flwsp >> +#endif >> +#if __riscv_flen >=3D 32 || __riscv_xlen =3D=3D 64 >> + case 0b00'011: // c.flw / c.ld >> +#endif >> +#if __riscv_flen =3D=3D 64 >> + case 0b00'001: // c.fld >> + case 0b10'001: // c.fldsp >> +#endif >> + return SignalContext::READ; >> + case 0b00'110: // c.sw >> + case 0b10'110: // c.swsp >> +#if __riscv_flen >=3D 32 || __riscv_xlen =3D=3D 64 >> + case 0b00'111: // c.fsw / c.sd >> + case 0b10'111: // c.fswsp / c.sdsp >> +#endif >> +#if __riscv_flen =3D=3D 64 >> + case 0b00'101: // c.fsd >> + case 0b10'101: // c.fsdsp >> +#endif >> + return SignalContext::WRITE; >> + default: >> + return SignalContext::UNKNOWN; >> + } >> + } >> +#endif >> + >> + unsigned opcode =3D faulty_instruction & 0x7f; // lower 7 bit= s >> + unsigned funct3 =3D (faulty_instruction >> 12) & 0x7; // bits >> 12-14, inclusive >> + switch (opcode) { >> + case 0b0000011: // loads >> + switch (funct3) { >> + case 0b000: // lb >> + case 0b001: // lh >> + case 0b010: // lw >> +#if __riscv_xlen =3D=3D 64 >> + case 0b011: // ld >> +#endif >> + case 0b100: // lbu >> + case 0b101: // lhu >> + return SignalContext::READ; >> + default: >> + return SignalContext::UNKNOWN; >> + } >> + case 0b0100011: // stores >> + switch (funct3) { >> + case 0b000: // sb >> + case 0b001: // sh >> + case 0b010: // sw >> +#if __riscv_xlen =3D=3D 64 >> + case 0b011: // sd >> +#endif >> + return SignalContext::WRITE; >> + default: >> + return SignalContext::UNKNOWN; >> + } >> +#if __riscv_flen >=3D 32 >> + case 0b0000111: // floating-point loads >> + switch (funct3) { >> + case 0b010: // flw >> +#if __riscv_flen =3D=3D 64 >> + case 0b011: // fld >> +#endif >> + return SignalContext::READ; >> + default: >> + return SignalContext::UNKNOWN; >> + } >> + case 0b0100111: // floating-point stores >> + switch (funct3) { >> + case 0b010: // fsw >> +#if __riscv_flen =3D=3D 64 >> + case 0b011: // fsd >> +#endif >> + return SignalContext::WRITE; >> + default: >> + return SignalContext::UNKNOWN; >> + } >> +#endif >> + default: >> + return SignalContext::UNKNOWN; >> + } >> #else >> (void)ucontext; >> return UNKNOWN; // FIXME: Implement. >> @@ -2011,7 +2130,9 @@ void CheckASLR() { >> } >> >> if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)) { >> - Printf("This sanitizer is not compatible with enabled ASLR\n"); >> + Printf("This sanitizer is not compatible with enabled ASLR.\n" >> + "To disable ASLR, please run \"paxctl +a %s\" and try >> again.\n", >> + GetArgv()[0]); >> Die(); >> } >> #elif SANITIZER_PPC64V2 >> diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h >> b/libsanitizer/sanitizer_common/sanitizer_linux.h >> index c28347ad963..c162d1ca5d2 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_linux.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_linux.h >> @@ -25,6 +25,7 @@ >> #include "sanitizer_posix.h" >> >> struct link_map; // Opaque type returned by dlopen(). >> +struct utsname; >> >> namespace __sanitizer { >> // Dirent structure for getdents(). Note that this structure is >> different from >> @@ -65,6 +66,7 @@ void internal_sigdelset(__sanitizer_sigset_t *set, >> int signum); >> uptr internal_clone(int (*fn)(void *), void *child_stack, int >> flags, void *arg, >> int *parent_tidptr, void *newtls, int >> *child_tidptr); >> #endif >> +int internal_uname(struct utsname *buf); >> #elif SANITIZER_FREEBSD >> void internal_sigdelset(__sanitizer_sigset_t *set, int signum); >> #elif SANITIZER_NETBSD >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp >> b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp >> index e09d568d802..4d17c9686e4 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp >> @@ -35,6 +35,10 @@ >> #include >> #include >> >> +#if !defined(ElfW) >> +#define ElfW(type) Elf_##type >> +#endif >> + >> #if SANITIZER_FREEBSD >> #include >> #include >> @@ -50,6 +54,7 @@ >> #if SANITIZER_NETBSD >> #include >> #include >> +#include >> #endif >> >> #if SANITIZER_SOLARIS >> @@ -399,13 +404,7 @@ uptr ThreadSelf() { >> >> #if SANITIZER_NETBSD >> static struct tls_tcb * ThreadSelfTlsTcb() { >> - struct tls_tcb * tcb; >> -# ifdef __HAVE___LWP_GETTCB_FAST >> - tcb =3D (struct tls_tcb *)__lwp_gettcb_fast(); >> -# elif defined(__HAVE___LWP_GETPRIVATE_FAST) >> - tcb =3D (struct tls_tcb *)__lwp_getprivate_fast(); >> -# endif >> - return tcb; >> + return (struct tls_tcb *)_lwp_getprivate(); >> } >> >> uptr ThreadSelf() { >> @@ -698,13 +697,9 @@ u32 GetNumberOfCPUs() { >> #elif SANITIZER_SOLARIS >> return sysconf(_SC_NPROCESSORS_ONLN); >> #else >> -#if defined(CPU_COUNT) >> cpu_set_t CPUs; >> CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); >> return CPU_COUNT(&CPUs); >> -#else >> - return 1; >> -#endif >> #endif >> } >> >> diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cpp >> b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cpp >> index 41e187eaf8d..bb2f5b5f9f7 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_linux_s390.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_linux_s390.cpp >> @@ -15,19 +15,20 @@ >> >> #if SANITIZER_LINUX && SANITIZER_S390 >> >> -#include "sanitizer_libc.h" >> -#include "sanitizer_linux.h" >> - >> +#include >> #include >> #include >> #include >> #include >> >> +#include "sanitizer_libc.h" >> +#include "sanitizer_linux.h" >> + >> namespace __sanitizer { >> >> // --------------- sanitizer_libc.h >> uptr internal_mmap(void *addr, uptr length, int prot, int flags, >> int fd, >> - OFF_T offset) { >> + u64 offset) { >> struct s390_mmap_params { >> unsigned long addr; >> unsigned long length; >> @@ -123,7 +124,7 @@ static bool FixedCVE_2016_2143() { >> struct utsname buf; >> unsigned int major, minor, patch =3D 0; >> // This should never fail, but just in case... >> - if (uname(&buf)) >> + if (internal_uname(&buf)) >> return false; >> const char *ptr =3D buf.release; >> major =3D internal_simple_strtoll(ptr, &ptr, 10); >> diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cpp >> b/libsanitizer/sanitizer_common/sanitizer_mac.cpp >> index b971ad058e9..7550545ea6f 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_mac.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cpp >> @@ -30,6 +30,7 @@ >> #include "sanitizer_placement_new.h" >> #include "sanitizer_platform_limits_posix.h" >> #include "sanitizer_procmaps.h" >> +#include "sanitizer_ptrauth.h" >> >> #if !SANITIZER_IOS >> #include =A0 // for _NSGetEnviron >> @@ -37,7 +38,7 @@ >> extern char **environ; >> #endif >> >> -#if defined(__has_include) && __has_include() && >> defined(__BLOCKS__) >> +#if defined(__has_include) && __has_include() >> #define SANITIZER_OS_TRACE 1 >> #include >> #else >> @@ -208,6 +209,10 @@ uptr internal_getpid() { >> return getpid(); >> } >> >> +int internal_dlinfo(void *handle, int request, void *p) { >> + UNIMPLEMENTED(); >> +} >> + >> int internal_sigaction(int signum, const void *act, void *oldact) { >> return sigaction(signum, >> (const struct sigaction *)act, (struct sigaction >> *)oldact); >> @@ -242,7 +247,8 @@ int internal_sysctlbyname(const char *sname, void >> *oldp, uptr *oldlenp, >> (size_t)newlen); >> } >> >> -static fd_t internal_spawn_impl(const char *argv[], pid_t *pid) { >> +static fd_t internal_spawn_impl(const char *argv[], const char *envp[], >> + pid_t *pid) { >> fd_t master_fd =3D kInvalidFd; >> fd_t slave_fd =3D kInvalidFd; >> >> @@ -298,8 +304,8 @@ static fd_t internal_spawn_impl(const char >> *argv[], pid_t *pid) { >> >> // posix_spawn >> char **argv_casted =3D const_cast(argv); >> - char **env =3D GetEnviron(); >> - res =3D posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, env); >> + char **envp_casted =3D const_cast(envp); >> + res =3D posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, >> envp_casted); >> if (res !=3D 0) return kInvalidFd; >> >> // Disable echo in the new terminal, disable CR. >> @@ -316,7 +322,7 @@ static fd_t internal_spawn_impl(const char >> *argv[], pid_t *pid) { >> return fd; >> } >> >> -fd_t internal_spawn(const char *argv[], pid_t *pid) { >> +fd_t internal_spawn(const char *argv[], const char *envp[], pid_t >> *pid) { >> // The client program may close its stdin and/or stdout and/or >> stderr thus >> // allowing open/posix_openpt to reuse file descriptors 0, 1 or >> 2. In this >> // case the communication is broken if either the parent or the >> child tries to >> @@ -331,7 +337,7 @@ fd_t internal_spawn(const char *argv[], pid_t >> *pid) { >> break; >> } >> >> - fd_t fd =3D internal_spawn_impl(argv, pid); >> + fd_t fd =3D internal_spawn_impl(argv, envp, pid); >> >> for (; count > 0; count--) { >> internal_close(low_fds[count]); >> @@ -623,19 +629,13 @@ MacosVersion GetMacosVersionInternal() { >> if (*p !=3D '.') return MACOS_VERSION_UNKNOWN; >> >> switch (major) { >> - case 9: return MACOS_VERSION_LEOPARD; >> - case 10: return MACOS_VERSION_SNOW_LEOPARD; >> case 11: return MACOS_VERSION_LION; >> case 12: return MACOS_VERSION_MOUNTAIN_LION; >> case 13: return MACOS_VERSION_MAVERICKS; >> case 14: return MACOS_VERSION_YOSEMITE; >> case 15: return MACOS_VERSION_EL_CAPITAN; >> case 16: return MACOS_VERSION_SIERRA; >> - case 17: >> - // Not a typo, 17.5 Darwin Kernel Version maps to High Sierra >> 10.13.4. >> - if (minor >=3D 5) >> - return MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; >> - return MACOS_VERSION_HIGH_SIERRA; >> + case 17: return MACOS_VERSION_HIGH_SIERRA; >> case 18: return MACOS_VERSION_MOJAVE; >> case 19: return MACOS_VERSION_CATALINA; >> default: >> @@ -656,13 +656,21 @@ MacosVersion GetMacosVersion() { >> return result; >> } >> >> -bool PlatformHasDifferentMemcpyAndMemmove() { >> - // On OS X 10.7 memcpy() and memmove() are both resolved >> - // into memmove$VARIANT$sse42. >> - // See also https://github.com/google/sanitizers/issues/34. >> - // TODO(glider): need to check dynamically that memcpy() and >> memmove() are >> - // actually the same function. >> - return GetMacosVersion() =3D=3D MACOS_VERSION_SNOW_LEOPARD; >> +DarwinKernelVersion GetDarwinKernelVersion() { >> + char buf[100]; >> + size_t len =3D sizeof(buf); >> + int res =3D internal_sysctlbyname("kern.osrelease", buf, &len, >> nullptr, 0); >> + CHECK_EQ(res, 0); >> + >> + // Format: ..\0 >> + CHECK_GE(len, 6); >> + const char *p =3D buf; >> + u16 major =3D internal_simple_strtoll(p, &p, /*base=3D*/10); >> + CHECK_EQ(*p, '.'); >> + p +=3D 1; >> + u16 minor =3D internal_simple_strtoll(p, &p, /*base=3D*/10); >> + >> + return DarwinKernelVersion(major, minor); >> } >> >> uptr GetRSS() { >> @@ -677,13 +685,13 @@ uptr GetRSS() { >> return info.resident_size; >> } >> >> -void *internal_start_thread(void(*func)(void *arg), void *arg) { >> +void *internal_start_thread(void *(*func)(void *arg), void *arg) { >> // Start the thread with signals blocked, otherwise it can steal >> user signals. >> __sanitizer_sigset_t set, old; >> internal_sigfillset(&set); >> internal_sigprocmask(SIG_SETMASK, &set, &old); >> pthread_t th; >> - pthread_create(&th, 0, (void*(*)(void *arg))func, arg); >> + pthread_create(&th, 0, func, arg); >> internal_sigprocmask(SIG_SETMASK, &old, 0); >> return th; >> } >> @@ -760,16 +768,24 @@ bool SignalContext::IsTrueFaultingAddress() >> const { >> return si->si_signo =3D=3D SIGSEGV && si->si_code !=3D 0; >> } >> >> +#if defined(__aarch64__) && defined(arm_thread_state64_get_sp) >> + #define AARCH64_GET_REG(r) \ >> + (uptr)ptrauth_strip( \ >> + (void >> *)arm_thread_state64_get_##r(ucontext->uc_mcontext->__ss), 0) >> +#else >> + #define AARCH64_GET_REG(r) ucontext->uc_mcontext->__ss.__##r >> +#endif >> + >> static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { >> ucontext_t *ucontext =3D (ucontext_t*)context; >> # if defined(__aarch64__) >> - *pc =3D ucontext->uc_mcontext->__ss.__pc; >> + *pc =3D AARCH64_GET_REG(pc); >> # if defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=3D >> __IPHONE_8_0 >> - *bp =3D ucontext->uc_mcontext->__ss.__fp; >> + *bp =3D AARCH64_GET_REG(fp); >> # else >> - *bp =3D ucontext->uc_mcontext->__ss.__lr; >> + *bp =3D AARCH64_GET_REG(lr); >> # endif >> - *sp =3D ucontext->uc_mcontext->__ss.__sp; >> + *sp =3D AARCH64_GET_REG(sp); >> # elif defined(__x86_64__) >> *pc =3D ucontext->uc_mcontext->__ss.__rip; >> *bp =3D ucontext->uc_mcontext->__ss.__rbp; >> @@ -787,13 +803,16 @@ static void GetPcSpBp(void *context, uptr *pc, >> uptr *sp, uptr *bp) { >> # endif >> } >> >> -void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } >> +void SignalContext::InitPcSpBp() { >> + addr =3D (uptr)ptrauth_strip((void *)addr, 0); >> + GetPcSpBp(context, &pc, &sp, &bp); >> +} >> >> void InitializePlatformEarly() { >> - // Only use xnu_fast_mmap when on x86_64 and the OS supports it. >> + // Only use xnu_fast_mmap when on x86_64 and the kernel supports it. >> use_xnu_fast_mmap =3D >> #if defined(__x86_64__) >> - GetMacosVersion() >=3D MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4; >> + GetDarwinKernelVersion() >=3D DarwinKernelVersion(17, 5); >> #else >> false; >> #endif >> @@ -1123,6 +1142,8 @@ void SignalContext::DumpAllRegisters(void >> *context) { >> ucontext_t *ucontext =3D (ucontext_t*)context; >> # define DUMPREG64(r) \ >> Printf("%s =3D 0x%016llx ", #r, ucontext->uc_mcontext->__ss.__ >> ## r); >> +# define DUMPREGA64(r) \ >> + Printf("=A0=A0 %s =3D 0x%016llx ", #r, AARCH64_GET_REG(r)); >> # define DUMPREG32(r) \ >> Printf("%s =3D 0x%08x ", #r, ucontext->uc_mcontext->__ss.__ ## r)= ; >> # define DUMPREG_(r) Printf(" "); DUMPREG(r); >> @@ -1148,7 +1169,7 @@ void SignalContext::DumpAllRegisters(void >> *context) { >> DUMPREG(x[16]); DUMPREG(x[17]); DUMPREG(x[18]); DUMPREG(x[19]); >> Printf("\n"); >> DUMPREG(x[20]); DUMPREG(x[21]); DUMPREG(x[22]); DUMPREG(x[23]); >> Printf("\n"); >> DUMPREG(x[24]); DUMPREG(x[25]); DUMPREG(x[26]); DUMPREG(x[27]); >> Printf("\n"); >> - DUMPREG(x[28]); DUMPREG___(fp); DUMPREG___(lr); DUMPREG___(sp); >> Printf("\n"); >> + DUMPREG(x[28]); DUMPREGA64(fp); DUMPREGA64(lr); DUMPREGA64(sp); >> Printf("\n"); >> # elif defined(__arm__) >> # define DUMPREG(r) DUMPREG32(r) >> DUMPREG_(r[0]); DUMPREG_(r[1]); DUMPREG_(r[2]); DUMPREG_(r[3]); >> Printf("\n"); >> diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.h >> b/libsanitizer/sanitizer_common/sanitizer_mac.h >> index 2257883084e..34dc2c05dcf 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_mac.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_mac.h >> @@ -33,22 +33,35 @@ struct MemoryMappingLayoutData { >> enum MacosVersion { >> MACOS_VERSION_UNINITIALIZED =3D 0, >> MACOS_VERSION_UNKNOWN, >> - MACOS_VERSION_LEOPARD, >> - MACOS_VERSION_SNOW_LEOPARD, >> - MACOS_VERSION_LION, >> + MACOS_VERSION_LION, // macOS 10.7; oldest currently supported >> MACOS_VERSION_MOUNTAIN_LION, >> MACOS_VERSION_MAVERICKS, >> MACOS_VERSION_YOSEMITE, >> MACOS_VERSION_EL_CAPITAN, >> MACOS_VERSION_SIERRA, >> MACOS_VERSION_HIGH_SIERRA, >> - MACOS_VERSION_HIGH_SIERRA_DOT_RELEASE_4, >> MACOS_VERSION_MOJAVE, >> MACOS_VERSION_CATALINA, >> MACOS_VERSION_UNKNOWN_NEWER >> }; >> >> +struct DarwinKernelVersion { >> + u16 major; >> + u16 minor; >> + >> + DarwinKernelVersion(u16 major, u16 minor) : major(major), >> minor(minor) {} >> + >> + bool operator=3D=3D(const DarwinKernelVersion &other) const { >> + return major =3D=3D other.major && minor =3D=3D other.minor; >> + } >> + bool operator>=3D(const DarwinKernelVersion &other) const { >> + return major >=3D other.major || >> + (major =3D=3D other.major && minor >=3D other.minor); >> + } >> +}; >> + >> MacosVersion GetMacosVersion(); >> +DarwinKernelVersion GetDarwinKernelVersion(); >> >> char **GetEnviron(); >> >> diff --git a/libsanitizer/sanitizer_common/sanitizer_malloc_mac.inc >> b/libsanitizer/sanitizer_common/sanitizer_malloc_mac.inc >> index 11adbe5c25b..647bcdfe105 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_malloc_mac.inc >> +++ b/libsanitizer/sanitizer_common/sanitizer_malloc_mac.inc >> @@ -61,12 +61,10 @@ INTERCEPTOR(malloc_zone_t *, malloc_create_zone, >> malloc_zone_t *new_zone =3D (malloc_zone_t *)p; >> internal_memcpy(new_zone, &sanitizer_zone, sizeof(sanitizer_zone)); >> new_zone->zone_name =3D NULL; // The name will be changed anyway. >> - if (GetMacosVersion() >=3D MACOS_VERSION_LION) { >> - // Prevent the client app from overwriting the zone contents. >> - // Library functions that need to modify the zone will set >> PROT_WRITE on it. >> - // This matches the behavior of malloc_create_zone() on OSX 10.7 >> and higher. >> - mprotect(new_zone, allocated_size, PROT_READ); >> - } >> + // Prevent the client app from overwriting the zone contents. >> + // Library functions that need to modify the zone will set >> PROT_WRITE on it. >> + // This matches the behavior of malloc_create_zone() on OSX 10.7 >> and higher. >> + mprotect(new_zone, allocated_size, PROT_READ); >> // We're explicitly *NOT* registering the zone. >> return new_zone; >> } >> @@ -75,11 +73,9 @@ INTERCEPTOR(void, malloc_destroy_zone, >> malloc_zone_t *zone) { >> COMMON_MALLOC_ENTER(); >> // We don't need to do anything here. We're not registering new >> zones, so we >> // don't to unregister. Just un-mprotect and free() the zone. >> - if (GetMacosVersion() >=3D MACOS_VERSION_LION) { >> - uptr page_size =3D GetPageSizeCached(); >> - uptr allocated_size =3D RoundUpTo(sizeof(sanitizer_zone), page_size= ); >> - mprotect(zone, allocated_size, PROT_READ | PROT_WRITE); >> - } >> + uptr page_size =3D GetPageSizeCached(); >> + uptr allocated_size =3D RoundUpTo(sizeof(sanitizer_zone), page_size); >> + mprotect(zone, allocated_size, PROT_READ | PROT_WRITE); >> if (zone->zone_name) { >> COMMON_MALLOC_FREE((void *)zone->zone_name); >> } >> diff --git a/libsanitizer/sanitizer_common/sanitizer_netbsd.cpp >> b/libsanitizer/sanitizer_common/sanitizer_netbsd.cpp >> index 4e74f6a3b51..d9aff51d8ae 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_netbsd.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_netbsd.cpp >> @@ -95,7 +95,7 @@ static void *GetRealLibcAddress(const char *symbol) { >> >> // --------------- sanitizer_libc.h >> uptr internal_mmap(void *addr, uptr length, int prot, int flags, >> int fd, >> - OFF_T offset) { >> + u64 offset) { >> CHECK(&__mmap); >> return (uptr)__mmap(addr, length, prot, flags, fd, 0, offset); >> } >> @@ -265,6 +265,11 @@ uptr internal_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); >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h >> index 61a6b82ef81..9dd6d285f59 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h >> @@ -90,6 +90,24 @@ >> # define SI_IOS 0 >> #endif >> >> +#if SANITIZER_IOSSIM >> +# define SI_IOSSIM 1 >> +#else >> +# define SI_IOSSIM 0 >> +#endif >> + >> +#if SANITIZER_WATCHOS >> +# define SI_WATCHOS 1 >> +#else >> +# define SI_WATCHOS 0 >> +#endif >> + >> +#if SANITIZER_TVOS >> +# define SI_TVOS 1 >> +#else >> +# define SI_TVOS 0 >> +#endif >> + >> #if SANITIZER_FUCHSIA >> # define SI_NOT_FUCHSIA 0 >> #else >> @@ -575,5 +593,11 @@ >> #define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD >> #define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD >> #define SANITIZER_INTERCEPT_GETENTROPY SI_FREEBSD >> +#define SANITIZER_INTERCEPT_QSORT \ >> + (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID) >> +#define SANITIZER_INTERCEPT_QSORT_R (SI_LINUX && !SI_ANDROID) >> +#define SANITIZER_INTERCEPT_SIGALTSTACK SI_POSIX >> +#define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD) >> +#define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD >> >> #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp >> index 2d1bb1a12da..dcc6c71c07d 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.cpp >> @@ -15,342 +15,348 @@ >> >> #if SANITIZER_FREEBSD >> >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +// >> #include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +// >> #include >> -#include >> +#include >> #include >> +#include >> +#include >> #include >> +#include >> #include >> -#include >> -#include >> #include >> #include >> #include >> #include >> +#include >> #include >> #include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> - >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> -#include >> #include >> #include >> #include >> +#include >> +#include >> +#include >> #include >> -#include >> #include >> +#include >> +#include >> >> #define _KERNEL // to declare 'shminfo' structure >> -# include >> +#include >> #undef _KERNEL >> >> #undef INLINE // to avoid clashes with sanitizers' definitions >> >> #undef IOC_DIRMASK >> >> -# include >> -# include >> -# include >> - >> -#include >> -#include >> -#include >> - >> // Include these after system headers to avoid name clashes and >> ambiguities. >> #include "sanitizer_internal_defs.h" >> +#include "sanitizer_libc.h" >> #include "sanitizer_platform_limits_freebsd.h" >> >> namespace __sanitizer { >> - unsigned struct_cap_rights_sz =3D sizeof(cap_rights_t); >> - unsigned struct_utsname_sz =3D sizeof(struct utsname); >> - unsigned struct_stat_sz =3D sizeof(struct stat); >> - unsigned struct_rusage_sz =3D sizeof(struct rusage); >> - unsigned struct_tm_sz =3D sizeof(struct tm); >> - unsigned struct_passwd_sz =3D sizeof(struct passwd); >> - unsigned struct_group_sz =3D sizeof(struct group); >> - unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> - unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> - unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> - unsigned pthread_t_sz =3D sizeof(pthread_t); >> - unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> - unsigned pthread_cond_t_sz =3D sizeof(pthread_cond_t); >> - unsigned pid_t_sz =3D sizeof(pid_t); >> - unsigned timeval_sz =3D sizeof(timeval); >> - unsigned uid_t_sz =3D sizeof(uid_t); >> - unsigned gid_t_sz =3D sizeof(gid_t); >> - unsigned fpos_t_sz =3D sizeof(fpos_t); >> - unsigned mbstate_t_sz =3D sizeof(mbstate_t); >> - unsigned sigset_t_sz =3D sizeof(sigset_t); >> - unsigned struct_timezone_sz =3D sizeof(struct timezone); >> - unsigned struct_tms_sz =3D sizeof(struct tms); >> - unsigned struct_sigevent_sz =3D sizeof(struct sigevent); >> - unsigned struct_sched_param_sz =3D sizeof(struct sched_param); >> - unsigned struct_statfs_sz =3D sizeof(struct statfs); >> - unsigned struct_sockaddr_sz =3D sizeof(struct sockaddr); >> - unsigned ucontext_t_sz =3D sizeof(ucontext_t); >> - unsigned struct_rlimit_sz =3D sizeof(struct rlimit); >> - unsigned struct_timespec_sz =3D sizeof(struct timespec); >> - unsigned struct_utimbuf_sz =3D sizeof(struct utimbuf); >> - unsigned struct_itimerspec_sz =3D sizeof(struct itimerspec); >> - unsigned struct_timeb_sz =3D sizeof(struct timeb); >> - unsigned struct_msqid_ds_sz =3D sizeof(struct msqid_ds); >> - unsigned struct_mq_attr_sz =3D sizeof(struct mq_attr); >> - unsigned struct_statvfs_sz =3D sizeof(struct statvfs); >> - unsigned struct_shminfo_sz =3D sizeof(struct shminfo); >> - unsigned struct_shm_info_sz =3D sizeof(struct shm_info); >> - unsigned struct_regmatch_sz =3D sizeof(regmatch_t); >> - unsigned struct_regex_sz =3D sizeof(regex_t); >> - unsigned struct_fstab_sz =3D sizeof(struct fstab); >> - unsigned struct_FTS_sz =3D sizeof(FTS); >> - unsigned struct_FTSENT_sz =3D sizeof(FTSENT); >> - unsigned struct_StringList_sz =3D sizeof(StringList); >> - >> - const uptr sig_ign =3D (uptr)SIG_IGN; >> - const uptr sig_dfl =3D (uptr)SIG_DFL; >> - const uptr sig_err =3D (uptr)SIG_ERR; >> - const uptr sa_siginfo =3D (uptr)SA_SIGINFO; >> - >> - int shmctl_ipc_stat =3D (int)IPC_STAT; >> - int shmctl_ipc_info =3D (int)IPC_INFO; >> - int shmctl_shm_info =3D (int)SHM_INFO; >> - int shmctl_shm_stat =3D (int)SHM_STAT; >> - unsigned struct_utmpx_sz =3D sizeof(struct utmpx); >> - >> - int map_fixed =3D MAP_FIXED; >> - >> - int af_inet =3D (int)AF_INET; >> - int af_inet6 =3D (int)AF_INET6; >> - >> - uptr __sanitizer_in_addr_sz(int af) { >> - if (af =3D=3D AF_INET) >> - return sizeof(struct in_addr); >> - else if (af =3D=3D AF_INET6) >> - return sizeof(struct in6_addr); >> - else >> - return 0; >> - } >> - >> - unsigned struct_ElfW_Phdr_sz =3D sizeof(Elf_Phdr); >> - int glob_nomatch =3D GLOB_NOMATCH; >> - int glob_altdirfunc =3D GLOB_ALTDIRFUNC; >> - >> - unsigned path_max =3D PATH_MAX; >> - >> - // ioctl arguments >> - unsigned struct_ifreq_sz =3D sizeof(struct ifreq); >> - unsigned struct_termios_sz =3D sizeof(struct termios); >> - unsigned struct_winsize_sz =3D sizeof(struct winsize); >> +void *__sanitizer_get_link_map_by_dlopen_handle(void *handle) { >> + void *p =3D nullptr; >> + return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) =3D=3D 0 ? p : >> nullptr; >> +} >> + >> +unsigned struct_cap_rights_sz =3D sizeof(cap_rights_t); >> +unsigned struct_utsname_sz =3D sizeof(struct utsname); >> +unsigned struct_stat_sz =3D sizeof(struct stat); >> +unsigned struct_rusage_sz =3D sizeof(struct rusage); >> +unsigned struct_tm_sz =3D sizeof(struct tm); >> +unsigned struct_passwd_sz =3D sizeof(struct passwd); >> +unsigned struct_group_sz =3D sizeof(struct group); >> +unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> +unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> +unsigned struct_stack_t_sz =3D sizeof(stack_t); >> +unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> +unsigned pthread_t_sz =3D sizeof(pthread_t); >> +unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> +unsigned pthread_cond_t_sz =3D sizeof(pthread_cond_t); >> +unsigned pid_t_sz =3D sizeof(pid_t); >> +unsigned timeval_sz =3D sizeof(timeval); >> +unsigned uid_t_sz =3D sizeof(uid_t); >> +unsigned gid_t_sz =3D sizeof(gid_t); >> +unsigned fpos_t_sz =3D sizeof(fpos_t); >> +unsigned mbstate_t_sz =3D sizeof(mbstate_t); >> +unsigned sigset_t_sz =3D sizeof(sigset_t); >> +unsigned struct_timezone_sz =3D sizeof(struct timezone); >> +unsigned struct_tms_sz =3D sizeof(struct tms); >> +unsigned struct_sigevent_sz =3D sizeof(struct sigevent); >> +unsigned struct_sched_param_sz =3D sizeof(struct sched_param); >> +unsigned struct_statfs_sz =3D sizeof(struct statfs); >> +unsigned struct_sockaddr_sz =3D sizeof(struct sockaddr); >> +unsigned ucontext_t_sz =3D sizeof(ucontext_t); >> +unsigned struct_rlimit_sz =3D sizeof(struct rlimit); >> +unsigned struct_timespec_sz =3D sizeof(struct timespec); >> +unsigned struct_utimbuf_sz =3D sizeof(struct utimbuf); >> +unsigned struct_itimerspec_sz =3D sizeof(struct itimerspec); >> +unsigned struct_timeb_sz =3D sizeof(struct timeb); >> +unsigned struct_msqid_ds_sz =3D sizeof(struct msqid_ds); >> +unsigned struct_mq_attr_sz =3D sizeof(struct mq_attr); >> +unsigned struct_statvfs_sz =3D sizeof(struct statvfs); >> +unsigned struct_shminfo_sz =3D sizeof(struct shminfo); >> +unsigned struct_shm_info_sz =3D sizeof(struct shm_info); >> +unsigned struct_regmatch_sz =3D sizeof(regmatch_t); >> +unsigned struct_regex_sz =3D sizeof(regex_t); >> +unsigned struct_fstab_sz =3D sizeof(struct fstab); >> +unsigned struct_FTS_sz =3D sizeof(FTS); >> +unsigned struct_FTSENT_sz =3D sizeof(FTSENT); >> +unsigned struct_StringList_sz =3D sizeof(StringList); >> + >> +const uptr sig_ign =3D (uptr)SIG_IGN; >> +const uptr sig_dfl =3D (uptr)SIG_DFL; >> +const uptr sig_err =3D (uptr)SIG_ERR; >> +const uptr sa_siginfo =3D (uptr)SA_SIGINFO; >> + >> +int shmctl_ipc_stat =3D (int)IPC_STAT; >> +int shmctl_ipc_info =3D (int)IPC_INFO; >> +int shmctl_shm_info =3D (int)SHM_INFO; >> +int shmctl_shm_stat =3D (int)SHM_STAT; >> +unsigned struct_utmpx_sz =3D sizeof(struct utmpx); >> + >> +int map_fixed =3D MAP_FIXED; >> + >> +int af_inet =3D (int)AF_INET; >> +int af_inet6 =3D (int)AF_INET6; >> + >> +uptr __sanitizer_in_addr_sz(int af) { >> + if (af =3D=3D AF_INET) >> + return sizeof(struct in_addr); >> + else if (af =3D=3D AF_INET6) >> + return sizeof(struct in6_addr); >> + else >> + return 0; >> +} >> + >> +unsigned struct_ElfW_Phdr_sz =3D sizeof(Elf_Phdr); >> +int glob_nomatch =3D GLOB_NOMATCH; >> +int glob_altdirfunc =3D GLOB_ALTDIRFUNC; >> + >> +unsigned path_max =3D PATH_MAX; >> + >> +// ioctl arguments >> +unsigned struct_ifreq_sz =3D sizeof(struct ifreq); >> +unsigned struct_termios_sz =3D sizeof(struct termios); >> +unsigned struct_winsize_sz =3D sizeof(struct winsize); >> #if SOUND_VERSION >=3D 0x040000 >> - unsigned struct_copr_buffer_sz =3D 0; >> - unsigned struct_copr_debug_buf_sz =3D 0; >> - unsigned struct_copr_msg_sz =3D 0; >> +unsigned struct_copr_buffer_sz =3D 0; >> +unsigned struct_copr_debug_buf_sz =3D 0; >> +unsigned struct_copr_msg_sz =3D 0; >> #else >> - unsigned struct_copr_buffer_sz =3D sizeof(struct copr_buffer); >> - unsigned struct_copr_debug_buf_sz =3D sizeof(struct copr_debug_buf); >> - unsigned struct_copr_msg_sz =3D sizeof(struct copr_msg); >> +unsigned struct_copr_buffer_sz =3D sizeof(struct copr_buffer); >> +unsigned struct_copr_debug_buf_sz =3D sizeof(struct copr_debug_buf); >> +unsigned struct_copr_msg_sz =3D sizeof(struct copr_msg); >> #endif >> - unsigned struct_midi_info_sz =3D sizeof(struct midi_info); >> - unsigned struct_mtget_sz =3D sizeof(struct mtget); >> - unsigned struct_mtop_sz =3D sizeof(struct mtop); >> - unsigned struct_sbi_instrument_sz =3D sizeof(struct sbi_instrument); >> - unsigned struct_seq_event_rec_sz =3D sizeof(struct seq_event_rec); >> - unsigned struct_synth_info_sz =3D sizeof(struct synth_info); >> - unsigned struct_audio_buf_info_sz =3D sizeof(struct audio_buf_info); >> - unsigned struct_ppp_stats_sz =3D sizeof(struct ppp_stats); >> - unsigned struct_sioc_sg_req_sz =3D sizeof(struct sioc_sg_req); >> - unsigned struct_sioc_vif_req_sz =3D sizeof(struct sioc_vif_req); >> - const unsigned long __sanitizer_bufsiz =3D BUFSIZ; >> - >> - const unsigned IOCTL_NOT_PRESENT =3D 0; >> - >> - unsigned IOCTL_FIOASYNC =3D FIOASYNC; >> - unsigned IOCTL_FIOCLEX =3D FIOCLEX; >> - unsigned IOCTL_FIOGETOWN =3D FIOGETOWN; >> - unsigned IOCTL_FIONBIO =3D FIONBIO; >> - unsigned IOCTL_FIONCLEX =3D FIONCLEX; >> - unsigned IOCTL_FIOSETOWN =3D FIOSETOWN; >> - unsigned IOCTL_SIOCADDMULTI =3D SIOCADDMULTI; >> - unsigned IOCTL_SIOCATMARK =3D SIOCATMARK; >> - unsigned IOCTL_SIOCDELMULTI =3D SIOCDELMULTI; >> - unsigned IOCTL_SIOCGIFADDR =3D SIOCGIFADDR; >> - unsigned IOCTL_SIOCGIFBRDADDR =3D SIOCGIFBRDADDR; >> - unsigned IOCTL_SIOCGIFCONF =3D SIOCGIFCONF; >> - unsigned IOCTL_SIOCGIFDSTADDR =3D SIOCGIFDSTADDR; >> - unsigned IOCTL_SIOCGIFFLAGS =3D SIOCGIFFLAGS; >> - unsigned IOCTL_SIOCGIFMETRIC =3D SIOCGIFMETRIC; >> - unsigned IOCTL_SIOCGIFMTU =3D SIOCGIFMTU; >> - unsigned IOCTL_SIOCGIFNETMASK =3D SIOCGIFNETMASK; >> - unsigned IOCTL_SIOCGPGRP =3D SIOCGPGRP; >> - unsigned IOCTL_SIOCSIFADDR =3D SIOCSIFADDR; >> - unsigned IOCTL_SIOCSIFBRDADDR =3D SIOCSIFBRDADDR; >> - unsigned IOCTL_SIOCSIFDSTADDR =3D SIOCSIFDSTADDR; >> - unsigned IOCTL_SIOCSIFFLAGS =3D SIOCSIFFLAGS; >> - unsigned IOCTL_SIOCSIFMETRIC =3D SIOCSIFMETRIC; >> - unsigned IOCTL_SIOCSIFMTU =3D SIOCSIFMTU; >> - unsigned IOCTL_SIOCSIFNETMASK =3D SIOCSIFNETMASK; >> - unsigned IOCTL_SIOCSPGRP =3D SIOCSPGRP; >> - unsigned IOCTL_TIOCCONS =3D TIOCCONS; >> - unsigned IOCTL_TIOCEXCL =3D TIOCEXCL; >> - unsigned IOCTL_TIOCGETD =3D TIOCGETD; >> - unsigned IOCTL_TIOCGPGRP =3D TIOCGPGRP; >> - unsigned IOCTL_TIOCGWINSZ =3D TIOCGWINSZ; >> - unsigned IOCTL_TIOCMBIC =3D TIOCMBIC; >> - unsigned IOCTL_TIOCMBIS =3D TIOCMBIS; >> - unsigned IOCTL_TIOCMGET =3D TIOCMGET; >> - unsigned IOCTL_TIOCMSET =3D TIOCMSET; >> - unsigned IOCTL_TIOCNOTTY =3D TIOCNOTTY; >> - unsigned IOCTL_TIOCNXCL =3D TIOCNXCL; >> - unsigned IOCTL_TIOCOUTQ =3D TIOCOUTQ; >> - unsigned IOCTL_TIOCPKT =3D TIOCPKT; >> - unsigned IOCTL_TIOCSCTTY =3D TIOCSCTTY; >> - unsigned IOCTL_TIOCSETD =3D TIOCSETD; >> - unsigned IOCTL_TIOCSPGRP =3D TIOCSPGRP; >> - unsigned IOCTL_TIOCSTI =3D TIOCSTI; >> - unsigned IOCTL_TIOCSWINSZ =3D TIOCSWINSZ; >> - unsigned IOCTL_SIOCGETSGCNT =3D SIOCGETSGCNT; >> - unsigned IOCTL_SIOCGETVIFCNT =3D SIOCGETVIFCNT; >> - unsigned IOCTL_MTIOCGET =3D MTIOCGET; >> - unsigned IOCTL_MTIOCTOP =3D MTIOCTOP; >> - unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE =3D SNDCTL_DSP_GETBLKSIZE; >> - unsigned IOCTL_SNDCTL_DSP_GETFMTS =3D SNDCTL_DSP_GETFMTS; >> - unsigned IOCTL_SNDCTL_DSP_NONBLOCK =3D SNDCTL_DSP_NONBLOCK; >> - unsigned IOCTL_SNDCTL_DSP_POST =3D SNDCTL_DSP_POST; >> - unsigned IOCTL_SNDCTL_DSP_RESET =3D SNDCTL_DSP_RESET; >> - unsigned IOCTL_SNDCTL_DSP_SETFMT =3D SNDCTL_DSP_SETFMT; >> - unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT =3D SNDCTL_DSP_SETFRAGMENT; >> - unsigned IOCTL_SNDCTL_DSP_SPEED =3D SNDCTL_DSP_SPEED; >> - unsigned IOCTL_SNDCTL_DSP_STEREO =3D SNDCTL_DSP_STEREO; >> - unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE =3D SNDCTL_DSP_SUBDIVIDE; >> - unsigned IOCTL_SNDCTL_DSP_SYNC =3D SNDCTL_DSP_SYNC; >> - unsigned IOCTL_SNDCTL_FM_4OP_ENABLE =3D SNDCTL_FM_4OP_ENABLE; >> - unsigned IOCTL_SNDCTL_FM_LOAD_INSTR =3D SNDCTL_FM_LOAD_INSTR; >> - unsigned IOCTL_SNDCTL_MIDI_INFO =3D SNDCTL_MIDI_INFO; >> - unsigned IOCTL_SNDCTL_MIDI_PRETIME =3D SNDCTL_MIDI_PRETIME; >> - unsigned IOCTL_SNDCTL_SEQ_CTRLRATE =3D SNDCTL_SEQ_CTRLRATE; >> - unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT =3D SNDCTL_SEQ_GETINCOUNT; >> - unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT =3D SNDCTL_SEQ_GETOUTCOUNT; >> - unsigned IOCTL_SNDCTL_SEQ_NRMIDIS =3D SNDCTL_SEQ_NRMIDIS; >> - unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS =3D SNDCTL_SEQ_NRSYNTHS; >> - unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND =3D SNDCTL_SEQ_OUTOFBAND; >> - unsigned IOCTL_SNDCTL_SEQ_PANIC =3D SNDCTL_SEQ_PANIC; >> - unsigned IOCTL_SNDCTL_SEQ_PERCMODE =3D SNDCTL_SEQ_PERCMODE; >> - unsigned IOCTL_SNDCTL_SEQ_RESET =3D SNDCTL_SEQ_RESET; >> - unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES =3D SNDCTL_SEQ_RESETSAMPLES; >> - unsigned IOCTL_SNDCTL_SEQ_SYNC =3D SNDCTL_SEQ_SYNC; >> - unsigned IOCTL_SNDCTL_SEQ_TESTMIDI =3D SNDCTL_SEQ_TESTMIDI; >> - unsigned IOCTL_SNDCTL_SEQ_THRESHOLD =3D SNDCTL_SEQ_THRESHOLD; >> - unsigned IOCTL_SNDCTL_SYNTH_INFO =3D SNDCTL_SYNTH_INFO; >> - unsigned IOCTL_SNDCTL_SYNTH_MEMAVL =3D SNDCTL_SYNTH_MEMAVL; >> - unsigned IOCTL_SNDCTL_TMR_CONTINUE =3D SNDCTL_TMR_CONTINUE; >> - unsigned IOCTL_SNDCTL_TMR_METRONOME =3D SNDCTL_TMR_METRONOME; >> - unsigned IOCTL_SNDCTL_TMR_SELECT =3D SNDCTL_TMR_SELECT; >> - unsigned IOCTL_SNDCTL_TMR_SOURCE =3D SNDCTL_TMR_SOURCE; >> - unsigned IOCTL_SNDCTL_TMR_START =3D SNDCTL_TMR_START; >> - unsigned IOCTL_SNDCTL_TMR_STOP =3D SNDCTL_TMR_STOP; >> - unsigned IOCTL_SNDCTL_TMR_TEMPO =3D SNDCTL_TMR_TEMPO; >> - unsigned IOCTL_SNDCTL_TMR_TIMEBASE =3D SNDCTL_TMR_TIMEBASE; >> - unsigned IOCTL_SOUND_MIXER_READ_ALTPCM =3D SOUND_MIXER_READ_ALTPCM; >> - unsigned IOCTL_SOUND_MIXER_READ_BASS =3D SOUND_MIXER_READ_BASS; >> - unsigned IOCTL_SOUND_MIXER_READ_CAPS =3D SOUND_MIXER_READ_CAPS; >> - unsigned IOCTL_SOUND_MIXER_READ_CD =3D SOUND_MIXER_READ_CD; >> - unsigned IOCTL_SOUND_MIXER_READ_DEVMASK =3D SOUND_MIXER_READ_DEVMASK; >> - unsigned IOCTL_SOUND_MIXER_READ_ENHANCE =3D SOUND_MIXER_READ_ENHANCE; >> - unsigned IOCTL_SOUND_MIXER_READ_IGAIN =3D SOUND_MIXER_READ_IGAIN; >> - unsigned IOCTL_SOUND_MIXER_READ_IMIX =3D SOUND_MIXER_READ_IMIX; >> - unsigned IOCTL_SOUND_MIXER_READ_LINE =3D SOUND_MIXER_READ_LINE; >> - unsigned IOCTL_SOUND_MIXER_READ_LINE1 =3D SOUND_MIXER_READ_LINE1; >> - unsigned IOCTL_SOUND_MIXER_READ_LINE2 =3D SOUND_MIXER_READ_LINE2; >> - unsigned IOCTL_SOUND_MIXER_READ_LINE3 =3D SOUND_MIXER_READ_LINE3; >> - unsigned IOCTL_SOUND_MIXER_READ_LOUD =3D SOUND_MIXER_READ_LOUD; >> - unsigned IOCTL_SOUND_MIXER_READ_MIC =3D SOUND_MIXER_READ_MIC; >> - unsigned IOCTL_SOUND_MIXER_READ_MUTE =3D SOUND_MIXER_READ_MUTE; >> - unsigned IOCTL_SOUND_MIXER_READ_OGAIN =3D SOUND_MIXER_READ_OGAIN; >> - unsigned IOCTL_SOUND_MIXER_READ_PCM =3D SOUND_MIXER_READ_PCM; >> - unsigned IOCTL_SOUND_MIXER_READ_RECLEV =3D SOUND_MIXER_READ_RECLEV; >> - unsigned IOCTL_SOUND_MIXER_READ_RECMASK =3D SOUND_MIXER_READ_RECMASK; >> - unsigned IOCTL_SOUND_MIXER_READ_RECSRC =3D SOUND_MIXER_READ_RECSRC; >> - unsigned IOCTL_SOUND_MIXER_READ_SPEAKER =3D SOUND_MIXER_READ_SPEAKER; >> - unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS =3D >> SOUND_MIXER_READ_STEREODEVS; >> - unsigned IOCTL_SOUND_MIXER_READ_SYNTH =3D SOUND_MIXER_READ_SYNTH; >> - unsigned IOCTL_SOUND_MIXER_READ_TREBLE =3D SOUND_MIXER_READ_TREBLE; >> - unsigned IOCTL_SOUND_MIXER_READ_VOLUME =3D SOUND_MIXER_READ_VOLUME; >> - unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM =3D SOUND_MIXER_WRITE_ALTPCM; >> - unsigned IOCTL_SOUND_MIXER_WRITE_BASS =3D SOUND_MIXER_WRITE_BASS; >> - unsigned IOCTL_SOUND_MIXER_WRITE_CD =3D SOUND_MIXER_WRITE_CD; >> - unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE =3D SOUND_MIXER_WRITE_ENHANC= E; >> - unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN =3D SOUND_MIXER_WRITE_IGAIN; >> - unsigned IOCTL_SOUND_MIXER_WRITE_IMIX =3D SOUND_MIXER_WRITE_IMIX; >> - unsigned IOCTL_SOUND_MIXER_WRITE_LINE =3D SOUND_MIXER_WRITE_LINE; >> - unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 =3D SOUND_MIXER_WRITE_LINE1; >> - unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 =3D SOUND_MIXER_WRITE_LINE2; >> - unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 =3D SOUND_MIXER_WRITE_LINE3; >> - unsigned IOCTL_SOUND_MIXER_WRITE_LOUD =3D SOUND_MIXER_WRITE_LOUD; >> - unsigned IOCTL_SOUND_MIXER_WRITE_MIC =3D SOUND_MIXER_WRITE_MIC; >> - unsigned IOCTL_SOUND_MIXER_WRITE_MUTE =3D SOUND_MIXER_WRITE_MUTE; >> - unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN =3D SOUND_MIXER_WRITE_OGAIN; >> - unsigned IOCTL_SOUND_MIXER_WRITE_PCM =3D SOUND_MIXER_WRITE_PCM; >> - unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV =3D SOUND_MIXER_WRITE_RECLEV; >> - unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC =3D SOUND_MIXER_WRITE_RECSRC; >> - unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER =3D SOUND_MIXER_WRITE_SPEAKE= R; >> - unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH =3D SOUND_MIXER_WRITE_SYNTH; >> - unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE =3D SOUND_MIXER_WRITE_TREBLE; >> - unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME =3D SOUND_MIXER_WRITE_VOLUME; >> - unsigned IOCTL_VT_ACTIVATE =3D VT_ACTIVATE; >> - unsigned IOCTL_VT_GETMODE =3D VT_GETMODE; >> - unsigned IOCTL_VT_OPENQRY =3D VT_OPENQRY; >> - unsigned IOCTL_VT_RELDISP =3D VT_RELDISP; >> - unsigned IOCTL_VT_SETMODE =3D VT_SETMODE; >> - unsigned IOCTL_VT_WAITACTIVE =3D VT_WAITACTIVE; >> - unsigned IOCTL_GIO_SCRNMAP =3D GIO_SCRNMAP; >> - unsigned IOCTL_KDDISABIO =3D KDDISABIO; >> - unsigned IOCTL_KDENABIO =3D KDENABIO; >> - unsigned IOCTL_KDGETLED =3D KDGETLED; >> - unsigned IOCTL_KDGETMODE =3D KDGETMODE; >> - unsigned IOCTL_KDGKBMODE =3D KDGKBMODE; >> - unsigned IOCTL_KDGKBTYPE =3D KDGKBTYPE; >> - unsigned IOCTL_KDMKTONE =3D KDMKTONE; >> - unsigned IOCTL_KDSETLED =3D KDSETLED; >> - unsigned IOCTL_KDSETMODE =3D KDSETMODE; >> - unsigned IOCTL_KDSKBMODE =3D KDSKBMODE; >> - unsigned IOCTL_KIOCSOUND =3D KIOCSOUND; >> - unsigned IOCTL_PIO_SCRNMAP =3D PIO_SCRNMAP; >> - unsigned IOCTL_SNDCTL_DSP_GETISPACE =3D SNDCTL_DSP_GETISPACE; >> - >> - const int si_SEGV_MAPERR =3D SEGV_MAPERR; >> - const int si_SEGV_ACCERR =3D SEGV_ACCERR; >> - const int unvis_valid =3D UNVIS_VALID; >> - const int unvis_validpush =3D UNVIS_VALIDPUSH; >> -} // namespace __sanitizer >> +unsigned struct_midi_info_sz =3D sizeof(struct midi_info); >> +unsigned struct_mtget_sz =3D sizeof(struct mtget); >> +unsigned struct_mtop_sz =3D sizeof(struct mtop); >> +unsigned struct_sbi_instrument_sz =3D sizeof(struct sbi_instrument); >> +unsigned struct_seq_event_rec_sz =3D sizeof(struct seq_event_rec); >> +unsigned struct_synth_info_sz =3D sizeof(struct synth_info); >> +unsigned struct_audio_buf_info_sz =3D sizeof(struct audio_buf_info); >> +unsigned struct_ppp_stats_sz =3D sizeof(struct ppp_stats); >> +unsigned struct_sioc_sg_req_sz =3D sizeof(struct sioc_sg_req); >> +unsigned struct_sioc_vif_req_sz =3D sizeof(struct sioc_vif_req); >> +const unsigned long __sanitizer_bufsiz =3D BUFSIZ; >> + >> +const unsigned IOCTL_NOT_PRESENT =3D 0; >> + >> +unsigned IOCTL_FIOASYNC =3D FIOASYNC; >> +unsigned IOCTL_FIOCLEX =3D FIOCLEX; >> +unsigned IOCTL_FIOGETOWN =3D FIOGETOWN; >> +unsigned IOCTL_FIONBIO =3D FIONBIO; >> +unsigned IOCTL_FIONCLEX =3D FIONCLEX; >> +unsigned IOCTL_FIOSETOWN =3D FIOSETOWN; >> +unsigned IOCTL_SIOCADDMULTI =3D SIOCADDMULTI; >> +unsigned IOCTL_SIOCATMARK =3D SIOCATMARK; >> +unsigned IOCTL_SIOCDELMULTI =3D SIOCDELMULTI; >> +unsigned IOCTL_SIOCGIFADDR =3D SIOCGIFADDR; >> +unsigned IOCTL_SIOCGIFBRDADDR =3D SIOCGIFBRDADDR; >> +unsigned IOCTL_SIOCGIFCONF =3D SIOCGIFCONF; >> +unsigned IOCTL_SIOCGIFDSTADDR =3D SIOCGIFDSTADDR; >> +unsigned IOCTL_SIOCGIFFLAGS =3D SIOCGIFFLAGS; >> +unsigned IOCTL_SIOCGIFMETRIC =3D SIOCGIFMETRIC; >> +unsigned IOCTL_SIOCGIFMTU =3D SIOCGIFMTU; >> +unsigned IOCTL_SIOCGIFNETMASK =3D SIOCGIFNETMASK; >> +unsigned IOCTL_SIOCGPGRP =3D SIOCGPGRP; >> +unsigned IOCTL_SIOCSIFADDR =3D SIOCSIFADDR; >> +unsigned IOCTL_SIOCSIFBRDADDR =3D SIOCSIFBRDADDR; >> +unsigned IOCTL_SIOCSIFDSTADDR =3D SIOCSIFDSTADDR; >> +unsigned IOCTL_SIOCSIFFLAGS =3D SIOCSIFFLAGS; >> +unsigned IOCTL_SIOCSIFMETRIC =3D SIOCSIFMETRIC; >> +unsigned IOCTL_SIOCSIFMTU =3D SIOCSIFMTU; >> +unsigned IOCTL_SIOCSIFNETMASK =3D SIOCSIFNETMASK; >> +unsigned IOCTL_SIOCSPGRP =3D SIOCSPGRP; >> +unsigned IOCTL_TIOCCONS =3D TIOCCONS; >> +unsigned IOCTL_TIOCEXCL =3D TIOCEXCL; >> +unsigned IOCTL_TIOCGETD =3D TIOCGETD; >> +unsigned IOCTL_TIOCGPGRP =3D TIOCGPGRP; >> +unsigned IOCTL_TIOCGWINSZ =3D TIOCGWINSZ; >> +unsigned IOCTL_TIOCMBIC =3D TIOCMBIC; >> +unsigned IOCTL_TIOCMBIS =3D TIOCMBIS; >> +unsigned IOCTL_TIOCMGET =3D TIOCMGET; >> +unsigned IOCTL_TIOCMSET =3D TIOCMSET; >> +unsigned IOCTL_TIOCNOTTY =3D TIOCNOTTY; >> +unsigned IOCTL_TIOCNXCL =3D TIOCNXCL; >> +unsigned IOCTL_TIOCOUTQ =3D TIOCOUTQ; >> +unsigned IOCTL_TIOCPKT =3D TIOCPKT; >> +unsigned IOCTL_TIOCSCTTY =3D TIOCSCTTY; >> +unsigned IOCTL_TIOCSETD =3D TIOCSETD; >> +unsigned IOCTL_TIOCSPGRP =3D TIOCSPGRP; >> +unsigned IOCTL_TIOCSTI =3D TIOCSTI; >> +unsigned IOCTL_TIOCSWINSZ =3D TIOCSWINSZ; >> +unsigned IOCTL_SIOCGETSGCNT =3D SIOCGETSGCNT; >> +unsigned IOCTL_SIOCGETVIFCNT =3D SIOCGETVIFCNT; >> +unsigned IOCTL_MTIOCGET =3D MTIOCGET; >> +unsigned IOCTL_MTIOCTOP =3D MTIOCTOP; >> +unsigned IOCTL_SNDCTL_DSP_GETBLKSIZE =3D SNDCTL_DSP_GETBLKSIZE; >> +unsigned IOCTL_SNDCTL_DSP_GETFMTS =3D SNDCTL_DSP_GETFMTS; >> +unsigned IOCTL_SNDCTL_DSP_NONBLOCK =3D SNDCTL_DSP_NONBLOCK; >> +unsigned IOCTL_SNDCTL_DSP_POST =3D SNDCTL_DSP_POST; >> +unsigned IOCTL_SNDCTL_DSP_RESET =3D SNDCTL_DSP_RESET; >> +unsigned IOCTL_SNDCTL_DSP_SETFMT =3D SNDCTL_DSP_SETFMT; >> +unsigned IOCTL_SNDCTL_DSP_SETFRAGMENT =3D SNDCTL_DSP_SETFRAGMENT; >> +unsigned IOCTL_SNDCTL_DSP_SPEED =3D SNDCTL_DSP_SPEED; >> +unsigned IOCTL_SNDCTL_DSP_STEREO =3D SNDCTL_DSP_STEREO; >> +unsigned IOCTL_SNDCTL_DSP_SUBDIVIDE =3D SNDCTL_DSP_SUBDIVIDE; >> +unsigned IOCTL_SNDCTL_DSP_SYNC =3D SNDCTL_DSP_SYNC; >> +unsigned IOCTL_SNDCTL_FM_4OP_ENABLE =3D SNDCTL_FM_4OP_ENABLE; >> +unsigned IOCTL_SNDCTL_FM_LOAD_INSTR =3D SNDCTL_FM_LOAD_INSTR; >> +unsigned IOCTL_SNDCTL_MIDI_INFO =3D SNDCTL_MIDI_INFO; >> +unsigned IOCTL_SNDCTL_MIDI_PRETIME =3D SNDCTL_MIDI_PRETIME; >> +unsigned IOCTL_SNDCTL_SEQ_CTRLRATE =3D SNDCTL_SEQ_CTRLRATE; >> +unsigned IOCTL_SNDCTL_SEQ_GETINCOUNT =3D SNDCTL_SEQ_GETINCOUNT; >> +unsigned IOCTL_SNDCTL_SEQ_GETOUTCOUNT =3D SNDCTL_SEQ_GETOUTCOUNT; >> +unsigned IOCTL_SNDCTL_SEQ_NRMIDIS =3D SNDCTL_SEQ_NRMIDIS; >> +unsigned IOCTL_SNDCTL_SEQ_NRSYNTHS =3D SNDCTL_SEQ_NRSYNTHS; >> +unsigned IOCTL_SNDCTL_SEQ_OUTOFBAND =3D SNDCTL_SEQ_OUTOFBAND; >> +unsigned IOCTL_SNDCTL_SEQ_PANIC =3D SNDCTL_SEQ_PANIC; >> +unsigned IOCTL_SNDCTL_SEQ_PERCMODE =3D SNDCTL_SEQ_PERCMODE; >> +unsigned IOCTL_SNDCTL_SEQ_RESET =3D SNDCTL_SEQ_RESET; >> +unsigned IOCTL_SNDCTL_SEQ_RESETSAMPLES =3D SNDCTL_SEQ_RESETSAMPLES; >> +unsigned IOCTL_SNDCTL_SEQ_SYNC =3D SNDCTL_SEQ_SYNC; >> +unsigned IOCTL_SNDCTL_SEQ_TESTMIDI =3D SNDCTL_SEQ_TESTMIDI; >> +unsigned IOCTL_SNDCTL_SEQ_THRESHOLD =3D SNDCTL_SEQ_THRESHOLD; >> +unsigned IOCTL_SNDCTL_SYNTH_INFO =3D SNDCTL_SYNTH_INFO; >> +unsigned IOCTL_SNDCTL_SYNTH_MEMAVL =3D SNDCTL_SYNTH_MEMAVL; >> +unsigned IOCTL_SNDCTL_TMR_CONTINUE =3D SNDCTL_TMR_CONTINUE; >> +unsigned IOCTL_SNDCTL_TMR_METRONOME =3D SNDCTL_TMR_METRONOME; >> +unsigned IOCTL_SNDCTL_TMR_SELECT =3D SNDCTL_TMR_SELECT; >> +unsigned IOCTL_SNDCTL_TMR_SOURCE =3D SNDCTL_TMR_SOURCE; >> +unsigned IOCTL_SNDCTL_TMR_START =3D SNDCTL_TMR_START; >> +unsigned IOCTL_SNDCTL_TMR_STOP =3D SNDCTL_TMR_STOP; >> +unsigned IOCTL_SNDCTL_TMR_TEMPO =3D SNDCTL_TMR_TEMPO; >> +unsigned IOCTL_SNDCTL_TMR_TIMEBASE =3D SNDCTL_TMR_TIMEBASE; >> +unsigned IOCTL_SOUND_MIXER_READ_ALTPCM =3D SOUND_MIXER_READ_ALTPCM; >> +unsigned IOCTL_SOUND_MIXER_READ_BASS =3D SOUND_MIXER_READ_BASS; >> +unsigned IOCTL_SOUND_MIXER_READ_CAPS =3D SOUND_MIXER_READ_CAPS; >> +unsigned IOCTL_SOUND_MIXER_READ_CD =3D SOUND_MIXER_READ_CD; >> +unsigned IOCTL_SOUND_MIXER_READ_DEVMASK =3D SOUND_MIXER_READ_DEVMASK; >> +unsigned IOCTL_SOUND_MIXER_READ_ENHANCE =3D SOUND_MIXER_READ_ENHANCE; >> +unsigned IOCTL_SOUND_MIXER_READ_IGAIN =3D SOUND_MIXER_READ_IGAIN; >> +unsigned IOCTL_SOUND_MIXER_READ_IMIX =3D SOUND_MIXER_READ_IMIX; >> +unsigned IOCTL_SOUND_MIXER_READ_LINE =3D SOUND_MIXER_READ_LINE; >> +unsigned IOCTL_SOUND_MIXER_READ_LINE1 =3D SOUND_MIXER_READ_LINE1; >> +unsigned IOCTL_SOUND_MIXER_READ_LINE2 =3D SOUND_MIXER_READ_LINE2; >> +unsigned IOCTL_SOUND_MIXER_READ_LINE3 =3D SOUND_MIXER_READ_LINE3; >> +unsigned IOCTL_SOUND_MIXER_READ_LOUD =3D SOUND_MIXER_READ_LOUD; >> +unsigned IOCTL_SOUND_MIXER_READ_MIC =3D SOUND_MIXER_READ_MIC; >> +unsigned IOCTL_SOUND_MIXER_READ_MUTE =3D SOUND_MIXER_READ_MUTE; >> +unsigned IOCTL_SOUND_MIXER_READ_OGAIN =3D SOUND_MIXER_READ_OGAIN; >> +unsigned IOCTL_SOUND_MIXER_READ_PCM =3D SOUND_MIXER_READ_PCM; >> +unsigned IOCTL_SOUND_MIXER_READ_RECLEV =3D SOUND_MIXER_READ_RECLEV; >> +unsigned IOCTL_SOUND_MIXER_READ_RECMASK =3D SOUND_MIXER_READ_RECMASK; >> +unsigned IOCTL_SOUND_MIXER_READ_RECSRC =3D SOUND_MIXER_READ_RECSRC; >> +unsigned IOCTL_SOUND_MIXER_READ_SPEAKER =3D SOUND_MIXER_READ_SPEAKER; >> +unsigned IOCTL_SOUND_MIXER_READ_STEREODEVS =3D >> SOUND_MIXER_READ_STEREODEVS; >> +unsigned IOCTL_SOUND_MIXER_READ_SYNTH =3D SOUND_MIXER_READ_SYNTH; >> +unsigned IOCTL_SOUND_MIXER_READ_TREBLE =3D SOUND_MIXER_READ_TREBLE; >> +unsigned IOCTL_SOUND_MIXER_READ_VOLUME =3D SOUND_MIXER_READ_VOLUME; >> +unsigned IOCTL_SOUND_MIXER_WRITE_ALTPCM =3D SOUND_MIXER_WRITE_ALTPCM; >> +unsigned IOCTL_SOUND_MIXER_WRITE_BASS =3D SOUND_MIXER_WRITE_BASS; >> +unsigned IOCTL_SOUND_MIXER_WRITE_CD =3D SOUND_MIXER_WRITE_CD; >> +unsigned IOCTL_SOUND_MIXER_WRITE_ENHANCE =3D SOUND_MIXER_WRITE_ENHANCE; >> +unsigned IOCTL_SOUND_MIXER_WRITE_IGAIN =3D SOUND_MIXER_WRITE_IGAIN; >> +unsigned IOCTL_SOUND_MIXER_WRITE_IMIX =3D SOUND_MIXER_WRITE_IMIX; >> +unsigned IOCTL_SOUND_MIXER_WRITE_LINE =3D SOUND_MIXER_WRITE_LINE; >> +unsigned IOCTL_SOUND_MIXER_WRITE_LINE1 =3D SOUND_MIXER_WRITE_LINE1; >> +unsigned IOCTL_SOUND_MIXER_WRITE_LINE2 =3D SOUND_MIXER_WRITE_LINE2; >> +unsigned IOCTL_SOUND_MIXER_WRITE_LINE3 =3D SOUND_MIXER_WRITE_LINE3; >> +unsigned IOCTL_SOUND_MIXER_WRITE_LOUD =3D SOUND_MIXER_WRITE_LOUD; >> +unsigned IOCTL_SOUND_MIXER_WRITE_MIC =3D SOUND_MIXER_WRITE_MIC; >> +unsigned IOCTL_SOUND_MIXER_WRITE_MUTE =3D SOUND_MIXER_WRITE_MUTE; >> +unsigned IOCTL_SOUND_MIXER_WRITE_OGAIN =3D SOUND_MIXER_WRITE_OGAIN; >> +unsigned IOCTL_SOUND_MIXER_WRITE_PCM =3D SOUND_MIXER_WRITE_PCM; >> +unsigned IOCTL_SOUND_MIXER_WRITE_RECLEV =3D SOUND_MIXER_WRITE_RECLEV; >> +unsigned IOCTL_SOUND_MIXER_WRITE_RECSRC =3D SOUND_MIXER_WRITE_RECSRC; >> +unsigned IOCTL_SOUND_MIXER_WRITE_SPEAKER =3D SOUND_MIXER_WRITE_SPEAKER; >> +unsigned IOCTL_SOUND_MIXER_WRITE_SYNTH =3D SOUND_MIXER_WRITE_SYNTH; >> +unsigned IOCTL_SOUND_MIXER_WRITE_TREBLE =3D SOUND_MIXER_WRITE_TREBLE; >> +unsigned IOCTL_SOUND_MIXER_WRITE_VOLUME =3D SOUND_MIXER_WRITE_VOLUME; >> +unsigned IOCTL_VT_ACTIVATE =3D VT_ACTIVATE; >> +unsigned IOCTL_VT_GETMODE =3D VT_GETMODE; >> +unsigned IOCTL_VT_OPENQRY =3D VT_OPENQRY; >> +unsigned IOCTL_VT_RELDISP =3D VT_RELDISP; >> +unsigned IOCTL_VT_SETMODE =3D VT_SETMODE; >> +unsigned IOCTL_VT_WAITACTIVE =3D VT_WAITACTIVE; >> +unsigned IOCTL_GIO_SCRNMAP =3D GIO_SCRNMAP; >> +unsigned IOCTL_KDDISABIO =3D KDDISABIO; >> +unsigned IOCTL_KDENABIO =3D KDENABIO; >> +unsigned IOCTL_KDGETLED =3D KDGETLED; >> +unsigned IOCTL_KDGETMODE =3D KDGETMODE; >> +unsigned IOCTL_KDGKBMODE =3D KDGKBMODE; >> +unsigned IOCTL_KDGKBTYPE =3D KDGKBTYPE; >> +unsigned IOCTL_KDMKTONE =3D KDMKTONE; >> +unsigned IOCTL_KDSETLED =3D KDSETLED; >> +unsigned IOCTL_KDSETMODE =3D KDSETMODE; >> +unsigned IOCTL_KDSKBMODE =3D KDSKBMODE; >> +unsigned IOCTL_KIOCSOUND =3D KIOCSOUND; >> +unsigned IOCTL_PIO_SCRNMAP =3D PIO_SCRNMAP; >> +unsigned IOCTL_SNDCTL_DSP_GETISPACE =3D SNDCTL_DSP_GETISPACE; >> + >> +const int si_SEGV_MAPERR =3D SEGV_MAPERR; >> +const int si_SEGV_ACCERR =3D SEGV_ACCERR; >> +const int unvis_valid =3D UNVIS_VALID; >> +const int unvis_validpush =3D UNVIS_VALIDPUSH; >> +}=A0 // namespace __sanitizer >> >> using namespace __sanitizer; >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h >> index 71cf5b9c357..5e0ca9c7d78 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_freebsd.h >> @@ -18,18 +18,17 @@ >> >> #include "sanitizer_internal_defs.h" >> #include "sanitizer_platform.h" >> - >> #include "sanitizer_platform_limits_posix.h" >> >> -// FreeBSD's dlopen() returns a pointer to an Obj_Entry structure that >> -// incorporates the map structure. >> -# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ >> - ((link_map*)((handle) =3D=3D nullptr ? nullptr : ((char*)(handle) + >> 560))) >> // Get sys/_types.h, because that tells us whether 64-bit inodes are >> // used in struct dirent below. >> #include >> >> namespace __sanitizer { >> +void *__sanitizer_get_link_map_by_dlopen_handle(void *handle); >> +#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ >> + (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle) >> + >> extern unsigned struct_utsname_sz; >> extern unsigned struct_stat_sz; >> #if defined(__powerpc64__) >> @@ -53,6 +52,7 @@ extern unsigned struct_timezone_sz; >> extern unsigned struct_tms_sz; >> extern unsigned struct_itimerspec_sz; >> extern unsigned struct_sigevent_sz; >> +extern unsigned struct_stack_t_sz; >> extern unsigned struct_sched_param_sz; >> extern unsigned struct_statfs64_sz; >> extern unsigned struct_statfs_sz; >> @@ -147,7 +147,7 @@ struct __sanitizer_ifaddrs { >> unsigned int ifa_flags; >> void *ifa_addr; // (struct sockaddr *) >> void *ifa_netmask; // (struct sockaddr *) >> -# undef ifa_dstaddr >> +#undef ifa_dstaddr >> void *ifa_dstaddr; // (struct sockaddr *) >> void *ifa_data; >> }; >> @@ -630,27 +630,27 @@ extern unsigned struct_cap_rights_sz; >> >> extern unsigned struct_fstab_sz; >> extern unsigned struct_StringList_sz; >> -} // namespace __sanitizer >> +}=A0 // namespace __sanitizer >> >> #define CHECK_TYPE_SIZE(TYPE) \ >> COMPILER_CHECK(sizeof(__sanitizer_##TYPE) =3D=3D sizeof(TYPE)) >> >> -#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ >> - COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *) NULL)->MEMBER) =3D=3D = \ >> - sizeof(((CLASS *) NULL)->MEMBER)); \ >> - COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) =3D=3D = \ >> +#define CHECK_SIZE_AND_OFFSET(CLASS, MEMBER) \ >> + COMPILER_CHECK(sizeof(((__sanitizer_##CLASS *)NULL)->MEMBER) =3D=3D \ >> + sizeof(((CLASS *)NULL)->MEMBER)); \ >> + COMPILER_CHECK(offsetof(__sanitizer_##CLASS, MEMBER) =3D=3D \ >> 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) =3D=3D \ >> - sizeof(((struct CLASS *) >> NULL)->MEMBER)); \ >> - COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) >> =3D=3D \ >> +#define CHECK_STRUCT_SIZE_AND_OFFSET(CLASS, >> MEMBER) \ >> + COMPILER_CHECK(sizeof(((struct __sanitizer_##CLASS >> *)NULL)->MEMBER) =3D=3D \ >> + sizeof(((struct CLASS >> *)NULL)->MEMBER)); \ >> + COMPILER_CHECK(offsetof(struct __sanitizer_##CLASS, MEMBER) >> =3D=3D \ >> offsetof(struct CLASS, MEMBER)) >> >> #define SIGACTION_SYMNAME sigaction >> >> #endif >> >> -#endif // SANITIZER_FREEBSD >> +#endif // SANITIZER_FREEBSD >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp >> index f22f5039128..c51327e1269 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp >> @@ -26,12 +26,9 @@ >> >> // With old kernels (and even new kernels on powerpc) asm/stat.h >> uses types that >> // are not defined anywhere in userspace headers. Fake them. This >> seems to work >> -// fine with newer headers, too. Beware that with , >> struct stat >> -// takes the form of struct stat64 on 32-bit platforms if >> _FILE_OFFSET_BITS=3D64. >> -// Also, for some platforms (e.g. mips) there are additional members >> in the >> -// struct stat:s. >> +// fine with newer headers, too. >> #include >> -#if defined(__x86_64__) >> +#if defined(__x86_64__) ||=A0 defined(__mips__) >> #include >> #else >> #define ino_t __kernel_ino_t >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp >> index f01de6c995e..25da334b63f 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.cpp >> @@ -17,6 +17,7 @@ >> >> #define _KMEMUSER >> #define RAY_DO_SIGLEV >> +#define __LEGACY_PT_LWPINFO >> >> // clang-format off >> #include >> @@ -71,6 +72,15 @@ >> #include >> #include >> #include >> + >> +// Compat for NetBSD < 9.99.30. >> +#ifndef PT_LWPSTATUS >> +#define PT_LWPSTATUS 24 >> +#endif >> +#ifndef PT_LWPNEXT >> +#define PT_LWPNEXT 25 >> +#endif >> + >> #include >> #include >> #include >> @@ -109,7 +119,12 @@ >> #include >> #include >> #include >> +#if !__NetBSD_Prereq__(9, 99, 26) >> #include >> +#else >> +#define FILEMON_SET_FD _IOWR('S', 1, int) >> +#define FILEMON_SET_PID _IOWR('S', 2, pid_t) >> +#endif >> #include >> #include >> #include >> @@ -146,12 +161,121 @@ >> #include >> #include >> #include >> +#if __has_include() >> #include >> #include >> #include >> +#else >> +/* Fallback for MKIPFILTER=3Dno */ >> + >> +typedef struct ap_control { >> + char apc_label[16]; >> + char apc_config[16]; >> + unsigned char apc_p; >> + unsigned long apc_cmd; >> + unsigned long apc_arg; >> + void *apc_data; >> + size_t apc_dsize; >> +} ap_ctl_t; >> + >> +typedef struct ipftq { >> + ipfmutex_t ifq_lock; >> + unsigned int ifq_ttl; >> + void *ifq_head; >> + void **ifq_tail; >> + void *ifq_next; >> + void **ifq_pnext; >> + int ifq_ref; >> + unsigned int ifq_flags; >> +} ipftq_t; >> + >> +typedef struct ipfobj { >> + uint32_t ipfo_rev; >> + uint32_t ipfo_size; >> + void *ipfo_ptr; >> + int ipfo_type; >> + int ipfo_offset; >> + int ipfo_retval; >> + unsigned char ipfo_xxxpad[28]; >> +} ipfobj_t; >> + >> +#define SIOCADNAT _IOW('r', 60, struct ipfobj) >> +#define SIOCRMNAT _IOW('r', 61, struct ipfobj) >> +#define SIOCGNATS _IOWR('r', 62, struct ipfobj) >> +#define SIOCGNATL _IOWR('r', 63, struct ipfobj) >> +#define SIOCPURGENAT _IOWR('r', 100, struct ipfobj) >> +#endif >> #include >> #include >> +#if !__NetBSD_Prereq__(9, 99, 51) >> #include >> +#else >> +struct smbioc_flags { >> + int ioc_level; >> + int ioc_mask; >> + int ioc_flags; >> +}; >> +struct smbioc_oshare { >> + int ioc_opt; >> + int ioc_stype; >> + char ioc_share[129]; >> + char ioc_password[129]; >> + uid_t ioc_owner; >> + gid_t ioc_group; >> + mode_t ioc_mode; >> + mode_t ioc_rights; >> +}; >> +struct smbioc_ossn { >> + int ioc_opt; >> + uint32_t ioc_svlen; >> + struct sockaddr *ioc_server; >> + uint32_t ioc_lolen; >> + struct sockaddr *ioc_local; >> + char ioc_srvname[16]; >> + int ioc_timeout; >> + int ioc_retrycount; >> + char ioc_localcs[16]; >> + char ioc_servercs[16]; >> + char ioc_user[129]; >> + char ioc_workgroup[129]; >> + char ioc_password[129]; >> + uid_t ioc_owner; >> + gid_t ioc_group; >> + mode_t ioc_mode; >> + mode_t ioc_rights; >> +}; >> +struct smbioc_lookup { >> + int ioc_level; >> + int ioc_flags; >> + struct smbioc_ossn ioc_ssn; >> + struct smbioc_oshare ioc_sh; >> +}; >> +struct smbioc_rq { >> + u_char ioc_cmd; >> + u_char ioc_twc; >> + void *ioc_twords; >> + u_short ioc_tbc; >> + void *ioc_tbytes; >> + int ioc_rpbufsz; >> + char *ioc_rpbuf; >> + u_char ioc_rwc; >> + u_short ioc_rbc; >> +}; >> +struct smbioc_rw { >> + u_int16_t ioc_fh; >> + char *ioc_base; >> + off_t ioc_offset; >> + int ioc_cnt; >> +}; >> +#define SMBIOC_OPENSESSION _IOW('n', 100, struct smbioc_ossn) >> +#define SMBIOC_OPENSHARE _IOW('n', 101, struct smbioc_oshare) >> +#define SMBIOC_REQUEST _IOWR('n', 102, struct smbioc_rq) >> +#define SMBIOC_T2RQ _IOWR('n', 103, struct smbioc_t2rq) >> +#define SMBIOC_SETFLAGS _IOW('n', 104, struct smbioc_flags) >> +#define SMBIOC_LOOKUP _IOW('n', 106, struct smbioc_lookup) >> +#define SMBIOC_READ _IOWR('n', 107, struct smbioc_rw) >> +#define SMBIOC_WRITE _IOWR('n', 108, struct smbioc_rw) >> +#endif >> #include >> #include >> #include >> @@ -175,7 +299,21 @@ >> #include >> #include >> #include >> +#if !__NetBSD_Prereq__(9, 99, 44) >> #include >> +#else >> +struct urio_command { >> + unsigned short length; >> + int request; >> + int requesttype; >> + int value; >> + int index; >> + void *buffer; >> + int timeout; >> +}; >> +#define URIO_SEND_COMMAND _IOWR('U', 200, struct urio_command) >> +#define URIO_RECV_COMMAND _IOWR('U', 201, struct urio_command) >> +#endif >> #include >> #include >> #include >> @@ -184,6 +322,7 @@ >> #include >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -229,9 +368,15 @@ >> >> // Include these after system headers to avoid name clashes and >> ambiguities. >> #include "sanitizer_internal_defs.h" >> +#include "sanitizer_libc.h" >> #include "sanitizer_platform_limits_netbsd.h" >> >> namespace __sanitizer { >> +void *__sanitizer_get_link_map_by_dlopen_handle(void* handle) { >> + void *p =3D nullptr; >> + return internal_dlinfo(handle, RTLD_DI_LINKMAP, &p) =3D=3D 0 ? p : >> nullptr; >> +} >> + >> unsigned struct_utsname_sz =3D sizeof(struct utsname); >> unsigned struct_stat_sz =3D sizeof(struct stat); >> unsigned struct_rusage_sz =3D sizeof(struct rusage); >> @@ -240,6 +385,7 @@ unsigned struct_passwd_sz =3D sizeof(struct passwd); >> unsigned struct_group_sz =3D sizeof(struct group); >> unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> +unsigned struct_stack_t_sz =3D sizeof(stack_t); >> unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> unsigned pthread_t_sz =3D sizeof(pthread_t); >> unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> @@ -287,6 +433,8 @@ int ptrace_pt_get_event_mask =3D PT_GET_EVENT_MASK; >> int ptrace_pt_get_process_state =3D PT_GET_PROCESS_STATE; >> int ptrace_pt_set_siginfo =3D PT_SET_SIGINFO; >> int ptrace_pt_get_siginfo =3D PT_GET_SIGINFO; >> +int ptrace_pt_lwpstatus =3D PT_LWPSTATUS; >> +int ptrace_pt_lwpnext =3D PT_LWPNEXT; >> int ptrace_piod_read_d =3D PIOD_READ_D; >> int ptrace_piod_write_d =3D PIOD_WRITE_D; >> int ptrace_piod_read_i =3D PIOD_READ_I; >> @@ -319,6 +467,8 @@ int ptrace_pt_getdbregs =3D -1; >> >> unsigned struct_ptrace_ptrace_io_desc_struct_sz =3D sizeof(struct >> ptrace_io_desc); >> unsigned struct_ptrace_ptrace_lwpinfo_struct_sz =3D sizeof(struct >> ptrace_lwpinfo); >> +unsigned struct_ptrace_ptrace_lwpstatus_struct_sz =3D >> + sizeof(struct __sanitizer_ptrace_lwpstatus); >> unsigned struct_ptrace_ptrace_event_struct_sz =3D >> sizeof(ptrace_event_t); >> unsigned struct_ptrace_ptrace_siginfo_struct_sz =3D >> sizeof(ptrace_siginfo_t); >> >> @@ -698,6 +848,7 @@ unsigned struct_nvmm_ioc_machine_configure_sz =3D >> sizeof(nvmm_ioc_machine_configure); >> unsigned struct_nvmm_ioc_vcpu_create_sz =3D >> sizeof(nvmm_ioc_vcpu_create); >> unsigned struct_nvmm_ioc_vcpu_destroy_sz =3D >> sizeof(nvmm_ioc_vcpu_destroy); >> +unsigned struct_nvmm_ioc_vcpu_configure_sz =3D >> sizeof(nvmm_ioc_vcpu_configure); >> unsigned struct_nvmm_ioc_vcpu_setstate_sz =3D >> sizeof(nvmm_ioc_vcpu_destroy); >> unsigned struct_nvmm_ioc_vcpu_getstate_sz =3D >> sizeof(nvmm_ioc_vcpu_getstate); >> unsigned struct_nvmm_ioc_vcpu_inject_sz =3D >> sizeof(nvmm_ioc_vcpu_inject); >> @@ -1458,6 +1609,7 @@ unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY =3D >> NVMM_IOC_MACHINE_DESTROY; >> unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE =3D >> NVMM_IOC_MACHINE_CONFIGURE; >> unsigned IOCTL_NVMM_IOC_VCPU_CREATE =3D NVMM_IOC_VCPU_CREATE; >> unsigned IOCTL_NVMM_IOC_VCPU_DESTROY =3D NVMM_IOC_VCPU_DESTROY; >> +unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE =3D NVMM_IOC_VCPU_CONFIGURE; >> unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE =3D NVMM_IOC_VCPU_SETSTATE; >> unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE =3D NVMM_IOC_VCPU_GETSTATE; >> unsigned IOCTL_NVMM_IOC_VCPU_INJECT =3D NVMM_IOC_VCPU_INJECT; >> @@ -1534,6 +1686,7 @@ unsigned IOCTL_IOC_NPF_STATS =3D IOC_NPF_STATS; >> unsigned IOCTL_IOC_NPF_SAVE =3D IOC_NPF_SAVE; >> unsigned IOCTL_IOC_NPF_RULE =3D IOC_NPF_RULE; >> unsigned IOCTL_IOC_NPF_CONN_LOOKUP =3D IOC_NPF_CONN_LOOKUP; >> +unsigned IOCTL_IOC_NPF_TABLE_REPLACE =3D IOC_NPF_TABLE_REPLACE; >> unsigned IOCTL_PPPOESETPARMS =3D PPPOESETPARMS; >> unsigned IOCTL_PPPOEGETPARMS =3D PPPOEGETPARMS; >> unsigned IOCTL_PPPOEGETSESSION =3D PPPOEGETSESSION; >> @@ -2392,4 +2545,42 @@ CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_flags); >> CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_props); >> CHECK_SIZE_AND_OFFSET(modctl_load_t, ml_propslen); >> >> +// Compat with 9.0 >> +struct statvfs90 { >> + unsigned long f_flag; >> + unsigned long f_bsize; >> + unsigned long f_frsize; >> + unsigned long f_iosize; >> + >> + u64 f_blocks; >> + u64 f_bfree; >> + u64 f_bavail; >> + u64 f_bresvd; >> + >> + u64 f_files; >> + u64 f_ffree; >> + u64 f_favail; >> + u64 f_fresvd; >> + >> + u64 f_syncreads; >> + u64 f_syncwrites; >> + >> + u64 f_asyncreads; >> + u64 f_asyncwrites; >> + >> + struct { >> + s32 __fsid_val[2]; >> + } f_fsidx; >> + unsigned long f_fsid; >> + unsigned long f_namemax; >> + u32 f_owner; >> + >> + u32 f_spare[4]; >> + >> + char f_fstypename[32]; >> + char f_mntonname[32]; >> + char f_mntfromname[32]; >> +}; >> +unsigned struct_statvfs90_sz =3D sizeof(struct statvfs90); >> + >> #endif // SANITIZER_NETBSD >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h >> index 419d830c69e..d80280d9bf8 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_netbsd.h >> @@ -19,18 +19,11 @@ >> #include "sanitizer_internal_defs.h" >> #include "sanitizer_platform.h" >> >> -#define _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, shift) \ >> - ((link_map *)((handle) =3D=3D nullptr ? nullptr : ((char *)(handle) + >> (shift)))) >> - >> -#if defined(__x86_64__) >> -#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ >> - _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 264) >> -#elif defined(__i386__) >> -#define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ >> - _GET_LINK_MAP_BY_DLOPEN_HANDLE(handle, 136) >> -#endif >> - >> namespace __sanitizer { >> +void *__sanitizer_get_link_map_by_dlopen_handle(void *handle); >> +# define GET_LINK_MAP_BY_DLOPEN_HANDLE(handle) \ >> + (link_map *)__sanitizer_get_link_map_by_dlopen_handle(handle) >> + >> extern unsigned struct_utsname_sz; >> extern unsigned struct_stat_sz; >> extern unsigned struct_rusage_sz; >> @@ -48,6 +41,7 @@ extern unsigned struct_timezone_sz; >> extern unsigned struct_tms_sz; >> extern unsigned struct_itimerspec_sz; >> extern unsigned struct_sigevent_sz; >> +extern unsigned struct_stack_t_sz; >> extern unsigned struct_sched_param_sz; >> extern unsigned struct_statfs_sz; >> extern unsigned struct_sockaddr_sz; >> @@ -412,6 +406,8 @@ extern int ptrace_pt_get_event_mask; >> extern int ptrace_pt_get_process_state; >> extern int ptrace_pt_set_siginfo; >> extern int ptrace_pt_get_siginfo; >> +extern int ptrace_pt_lwpstatus; >> +extern int ptrace_pt_lwpnext; >> extern int ptrace_piod_read_d; >> extern int ptrace_piod_write_d; >> extern int ptrace_piod_read_i; >> @@ -436,8 +432,17 @@ struct __sanitizer_ptrace_lwpinfo { >> int pl_event; >> }; >> >> +struct __sanitizer_ptrace_lwpstatus { >> + __sanitizer_lwpid_t pl_lwpid; >> + __sanitizer_sigset_t pl_sigpend; >> + __sanitizer_sigset_t pl_sigmask; >> + char pl_name[20]; >> + void *pl_private; >> +}; >> + >> extern unsigned struct_ptrace_ptrace_io_desc_struct_sz; >> extern unsigned struct_ptrace_ptrace_lwpinfo_struct_sz; >> +extern unsigned struct_ptrace_ptrace_lwpstatus_struct_sz; >> extern unsigned struct_ptrace_ptrace_event_struct_sz; >> extern unsigned struct_ptrace_ptrace_siginfo_struct_sz; >> >> @@ -862,6 +867,7 @@ extern unsigned struct_nvmm_ioc_machine_destroy_sz; >> extern unsigned struct_nvmm_ioc_machine_configure_sz; >> extern unsigned struct_nvmm_ioc_vcpu_create_sz; >> extern unsigned struct_nvmm_ioc_vcpu_destroy_sz; >> +extern unsigned struct_nvmm_ioc_vcpu_configure_sz; >> extern unsigned struct_nvmm_ioc_vcpu_setstate_sz; >> extern unsigned struct_nvmm_ioc_vcpu_getstate_sz; >> extern unsigned struct_nvmm_ioc_vcpu_inject_sz; >> @@ -1611,6 +1617,7 @@ extern unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY; >> extern unsigned IOCTL_NVMM_IOC_MACHINE_CONFIGURE; >> extern unsigned IOCTL_NVMM_IOC_VCPU_CREATE; >> extern unsigned IOCTL_NVMM_IOC_VCPU_DESTROY; >> +extern unsigned IOCTL_NVMM_IOC_VCPU_CONFIGURE; >> extern unsigned IOCTL_NVMM_IOC_VCPU_SETSTATE; >> extern unsigned IOCTL_NVMM_IOC_VCPU_GETSTATE; >> extern unsigned IOCTL_NVMM_IOC_VCPU_INJECT; >> @@ -1685,6 +1692,7 @@ extern unsigned IOCTL_IOC_NPF_STATS; >> extern unsigned IOCTL_IOC_NPF_SAVE; >> extern unsigned IOCTL_IOC_NPF_RULE; >> extern unsigned IOCTL_IOC_NPF_CONN_LOOKUP; >> +extern unsigned IOCTL_IOC_NPF_TABLE_REPLACE; >> extern unsigned IOCTL_PPPOESETPARMS; >> extern unsigned IOCTL_PPPOEGETPARMS; >> extern unsigned IOCTL_PPPOEGETSESSION; >> @@ -2406,6 +2414,9 @@ struct __sanitizer_cdbw { >> >> #define SIGACTION_SYMNAME __sigaction14 >> >> +// Compat with 9.0 >> +extern unsigned struct_statvfs90_sz; >> + >> #endif // SANITIZER_NETBSD >> >> #endif >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.cpp >> index 12515626ce5..1420ecbfa56 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.cpp >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.cpp >> @@ -72,6 +72,7 @@ unsigned struct_passwd_sz =3D sizeof(struct passwd); >> unsigned struct_group_sz =3D sizeof(struct group); >> unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> +unsigned struct_stack_t_sz =3D sizeof(stack_t); >> unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> unsigned pthread_t_sz =3D sizeof(pthread_t); >> unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.h >> index 6d8b062716b..8a194872360 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_openbsd.h >> @@ -50,6 +50,7 @@ extern unsigned struct_timezone_sz; >> extern unsigned struct_tms_sz; >> extern unsigned struct_itimerspec_sz; >> extern unsigned struct_sigevent_sz; >> +extern unsigned struct_stack_t_sz; >> extern unsigned struct_statfs_sz; >> extern unsigned struct_sockaddr_sz; >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp >> index aa845df4dde..e71515f12e9 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp >> @@ -179,6 +179,7 @@ namespace __sanitizer { >> unsigned struct_group_sz =3D sizeof(struct group); >> unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> + unsigned struct_stack_t_sz =3D sizeof(stack_t); >> unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> unsigned pthread_t_sz =3D sizeof(pthread_t); >> unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h >> index d82fd5e4005..f6c8a1450a9 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h >> @@ -47,6 +47,7 @@ extern unsigned struct_timezone_sz; >> extern unsigned struct_tms_sz; >> extern unsigned struct_itimerspec_sz; >> extern unsigned struct_sigevent_sz; >> +extern unsigned struct_stack_t_sz; >> extern unsigned struct_sched_param_sz; >> extern unsigned struct_statfs64_sz; >> extern unsigned struct_regex_sz; >> @@ -82,7 +83,7 @@ const unsigned struct_kernel_stat64_sz =3D 104; >> #elif defined(__mips__) >> const unsigned struct_kernel_stat_sz =3D SANITIZER_ANDROID >> ? >> FIRST_32_SECOND_64(104, 128) >> - : FIRST_32_SECOND_64(144, >> 216); >> + : FIRST_32_SECOND_64(160, >> 216); >> const unsigned struct_kernel_stat64_sz =3D 104; >> #elif defined(__s390__) && !defined(__s390x__) >> const unsigned struct_kernel_stat_sz =3D 64; >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp >> index 9717d98ebf1..6ec1a1bdd11 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.cpp >> @@ -72,6 +72,7 @@ namespace __sanitizer { >> unsigned struct_group_sz =3D sizeof(struct group); >> unsigned siginfo_t_sz =3D sizeof(siginfo_t); >> unsigned struct_sigaction_sz =3D sizeof(struct sigaction); >> + unsigned struct_stack_t_sz =3D sizeof(stack_t); >> unsigned struct_itimerval_sz =3D sizeof(struct itimerval); >> unsigned pthread_t_sz =3D sizeof(pthread_t); >> unsigned pthread_mutex_t_sz =3D sizeof(pthread_mutex_t); >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h >> b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h >> index 77ae6e6a44d..85995e79792 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_solaris.h >> @@ -38,6 +38,7 @@ extern unsigned struct_timezone_sz; >> extern unsigned struct_tms_sz; >> extern unsigned struct_itimerspec_sz; >> extern unsigned struct_sigevent_sz; >> +extern unsigned struct_stack_t_sz; >> extern unsigned struct_sched_param_sz; >> extern unsigned struct_statfs64_sz; >> extern unsigned struct_statfs_sz; >> diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cpp >> b/libsanitizer/sanitizer_common/sanitizer_posix.cpp >> index d890a3a3177..e21661b42f8 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_posix.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_posix.cpp >> @@ -347,9 +347,17 @@ int GetNamedMappingFd(const char *name, uptr >> size, int *flags) { >> CHECK(internal_strlen(name) < sizeof(shmname) - 10); >> internal_snprintf(shmname, sizeof(shmname), "/dev/shm/%zu [%s]", >> internal_getpid(), name); >> + int o_cloexec =3D 0; >> +#if defined(O_CLOEXEC) >> + o_cloexec =3D O_CLOEXEC; >> +#endif >> int fd =3D ReserveStandardFds( >> - internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, >> S_IRWXU)); >> + internal_open(shmname, O_RDWR | O_CREAT | O_TRUNC | o_cloexec, >> S_IRWXU)); >> CHECK_GE(fd, 0); >> + if (!o_cloexec) { >> + int res =3D fcntl(fd, F_SETFD, FD_CLOEXEC); >> + CHECK_EQ(0, res); >> + } >> int res =3D internal_ftruncate(fd, size); >> CHECK_EQ(0, res); >> res =3D internal_unlink(shmname); >> diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.h >> b/libsanitizer/sanitizer_common/sanitizer_posix.h >> index 05fb0f63020..a1b49702da2 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_posix.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_posix.h >> @@ -39,7 +39,7 @@ uptr internal_write(fd_t fd, const void *buf, uptr >> count); >> >> // Memory >> uptr internal_mmap(void *addr, uptr length, int prot, int flags, >> - int fd, OFF_T offset); >> + int fd, u64 offset); >> uptr internal_munmap(void *addr, uptr length); >> int internal_mprotect(void *addr, uptr length, int prot); >> >> @@ -63,7 +63,7 @@ uptr internal_ptrace(int request, int pid, void >> *addr, void *data); >> uptr internal_waitpid(int pid, int *status, int options); >> >> int internal_fork(); >> -fd_t internal_spawn(const char *argv[], pid_t *pid); >> +fd_t internal_spawn(const char *argv[], const char *envp[], pid_t >> *pid); >> >> int internal_sysctl(const int *name, unsigned int namelen, void *oldp, >> uptr *oldlenp, const void *newp, uptr newlen); >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp >> b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp >> index 304b3a01a08..f920172c06d 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_posix_libcdep.cpp >> @@ -426,7 +426,8 @@ void AdjustStackSize(void *attr_) { >> #endif // !SANITIZER_GO >> >> pid_t StartSubprocess(const char *program, const char *const argv[], >> - fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) { >> + const char *const envp[], fd_t stdin_fd, fd_t >> stdout_fd, >> + fd_t stderr_fd) { >> auto file_closer =3D at_scope_exit([&] { >> if (stdin_fd !=3D kInvalidFd) { >> internal_close(stdin_fd); >> @@ -469,7 +470,8 @@ pid_t StartSubprocess(const char *program, const >> char *const argv[], >> >> for (int fd =3D sysconf(_SC_OPEN_MAX); fd > 2; fd--) >> internal_close(fd); >> >> - execv(program, const_cast(&argv[0])); >> + internal_execve(program, const_cast(&argv[0]), >> + const_cast(envp)); >> internal__exit(1); >> } >> >> diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h >> b/libsanitizer/sanitizer_common/sanitizer_procmaps.h >> index d0e5245f84d..665ed45fa93 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h >> @@ -15,18 +15,19 @@ >> >> #include "sanitizer_platform.h" >> >> -#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD >> ||=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 \ >> - SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_SOLARIS >> +#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ >> + SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_SOLARIS || \ >> + SANITIZER_FUCHSIA >> >> #include "sanitizer_common.h" >> #include "sanitizer_internal_defs.h" >> +#include "sanitizer_fuchsia.h" >> #include "sanitizer_linux.h" >> #include "sanitizer_mac.h" >> #include "sanitizer_mutex.h" >> >> namespace __sanitizer { >> >> - >> // Memory protection masks. >> static const uptr kProtectionRead =3D 1; >> static const uptr kProtectionWrite =3D 2; >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_procmaps_fuchsia.cpp >> b/libsanitizer/sanitizer_common/sanitizer_procmaps_fuchsia.cpp >> new file mode 100644 >> index 00000000000..cc3e9be0645 >> --- /dev/null >> +++ b/libsanitizer/sanitizer_common/sanitizer_procmaps_fuchsia.cpp >> @@ -0,0 +1,80 @@ >> +//=3D=3D=3D-- sanitizer_procmaps_fuchsia.cpp >> +//----------------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ----------=3D=3D=3D// >> >> +// >> +// Information about the process mappings (Fuchsia-specific parts). >> +//=3D=3D=3D------------------------------------------------------------= ----------=3D=3D=3D// >> >> + >> +#include "sanitizer_platform.h" >> +#if SANITIZER_FUCHSIA >> +#include >> +#include >> + >> +#include "sanitizer_common.h" >> +#include "sanitizer_procmaps.h" >> + >> +namespace __sanitizer { >> + >> +// The cache flag is ignored on Fuchsia because a process can always >> get this >> +// information via its process-self handle. >> +MemoryMappingLayout::MemoryMappingLayout(bool) { Reset(); } >> + >> +void MemoryMappingLayout::Reset() { >> + data_.data.clear(); >> + data_.current =3D 0; >> + >> + size_t count; >> + zx_status_t status =3D _zx_object_get_info( >> + _zx_process_self(), ZX_INFO_PROCESS_MAPS, nullptr, 0, nullptr, >> &count); >> + if (status !=3D ZX_OK) { >> + return; >> + } >> + >> + size_t filled; >> + do { >> + data_.data.resize(count); >> + status =3D _zx_object_get_info( >> + _zx_process_self(), ZX_INFO_PROCESS_MAPS, data_.data.data(), >> + count * sizeof(zx_info_maps_t), &filled, &count); >> + if (status !=3D ZX_OK) { >> + data_.data.clear(); >> + return; >> + } >> + } while (filled < count); >> +} >> + >> +MemoryMappingLayout::~MemoryMappingLayout() {} >> + >> +bool MemoryMappingLayout::Error() const { return data_.data.empty(); } >> + >> +bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) { >> + while (data_.current < data_.data.size()) { >> + const auto &entry =3D data_.data[data_.current++]; >> + if (entry.type =3D=3D ZX_INFO_MAPS_TYPE_MAPPING) { >> + segment->start =3D entry.base; >> + segment->end =3D entry.base + entry.size; >> + segment->offset =3D entry.u.mapping.vmo_offset; >> + const auto flags =3D entry.u.mapping.mmu_flags; >> + segment->protection =3D >> + ((flags & ZX_VM_PERM_READ) ? kProtectionRead : 0) | >> + ((flags & ZX_VM_PERM_WRITE) ? kProtectionWrite : 0) | >> + ((flags & ZX_VM_PERM_EXECUTE) ? kProtectionExecute : 0); >> + if (segment->filename && segment->filename_size > 0) { >> + uptr len =3D Min(sizeof(entry.name), segment->filename_size) - = 1; >> + internal_strncpy(segment->filename, entry.name, len); >> + segment->filename[len] =3D 0; >> + } >> + return true; >> + } >> + } >> + return false; >> +} >> + >> +}=A0 // namespace __sanitizer >> + >> +#endif // SANITIZER_FUCHSIA >> diff --git a/libsanitizer/sanitizer_common/sanitizer_ptrauth.h >> b/libsanitizer/sanitizer_common/sanitizer_ptrauth.h >> new file mode 100644 >> index 00000000000..4d0d96a64f6 >> --- /dev/null >> +++ b/libsanitizer/sanitizer_common/sanitizer_ptrauth.h >> @@ -0,0 +1,21 @@ >> +//=3D=3D=3D-- sanitizer_ptrauth.h -------------------------------------= *- >> C++ -*-=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ----------=3D=3D=3D// >> >> + >> +#ifndef SANITIZER_PTRAUTH_H >> +#define SANITIZER_PTRAUTH_H >> + >> +#if __has_feature(ptrauth_calls) >> +#include >> +#else >> +// Copied from >> +#define ptrauth_strip(__value, __key) __value >> +#define ptrauth_auth_data(__value, __old_key, __old_data) __value >> +#define ptrauth_string_discriminator(__string) ((int)0) >> +#endif >> + >> +#endif // SANITIZER_PTRAUTH_H >> diff --git a/libsanitizer/sanitizer_common/sanitizer_rtems.cpp >> b/libsanitizer/sanitizer_common/sanitizer_rtems.cpp >> index 0d2576c00ab..29bcfcfa6f1 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_rtems.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_rtems.cpp >> @@ -49,6 +49,10 @@ uptr internal_getpid() { >> return getpid(); >> } >> >> +int internal_dlinfo(void *handle, int request, void *p) { >> + UNIMPLEMENTED(); >> +} >> + >> bool FileExists(const char *filename) { >> struct stat st; >> if (stat(filename, &st)) >> diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp >> b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp >> index ce75cbe5d26..ef14fb704ee 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cpp >> @@ -60,8 +60,8 @@ static inline uhwptr *GetCanonicFrame(uptr bp, >> // Nope, this does not look right either. This means the frame >> after next does >> // not have a valid frame pointer, but we can still extract the >> caller PC. >> // Unfortunately, there is no way to decide between GCC and LLVM >> frame >> - // layouts. Assume GCC. >> - return bp_prev - 1; >> + // layouts. Assume LLVM. >> + return bp_prev; >> #else >> return (uhwptr*)bp; >> #endif >> @@ -84,21 +84,14 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr >> bp, uptr stack_top, >> IsAligned((uptr)frame, sizeof(*frame)) && >> size < max_depth) { >> #ifdef __powerpc__ >> - // PowerPC ABIs specify that the return address is saved on the >> - // *caller's* stack frame. Thus we must dereference the back chain >> - // to find the caller frame before extracting it. >> + // PowerPC ABIs specify that the return address is saved at offset >> + // 16 of the *caller's* stack frame. Thus we must dereference the >> + // back chain to find the caller frame before extracting it. >> uhwptr *caller_frame =3D (uhwptr*)frame[0]; >> if (!IsValidFrame((uptr)caller_frame, stack_top, bottom) || >> !IsAligned((uptr)caller_frame, sizeof(uhwptr))) >> break; >> - // For most ABIs the offset where the return address is saved is >> two >> - // register sizes. The exception is the SVR4 ABI, which uses an >> - // offset of only one register size. >> -#ifdef _CALL_SYSV >> - uhwptr pc1 =3D caller_frame[1]; >> -#else >> uhwptr pc1 =3D caller_frame[2]; >> -#endif >> #elif defined(__s390__) >> uhwptr pc1 =3D frame[14]; >> #else >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp >> b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp >> new file mode 100644 >> index 00000000000..3a246443ed9 >> --- /dev/null >> +++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_fuchsia.cpp >> @@ -0,0 +1,42 @@ >> +//=3D=3D=3D-- sanitizer_stoptheworld_fuchsia.cpp >> -------------------------------=3D=3D=3D// >> +// >> +// 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 >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> +// >> +// See sanitizer_stoptheworld.h for details. >> +// >> +//=3D=3D=3D------------------------------------------------------------= ---------=3D=3D=3D// >> >> + >> +#include "sanitizer_platform.h" >> + >> +#if SANITIZER_FUCHSIA >> + >> +#include >> + >> +#include "sanitizer_stoptheworld.h" >> + >> +namespace __sanitizer { >> + >> +// The Fuchsia implementation stops the world but doesn't offer a real >> +// SuspendedThreadsList argument. This is enough for ASan's use case, >> +// and LSan does not use this API on Fuchsia. >> +void StopTheWorld(StopTheWorldCallback callback, void *argument) { >> + struct Params { >> + StopTheWorldCallback callback; >> + void *argument; >> + } params =3D {callback, argument}; >> + __sanitizer_memory_snapshot( >> + nullptr, nullptr, nullptr, nullptr, >> + [](zx_status_t, void *data) { >> + auto params =3D reinterpret_cast(data); >> + params->callback({}, params->argument); >> + }, >> + ¶ms); >> +} >> + >> +}=A0 // namespace __sanitizer >> + >> +#endif // SANITIZER_FUCHSIA >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_mac.cpp >> b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_mac.cpp >> index 9dffd21ecb7..6c577426ad5 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_mac.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_mac.cpp >> @@ -50,7 +50,7 @@ struct RunThreadArgs { >> void *argument; >> }; >> >> -void RunThread(void *arg) { >> +void *RunThread(void *arg) { >> struct RunThreadArgs *run_args =3D (struct RunThreadArgs *)arg; >> SuspendedThreadsListMac suspended_threads_list; >> >> @@ -59,7 +59,7 @@ void RunThread(void *arg) { >> kern_return_t err =3D task_threads(mach_task_self(), &threads, >> &num_threads); >> if (err !=3D KERN_SUCCESS) { >> VReport(1, "Failed to get threads for task (errno %d).\n", err); >> - return; >> + return nullptr; >> } >> >> thread_t thread_self =3D mach_thread_self(); >> @@ -76,6 +76,7 @@ void RunThread(void *arg) { >> for (unsigned int i =3D 0; i < num_suspended; ++i) { >> thread_resume(suspended_threads_list.GetThread(i)); >> } >> + return nullptr; >> } >> >> void StopTheWorld(StopTheWorldCallback callback, void *argument) { >> @@ -159,7 +160,11 @@ PtraceRegistersStatus >> SuspendedThreadsListMac::GetRegistersAndSP( >> } >> >> internal_memcpy(buffer, ®s, sizeof(regs)); >> +#if defined(__aarch64__) && defined(arm_thread_state64_get_sp) >> + *sp =3D arm_thread_state64_get_sp(regs); >> +#else >> *sp =3D regs.SP_REG; >> +#endif >> >> // On x86_64 and aarch64, we must account for the stack redzone, >> which is 128 >> // bytes. >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cp= p >> b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cp= p >> >> index 5690d75097f..1ed21343254 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cp= p >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cp= p >> @@ -120,10 +120,18 @@ bool ThreadSuspender::SuspendAllThreads() { >> >> VReport(2, "Attached to process %d.\n", pid_); >> >> +#ifdef PT_LWPNEXT >> + struct ptrace_lwpstatus pl; >> + int op =3D PT_LWPNEXT; >> +#else >> struct ptrace_lwpinfo pl; >> - int val; >> + int op =3D PT_LWPINFO; >> +#endif >> + >> pl.pl_lwpid =3D 0; >> - while ((val =3D ptrace(PT_LWPINFO, pid_, (void *)&pl, sizeof(pl))) >> !=3D -1 && >> + >> + int val; >> + while ((val =3D ptrace(op, pid_, (void *)&pl, sizeof(pl))) !=3D -1 && >> pl.pl_lwpid !=3D 0) { >> suspended_threads_list_.Append(pl.pl_lwpid); >> VReport(2, "Appended thread %d in process %d.\n", pl.pl_lwpid, >> pid_); >> diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cpp >> index ce2ece5f4d5..0c4b84c767a 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cpp >> @@ -126,4 +126,10 @@ Symbolizer::SymbolizerScope::~SymbolizerScope() { >> sym_->end_hook_(); >> } >> >> +void Symbolizer::LateInitializeTools() { >> + for (auto &tool : tools_) { >> + tool.LateInitialize(); >> + } >> +} >> + >> }=A0 // namespace __sanitizer >> diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h >> index 51648e2d0e8..2476b0ea7bf 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h >> @@ -209,6 +209,9 @@ class Symbolizer final { >> private: >> const Symbolizer *sym_; >> }; >> + >> + // Calls `LateInitialize()` on all items in `tools_`. >> + void LateInitializeTools(); >> }; >> >> #ifdef SANITIZER_WINDOWS >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h >> index c04797dd61b..e4c351e667b 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_internal.h >> @@ -69,6 +69,11 @@ class SymbolizerTool { >> virtual const char *Demangle(const char *name) { >> return nullptr; >> } >> + >> + // Called during the LateInitialize phase of Sanitizer >> initialization. >> + // Usually this is a safe place to call code that might need to >> use user >> + // memory allocators. >> + virtual void LateInitialize() {} >> }; >> >> // SymbolizerProcess encapsulates communication between the tool and >> @@ -86,6 +91,8 @@ class SymbolizerProcess { >> // Customizable by subclasses. >> virtual bool StartSymbolizerSubprocess(); >> virtual bool ReadFromSymbolizer(char *buffer, uptr max_length); >> + // Return the environment to run the symbolizer in. >> + virtual char **GetEnvP() { return GetEnviron(); } >> >> private: >> virtual bool ReachedEndOfOutput(const char *buffer, uptr length) >> const { >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp >> index 3b19a6836ec..490c6fe89be 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp >> @@ -39,9 +39,9 @@ const char *ExtractToken(const char *str, const >> char *delims, char **result) { >> } >> >> const char *ExtractInt(const char *str, const char *delims, int >> *result) { >> - char *buff; >> + char *buff =3D nullptr; >> const char *ret =3D ExtractToken(str, delims, &buff); >> - if (buff !=3D 0) { >> + if (buff) { >> *result =3D (int)internal_atoll(buff); >> } >> InternalFree(buff); >> @@ -49,9 +49,9 @@ const char *ExtractInt(const char *str, const char >> *delims, int *result) { >> } >> >> const char *ExtractUptr(const char *str, const char *delims, uptr >> *result) { >> - char *buff; >> + char *buff =3D nullptr; >> const char *ret =3D ExtractToken(str, delims, &buff); >> - if (buff !=3D 0) { >> + if (buff) { >> *result =3D (uptr)internal_atoll(buff); >> } >> InternalFree(buff); >> @@ -59,9 +59,9 @@ const char *ExtractUptr(const char *str, const char >> *delims, uptr *result) { >> } >> >> const char *ExtractSptr(const char *str, const char *delims, sptr >> *result) { >> - char *buff; >> + char *buff =3D nullptr; >> const char *ret =3D ExtractToken(str, delims, &buff); >> - if (buff !=3D 0) { >> + if (buff) { >> *result =3D (sptr)internal_atoll(buff); >> } >> InternalFree(buff); >> @@ -83,7 +83,7 @@ const char *ExtractTokenUpToDelimiter(const char >> *str, const char *delimiter, >> >> SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { >> BlockingMutexLock l(&mu_); >> - const char *module_name; >> + const char *module_name =3D nullptr; >> uptr module_offset; >> ModuleArch arch; >> SymbolizedStack *res =3D SymbolizedStack::New(addr); >> @@ -103,7 +103,7 @@ SymbolizedStack *Symbolizer::SymbolizePC(uptr >> addr) { >> >> bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { >> BlockingMutexLock l(&mu_); >> - const char *module_name; >> + const char *module_name =3D nullptr; >> uptr module_offset; >> ModuleArch arch; >> if (!FindModuleNameAndOffsetForAddress(addr, &module_name, >> &module_offset, >> @@ -124,7 +124,7 @@ bool Symbolizer::SymbolizeData(uptr addr, >> DataInfo *info) { >> >> bool Symbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { >> BlockingMutexLock l(&mu_); >> - const char *module_name; >> + const char *module_name =3D nullptr; >> if (!FindModuleNameAndOffsetForAddress( >> addr, &module_name, &info->module_offset, >> &info->module_arch)) >> return false; >> @@ -175,7 +175,7 @@ bool >> Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, >> uptr >> *module_offset, >> ModuleArch >> *module_arch) { >> const LoadedModule *module =3D FindModuleForAddress(address); >> - if (module =3D=3D nullptr) >> + if (!module) >> return false; >> *module_name =3D module->full_name(); >> *module_offset =3D address - module->base_address(); >> @@ -292,7 +292,7 @@ LLVMSymbolizer::LLVMSymbolizer(const char *path, >> LowLevelAllocator *allocator) >> // Windows, so extract tokens from the right hand side first. The >> column info is >> // also optional. >> static const char *ParseFileLineInfo(AddressInfo *info, const char >> *str) { >> - char *file_line_info =3D 0; >> + char *file_line_info =3D nullptr; >> str =3D ExtractToken(str, "\n", &file_line_info); >> CHECK(file_line_info); >> >> @@ -323,7 +323,7 @@ void ParseSymbolizePCOutput(const char *str, >> SymbolizedStack *res) { >> bool top_frame =3D true; >> SymbolizedStack *last =3D res; >> while (true) { >> - char *function_name =3D 0; >> + char *function_name =3D nullptr; >> str =3D ExtractToken(str, "\n", &function_name); >> CHECK(function_name); >> if (function_name[0] =3D=3D '\0') { >> @@ -402,32 +402,29 @@ bool LLVMSymbolizer::SymbolizePC(uptr addr, >> SymbolizedStack *stack) { >> AddressInfo *info =3D &stack->info; >> const char *buf =3D FormatAndSendCommand( >> "CODE", info->module, info->module_offset, info->module_arch); >> - if (buf) { >> - ParseSymbolizePCOutput(buf, stack); >> - return true; >> - } >> - return false; >> + if (!buf) >> + return false; >> + ParseSymbolizePCOutput(buf, stack); >> + return true; >> } >> >> bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { >> const char *buf =3D FormatAndSendCommand( >> "DATA", info->module, info->module_offset, info->module_arch); >> - if (buf) { >> - ParseSymbolizeDataOutput(buf, info); >> - info->start +=3D (addr - info->module_offset); // Add the base >> address. >> - return true; >> - } >> - return false; >> + if (!buf) >> + return false; >> + ParseSymbolizeDataOutput(buf, info); >> + info->start +=3D (addr - info->module_offset); // Add the base addres= s. >> + return true; >> } >> >> bool LLVMSymbolizer::SymbolizeFrame(uptr addr, FrameInfo *info) { >> const char *buf =3D FormatAndSendCommand( >> "FRAME", info->module, info->module_offset, info->module_arch); >> - if (buf) { >> - ParseSymbolizeFrameOutput(buf, &info->locals); >> - return true; >> - } >> - return false; >> + if (!buf) >> + return false; >> + ParseSymbolizeFrameOutput(buf, &info->locals); >> + return true; >> } >> >> const char *LLVMSymbolizer::FormatAndSendCommand(const char >> *command_prefix, >> @@ -435,21 +432,21 @@ const char >> *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix, >> uptr module_offset, >> ModuleArch arch) { >> CHECK(module_name); >> - if (arch =3D=3D kModuleArchUnknown) { >> - if (internal_snprintf(buffer_, kBufferSize, "%s \"%s\" 0x%zx\n", >> - command_prefix, module_name, >> - module_offset) >=3D >> static_cast(kBufferSize)) { >> - Report("WARNING: Command buffer too small"); >> - return nullptr; >> - } >> - } else { >> - if (internal_snprintf(buffer_, kBufferSize, "%s \"%s:%s\" 0x%zx\n", >> - command_prefix, module_name, >> ModuleArchToString(arch), >> - module_offset) >=3D >> static_cast(kBufferSize)) { >> - Report("WARNING: Command buffer too small"); >> - return nullptr; >> - } >> + int size_needed =3D 0; >> + if (arch =3D=3D kModuleArchUnknown) >> + size_needed =3D internal_snprintf(buffer_, kBufferSize, "%s \"%s\" >> 0x%zx\n", >> + command_prefix, module_name, >> module_offset); >> + else >> + size_needed =3D internal_snprintf(buffer_, kBufferSize, >> + "%s \"%s:%s\" 0x%zx\n", >> command_prefix, >> + module_name, >> ModuleArchToString(arch), >> + module_offset); >> + >> + if (size_needed >=3D static_cast(kBufferSize)) { >> + Report("WARNING: Command buffer too small"); >> + return nullptr; >> } >> + >> return symbolizer_process_->SendCommand(buffer_); >> } >> >> @@ -492,16 +489,16 @@ const char >> *SymbolizerProcess::SendCommand(const char *command) { >> Report("WARNING: Failed to use and restart external >> symbolizer!\n"); >> failed_to_start_ =3D true; >> } >> - return 0; >> + return nullptr; >> } >> >> const char *SymbolizerProcess::SendCommandImpl(const char *command) { >> if (input_fd_ =3D=3D kInvalidFd || output_fd_ =3D=3D kInvalidFd) >> - return 0; >> + return nullptr; >> if (!WriteToSymbolizer(command, internal_strlen(command))) >> - return 0; >> + return nullptr; >> if (!ReadFromSymbolizer(buffer_, kBufferSize)) >> - return 0; >> + return nullptr; >> return buffer_; >> } >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cpp >> index a619ed092f0..cc233408d0c 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cpp >> @@ -20,6 +20,7 @@ >> >> #include >> #include >> +#include >> #include >> #include >> #include >> @@ -31,6 +32,9 @@ bool DlAddrSymbolizer::SymbolizePC(uptr addr, >> SymbolizedStack *stack) { >> Dl_info info; >> int result =3D dladdr((const void *)addr, &info); >> if (!result) return false; >> + >> + CHECK(addr >=3D reinterpret_cast(info.dli_saddr)); >> + stack->info.function_offset =3D addr - >> reinterpret_cast(info.dli_saddr); >> const char *demangled =3D DemangleSwiftAndCXX(info.dli_sname); >> if (!demangled) return false; >> stack->info.function =3D internal_strdup(demangled); >> @@ -47,18 +51,65 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, >> DataInfo *datainfo) { >> return true; >> } >> >> +#define K_ATOS_ENV_VAR "__check_mach_ports_lookup" >> + >> +// This cannot live in `AtosSymbolizerProcess` because instances of >> that object >> +// are allocated by the internal allocator which under ASan is >> poisoned with >> +// kAsanInternalHeapMagic. >> +static char kAtosMachPortEnvEntry[] =3D K_ATOS_ENV_VAR >> "=3D000000000000000"; >> + >> class AtosSymbolizerProcess : public SymbolizerProcess { >> public: >> - explicit AtosSymbolizerProcess(const char *path, pid_t parent_pid) >> + explicit AtosSymbolizerProcess(const char *path) >> : SymbolizerProcess(path, /*use_posix_spawn*/ true) { >> - // Put the string command line argument in the object so that it >> outlives >> - // the call to GetArgV. >> - internal_snprintf(pid_str_, sizeof(pid_str_), "%d", parent_pid); >> + pid_str_[0] =3D '\0'; >> + } >> + >> + void LateInitialize() { >> + if (SANITIZER_IOSSIM) { >> + // `putenv()` may call malloc/realloc so it is only safe to do >> this >> + // during LateInitialize() or later (i.e. we can't do this in the >> + // constructor). We also can't do this in >> `StartSymbolizerSubprocess()` >> + // because in TSan we switch allocators when we're symbolizing. >> + // We use `putenv()` rather than `setenv()` so that we can >> later directly >> + // write into the storage without LibC getting involved to >> change what the >> + // variable is set to >> + int result =3D putenv(kAtosMachPortEnvEntry); >> + CHECK_EQ(result, 0); >> + } >> } >> >> private: >> bool StartSymbolizerSubprocess() override { >> // Configure sandbox before starting atos process. >> + >> + // Put the string command line argument in the object so that it >> outlives >> + // the call to GetArgV. >> + internal_snprintf(pid_str_, sizeof(pid_str_), "%d", >> internal_getpid()); >> + >> + if (SANITIZER_IOSSIM) { >> + // `atos` in the simulator is restricted in its ability to >> retrieve the >> + // task port for the target process (us) so we need to do >> extra work >> + // to pass our task port to it. >> + mach_port_t ports[]{mach_task_self()}; >> + kern_return_t ret =3D >> + mach_ports_register(mach_task_self(), ports, /*count=3D*/1); >> + CHECK_EQ(ret, KERN_SUCCESS); >> + >> + // Set environment variable that signals to `atos` that it >> should look >> + // for our task port. We can't call `setenv()` here because it >> might call >> + // malloc/realloc. To avoid that we instead update the >> + // `mach_port_env_var_entry_` variable with our current PID. >> + uptr count =3D internal_snprintf(kAtosMachPortEnvEntry, >> + sizeof(kAtosMachPortEnvEntry), >> + K_ATOS_ENV_VAR "=3D%s", pid_str_); >> + CHECK_GE(count, sizeof(K_ATOS_ENV_VAR) + >> internal_strlen(pid_str_)); >> + // Document our assumption but without calling `getenv()` in >> normal >> + // builds. >> + DCHECK(getenv(K_ATOS_ENV_VAR)); >> + DCHECK_EQ(internal_strcmp(getenv(K_ATOS_ENV_VAR), pid_str_), 0); >> + } >> + >> return SymbolizerProcess::StartSymbolizerSubprocess(); >> } >> >> @@ -82,8 +133,14 @@ class AtosSymbolizerProcess : public >> SymbolizerProcess { >> } >> >> char pid_str_[16]; >> + // Space for `\0` in `K_ATOS_ENV_VAR` is reused for `=3D`. >> + static_assert(sizeof(kAtosMachPortEnvEntry) =3D=3D >> + (sizeof(K_ATOS_ENV_VAR) + sizeof(pid_str_)), >> + "sizes should match"); >> }; >> >> +#undef K_ATOS_ENV_VAR >> + >> static bool ParseCommandOutput(const char *str, uptr addr, char >> **out_name, >> char **out_module, char **out_file, >> uptr *line, >> uptr *start_address) { >> @@ -135,7 +192,7 @@ static bool ParseCommandOutput(const char *str, >> uptr addr, char **out_name, >> } >> >> AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator >> *allocator) >> - : process_(new(*allocator) AtosSymbolizerProcess(path, >> getpid())) {} >> + : process_(new (*allocator) AtosSymbolizerProcess(path)) {} >> >> bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { >> if (!process_) return false; >> @@ -145,12 +202,29 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, >> SymbolizedStack *stack) { >> const char *buf =3D process_->SendCommand(command); >> if (!buf) return false; >> uptr line; >> + uptr start_address =3D AddressInfo::kUnknown; >> if (!ParseCommandOutput(buf, addr, &stack->info.function, >> &stack->info.module, >> - &stack->info.file, &line, nullptr)) { >> + &stack->info.file, &line, &start_address)) { >> process_ =3D nullptr; >> return false; >> } >> stack->info.line =3D (int)line; >> + >> + if (start_address =3D=3D AddressInfo::kUnknown) { >> + // Fallback to dladdr() to get function start address if atos >> doesn't report >> + // it. >> + Dl_info info; >> + int result =3D dladdr((const void *)addr, &info); >> + if (result) >> + start_address =3D reinterpret_cast(info.dli_saddr); >> + } >> + >> + // Only assig to `function_offset` if we were able to get the >> function's >> + // start address. >> + if (start_address !=3D AddressInfo::kUnknown) { >> + CHECK(addr >=3D start_address); >> + stack->info.function_offset =3D addr - start_address; >> + } >> return true; >> } >> >> @@ -168,6 +242,8 @@ bool AtosSymbolizer::SymbolizeData(uptr addr, >> DataInfo *info) { >> return true; >> } >> >> +void AtosSymbolizer::LateInitialize() { process_->LateInitialize(); } >> + >> }=A0 // namespace __sanitizer >> >> #endif // SANITIZER_MAC >> diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.h >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.h >> index 68521375e64..8996131fc13 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.h >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.h >> @@ -35,6 +35,7 @@ class AtosSymbolizer : public SymbolizerTool { >> >> bool SymbolizePC(uptr addr, SymbolizedStack *stack) override; >> bool SymbolizeData(uptr addr, DataInfo *info) override; >> + void LateInitialize() override; >> >> private: >> AtosSymbolizerProcess *process_; >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_markup.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_markup.cpp >> index 57b4d0c9d96..2963af95360 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_markup.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_markup.cpp >> @@ -94,7 +94,9 @@ Symbolizer *Symbolizer::PlatformInit() { >> return new (symbolizer_allocator_) Symbolizer({}); >> } >> >> -void Symbolizer::LateInitialize() { Symbolizer::GetOrInit(); } >> +void Symbolizer::LateInitialize() { >> + Symbolizer::GetOrInit()->LateInitializeTools(); >> +} >> >> void StartReportDeadlySignal() {} >> void ReportDeadlySignal(const SignalContext &sig, u32 tid, >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp >> index c123ecb1120..d7b931bc237 100644 >> --- >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp >> +++ >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp >> @@ -151,9 +151,19 @@ bool >> SymbolizerProcess::StartSymbolizerSubprocess() { >> GetArgV(path_, argv); >> pid_t pid; >> >> + // Report how symbolizer is being launched for debugging purposes. >> + if (Verbosity() >=3D 3) { >> + // Only use `Report` for first line so subsequent prints don't >> get prefixed >> + // with current PID. >> + Report("Launching Symbolizer process: "); >> + for (unsigned index =3D 0; index < kArgVMax && argv[index]; ++index= ) >> + Printf("%s ", argv[index]); >> + Printf("\n"); >> + } >> + >> if (use_posix_spawn_) { >> #if SANITIZER_MAC >> - fd_t fd =3D internal_spawn(argv, &pid); >> + fd_t fd =3D internal_spawn(argv, const_cast> **>(GetEnvP()), &pid); >> if (fd =3D=3D kInvalidFd) { >> Report("WARNING: failed to spawn external symbolizer (errno: >> %d)\n", >> errno); >> @@ -173,7 +183,7 @@ bool >> SymbolizerProcess::StartSymbolizerSubprocess() { >> return false; >> } >> >> - pid =3D StartSubprocess(path_, argv, /* stdin */ outfd[0], >> + pid =3D StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0= ], >> /* stdout */ infd[1]); >> if (pid < 0) { >> internal_close(infd[0]); >> @@ -478,7 +488,7 @@ Symbolizer *Symbolizer::PlatformInit() { >> } >> >> void Symbolizer::LateInitialize() { >> - Symbolizer::GetOrInit(); >> + Symbolizer::GetOrInit()->LateInitializeTools(); >> InitializeSwiftDemangler(); >> } >> >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cpp >> b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cpp >> index 2808779156e..373437e7ee2 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cpp >> @@ -310,7 +310,7 @@ Symbolizer *Symbolizer::PlatformInit() { >> } >> >> void Symbolizer::LateInitialize() { >> - Symbolizer::GetOrInit(); >> + Symbolizer::GetOrInit()->LateInitializeTools(); >> } >> >> }=A0 // namespace __sanitizer >> diff --git >> a/libsanitizer/sanitizer_common/sanitizer_syscalls_netbsd.inc >> b/libsanitizer/sanitizer_common/sanitizer_syscalls_netbsd.inc >> index 69e59871874..02b7e11b167 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_syscalls_netbsd.inc >> +++ b/libsanitizer/sanitizer_common/sanitizer_syscalls_netbsd.inc >> @@ -42,7 +42,7 @@ >> // DO NOT EDIT! THIS FILE HAS BEEN GENERATED! >> // >> // Generated with: generate_netbsd_syscalls.awk >> -// Generated date: 2019-11-01 >> +// Generated date: 2019-12-24 >> // Generated from: syscalls.master,v 1.296 2019/09/22 22:59:39 >> christos Exp >> // >> //=3D=3D=3D-----------------------------------------------------------= -----------=3D=3D=3D// >> >> @@ -323,6 +323,16 @@ PRE_SYSCALL(ptrace) >> PRE_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_get_siginfo) { >> PRE_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz); >> + } else if (req_ =3D=3D ptrace_pt_lwpstatus) { >> + struct __sanitizer_ptrace_lwpstatus *addr =3D >> + (struct __sanitizer_ptrace_lwpstatus *)addr_; >> + PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t)); >> + PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz); >> + } else if (req_ =3D=3D ptrace_pt_lwpnext) { >> + struct __sanitizer_ptrace_lwpstatus *addr =3D >> + (struct __sanitizer_ptrace_lwpstatus *)addr_; >> + PRE_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t)); >> + PRE_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_setregs) { >> PRE_READ(addr_, struct_ptrace_reg_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_getregs) { >> @@ -366,6 +376,16 @@ POST_SYSCALL(ptrace) >> POST_READ(addr_, struct_ptrace_ptrace_siginfo_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_get_siginfo) { >> POST_WRITE(addr_, struct_ptrace_ptrace_siginfo_struct_sz); >> + } else if (req_ =3D=3D ptrace_pt_lwpstatus) { >> + struct __sanitizer_ptrace_lwpstatus *addr =3D >> + (struct __sanitizer_ptrace_lwpstatus *)addr_; >> + POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t)); >> + POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz); >> + } else if (req_ =3D=3D ptrace_pt_lwpnext) { >> + struct __sanitizer_ptrace_lwpstatus *addr =3D >> + (struct __sanitizer_ptrace_lwpstatus *)addr_; >> + POST_READ(&addr->pl_lwpid, sizeof(__sanitizer_lwpid_t)); >> + POST_WRITE(addr, struct_ptrace_ptrace_lwpstatus_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_setregs) { >> POST_READ(addr_, struct_ptrace_reg_struct_sz); >> } else if (req_ =3D=3D ptrace_pt_getregs) { >> diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cpp >> b/libsanitizer/sanitizer_common/sanitizer_win.cpp >> index 36dde49d870..fca15beb616 100644 >> --- a/libsanitizer/sanitizer_common/sanitizer_win.cpp >> +++ b/libsanitizer/sanitizer_common/sanitizer_win.cpp >> @@ -94,6 +94,10 @@ uptr internal_getpid() { >> return GetProcessId(GetCurrentProcess()); >> } >> >> +int internal_dlinfo(void *handle, int request, void *p) { >> + UNIMPLEMENTED(); >> +} >> + >> // In contrast to POSIX, on Windows GetCurrentThreadId() >> // returns a system-unique identifier. >> tid_t GetTid() { >> @@ -787,7 +791,7 @@ uptr GetRSS() { >> return counters.WorkingSetSize; >> } >> >> -void *internal_start_thread(void (*func)(void *arg), void *arg) { >> return 0; } >> +void *internal_start_thread(void *(*func)(void *arg), void *arg) { >> return 0; } >> void internal_join_thread(void *th) { } >> >> // ---------------------- BlockingMutex ---------------- {{{1 >> @@ -1060,7 +1064,8 @@ char **GetEnviron() { >> } >> >> pid_t StartSubprocess(const char *program, const char *const argv[], >> - fd_t stdin_fd, fd_t stdout_fd, fd_t stderr_fd) { >> + const char *const envp[], fd_t stdin_fd, fd_t >> stdout_fd, >> + fd_t stderr_fd) { >> // FIXME: implement on this platform >> // Should be implemented based on >> // SymbolizerProcess::StarAtSymbolizerSubprocess >> diff --git a/libsanitizer/tsan/tsan_clock.cpp >> b/libsanitizer/tsan/tsan_clock.cpp >> index 4b7aa0653da..c91b29cb22b 100644 >> --- a/libsanitizer/tsan/tsan_clock.cpp >> +++ b/libsanitizer/tsan/tsan_clock.cpp >> @@ -30,6 +30,14 @@ >> // dst->clock[i] =3D max(dst->clock[i], clock[i]); >> // } >> // >> +// void ThreadClock::releaseStoreAcquire(SyncClock *sc) const { >> +// for (int i =3D 0; i < kMaxThreads; i++) { >> +// tmp =3D clock[i]; >> +// clock[i] =3D max(clock[i], sc->clock[i]); >> +// sc->clock[i] =3D tmp; >> +// } >> +// } >> +// >> // void ThreadClock::ReleaseStore(SyncClock *dst) const { >> // for (int i =3D 0; i < kMaxThreads; i++) >> // dst->clock[i] =3D clock[i]; >> @@ -107,13 +115,14 @@ static void UnrefClockBlock(ClockCache *c, u32 >> idx, uptr blocks) { >> ThreadClock::ThreadClock(unsigned tid, unsigned reused) >> : tid_(tid) >> , reused_(reused + 1) // 0 has special meaning >> + , last_acquire_() >> + , global_acquire_() >> , cached_idx_() >> , cached_size_() >> , cached_blocks_() { >> CHECK_LT(tid, kMaxTidInClock); >> CHECK_EQ(reused_, ((u64)reused_ << kClkBits) >> kClkBits); >> nclk_ =3D tid_ + 1; >> - last_acquire_ =3D 0; >> internal_memset(clk_, 0, sizeof(clk_)); >> } >> >> @@ -177,6 +186,49 @@ void ThreadClock::acquire(ClockCache *c, >> SyncClock *src) { >> } >> } >> >> +void ThreadClock::releaseStoreAcquire(ClockCache *c, SyncClock *sc) { >> + DCHECK_LE(nclk_, kMaxTid); >> + DCHECK_LE(sc->size_, kMaxTid); >> + >> + if (sc->size_ =3D=3D 0) { >> + // ReleaseStore will correctly set release_store_tid_, >> + // which can be important for future operations. >> + ReleaseStore(c, sc); >> + return; >> + } >> + >> + nclk_ =3D max(nclk_, (uptr) sc->size_); >> + >> + // Check if we need to resize sc. >> + if (sc->size_ < nclk_) >> + sc->Resize(c, nclk_); >> + >> + bool acquired =3D false; >> + >> + sc->Unshare(c); >> + // Update sc->clk_. >> + sc->FlushDirty(); >> + uptr i =3D 0; >> + for (ClockElem &ce : *sc) { >> + u64 tmp =3D clk_[i]; >> + if (clk_[i] < ce.epoch) { >> + clk_[i] =3D ce.epoch; >> + acquired =3D true; >> + } >> + ce.epoch =3D tmp; >> + ce.reused =3D 0; >> + i++; >> + } >> + sc->release_store_tid_ =3D kInvalidTid; >> + sc->release_store_reused_ =3D 0; >> + >> + if (acquired) { >> + CPP_STAT_INC(StatClockAcquiredSomething); >> + last_acquire_ =3D clk_[tid_]; >> + ResetCached(c); >> + } >> +} >> + >> void ThreadClock::release(ClockCache *c, SyncClock *dst) { >> DCHECK_LE(nclk_, kMaxTid); >> DCHECK_LE(dst->size_, kMaxTid); >> @@ -196,7 +248,7 @@ void ThreadClock::release(ClockCache *c, >> SyncClock *dst) { >> // Check if we had not acquired anything from other threads >> // since the last release on dst. If so, we need to update >> // only dst->elem(tid_). >> - if (dst->elem(tid_).epoch > last_acquire_) { >> + if (!HasAcquiredAfterRelease(dst)) { >> UpdateCurrentThread(c, dst); >> if (dst->release_store_tid_ !=3D tid_ || >> dst->release_store_reused_ !=3D reused_) >> @@ -222,8 +274,6 @@ void ThreadClock::release(ClockCache *c, >> SyncClock *dst) { >> // Clear 'acquired' flag in the remaining elements. >> if (nclk_ < dst->size_) >> CPP_STAT_INC(StatClockReleaseClearTail); >> - for (uptr i =3D nclk_; i < dst->size_; i++) >> - dst->elem(i).reused =3D 0; >> dst->release_store_tid_ =3D kInvalidTid; >> dst->release_store_reused_ =3D 0; >> // If we've acquired dst, remember this fact, >> @@ -269,7 +319,7 @@ void ThreadClock::ReleaseStore(ClockCache *c, >> SyncClock *dst) { >> >> if (dst->release_store_tid_ =3D=3D tid_ && >> dst->release_store_reused_ =3D=3D reused_ && >> - dst->elem(tid_).epoch > last_acquire_) { >> + !HasAcquiredAfterRelease(dst)) { >> CPP_STAT_INC(StatClockStoreFast); >> UpdateCurrentThread(c, dst); >> return; >> @@ -351,6 +401,14 @@ bool ThreadClock::IsAlreadyAcquired(const >> SyncClock *src) const { >> return true; >> } >> >> +// Checks whether the current thread has acquired anything >> +// from other clocks after releasing to dst (directly or indirectly). >> +bool ThreadClock::HasAcquiredAfterRelease(const SyncClock *dst) const { >> + const u64 my_epoch =3D dst->elem(tid_).epoch; >> + return my_epoch <=3D last_acquire_ || >> + my_epoch <=3D atomic_load_relaxed(&global_acquire_); >> +} >> + >> // Sets a single element in the vector clock. >> // This function is called only from weird places like AcquireGlobal. >> void ThreadClock::set(ClockCache *c, unsigned tid, u64 v) { >> diff --git a/libsanitizer/tsan/tsan_clock.h >> b/libsanitizer/tsan/tsan_clock.h >> index 6a1d15a2a16..736cdae06ba 100644 >> --- a/libsanitizer/tsan/tsan_clock.h >> +++ b/libsanitizer/tsan/tsan_clock.h >> @@ -134,10 +134,12 @@ class ThreadClock { >> uptr size() const; >> >> void acquire(ClockCache *c, SyncClock *src); >> + void releaseStoreAcquire(ClockCache *c, SyncClock *src); >> void release(ClockCache *c, SyncClock *dst); >> void acq_rel(ClockCache *c, SyncClock *dst); >> void ReleaseStore(ClockCache *c, SyncClock *dst); >> void ResetCached(ClockCache *c); >> + void NoteGlobalAcquire(u64 v); >> >> void DebugReset(); >> void DebugDump(int(*printf)(const char *s, ...)); >> @@ -150,6 +152,53 @@ class ThreadClock { >> // Current thread time when it acquired something from other >> threads. >> u64 last_acquire_; >> >> + // Last time another thread has done a global acquire of this >> thread's clock. >> + // It helps to avoid problem described in: >> + // https://github.com/golang/go/issues/39186 >> + // See test/tsan/java_finalizer2.cpp for a regression test. >> + // Note the failuire is _extremely_ hard to hit, so if you are trying >> + // to reproduce it, you may want to run something like: >> + // $ go get golang.org/x/tools/cmd/stress >> + // $ stress -p=3D64 ./a.out >> + // >> + // The crux of the problem is roughly as follows. >> + // A number of O(1) optimizations in the clocks algorithm assume >> proper >> + // transitive cumulative propagation of clock values. The >> AcquireGlobal >> + // operation may produce an inconsistent non-linearazable view of >> + // thread clocks. Namely, it may acquire a later value from a thread >> + // with a higher ID, but fail to acquire an earlier value from a >> thread >> + // with a lower ID. If a thread that executed AcquireGlobal then >> releases >> + // to a sync clock, it will spoil the sync clock with the >> inconsistent >> + // values. If another thread later releases to the sync clock, the >> optimized >> + // algorithm may break. >> + // >> + // The exact sequence of events that leads to the failure. >> + // - thread 1 executes AcquireGlobal >> + // - thread 1 acquires value 1 for thread 2 >> + // - thread 2 increments clock to 2 >> + // - thread 2 releases to sync object 1 >> + // - thread 3 at time 1 >> + // - thread 3 acquires from sync object 1 >> + // - thread 3 increments clock to 2 >> + // - thread 1 acquires value 2 for thread 3 >> + // - thread 1 releases to sync object 2 >> + // - sync object 2 clock has 1 for thread 2 and 2 for thread 3 >> + // - thread 3 releases to sync object 2 >> + // - thread 3 sees value 2 in the clock for itself >> + // and decides that it has already released to the clock >> + // and did not acquire anything from other threads after that >> + // (the last_acquire_ check in release operation) >> + // - thread 3 does not update the value for thread 2 in the clock >> from 1 to 2 >> + // - thread 4 acquires from sync object 2 >> + // - thread 4 detects a false race with thread 2 >> + // as it should have been synchronized with thread 2 up to time 2, >> + // but because of the broken clock it is now synchronized only >> up to time 1 >> + // >> + // The global_acquire_ value helps to prevent this scenario. >> + // Namely, thread 3 will not trust any own clock values up to >> global_acquire_ >> + // for the purposes of the last_acquire_ optimization. >> + atomic_uint64_t global_acquire_; >> + >> // Cached SyncClock (without dirty entries and release_store_tid_). >> // We reuse it for subsequent store-release operations without >> intervening >> // acquire operations. Since it is shared (and thus constant), >> clock value >> @@ -164,6 +213,7 @@ class ThreadClock { >> u64 clk_[kMaxTidInClock]; // Fixed size vector clock. >> >> bool IsAlreadyAcquired(const SyncClock *src) const; >> + bool HasAcquiredAfterRelease(const SyncClock *dst) const; >> void UpdateCurrentThread(ClockCache *c, SyncClock *dst) const; >> }; >> >> @@ -185,6 +235,14 @@ ALWAYS_INLINE uptr ThreadClock::size() const { >> return nclk_; >> } >> >> +ALWAYS_INLINE void ThreadClock::NoteGlobalAcquire(u64 v) { >> + // Here we rely on the fact that AcquireGlobal is protected by >> + // ThreadRegistryLock, thus only one thread at a time executes it >> + // and values passed to this function should not go backwards. >> + CHECK_LE(atomic_load_relaxed(&global_acquire_), v); >> + atomic_store_relaxed(&global_acquire_, v); >> +} >> + >> ALWAYS_INLINE SyncClock::Iter SyncClock::begin() { >> return Iter(this); >> } >> diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp >> b/libsanitizer/tsan/tsan_interceptors_posix.cpp >> index 8aea1e4ec05..718957c3703 100644 >> --- a/libsanitizer/tsan/tsan_interceptors_posix.cpp >> +++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp >> @@ -891,13 +891,16 @@ void DestroyThreadState() { >> ThreadFinish(thr); >> ProcUnwire(proc, thr); >> ProcDestroy(proc); >> + DTLS_Destroy(); >> + cur_thread_finalize(); >> +} >> + >> +void PlatformCleanUpThreadState(ThreadState *thr) { >> ThreadSignalContext *sctx =3D thr->signal_ctx; >> if (sctx) { >> thr->signal_ctx =3D 0; >> UnmapOrDie(sctx, sizeof(*sctx)); >> } >> - DTLS_Destroy(); >> - cur_thread_finalize(); >> } >> }=A0 // namespace __tsan >> >> @@ -1016,7 +1019,7 @@ TSAN_INTERCEPTOR(int, pthread_create, >> >> TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) { >> SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret); >> - int tid =3D ThreadTid(thr, pc, (uptr)th); >> + int tid =3D ThreadConsumeTid(thr, pc, (uptr)th); >> ThreadIgnoreBegin(thr, pc); >> int res =3D BLOCK_REAL(pthread_join)(th, ret); >> ThreadIgnoreEnd(thr, pc); >> @@ -1029,8 +1032,8 @@ TSAN_INTERCEPTOR(int, pthread_join, void *th, >> void **ret) { >> DEFINE_REAL_PTHREAD_FUNCTIONS >> >> TSAN_INTERCEPTOR(int, pthread_detach, void *th) { >> - SCOPED_TSAN_INTERCEPTOR(pthread_detach, th); >> - int tid =3D ThreadTid(thr, pc, (uptr)th); >> + SCOPED_INTERCEPTOR_RAW(pthread_detach, th); >> + int tid =3D ThreadConsumeTid(thr, pc, (uptr)th); >> int res =3D REAL(pthread_detach)(th); >> if (res =3D=3D 0) { >> ThreadDetach(thr, pc, tid); >> @@ -1050,8 +1053,8 @@ TSAN_INTERCEPTOR(void, pthread_exit, void >> *retval) { >> >> #if SANITIZER_LINUX >> TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void *th, void **ret) { >> - SCOPED_TSAN_INTERCEPTOR(pthread_tryjoin_np, th, ret); >> - int tid =3D ThreadTid(thr, pc, (uptr)th); >> + SCOPED_INTERCEPTOR_RAW(pthread_tryjoin_np, th, ret); >> + int tid =3D ThreadConsumeTid(thr, pc, (uptr)th); >> ThreadIgnoreBegin(thr, pc); >> int res =3D REAL(pthread_tryjoin_np)(th, ret); >> ThreadIgnoreEnd(thr, pc); >> @@ -1064,8 +1067,8 @@ TSAN_INTERCEPTOR(int, pthread_tryjoin_np, void >> *th, void **ret) { >> >> TSAN_INTERCEPTOR(int, pthread_timedjoin_np, void *th, void **ret, >> const struct timespec *abstime) { >> - SCOPED_TSAN_INTERCEPTOR(pthread_timedjoin_np, th, ret, abstime); >> - int tid =3D ThreadTid(thr, pc, (uptr)th); >> + SCOPED_INTERCEPTOR_RAW(pthread_timedjoin_np, th, ret, abstime); >> + int tid =3D ThreadConsumeTid(thr, pc, (uptr)th); >> ThreadIgnoreBegin(thr, pc); >> int res =3D BLOCK_REAL(pthread_timedjoin_np)(th, ret, abstime); >> ThreadIgnoreEnd(thr, pc); >> diff --git a/libsanitizer/tsan/tsan_platform.h >> b/libsanitizer/tsan/tsan_platform.h >> index 63eb14fcd34..7256d64e507 100644 >> --- a/libsanitizer/tsan/tsan_platform.h >> +++ b/libsanitizer/tsan/tsan_platform.h >> @@ -1021,6 +1021,7 @@ int >> call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, >> void(*cleanup)(void *arg), void *arg); >> >> void DestroyThreadState(); >> +void PlatformCleanUpThreadState(ThreadState *thr); >> >> }=A0 // namespace __tsan >> >> diff --git a/libsanitizer/tsan/tsan_platform_mac.cpp >> b/libsanitizer/tsan/tsan_platform_mac.cpp >> index 326ca8532e5..f92ecc5e40f 100644 >> --- a/libsanitizer/tsan/tsan_platform_mac.cpp >> +++ b/libsanitizer/tsan/tsan_platform_mac.cpp >> @@ -19,6 +19,7 @@ >> #include "sanitizer_common/sanitizer_libc.h" >> #include "sanitizer_common/sanitizer_posix.h" >> #include "sanitizer_common/sanitizer_procmaps.h" >> +#include "sanitizer_common/sanitizer_ptrauth.h" >> #include "sanitizer_common/sanitizer_stackdepot.h" >> #include "tsan_platform.h" >> #include "tsan_rtl.h" >> @@ -75,9 +76,14 @@ static uptr main_thread_identity =3D 0; >> ALIGNED(64) static char main_thread_state[sizeof(ThreadState)]; >> static ThreadState *main_thread_state_loc =3D (ThreadState >> *)main_thread_state; >> >> +// We cannot use pthread_self() before libpthread has been >> initialized. Our >> +// current heuristic for guarding this is checking >> `main_thread_identity` which >> +// is only assigned in `__tsan::InitializePlatform`. >> static ThreadState **cur_thread_location() { >> + if (main_thread_identity =3D=3D 0) >> + return &main_thread_state_loc; >> uptr thread_identity =3D (uptr)pthread_self(); >> - if (thread_identity =3D=3D main_thread_identity || >> main_thread_identity =3D=3D 0) >> + if (thread_identity =3D=3D main_thread_identity) >> return &main_thread_state_loc; >> return (ThreadState **)MemToShadow(thread_identity); >> } >> @@ -269,6 +275,8 @@ void InitializePlatform() { >> uptr ExtractLongJmpSp(uptr *env) { >> uptr mangled_sp =3D env[LONG_JMP_SP_ENV_SLOT]; >> uptr sp =3D mangled_sp ^ longjmp_xor_key; >> + sp =3D (uptr)ptrauth_auth_data((void *)sp, ptrauth_key_asdb, >> + ptrauth_string_discriminator("sp")); >> return sp; >> } >> >> diff --git a/libsanitizer/tsan/tsan_rtl.cpp >> b/libsanitizer/tsan/tsan_rtl.cpp >> index 3f3c0cce119..13c9b770f50 100644 >> --- a/libsanitizer/tsan/tsan_rtl.cpp >> +++ b/libsanitizer/tsan/tsan_rtl.cpp >> @@ -144,7 +144,7 @@ static void MemoryProfiler(Context *ctx, fd_t fd, >> int i) { >> WriteToFile(fd, buf.data(), internal_strlen(buf.data())); >> } >> >> -static void BackgroundThread(void *arg) { >> +static void *BackgroundThread(void *arg) { >> // This is a non-initialized non-user thread, nothing to see here. >> // We don't use ScopedIgnoreInterceptors, because we want ignores >> to be >> // enabled even when the thread function exits (e.g. during >> pthread thread >> @@ -220,6 +220,7 @@ static void BackgroundThread(void *arg) { >> } >> } >> } >> + return nullptr; >> } >> >> static void StartBackgroundThread() { >> @@ -494,14 +495,23 @@ int Finalize(ThreadState *thr) { >> void ForkBefore(ThreadState *thr, uptr pc) { >> ctx->thread_registry->Lock(); >> ctx->report_mtx.Lock(); >> + // Ignore memory accesses in the pthread_atfork callbacks. >> + // If any of them triggers a data race we will deadlock >> + // on the report_mtx. >> + // We could ignore interceptors and sync operations as well, >> + // but so far it's unclear if it will do more good or harm. >> + // Unnecessarily ignoring things can lead to false positives later. >> + ThreadIgnoreBegin(thr, pc); >> } >> >> void ForkParentAfter(ThreadState *thr, uptr pc) { >> + ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore. >> ctx->report_mtx.Unlock(); >> ctx->thread_registry->Unlock(); >> } >> >> void ForkChildAfter(ThreadState *thr, uptr pc) { >> + ThreadIgnoreEnd(thr, pc); // Begin is in ForkBefore. >> ctx->report_mtx.Unlock(); >> ctx->thread_registry->Unlock(); >> >> diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h >> index c38fc43a9f8..d3bb61ff87d 100644 >> --- a/libsanitizer/tsan/tsan_rtl.h >> +++ b/libsanitizer/tsan/tsan_rtl.h >> @@ -775,7 +775,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr >> uid, bool detached); >> void ThreadStart(ThreadState *thr, int tid, tid_t os_id, >> ThreadType thread_type); >> void ThreadFinish(ThreadState *thr); >> -int ThreadTid(ThreadState *thr, uptr pc, uptr uid); >> +int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid); >> void ThreadJoin(ThreadState *thr, uptr pc, int tid); >> void ThreadDetach(ThreadState *thr, uptr pc, int tid); >> void ThreadFinalize(ThreadState *thr); >> @@ -813,10 +813,12 @@ void Acquire(ThreadState *thr, uptr pc, uptr >> addr); >> // approximation of the actual required synchronization. >> void AcquireGlobal(ThreadState *thr, uptr pc); >> void Release(ThreadState *thr, uptr pc, uptr addr); >> +void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr); >> void ReleaseStore(ThreadState *thr, uptr pc, uptr addr); >> void AfterSleep(ThreadState *thr, uptr pc); >> void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c); >> void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); >> +void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c); >> void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c); >> void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c); >> >> diff --git a/libsanitizer/tsan/tsan_rtl_mutex.cpp >> b/libsanitizer/tsan/tsan_rtl_mutex.cpp >> index ce6e7cb2c4e..ebd0d722181 100644 >> --- a/libsanitizer/tsan/tsan_rtl_mutex.cpp >> +++ b/libsanitizer/tsan/tsan_rtl_mutex.cpp >> @@ -415,8 +415,10 @@ static void >> UpdateClockCallback(ThreadContextBase *tctx_base, void *arg) { >> ThreadState *thr =3D reinterpret_cast(arg); >> ThreadContext *tctx =3D static_cast(tctx_base); >> u64 epoch =3D tctx->epoch1; >> - if (tctx->status =3D=3D ThreadStatusRunning) >> + if (tctx->status =3D=3D ThreadStatusRunning) { >> epoch =3D tctx->thr->fast_state.epoch(); >> + tctx->thr->clock.NoteGlobalAcquire(epoch); >> + } >> thr->clock.set(&thr->proc()->clock_cache, tctx->tid, epoch); >> } >> >> @@ -429,6 +431,18 @@ void AcquireGlobal(ThreadState *thr, uptr pc) { >> UpdateClockCallback, thr); >> } >> >> +void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr) { >> + DPrintf("#%d: ReleaseStoreAcquire %zx\n", thr->tid, addr); >> + if (thr->ignore_sync) >> + return; >> + SyncVar *s =3D ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true); >> + thr->fast_state.IncrementEpoch(); >> + // Can't increment epoch w/o writing to the trace as well. >> + TraceAddEvent(thr, thr->fast_state, EventTypeMop, 0); >> + ReleaseStoreAcquireImpl(thr, pc, &s->clock); >> + s->mtx.Unlock(); >> +} >> + >> void Release(ThreadState *thr, uptr pc, uptr addr) { >> DPrintf("#%d: Release %zx\n", thr->tid, addr); >> if (thr->ignore_sync) >> @@ -482,6 +496,15 @@ void AcquireImpl(ThreadState *thr, uptr pc, >> SyncClock *c) { >> StatInc(thr, StatSyncAcquire); >> } >> >> +void ReleaseStoreAcquireImpl(ThreadState *thr, uptr pc, SyncClock *c) { >> + if (thr->ignore_sync) >> + return; >> + thr->clock.set(thr->fast_state.epoch()); >> + thr->fast_synch_epoch =3D thr->fast_state.epoch(); >> + thr->clock.releaseStoreAcquire(&thr->proc()->clock_cache, c); >> + StatInc(thr, StatSyncReleaseStoreAcquire); >> +} >> + >> void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c) { >> if (thr->ignore_sync) >> return; >> diff --git a/libsanitizer/tsan/tsan_rtl_ppc64.S >> b/libsanitizer/tsan/tsan_rtl_ppc64.S >> index 9e533a71a9c..8285e21aa1e 100644 >> --- a/libsanitizer/tsan/tsan_rtl_ppc64.S >> +++ b/libsanitizer/tsan/tsan_rtl_ppc64.S >> @@ -1,6 +1,5 @@ >> #include "tsan_ppc_regs.h" >> >> - .machine altivec >> .section .text >> .hidden __tsan_setjmp >> .globl _setjmp >> diff --git a/libsanitizer/tsan/tsan_rtl_thread.cpp >> b/libsanitizer/tsan/tsan_rtl_thread.cpp >> index 0ac1ee99c47..d80146735ea 100644 >> --- a/libsanitizer/tsan/tsan_rtl_thread.cpp >> +++ b/libsanitizer/tsan/tsan_rtl_thread.cpp >> @@ -144,6 +144,9 @@ void ThreadContext::OnFinished() { >> thr->clock.ResetCached(&thr->proc()->clock_cache); >> #if !SANITIZER_GO >> thr->last_sleep_clock.ResetCached(&thr->proc()->clock_cache); >> +#endif >> +#if !SANITIZER_GO >> + PlatformCleanUpThreadState(thr); >> #endif >> thr->~ThreadState(); >> #if TSAN_COLLECT_STATS >> @@ -285,19 +288,34 @@ void ThreadFinish(ThreadState *thr) { >> ctx->thread_registry->FinishThread(thr->tid); >> } >> >> -static bool FindThreadByUid(ThreadContextBase *tctx, void *arg) { >> - uptr uid =3D (uptr)arg; >> - if (tctx->user_id =3D=3D uid && tctx->status !=3D ThreadStatusInvalid= ) { >> +struct ConsumeThreadContext { >> + uptr uid; >> + ThreadContextBase *tctx; >> +}; >> + >> +static bool ConsumeThreadByUid(ThreadContextBase *tctx, void *arg) { >> + ConsumeThreadContext *findCtx =3D (ConsumeThreadContext *)arg; >> + if (tctx->user_id =3D=3D findCtx->uid && tctx->status !=3D >> ThreadStatusInvalid) { >> + if (findCtx->tctx) { >> + // Ensure that user_id is unique. If it's not the case we are >> screwed. >> + // Something went wrong before, but now there is no way to >> recover. >> + // Returning a wrong thread is not an option, it may lead to >> very hard >> + // to debug false positives (e.g. if we join a wrong thread). >> + Report("ThreadSanitizer: dup thread with used id 0x%zx\n", >> findCtx->uid); >> + Die(); >> + } >> + findCtx->tctx =3D tctx; >> tctx->user_id =3D 0; >> - return true; >> } >> return false; >> } >> >> -int ThreadTid(ThreadState *thr, uptr pc, uptr uid) { >> - int res =3D ctx->thread_registry->FindThread(FindThreadByUid, >> (void*)uid); >> - DPrintf("#%d: ThreadTid uid=3D%zu tid=3D%d\n", thr->tid, uid, res); >> - return res; >> +int ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid) { >> + ConsumeThreadContext findCtx =3D {uid, nullptr}; >> + ctx->thread_registry->FindThread(ConsumeThreadByUid, &findCtx); >> + int tid =3D findCtx.tctx ? findCtx.tctx->tid : >> ThreadRegistry::kUnknownTid; >> + DPrintf("#%d: ThreadTid uid=3D%zu tid=3D%d\n", thr->tid, uid, tid); >> + return tid; >> } >> >> void ThreadJoin(ThreadState *thr, uptr pc, int tid) { >> diff --git a/libsanitizer/tsan/tsan_stat.h >> b/libsanitizer/tsan/tsan_stat.h >> index 94e18bc66df..8b26a59bb2e 100644 >> --- a/libsanitizer/tsan/tsan_stat.h >> +++ b/libsanitizer/tsan/tsan_stat.h >> @@ -68,6 +68,7 @@ enum StatType { >> StatSyncDestroyed, >> StatSyncAcquire, >> StatSyncRelease, >> + StatSyncReleaseStoreAcquire, >> >> // Clocks - acquire. >> StatClockAcquire, >> diff --git a/libsanitizer/ubsan/ubsan_checks.inc >> b/libsanitizer/ubsan/ubsan_checks.inc >> index 33a8dfcde02..2c1529a7d92 100644 >> --- a/libsanitizer/ubsan/ubsan_checks.inc >> +++ b/libsanitizer/ubsan/ubsan_checks.inc >> @@ -18,6 +18,8 @@ >> >> UBSAN_CHECK(GenericUB, "undefined-behavior", "undefined") >> UBSAN_CHECK(NullPointerUse, "null-pointer-use", "null") >> +UBSAN_CHECK(NullPointerUseWithNullability, "null-pointer-use", >> + "nullability-assign") >> UBSAN_CHECK(NullptrWithOffset, "nullptr-with-offset", >> "pointer-overflow") >> UBSAN_CHECK(NullptrWithNonZeroOffset, "nullptr-with-nonzero-offset", >> "pointer-overflow") >> @@ -59,6 +61,10 @@ UBSAN_CHECK(InvalidEnumLoad, "invalid-enum-load", >> "enum") >> UBSAN_CHECK(FunctionTypeMismatch, "function-type-mismatch", >> "function") >> UBSAN_CHECK(InvalidNullReturn, "invalid-null-return", >> "returns-nonnull-attribute") >> +UBSAN_CHECK(InvalidNullReturnWithNullability, "invalid-null-return", >> + "nullability-return") >> UBSAN_CHECK(InvalidNullArgument, "invalid-null-argument", >> "nonnull-attribute") >> +UBSAN_CHECK(InvalidNullArgumentWithNullability, >> "invalid-null-argument", >> + "nullability-arg") >> UBSAN_CHECK(DynamicTypeMismatch, "dynamic-type-mismatch", "vptr") >> UBSAN_CHECK(CFIBadType, "cfi-bad-type", "cfi") >> diff --git a/libsanitizer/ubsan/ubsan_flags.cpp >> b/libsanitizer/ubsan/ubsan_flags.cpp >> index 80de2a6d101..721c2273f13 100644 >> --- a/libsanitizer/ubsan/ubsan_flags.cpp >> +++ b/libsanitizer/ubsan/ubsan_flags.cpp >> @@ -54,7 +54,6 @@ void InitializeFlags() { >> { >> CommonFlags cf; >> cf.CopyFrom(*common_flags()); >> - cf.print_summary =3D false; >> cf.external_symbolizer_path =3D GetFlag("UBSAN_SYMBOLIZER_PATH"); >> OverrideCommonFlags(cf); >> } >> diff --git a/libsanitizer/ubsan/ubsan_handlers.cpp >> b/libsanitizer/ubsan/ubsan_handlers.cpp >> index 0ddbb50c26c..7f6a46fb6cf 100644 >> --- a/libsanitizer/ubsan/ubsan_handlers.cpp >> +++ b/libsanitizer/ubsan/ubsan_handlers.cpp >> @@ -36,6 +36,45 @@ bool ignoreReport(SourceLocation SLoc, >> ReportOptions Opts, ErrorType ET) { >> return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, >> SLoc.getFilename()); >> } >> >> +/// Situations in which we might emit a check for the suitability of a >> +/// pointer or glvalue. Needs to be kept in sync with >> CodeGenFunction.h in >> +/// clang. >> +enum TypeCheckKind { >> + /// Checking the operand of a load. Must be suitably sized and >> aligned. >> + TCK_Load, >> + /// Checking the destination of a store. Must be suitably sized >> and aligned. >> + TCK_Store, >> + /// Checking the bound value in a reference binding. Must be >> suitably sized >> + /// and aligned, but is not required to refer to an object (until the >> + /// reference is used), per core issue 453. >> + TCK_ReferenceBinding, >> + /// Checking the object expression in a non-static data member >> access. Must >> + /// be an object within its lifetime. >> + TCK_MemberAccess, >> + /// Checking the 'this' pointer for a call to a non-static member >> function. >> + /// Must be an object within its lifetime. >> + TCK_MemberCall, >> + /// Checking the 'this' pointer for a constructor call. >> + TCK_ConstructorCall, >> + /// Checking the operand of a static_cast to a derived pointer >> type. Must be >> + /// null or an object within its lifetime. >> + TCK_DowncastPointer, >> + /// Checking the operand of a static_cast to a derived reference >> type. Must >> + /// be an object within its lifetime. >> + TCK_DowncastReference, >> + /// Checking the operand of a cast to a base object. Must be >> suitably sized >> + /// and aligned. >> + TCK_Upcast, >> + /// Checking the operand of a cast to a virtual base object. Must >> be an >> + /// object within its lifetime. >> + TCK_UpcastToVirtualBase, >> + /// Checking the value assigned to a _Nonnull pointer. Must not be >> null. >> + TCK_NonnullAssign, >> + /// Checking the operand of a dynamic_cast or a typeid >> expression. Must be >> + /// null or an object within its lifetime. >> + TCK_DynamicOperation >> +}; >> + >> const char *TypeCheckKinds[] =3D { >> "load of", "store to", "reference binding to", "member access >> within", >> "member call on", "constructor call on", "downcast of", >> "downcast of", >> @@ -50,7 +89,9 @@ static void handleTypeMismatchImpl(TypeMismatchData >> *Data, ValueHandle Pointer, >> uptr Alignment =3D (uptr)1 << Data->LogAlignment; >> ErrorType ET; >> if (!Pointer) >> - ET =3D ErrorType::NullPointerUse; >> + ET =3D (Data->TypeCheckKind =3D=3D TCK_NonnullAssign) >> + ? ErrorType::NullPointerUseWithNullability >> + : ErrorType::NullPointerUse; >> else if (Pointer & (Alignment - 1)) >> ET =3D ErrorType::MisalignedPointerUse; >> else >> @@ -71,6 +112,7 @@ static void >> handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, >> >> switch (ET) { >> case ErrorType::NullPointerUse: >> + case ErrorType::NullPointerUseWithNullability: >> Diag(Loc, DL_Error, ET, "%0 null pointer of type %1") >> << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; >> break; >> @@ -604,7 +646,8 @@ static void handleNonNullReturn(NonNullReturnData >> *Data, SourceLocation *LocPtr, >> UNREACHABLE("source location pointer is null!"); >> >> SourceLocation Loc =3D LocPtr->acquire(); >> - ErrorType ET =3D ErrorType::InvalidNullReturn; >> + ErrorType ET =3D IsAttr ? ErrorType::InvalidNullReturn >> + : ErrorType::InvalidNullReturnWithNullability; >> >> if (ignoreReport(Loc, Opts, ET)) >> return; >> @@ -648,7 +691,8 @@ void >> __ubsan::__ubsan_handle_nullability_return_v1_abort( >> static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts, >> bool IsAttr) { >> SourceLocation Loc =3D Data->Loc.acquire(); >> - ErrorType ET =3D ErrorType::InvalidNullArgument; >> + ErrorType ET =3D IsAttr ? ErrorType::InvalidNullArgument >> + : >> ErrorType::InvalidNullArgumentWithNullability; >> >> if (ignoreReport(Loc, Opts, ET)) >> return; >> @@ -819,21 +863,6 @@ void >> __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable, >> >> }=A0 // namespace __ubsan >> >> -void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData, >> - ValueHandle Function) { >> - GET_REPORT_OPTIONS(false); >> - CFICheckFailData Data =3D {CFITCK_ICall, CallData->Loc, >> CallData->Type}; >> - handleCFIBadIcall(&Data, Function, Opts); >> -} >> - >> -void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData >> *CallData, >> - ValueHandle >> Function) { >> - GET_REPORT_OPTIONS(true); >> - CFICheckFailData Data =3D {CFITCK_ICall, CallData->Loc, >> CallData->Type}; >> - handleCFIBadIcall(&Data, Function, Opts); >> - Die(); >> -} >> - >> void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data, >> ValueHandle Value, >> uptr ValidVtable) { >> diff --git a/libsanitizer/ubsan/ubsan_handlers.h >> b/libsanitizer/ubsan/ubsan_handlers.h >> index eba1cf918fc..22ca9642238 100644 >> --- a/libsanitizer/ubsan/ubsan_handlers.h >> +++ b/libsanitizer/ubsan/ubsan_handlers.h >> @@ -207,20 +207,12 @@ enum CFITypeCheckKind : unsigned char { >> CFITCK_VMFCall, >> }; >> >> -struct CFIBadIcallData { >> - SourceLocation Loc; >> - const TypeDescriptor &Type; >> -}; >> - >> struct CFICheckFailData { >> CFITypeCheckKind CheckKind; >> SourceLocation Loc; >> const TypeDescriptor &Type; >> }; >> >> -/// \brief Handle control flow integrity failure for indirect >> function calls. >> -RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function) >> - >> /// \brief Handle control flow integrity failures. >> RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle >> Function, >> uptr VtableIsValid) >> diff --git a/libsanitizer/ubsan/ubsan_init.cpp >> b/libsanitizer/ubsan/ubsan_init.cpp >> index 1a3b7d37267..e0be5a72ec4 100644 >> --- a/libsanitizer/ubsan/ubsan_init.cpp >> +++ b/libsanitizer/ubsan/ubsan_init.cpp >> @@ -37,10 +37,12 @@ static void CommonStandaloneInit() { >> SanitizerToolName =3D GetSanititizerToolName(); >> CacheBinaryName(); >> InitializeFlags(); >> + __sanitizer::InitializePlatformEarly(); >> __sanitizer_set_report_path(common_flags()->log_path); >> AndroidLogInit(); >> InitializeCoverage(common_flags()->coverage, >> common_flags()->coverage_dir); >> CommonInit(); >> + Symbolizer::LateInitialize(); >> } >> >> void __ubsan::InitAsStandalone() { >> diff --git a/libsanitizer/ubsan/ubsan_platform.h >> b/libsanitizer/ubsan/ubsan_platform.h >> index 58aabbe67b5..71d7fb18c9b 100644 >> --- a/libsanitizer/ubsan/ubsan_platform.h >> +++ b/libsanitizer/ubsan/ubsan_platform.h >> @@ -12,7 +12,6 @@ >> #ifndef UBSAN_PLATFORM_H >> #define UBSAN_PLATFORM_H >> >> -#ifndef CAN_SANITIZE_UB >> // Other platforms should be easy to add, and probably work as-is. >> #if defined(__linux__) || defined(__FreeBSD__) || >> defined(__APPLE__) ||=A0=A0=A0=A0=A0=A0=A0 \ >> defined(__NetBSD__) || defined(__OpenBSD__) || \ >> @@ -22,6 +21,5 @@ >> #else >> # define CAN_SANITIZE_UB 0 >> #endif >> -#endif //CAN_SANITIZE_UB >> >> #endif >> diff --git a/libsanitizer/ubsan/ubsan_type_hash_itanium.cpp >> b/libsanitizer/ubsan/ubsan_type_hash_itanium.cpp >> index 97846d4dd43..4f1708ba190 100644 >> --- a/libsanitizer/ubsan/ubsan_type_hash_itanium.cpp >> +++ b/libsanitizer/ubsan/ubsan_type_hash_itanium.cpp >> @@ -16,6 +16,7 @@ >> #include "ubsan_type_hash.h" >> >> #include "sanitizer_common/sanitizer_common.h" >> +#include "sanitizer_common/sanitizer_ptrauth.h" >> >> // The following are intended to be binary compatible with the >> definitions >> // given in the Itanium ABI. We make no attempt to be >> ODR-compatible with >> @@ -194,6 +195,7 @@ struct VtablePrefix { >> std::type_info *TypeInfo; >> }; >> VtablePrefix *getVtablePrefix(void *Vtable) { >> + Vtable =3D ptrauth_auth_data(Vtable, ptrauth_key_cxx_vtable_pointer, >> 0); >> VtablePrefix *Vptr =3D reinterpret_cast(Vtable); >> VtablePrefix *Prefix =3D Vptr - 1; >> if (!IsAccessibleMemoryRange((uptr)Prefix, sizeof(VtablePrefix))) > > ----------------- Mentor Graphics (Deutschland) GmbH, Arnulfstra=DFe 201, 80634 M=FCnchen / G= ermany Registergericht M=FCnchen HRB 106955, Gesch=E4ftsf=FChrer: Thomas Heurung, = Alexander Walter