LCOV - code coverage report
Current view: top level - util/sanitize - fd_asan.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 2 7 28.6 %
Date: 2025-12-06 04:45:29 Functions: 4 5682 0.1 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_sanitize_fd_asan_h
       2             : #define HEADER_fd_src_util_sanitize_fd_asan_h
       3             : 
       4             : #include "../fd_util_base.h"
       5             : 
       6             : /* AddressSanitizer (ASan) tracks allocated memory regions and
       7             :    instruments all memory accesses to detect possible out-of-bounds
       8             :    errors.
       9             : 
      10             :    This API is used to mark memory regions at runtime where default ASan
      11             :    instrumentation is missing.  Firedancer objects are mainly backed by
      12             :    shared memory segments via huge pages managed by a custom memory
      13             :    allocator.
      14             : 
      15             :    More info on ASan:
      16             :      - https://clang.llvm.org/docs/AddressSanitizer.html
      17             :      - https://github.com/google/sanitizers/wiki/AddressSanitizer
      18             : 
      19             :    For a guide on how to setup manual ASan memory poisoning, see
      20             :    https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */
      21             : 
      22             : /* Based on https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/sanitizer/asan_interface.h
      23             : 
      24             :    Part of the LLVM Project, under the Apache License v2.0 with LLVM
      25             :    Exceptions.  See https://llvm.org/LICENSE.txt for license
      26             :    information.  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      27             : 
      28             :    This file was originally part of AddressSanitizer (ASan). */
      29             : 
      30             : #ifndef FD_HAS_ASAN
      31             : #if defined(__has_feature)
      32             : #define FD_HAS_ASAN __has_feature(address_sanitizer)
      33             : #elif defined(__SANITIZE_ADDRESS__)
      34             : #define FD_HAS_ASAN 1
      35             : #else
      36             : #define FD_HAS_ASAN 0
      37             : #endif
      38             : #endif
      39             : 
      40             : /* FD_FN_NO_ASAN is a function attribute to disable ASan instrumentation
      41             :    when FD_HAS_ASAN is set (and expands to nothing if not). */
      42             : 
      43             : #if FD_HAS_ASAN
      44             : #define FD_FN_NO_ASAN __attribute__((no_sanitize("address")))
      45             : #else
      46             : #define FD_FN_NO_ASAN
      47             : #endif
      48             : 
      49             : FD_PROTOTYPES_BEGIN
      50             : 
      51             : /* If FD_HAS_ASAN is set:
      52             : 
      53             :    fd_asan_poison marks a memory region `[addr,addr+sz)` as
      54             :    unaddressable and returns addr.  This memory must be previously
      55             :    allocated by your program.  Instrumented code is forbidden from
      56             :    accessing addresses in this region until it is unpoisoned.  This
      57             :    function is not guaranteed to poison the entire region; it might
      58             :    poison only a sub-region of `[addr,addr+sz)` due to ASan alignment
      59             :    restrictions.
      60             : 
      61             :    fd_asan_unpoison marks a memory region `[addr,addr+sz)` as
      62             :    addressable and returns addr.  This memory must be previously
      63             :    allocated by your program.  Accessing addresses in this region is
      64             :    allowed until this region is poisoned again.  This function might
      65             :    unpoison a super-region of `[addr,addr+sz)` due to ASan alignment
      66             :    restrictions.
      67             : 
      68             :    fd_asan_test tests if an address is poisoned.  Returns 1 if addr is
      69             :    poisoned (that is, a 1-byte read/write access to this address would
      70             :    result in an error report from ASan).  Otherwise returns 0.
      71             : 
      72             :    fd_asan_query checks if a region is poisoned.  If at least one byte
      73             :    in `[addr,addr+sz)` is poisoned, returns the address of the first
      74             :    such byte.  Otherwise returns NULL.
      75             : 
      76             :    If FD_HAS_ASAN is not set fd_asan_{poison,unpoison} just return addr,
      77             :    fd_asan_test returns 0 and fd_asan_query returns NULL.
      78             : 
      79             :    FIXME: CONST CORRECT VERSIONS? */
      80             : 
      81             : #ifdef FD_HAS_DEEPASAN
      82           0 : #define FD_ASAN_ALIGN (8UL)
      83             : #endif
      84             : 
      85             : #if FD_HAS_ASAN
      86             : 
      87             : /* These are for internal use only */
      88             : 
      89             : void   __asan_poison_memory_region  ( void const volatile * addr, ulong sz );
      90             : void   __asan_unpoison_memory_region( void const volatile * addr, ulong sz );
      91             : int    __asan_address_is_poisoned   ( void const volatile * addr           );
      92             : void * __asan_region_is_poisoned    ( void *                addr, ulong sz );
      93             : 
      94             : void
      95             : __sanitizer_start_switch_fiber( void **      fake_stack_save,
      96             :                                 void const * stack_bottom,
      97             :                                 ulong        stack_size );
      98             : 
      99             : void
     100             : __sanitizer_finish_switch_fiber( void *        fake_stack_save,
     101             :                                  void const ** stack_bottom_old,
     102             :                                  ulong *       stack_size_old );
     103             : 
     104             : #ifdef FD_HAS_DEEPASAN_WATCH
     105             : void fd_asan_check_watch( int poison, void * addr, ulong sz );
     106             : void fd_asan_watch( void const * addr );
     107             : static inline void * fd_asan_poison  ( void * addr, ulong sz ) { __asan_poison_memory_region  ( addr, sz ); fd_asan_check_watch( 1, addr, sz ); return addr; }
     108             : static inline void * fd_asan_unpoison( void * addr, ulong sz ) { __asan_unpoison_memory_region( addr, sz ); fd_asan_check_watch( 0, addr, sz ); return addr; }
     109             : 
     110             : #else
     111             : static inline void * fd_asan_poison  ( void * addr, ulong sz ) { __asan_poison_memory_region  ( addr, sz ); return addr; }
     112             : static inline void * fd_asan_unpoison( void * addr, ulong sz ) { __asan_unpoison_memory_region( addr, sz ); return addr; }
     113             : #endif
     114             : 
     115             : static inline int    fd_asan_test    ( void * addr           ) { return __asan_address_is_poisoned( addr );     }
     116             : static inline void * fd_asan_query   ( void * addr, ulong sz ) { return __asan_region_is_poisoned ( addr, sz ); }
     117             : 
     118             : static inline void fd_asan_start_switch_fiber ( void ** a, void const *  b, ulong   c ) { __sanitizer_start_switch_fiber ( a, b, c ); }
     119             : static inline void fd_asan_finish_switch_fiber( void *  a, void const ** b, ulong * c ) { __sanitizer_finish_switch_fiber( a, b, c ); }
     120             : 
     121             : #else
     122             : 
     123           9 : static inline void * fd_asan_poison  ( void * addr, ulong sz ) { (void)sz;             return addr; }
     124           9 : static inline void * fd_asan_unpoison( void * addr, ulong sz ) { (void)sz;             return addr; }
     125           0 : static inline int    fd_asan_test    ( void * addr           ) { (void)addr;           return 0;    }
     126           0 : static inline void * fd_asan_query   ( void * addr, ulong sz ) { (void)addr; (void)sz; return NULL; }
     127             : 
     128           0 : static inline void fd_asan_start_switch_fiber ( void ** a, void const *  b, ulong   c ) { (void)a; (void)b; (void)c; }
     129           0 : static inline void fd_asan_finish_switch_fiber( void *  a, void const ** b, ulong * c ) { (void)a; (void)b; (void)c; }
     130             : 
     131             : #endif
     132             : 
     133             : FD_PROTOTYPES_END
     134             : 
     135             : #endif /* HEADER_fd_src_util_sanitize_fd_asan_h */

Generated by: LCOV version 1.14