GCC Middle and Back End API Reference
asan.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.


#define ASAN_RED_ZONE_SIZE   32
#define ASAN_STACK_MAGIC_LEFT   0xf1
#define ASAN_STACK_FRAME_MAGIC   0x41b58ab3
#define ASAN_STACK_RETIRED_MAGIC   0x45e0360e
#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE   "use after scope memory"
#define HWASAN_TAG_SIZE   targetm.memtag.tag_size ()
#define HWASAN_TAG_GRANULE_SIZE   targetm.memtag.granule_size ()
#define HWASAN_STACK_BACKGROUND   gen_int_mode (0, QImode)
#define DEF(X)   ASAN_MARK_##X


enum  asan_check_flags { ASAN_CHECK_STORE = 1 << 0 , ASAN_CHECK_SCALAR_ACCESS = 1 << 1 , ASAN_CHECK_NON_ZERO_LEN = 1 << 2 , ASAN_CHECK_LAST = 1 << 3 }
enum  asan_mark_flags { IFN_ASAN_MARK_FLAGS }


void asan_function_start (void)
void asan_finish_file (void)
rtx_insnasan_emit_stack_protection (rtx, rtx, unsigned int, HOST_WIDE_INT *, tree *, int)
rtx_insnasan_emit_allocas_unpoison (rtx, rtx, rtx_insn *)
bool asan_protect_global (tree, bool ignore_decl_rtl_set_p=false)
void initialize_sanitizer_builtins (void)
tree asan_dynamic_init_call (bool)
bool asan_expand_check_ifn (gimple_stmt_iterator *, bool)
bool asan_expand_mark_ifn (gimple_stmt_iterator *)
bool asan_expand_poison_ifn (gimple_stmt_iterator *, bool *, hash_map< tree, tree > &)
rtx asan_memfn_rtl (tree)
void hwasan_record_frame_init ()
void hwasan_record_stack_var (rtx, rtx, poly_int64, poly_int64)
void hwasan_emit_prologue ()
rtx_insnhwasan_emit_untag_frame (rtx, rtx)
rtx hwasan_get_frame_extent ()
rtx hwasan_frame_base ()
void hwasan_maybe_emit_frame_base_init (void)
bool stack_vars_base_reg_p (rtx)
uint8_t hwasan_current_frame_tag ()
void hwasan_increment_frame_tag ()
rtx hwasan_truncate_to_tag_size (rtx, rtx)
void hwasan_finish_file (void)
bool hwasan_sanitize_p (void)
bool hwasan_sanitize_stack_p (void)
bool hwasan_sanitize_allocas_p (void)
bool hwasan_expand_check_ifn (gimple_stmt_iterator *, bool)
bool hwasan_expand_mark_ifn (gimple_stmt_iterator *)
bool gate_hwasan (void)
gimple_stmt_iterator create_cond_insert_point (gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *)
bool asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
unsigned int asan_red_zone_size (unsigned int size)
unsigned HOST_WIDE_INT asan_var_and_redzone_size (unsigned HOST_WIDE_INT size)
bool set_asan_shadow_offset (const char *)
bool asan_shadow_offset_set_p ()
void set_sanitized_sections (const char *)
bool asan_sanitize_stack_p (void)
bool asan_sanitize_allocas_p (void)
bool asan_intercepted_p (enum built_in_function fcode)
bool asan_sanitize_use_after_scope (void)
bool asan_protect_stack_decl (tree decl)
bool sanitize_flags_p (unsigned int flag, const_tree fn=current_function_decl)
bool sanitize_coverage_p (const_tree fn=current_function_decl)


alias_set_type asan_shadow_set
hash_set< tree > * asan_used_labels
hash_set< tree > * asan_handled_variables

Macro Definition Documentation


Stack variable use more compact red zones.  The size includes also
size of variable itself.   

Referenced by asan_emit_stack_protection(), and expand_stack_vars().


#define ASAN_RED_ZONE_SIZE   32



