//===-- hwasan_thread_list.h ------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of HWAddressSanitizer. // //===----------------------------------------------------------------------===// // HwasanThreadList is a registry for live threads, as well as an allocator for // HwasanThread objects and their stack history ring buffers. There are // constraints on memory layout of the shadow region and CompactRingBuffer that // are part of the ABI contract between compiler-rt and llvm. // // * Start of the shadow memory region is aligned to 2**kShadowBaseAlignment. // * All stack ring buffers are located within (2**kShadowBaseAlignment) // sized region below and adjacent to the shadow region. // * Each ring buffer has a size of (2**N)*4096 where N is in [0, 7), and is // aligned to twice its size. The value of N can be different for each buffer. // // These constrains guarantee that, given an address A of any element of the // ring buffer, // A_next = (A + sizeof(uptr)) & ~((1 << (N + 13)) - 1) // is the address of the next element of that ring buffer (with wrap-around). // And, with K = kShadowBaseAlignment, // S = (A | ((1 << K) - 1)) + 1 // (align up to kShadowBaseAlignment) is the start of the shadow region. // // These calculations are used in compiler instrumentation to update the ring // buffer and obtain the base address of shadow using only two inputs: address // of the current element of the ring buffer, and N (i.e. size of the ring // buffer). Since the value of N is very limited, we pack both inputs into a // single thread-local word as // (1 << (N + 56)) | A // See the implementation of class CompactRingBuffer, which is what is stored in // said thread-local word. // // Note the unusual way of aligning up the address of the shadow: // (A | ((1 << K) - 1)) + 1 // It is only correct if A is not already equal to the shadow base address, but // it saves 2 instructions on AArch64. #include "hwasan.h" #include "hwasan_allocator.h" #include "hwasan_flags.h" #include "hwasan_thread.h" #include "sanitizer_common/sanitizer_thread_arg_retval.h" namespace __hwasan { static uptr RingBufferSize() { … } struct ThreadStats { … }; class SANITIZER_MUTEX HwasanThreadList { … }; void InitThreadList(uptr storage, uptr size); HwasanThreadList &hwasanThreadList(); ThreadArgRetval &hwasanThreadArgRetval(); } // namespace __hwasan