Shadow memory is found at
(address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().   

Referenced by asan_emit_stack_protection(), asan_expand_mark_ifn(), build_shadow_mem_access(), asan_redzone_buffer::emit_redzone_byte(), expand_stack_vars(), and expand_used_vars().


#define ASAN_STACK_FRAME_MAGIC   0x41b58ab3


#define ASAN_STACK_MAGIC_LEFT   0xf1
Shadow memory values for stack protection.  Left is below protected vars,
the first pointer in stack corresponding to that offset contains
ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing
the frame.  Middle is for padding in between variables, right is
above the last protected variable and partial immediately after variables
up to ASAN_RED_ZONE_SIZE alignment.   

Referenced by asan_emit_stack_protection().









Referenced by asan_store_shadow_bytes().


#define ASAN_STACK_RETIRED_MAGIC   0x45e0360e


#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE   "use after scope memory"


#define DEF ( X)    ASAN_MARK_##X


#define HWASAN_STACK_BACKGROUND   gen_int_mode (0, QImode)
Define the tag for the stack background.
This defines what tag the stack pointer will be and hence what tag all
variables that are not given special tags are (e.g. spilled registers,
and parameters passed on the stack).   

Referenced by expand_HWASAN_ALLOCA_UNPOISON(), expand_HWASAN_MARK(), and hwasan_emit_untag_frame().


#define HWASAN_TAG_GRANULE_SIZE   targetm.memtag.granule_size ()
Tag Granule of HWASAN shadow stack.
This is the size in real memory that each byte in the shadow memory refers
to.  I.e. if a variable is X bytes long in memory then its tag in shadow
memory will span X / HWASAN_TAG_GRANULE_SIZE bytes.
Most variables will need to be aligned to this amount since two variables
that are neighbors in memory and share a tag granule would need to share the
same tag (the shared tag granule can only store one tag).   

Referenced by align_local_variable(), asan_expand_mark_ifn(), asan_poison_variable(), expand_one_stack_var_1(), expand_stack_vars(), handle_builtin_alloca(), and hwasan_emit_prologue().


#define HWASAN_TAG_SIZE   targetm.memtag.tag_size ()
NOTE: The values below and the hooks under targetm.memtag define an ABI and
are hard-coded to these values in libhwasan, hence they can't be changed
independently here.   
How many bits are used to store a tag in a pointer.
The default version uses the entire top byte of a pointer (i.e. 8 bits).   

Referenced by hwasan_increment_frame_tag(), and hwasan_truncate_to_tag_size().


Flags for Asan check builtins.   

Referenced by dump_gimple_call_args().

Enumeration Type Documentation

◆ asan_check_flags

Various flags for Asan builtins.   

◆ asan_mark_flags


Function Documentation

◆ asan_dynamic_init_call()

tree asan_dynamic_init_call ( bool after_p)
__asan_before_dynamic_init (module_name)
__asan_after_dynamic_init ()

References asan_init_shadow_ptr_types(), asan_pp_string(), build_call_expr(), builtin_decl_implicit(), const_ptr_type_node, fold_convert, ggc_alloc(), NULL_TREE, pp_string(), and shadow_ptr_types.

◆ asan_emit_allocas_unpoison()

rtx_insn * asan_emit_allocas_unpoison ( rtx top,
rtx bot,
rtx_insn * before )
Emit __asan_allocas_unpoison (top, bot) call.  The BASE parameter corresponds
to BOT argument, for TOP virtual_stack_dynamic_rtx is used.  NEW_SEQUENCE
indicates whether we're emitting new instructions sequence or not.   

References convert_memory_address, do_pending_stack_adjust(), emit_library_call(), end_sequence(), get_insns(), ggc_alloc(), init_one_libfunc(), insns, LCT_NORMAL, ptr_mode, push_to_sequence(), and start_sequence().

Referenced by expand_used_vars().

◆ asan_emit_stack_protection()

rtx_insn * asan_emit_stack_protection ( rtx base,
rtx pbase,
unsigned int alignb,
HOST_WIDE_INT * offsets,
tree * decls,
int length )
Insert code to protect stack vars.  The prologue sequence should be emitted
directly, epilogue sequence returned.  BASE is the register holding the
stack base, against which OFFSETS array offsets are relative to, OFFSETS
array contains pairs of offsets in reverse order, always the end offset
of some gap that needs protection followed by starting offset,
and DECLS is an array of representative decls for each var partition.
LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1
elements long (OFFSETS include gap before the first variable as well
as gaps after each stack variable).  PBASE is, if non-NULL, some pseudo
register which stack vars DECL_RTLs are based on.  Either BASE should be
assigned to PBASE, when not doing use after return protection, or
corresponding address based on __asan_stack_malloc* return value.   

References adjust_address, asan_clear_shadow(), asan_detect_stack_use_after_return, asan_handled_variables, asan_init_shadow_ptr_types(), ASAN_MIN_RED_ZONE_SIZE, asan_pp_string(), ASAN_RED_ZONE_SIZE, ASAN_SHADOW_GRANULARITY, asan_shadow_offset(), asan_shadow_set, ASAN_SHADOW_SHIFT, ASAN_STACK_FRAME_MAGIC, ASAN_STACK_MAGIC_LEFT, ASAN_STACK_MAGIC_MIDDLE, ASAN_STACK_MAGIC_RIGHT, ASAN_STACK_MAGIC_USE_AFTER_RET, ASAN_STACK_RETIRED_MAGIC, asan_used_labels, build_decl(), build_fold_addr_expr, builtin_memset_read_str(), BUILTINS_LOCATION, can_store_by_pieces(), char_type_node, const0_rtx, hash_set< KeyId, Lazy, Traits >::contains(), convert_memory_address, crtl, current_function_decl, current_function_funcdef_no, DECL_ALIGN_RAW, DECL_ARTIFICIAL, DECL_EXTERNAL, DECL_IGNORED_P, DECL_INITIAL, DECL_NAME, DECL_P, DECL_SOURCE_LOCATION, decls, do_pending_stack_adjust(), dump_file, dump_flags, emit_cmp_and_jump_insns(), emit_jump(), emit_label(), emit_library_call(), emit_library_call_value(), emit_move_insn(), end_sequence(), expand_binop(), expand_location(), expand_normal(), floor_log2(), gcc_assert, gcc_checking_assert, GEN_INT, gen_int_mode(), gen_int_shift_amount(), gen_label_rtx(), gen_reg_rtx(), gen_rtx_MEM(), get_identifier(), get_insns(), GET_MODE_ALIGNMENT, GET_MODE_SIZE(), ggc_alloc(), HOST_WIDE_INT_1, IDENTIFIER_LENGTH, IDENTIFIER_POINTER, init_one_libfunc(), insns, integer_type_node, LCT_NORMAL, NULL, NULL_RTX, NULL_TREE, offset, OPTAB_DIRECT, plus_constant(), pointer_sized_int_node, pp_decimal_int, pp_space, pp_string(), pp_tree_identifier(), pp_wide_integer(), PRId64, ptr_mode, RETURN_BEGIN, seen_error(), SET_DECL_ASSEMBLER_NAME, set_mem_alias_set(), set_mem_align(), set_storage_via_setmem(), shadow_ptr_types, start_sequence(), store_by_pieces(), TDF_DETAILS, TREE_ADDRESSABLE, TREE_ASM_WRITTEN, TREE_PUBLIC, TREE_READONLY, TREE_STATIC, TREE_USED, TYPE_MODE, profile_probability::very_likely(), and profile_probability::very_unlikely().

Referenced by expand_used_vars().

◆ asan_expand_check_ifn()

◆ asan_expand_mark_ifn()

◆ asan_expand_poison_ifn()

◆ asan_finish_file()

◆ asan_function_start()

void asan_function_start ( void )
AddressSanitizer, a fast memory error detector.
   Copyright (C) 2011-2024 Free Software Foundation, Inc.
   Contributed by Kostya Serebryany <kcc@google.com>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see

References asm_out_file, ASM_OUTPUT_DEBUG_LABEL, and current_function_funcdef_no.

Referenced by assemble_function_label_final().

◆ asan_intercepted_p()

bool asan_intercepted_p ( enum built_in_function fcode)
Return TRUE if builtin with given FCODE will be intercepted by

References ggc_alloc(), and hwasan_sanitize_p().

Referenced by expand_builtin(), and get_mem_refs_of_builtin_call().

◆ asan_mark_p()

bool asan_mark_p ( gimple * stmt,
enum asan_mark_flags flag )
Return true if STMT is ASAN_MARK with FLAG as first argument.   

References ggc_alloc(), gimple_call_arg(), gimple_call_internal_p(), and tree_to_uhwi().

Referenced by execute_update_addresses_taken(), and transform_statements().

◆ asan_memfn_rtl()

◆ asan_protect_global()

◆ asan_protect_stack_decl()

bool asan_protect_stack_decl ( tree decl)
Return true if DECL should be guarded on the stack.   

References asan_sanitize_use_after_scope(), DECL_ARTIFICIAL, DECL_P, and TREE_ADDRESSABLE.

Referenced by asan_decl_phase_3(), and expand_stack_vars().

◆ asan_red_zone_size()

unsigned int asan_red_zone_size ( unsigned int size)
Return the size of padding needed to insert after a protected
decl of SIZE.   


Referenced by asan_add_global(), assemble_noswitch_variable(), assemble_variable(), output_constant_def_contents(), output_object_block(), and place_block_symbol().

◆ asan_sanitize_allocas_p()

bool asan_sanitize_allocas_p ( void )

◆ asan_sanitize_stack_p()

◆ asan_sanitize_use_after_scope()

bool asan_sanitize_use_after_scope ( void )
Return TRUE if we should instrument for use-after-scope sanity checking.   

References asan_sanitize_stack_p(), ggc_alloc(), and hwasan_sanitize_stack_p().

Referenced by asan_protect_stack_decl(), gimplify_function_tree(), instrument_derefs(), and maybe_register_def().

◆ asan_shadow_offset_set_p()

bool asan_shadow_offset_set_p ( )
Returns Asan shadow offset has been set.   

References asan_shadow_offset_computed.

Referenced by process_options().

◆ asan_var_and_redzone_size()

unsigned HOST_WIDE_INT asan_var_and_redzone_size ( unsigned HOST_WIDE_INT size)
Return how much a stack variable occupis on a stack
including a space for red zone.   

Referenced by expand_stack_vars().

◆ create_cond_insert_point()

gimple_stmt_iterator create_cond_insert_point ( gimple_stmt_iterator * iter,
bool before_p,
bool then_more_likely_p,
bool create_then_fallthru_edge,
basic_block * then_block,
basic_block * fallthrough_block )
Split the current basic block and create a condition statement
insertion point right before or after the statement pointed to by
ITER.  Return an iterator to the point at which the caller might
safely insert the condition statement.

THEN_BLOCK must be set to the address of an uninitialized instance
of basic_block.  The function will then set *THEN_BLOCK to the
'then block' of the condition statement to be inserted by the

If CREATE_THEN_FALLTHRU_EDGE is false, no edge will be created from

Similarly, the function will set *FALLTRHOUGH_BLOCK to the 'else
block' of the condition statement to be inserted by the caller.

Note that *FALLTHROUGH_BLOCK is a new block that contains the
statements starting from *ITER, and *THEN_BLOCK is a new empty

*ITER is adjusted to point to always point to the first statement
 of the basic block * FALLTHROUGH_BLOCK.  That statement is the
 same as what ITER was pointing to prior to calling this function,
 if BEFORE_P is true; otherwise, it is its following statement.   

References add_bb_to_loop(), CDI_DOMINATORS, basic_block_def::count, create_empty_bb(), current_loops, dom_info_available_p(), find_edge(), ggc_alloc(), gsi_bb(), gsi_end_p(), gsi_last_bb(), gsi_prev(), gsi_start_bb(), gsi_stmt(), LOOPS_NEED_FIXUP, loops_state_set(), make_edge(), make_single_succ_edge(), set_immediate_dominator(), split_block(), profile_probability::very_likely(), and profile_probability::very_unlikely().

Referenced by asan_expand_check_ifn(), insert_if_then_before_iter(), instrument_bool_enum_load(), instrument_builtin(), instrument_nonnull_arg(), instrument_nonnull_return(), ubsan_expand_bounds_ifn(), ubsan_expand_objsize_ifn(), and ubsan_expand_vptr_ifn().

◆ gate_hwasan()

bool gate_hwasan ( void )

Referenced by compile_file().

◆ hwasan_current_frame_tag()

uint8_t hwasan_current_frame_tag ( )
For stack tagging:

Return the offset from the frame base tag that the "next" expanded object
should have.   

References hwasan_frame_tag_offset.

Referenced by expand_HWASAN_CHOOSE_TAG(), expand_one_stack_var_at(), and hwasan_record_stack_var().

◆ hwasan_emit_prologue()

void hwasan_emit_prologue ( )
For stack tagging:
(Emits HWASAN equivalent of what is emitted by

Emits the extra prologue code to set the shadow stack as required for HWASAN
stack instrumentation.

Uses the vector of recorded stack variables hwasan_tagged_stack_vars.  When
this function has completed hwasan_tagged_stack_vars is empty and all
objects it had pointed to are deallocated.   

References convert_memory_address, emit_library_call(), gcc_assert, gen_int_mode(), ggc_alloc(), HWASAN_TAG_GRANULE_SIZE, hwasan_tagged_stack_vars, hwasan_truncate_to_tag_size(), init_one_libfunc(), known_ge, known_le, LCT_NORMAL, NULL_RTX, plus_constant(), ptr_mode, and targetm.

Referenced by expand_used_vars().

◆ hwasan_emit_untag_frame()

rtx_insn * hwasan_emit_untag_frame ( rtx dynamic,
rtx vars )
For stack tagging:

Return RTL insns to clear the tags between DYNAMIC and VARS pointers
into the stack.  These instructions should be emitted at the end of
every function.

If `dynamic` is NULL_RTX then no insns are returned.   

References convert_memory_address, do_pending_stack_adjust(), emit_library_call(), end_sequence(), expand_simple_binop(), FRAME_GROWS_DOWNWARD, get_insns(), ggc_alloc(), HWASAN_STACK_BACKGROUND, init_one_libfunc(), insns, LCT_NORMAL, NULL, NULL_RTX, OPTAB_DIRECT, ptr_mode, and start_sequence().

Referenced by expand_used_vars().

◆ hwasan_expand_check_ifn()

bool hwasan_expand_check_ifn ( gimple_stmt_iterator * iter,
bool  )
Expand the HWASAN_{LOAD,STORE} builtins.   

◆ hwasan_expand_mark_ifn()

bool hwasan_expand_mark_ifn ( gimple_stmt_iterator * )
For stack tagging:

Dummy: the HWASAN_MARK internal function should only ever be in the code
after the sanopt pass.   

◆ hwasan_finish_file()

void hwasan_finish_file ( void )
Needs to be tree hwasan_ctor_statements;

/** @verbatim Insert module initialization into this TU.  This initialization calls the
   initialization code for libhwasan.   

References append_to_statement_list(), build_call_expr(), builtin_decl_implicit(), cgraph_build_static_cdtor(), ggc_alloc(), MAX_RESERVED_INIT_PRIORITY, SANITIZE_HWADDRESS, and SANITIZE_KERNEL_HWADDRESS.

Referenced by compile_file().

◆ hwasan_frame_base()

rtx hwasan_frame_base ( )
For stack tagging:

Return the 'base pointer' for this function.  If that base pointer has not
yet been created then we create a register to hold it and record the insns
to initialize the register in `hwasan_frame_base_init_seq` for later

References end_sequence(), force_reg(), get_insns(), ggc_alloc(), hwasan_frame_base_init_seq, hwasan_frame_base_ptr, NULL_RTX, start_sequence(), targetm, and virtual_stack_vars_rtx.

Referenced by expand_HWASAN_CHOOSE_TAG(), expand_one_stack_var_1(), and expand_stack_vars().

◆ hwasan_get_frame_extent()

rtx hwasan_get_frame_extent ( )
Return the RTX representing the farthest extent of the statically allocated
stack objects for this frame.  If hwasan_frame_base_ptr has not been
initialized then we are not storing any static variables on the stack in
this frame.  In this case we return NULL_RTX to represent that.

Otherwise simply return virtual_stack_vars_rtx + frame_offset.   

References frame_offset, ggc_alloc(), hwasan_frame_base_ptr, NULL_RTX, plus_constant(), and virtual_stack_vars_rtx.

Referenced by expand_used_vars().

◆ hwasan_increment_frame_tag()

void hwasan_increment_frame_tag ( )
For stack tagging:

Increment the frame tag offset modulo the size a tag can represent.   

References CHAR_BIT, gcc_assert, ggc_alloc(), hwasan_frame_tag_offset, HWASAN_TAG_SIZE, sanitize_flags_p(), and SANITIZE_KERNEL_HWADDRESS.

Referenced by expand_HWASAN_CHOOSE_TAG(), expand_one_stack_var_1(), and expand_stack_vars().

◆ hwasan_maybe_emit_frame_base_init()

void hwasan_maybe_emit_frame_base_init ( void )
For stack tagging:

Emit frame base initialisation.
If hwasan_frame_base has been used before here then
hwasan_frame_base_init_seq contains the sequence of instructions to
initialize it.  This must be put just before the hwasan prologue, so we emit
the insns before parm_birth_insn (which will point to the first instruction
of the hwasan prologue if it exists).

We update `parm_birth_insn` to point to the start of this initialisation
since that represents the end of the initialisation done by
expand_function_{start,end} functions and we want to maintain that.   

References emit_insn_before(), hwasan_frame_base_init_seq, and parm_birth_insn.

◆ hwasan_record_frame_init()

void hwasan_record_frame_init ( )
Clear internal state for the next function.
This function is called before variables on the stack get expanded, in

References asan_used_labels, gcc_assert, ggc_alloc(), hwasan_frame_base_init_seq, hwasan_frame_base_ptr, hwasan_frame_tag_offset, hwasan_tagged_stack_vars, NULL, NULL_RTX, sanitize_flags_p(), and SANITIZE_KERNEL_HWADDRESS.

Referenced by init_vars_expansion().

◆ hwasan_record_stack_var()

void hwasan_record_stack_var ( rtx untagged_base,
rtx tagged_base,
poly_int64 nearest_offset,
poly_int64 farthest_offset )
Record a compile-time constant size stack variable that HWASAN will need to
tag.  This record of the range of a stack variable will be used by
`hwasan_emit_prologue` to emit the RTL at the start of each frame which will
set tags in the shadow memory according to the assigned tag for each object.

The range that the object spans in stack space should be described by the
bounds `untagged_base + nearest_offset` and
`untagged_base + farthest_offset`.
`tagged_base` is the base address which contains the "base frame tag" for
this frame, and from which the value to address this object with will be

We record the `untagged_base` since the functions in the hwasan library we
use to tag memory take pointers without a tag.   

References ggc_alloc(), hwasan_current_frame_tag(), and hwasan_tagged_stack_vars.

Referenced by expand_one_stack_var_1(), and expand_stack_vars().

◆ hwasan_sanitize_allocas_p()

bool hwasan_sanitize_allocas_p ( void )
Are we tagging alloca objects?   

References ggc_alloc(), and hwasan_sanitize_stack_p().

Referenced by expand_used_vars(), handle_builtin_alloca(), and handle_builtin_stack_restore().

◆ hwasan_sanitize_p()

bool hwasan_sanitize_p ( void )
HWAddressSanitizer (hwasan) is a probabilistic method for detecting
out-of-bounds and use-after-free bugs.
Read more:

Similar to AddressSanitizer (asan) it consists of two parts: the
instrumentation module in this file, and a run-time library.

The instrumentation module adds a run-time check before every memory insn in
the same manner as asan (see the block comment for AddressSanitizer above).
Currently, hwasan only adds out-of-line instrumentation, where each check is
implemented as a function call to the run-time library.  Hence a check for a
load of N bytes from address X would be implemented with a function call to
__hwasan_loadN(X), and checking a store of N bytes from address X would be
implemented with a function call to __hwasan_storeN(X).

The main difference between hwasan and asan is in the information stored to
help this checking.  Both sanitizers use a shadow memory area which stores
data recording the state of main memory at a corresponding address.

For hwasan, each 16 byte granule in main memory has a corresponding 1 byte
in shadow memory.  This shadow address can be calculated with equation:
  (addr >> log_2(HWASAN_TAG_GRANULE_SIZE))
       + __hwasan_shadow_memory_dynamic_address;
The conversion between real and shadow memory for asan is given in the block
comment at the top of this file.
The description of how this shadow memory is laid out for asan is in the
block comment at the top of this file, here we describe how this shadow
memory is used for hwasan.

For hwasan, each variable is assigned a byte-sized 'tag'.  The extent of
the shadow memory for that variable is filled with the assigned tag, and
every pointer referencing that variable has its top byte set to the same
tag.  The run-time library redefines malloc so that every allocation returns
a tagged pointer and tags the corresponding shadow memory with the same tag.

On each pointer dereference the tag found in the pointer is compared to the
tag found in the shadow memory corresponding to the accessed memory address.
If these tags are found to differ then this memory access is judged to be
invalid and a report is generated.

This method of bug detection is not perfect -- it can not catch every bad
access -- but catches them probabilistically instead.  There is always the
possibility that an invalid memory access will happen to access memory
tagged with the same tag as the pointer that this access used.
The chances of this are approx. 0.4% for any two uncorrelated objects.

Random tag generation can mitigate this problem by decreasing the
probability that an invalid access will be missed in the same manner over
multiple runs.  i.e. if two objects are tagged the same in one run of the
binary they are unlikely to be tagged the same in the next run.
Both heap and stack allocated objects have random tags by default.

[16 byte granule implications]
 Since the shadow memory only has a resolution on real memory of 16 bytes,
 invalid accesses that are within the same 16 byte granule as a valid
 address will not be caught.

 There is a "short-granule" feature in the runtime library which does catch
 such accesses, but this feature is not implemented for stack objects (since
 stack objects are allocated and tagged by compiler instrumentation, and
 this feature has not yet been implemented in GCC instrumentation).

 Another outcome of this 16 byte resolution is that each tagged object must
 be 16 byte aligned.  If two objects were to share any 16 byte granule in
 memory, then they both would have to be given the same tag, and invalid
 accesses to one using a pointer to the other would be undetectable.

[Compiler instrumentation]
 Compiler instrumentation ensures that two adjacent buffers on the stack are
 given different tags, this means an access to one buffer using a pointer
 generated from the other (e.g. through buffer overrun) will have mismatched
 tags and be caught by hwasan.

 We don't randomly tag every object on the stack, since that would require
 keeping many registers to record each tag.  Instead we randomly generate a
 tag for each function frame, and each new stack object uses a tag offset
 from that frame tag.
 i.e. each object is tagged as RFT + offset, where RFT is the "random frame
 tag" generated for this frame.
 This means that randomisation does not peturb the difference between tags
 on tagged stack objects within a frame, but this is mitigated by the fact
 that objects with the same tag within a frame are very far apart
 (approx. 2^HWASAN_TAG_SIZE objects apart).

 As a demonstration, using the same example program as in the asan block
 comment above:

  foo ()
    char a[24] = {0};
    int b[2] = {0};

    a[5] = 1;
    b[1] = 2;

    return a[5] + b[1];

 On AArch64 the stack will be ordered as follows for the above function:

 Slot 1/ [24 bytes for variable 'a']
 Slot 2/ [8 bytes padding for alignment]
 Slot 3/ [8 bytes for variable 'b']
 Slot 4/ [8 bytes padding for alignment]

 (The padding is there to ensure 16 byte alignment as described in the 16
  byte granule implications).

 While the shadow memory will be ordered as follows:

 - 2 bytes (representing 32 bytes in real memory) tagged with RFT + 1.
 - 1 byte (representing 16 bytes in real memory) tagged with RFT + 2.

 And any pointer to "a" will have the tag RFT + 1, and any pointer to "b"
 will have the tag RFT + 2.

[Top Byte Ignore requirements]
 Hwasan requires the ability to store an 8 bit tag in every pointer.  There
 is no instrumentation done to remove this tag from pointers before
 dereferencing, which means the hardware must ignore this tag during memory

 Architectures where this feature is available should indicate this using

[Stack requires cleanup on unwinding]
 During normal operation of a hwasan sanitized program more space in the
 shadow memory becomes tagged as the stack grows.  As the stack shrinks this
 shadow memory space must become untagged.  If it is not untagged then when
 the stack grows again (during other function calls later on in the program)
 objects on the stack that are usually not tagged (e.g. parameters passed on
 the stack) can be placed in memory whose shadow space is tagged with
 something else, and accesses can cause false positive reports.

 Hence we place untagging code on every epilogue of functions which tag some
 stack objects.

 Moreover, the run-time library intercepts longjmp & setjmp to untag when
 the stack is unwound this way.

 C++ exceptions are not yet handled, which means this sanitizer can not
 handle C++ code that throws exceptions -- it will give false positives
 after an exception has been thrown.  The implementation that the hwasan
 library has for handling these relies on the frame pointer being after any
 local variables.  This is not generally the case for GCC.   
Returns whether we are tagging pointers and checking those tags on memory

References sanitize_flags_p(), and SANITIZE_HWADDRESS.

Referenced by asan_expand_check_ifn(), asan_expand_mark_ifn(), asan_expand_poison_ifn(), asan_instrument(), asan_intercepted_p(), asan_poison_variable(), build_check_stmt(), get_mem_refs_of_builtin_call(), hwasan_instrument_reads(), hwasan_instrument_writes(), hwasan_memintrin(), hwasan_sanitize_stack_p(), instrument_derefs(), maybe_instrument_call(), report_error_func(), and sanopt_optimize_walker().

◆ hwasan_sanitize_stack_p()

◆ hwasan_truncate_to_tag_size()

rtx hwasan_truncate_to_tag_size ( rtx tag,
rtx target )
For stack tagging:

Truncate `tag` to the number of bits that a tag uses (i.e. to
HWASAN_TAG_SIZE).  Store the result in `target` if it's convenient.   

References expand_simple_binop(), gcc_assert, gen_int_mode(), GET_MODE, GET_MODE_PRECISION(), ggc_alloc(), HOST_WIDE_INT_1U, HWASAN_TAG_SIZE, and OPTAB_WIDEN.

Referenced by expand_HWASAN_CHOOSE_TAG(), and hwasan_emit_prologue().

◆ initialize_sanitizer_builtins()

◆ sanitize_coverage_p()

bool sanitize_coverage_p ( const_tree fn = current_function_decl)
Return true when coverage sanitization should happend for FN function.   

References DECL_ATTRIBUTES, ggc_alloc(), lookup_attribute(), and NULL_TREE.

Referenced by fold_range_test(), fold_truth_andor(), ifcombine_ifandif(), and sanitize_attrs_match_for_inline_p().

◆ sanitize_flags_p()

◆ set_asan_shadow_offset()

bool set_asan_shadow_offset ( const char * val)
Sets shadow offset to value in string VAL.   

References asan_shadow_offset_computed, asan_shadow_offset_value, errno, and ggc_alloc().

Referenced by handle_common_deferred_options().

◆ set_sanitized_sections()

void set_sanitized_sections ( const char * sections)
Set list of user-defined sections that need to be sanitized.   

References end(), FOR_EACH_VEC_ELT, free(), ggc_alloc(), i, and sanitized_sections.

Referenced by handle_common_deferred_options().

◆ stack_vars_base_reg_p()

bool stack_vars_base_reg_p ( rtx base)
For stack tagging:

Check whether this RTX is a standard pointer addressing the base of the
stack variables for this frame.  Returns true if the RTX is either
virtual_stack_vars_rtx or hwasan_frame_base_ptr.   

References hwasan_frame_base_ptr, and virtual_stack_vars_rtx.

Referenced by expand_one_stack_var_at().

Variable Documentation

◆ asan_handled_variables

hash_set<tree>* asan_handled_variables
Set of variable declarations that are going to be guarded by
use-after-scope sanitizer.   

Referenced by asan_emit_stack_protection(), asan_expand_mark_ifn(), and expand_stack_vars().

◆ asan_shadow_set

alias_set_type asan_shadow_set
Alias set for accessing the shadow memory.   

Referenced by asan_emit_stack_protection(), and asan_init_shadow_ptr_types().

◆ asan_used_labels

hash_set<tree>* asan_used_labels
Hash set of labels that are either used in a goto, or their address
has been taken.   

Referenced by asan_emit_stack_protection(), gimplify_expr(), and hwasan_record_frame_init().