LCOV - code coverage report
Current view: top level - gcc - asan.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.1 % 2037 1733
Test Date: 2026-08-22 16:33:35 Functions: 92.9 % 113 105
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* AddressSanitizer, a fast memory error detector.
       2              :    Copyright (C) 2012-2026 Free Software Foundation, Inc.
       3              :    Contributed by Kostya Serebryany <kcc@google.com>
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "target.h"
      27              : #include "rtl.h"
      28              : #include "tree.h"
      29              : #include "gimple.h"
      30              : #include "cfghooks.h"
      31              : #include "alloc-pool.h"
      32              : #include "tree-pass.h"
      33              : #include "memmodel.h"
      34              : #include "tm_p.h"
      35              : #include "ssa.h"
      36              : #include "stringpool.h"
      37              : #include "tree-ssanames.h"
      38              : #include "optabs.h"
      39              : #include "emit-rtl.h"
      40              : #include "cgraph.h"
      41              : #include "gimple-pretty-print.h"
      42              : #include "alias.h"
      43              : #include "fold-const.h"
      44              : #include "cfganal.h"
      45              : #include "gimplify.h"
      46              : #include "gimple-iterator.h"
      47              : #include "varasm.h"
      48              : #include "stor-layout.h"
      49              : #include "tree-iterator.h"
      50              : #include "stringpool.h"
      51              : #include "attribs.h"
      52              : #include "asan.h"
      53              : #include "dojump.h"
      54              : #include "explow.h"
      55              : #include "expr.h"
      56              : #include "output.h"
      57              : #include "langhooks.h"
      58              : #include "cfgloop.h"
      59              : #include "gimple-builder.h"
      60              : #include "gimple-fold.h"
      61              : #include "ubsan.h"
      62              : #include "builtins.h"
      63              : #include "fnmatch.h"
      64              : #include "tree-inline.h"
      65              : #include "tree-ssa.h"
      66              : #include "tree-eh.h"
      67              : #include "diagnostic-core.h"
      68              : 
      69              : /* AddressSanitizer finds out-of-bounds and use-after-free bugs
      70              :    with <2x slowdown on average.
      71              : 
      72              :    The tool consists of two parts:
      73              :    instrumentation module (this file) and a run-time library.
      74              :    The instrumentation module adds a run-time check before every memory insn.
      75              :      For a 8- or 16- byte load accessing address X:
      76              :        ShadowAddr = (X >> 3) + Offset
      77              :        ShadowValue = *(char*)ShadowAddr;  // *(short*) for 16-byte access.
      78              :        if (ShadowValue)
      79              :          __asan_report_load8(X);
      80              :      For a load of N bytes (N=1, 2 or 4) from address X:
      81              :        ShadowAddr = (X >> 3) + Offset
      82              :        ShadowValue = *(char*)ShadowAddr;
      83              :        if (ShadowValue)
      84              :          if ((X & 7) + N - 1 > ShadowValue)
      85              :            __asan_report_loadN(X);
      86              :    Stores are instrumented similarly, but using __asan_report_storeN functions.
      87              :    A call too __asan_init_vN() is inserted to the list of module CTORs.
      88              :    N is the version number of the AddressSanitizer API. The changes between the
      89              :    API versions are listed in libsanitizer/asan/asan_interface_internal.h.
      90              : 
      91              :    The run-time library redefines malloc (so that redzone are inserted around
      92              :    the allocated memory) and free (so that reuse of free-ed memory is delayed),
      93              :    provides __asan_report* and __asan_init_vN functions.
      94              : 
      95              :    Read more:
      96              :    http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
      97              : 
      98              :    The current implementation supports detection of out-of-bounds and
      99              :    use-after-free in the heap, on the stack and for global variables.
     100              : 
     101              :    [Protection of stack variables]
     102              : 
     103              :    To understand how detection of out-of-bounds and use-after-free works
     104              :    for stack variables, lets look at this example on x86_64 where the
     105              :    stack grows downward:
     106              : 
     107              :      int
     108              :      foo ()
     109              :      {
     110              :        char a[24] = {0};
     111              :        int b[2] = {0};
     112              : 
     113              :        a[5] = 1;
     114              :        b[1] = 2;
     115              : 
     116              :        return a[5] + b[1];
     117              :      }
     118              : 
     119              :    For this function, the stack protected by asan will be organized as
     120              :    follows, from the top of the stack to the bottom:
     121              : 
     122              :    Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone']
     123              : 
     124              :    Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make
     125              :            the next slot be 32 bytes aligned; this one is called Partial
     126              :            Redzone; this 32 bytes alignment is an asan constraint]
     127              : 
     128              :    Slot 3/ [24 bytes for variable 'a']
     129              : 
     130              :    Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
     131              : 
     132              :    Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
     133              : 
     134              :    Slot 6/ [8 bytes for variable 'b']
     135              : 
     136              :    Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called
     137              :             'LEFT RedZone']
     138              : 
     139              :    The 32 bytes of LEFT red zone at the bottom of the stack can be
     140              :    decomposed as such:
     141              : 
     142              :      1/ The first 8 bytes contain a magical asan number that is always
     143              :      0x41B58AB3.
     144              : 
     145              :      2/ The following 8 bytes contains a pointer to a string (to be
     146              :      parsed at runtime by the runtime asan library), which format is
     147              :      the following:
     148              : 
     149              :       "<function-name> <space> <num-of-variables-on-the-stack>
     150              :       (<32-bytes-aligned-offset-in-bytes-of-variable> <space>
     151              :       <length-of-var-in-bytes> ){n} "
     152              : 
     153              :         where '(...){n}' means the content inside the parenthesis occurs 'n'
     154              :         times, with 'n' being the number of variables on the stack.
     155              : 
     156              :      3/ The following 8 bytes contain the PC of the current function which
     157              :      will be used by the run-time library to print an error message.
     158              : 
     159              :      4/ The following 8 bytes are reserved for internal use by the run-time.
     160              : 
     161              :    The shadow memory for that stack layout is going to look like this:
     162              : 
     163              :      - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1.
     164              :        The F1 byte pattern is a magic number called
     165              :        ASAN_STACK_MAGIC_LEFT and is a way for the runtime to know that
     166              :        the memory for that shadow byte is part of a the LEFT red zone
     167              :        intended to seat at the bottom of the variables on the stack.
     168              : 
     169              :      - content of shadow memory 8 bytes for slots 6 and 5:
     170              :        0xF4F4F400.  The F4 byte pattern is a magic number
     171              :        called ASAN_STACK_MAGIC_PARTIAL.  It flags the fact that the
     172              :        memory region for this shadow byte is a PARTIAL red zone
     173              :        intended to pad a variable A, so that the slot following
     174              :        {A,padding} is 32 bytes aligned.
     175              : 
     176              :        Note that the fact that the least significant byte of this
     177              :        shadow memory content is 00 means that 8 bytes of its
     178              :        corresponding memory (which corresponds to the memory of
     179              :        variable 'b') is addressable.
     180              : 
     181              :      - content of shadow memory 8 bytes for slot 4: 0xF2F2F2F2.
     182              :        The F2 byte pattern is a magic number called
     183              :        ASAN_STACK_MAGIC_MIDDLE.  It flags the fact that the memory
     184              :        region for this shadow byte is a MIDDLE red zone intended to
     185              :        seat between two 32 aligned slots of {variable,padding}.
     186              : 
     187              :      - content of shadow memory 8 bytes for slot 3 and 2:
     188              :        0xF4000000.  This represents is the concatenation of
     189              :        variable 'a' and the partial red zone following it, like what we
     190              :        had for variable 'b'.  The least significant 3 bytes being 00
     191              :        means that the 3 bytes of variable 'a' are addressable.
     192              : 
     193              :      - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3.
     194              :        The F3 byte pattern is a magic number called
     195              :        ASAN_STACK_MAGIC_RIGHT.  It flags the fact that the memory
     196              :        region for this shadow byte is a RIGHT red zone intended to seat
     197              :        at the top of the variables of the stack.
     198              : 
     199              :    Note that the real variable layout is done in expand_used_vars in
     200              :    cfgexpand.cc.  As far as Address Sanitizer is concerned, it lays out
     201              :    stack variables as well as the different red zones, emits some
     202              :    prologue code to populate the shadow memory as to poison (mark as
     203              :    non-accessible) the regions of the red zones and mark the regions of
     204              :    stack variables as accessible, and emit some epilogue code to
     205              :    un-poison (mark as accessible) the regions of red zones right before
     206              :    the function exits.
     207              : 
     208              :    [Protection of global variables]
     209              : 
     210              :    The basic idea is to insert a red zone between two global variables
     211              :    and install a constructor function that calls the asan runtime to do
     212              :    the populating of the relevant shadow memory regions at load time.
     213              : 
     214              :    So the global variables are laid out as to insert a red zone between
     215              :    them. The size of the red zones is so that each variable starts on a
     216              :    32 bytes boundary.
     217              : 
     218              :    Then a constructor function is installed so that, for each global
     219              :    variable, it calls the runtime asan library function
     220              :    __asan_register_globals_with an instance of this type:
     221              : 
     222              :      struct __asan_global
     223              :      {
     224              :        // Address of the beginning of the global variable.
     225              :        const void *__beg;
     226              : 
     227              :        // Initial size of the global variable.
     228              :        uptr __size;
     229              : 
     230              :        // Size of the global variable + size of the red zone.  This
     231              :        //   size is 32 bytes aligned.
     232              :        uptr __size_with_redzone;
     233              : 
     234              :        // Name of the global variable.
     235              :        const void *__name;
     236              : 
     237              :        // Name of the module where the global variable is declared.
     238              :        const void *__module_name;
     239              : 
     240              :        // 1 if it has dynamic initialization, 0 otherwise.
     241              :        uptr __has_dynamic_init;
     242              : 
     243              :        // A pointer to struct that contains source location, could be NULL.
     244              :        __asan_global_source_location *__location;
     245              :      }
     246              : 
     247              :    A destructor function that calls the runtime asan library function
     248              :    _asan_unregister_globals is also installed.  */
     249              : 
     250              : static unsigned HOST_WIDE_INT asan_shadow_offset_value;
     251              : static bool asan_shadow_offset_computed;
     252              : static vec<char *> sanitized_sections;
     253              : static tree last_alloca_addr;
     254              : 
     255              : /* Set of variable declarations that are going to be guarded by
     256              :    use-after-scope sanitizer.  */
     257              : 
     258              : hash_set<tree> *asan_handled_variables = NULL;
     259              : 
     260              : hash_set <tree> *asan_used_labels = NULL;
     261              : 
     262              : /* Global variables for HWASAN stack tagging.  */
     263              : /* hwasan_frame_tag_offset records the offset from the frame base tag that the
     264              :    next object should have.  */
     265              : static uint8_t hwasan_frame_tag_offset = 0;
     266              : /* hwasan_frame_base_ptr is a pointer with the same address as
     267              :    `virtual_stack_vars_rtx` for the current frame, and with the frame base tag
     268              :    stored in it.  N.b. this global RTX does not need to be marked GTY, but is
     269              :    done so anyway.  The need is not there since all uses are in just one pass
     270              :    (cfgexpand) and there are no calls to ggc_collect between the uses.  We mark
     271              :    it GTY(()) anyway to allow the use of the variable later on if needed by
     272              :    future features.  */
     273              : static GTY(()) rtx hwasan_frame_base_ptr = NULL_RTX;
     274              : /* hwasan_frame_base_init_seq is the sequence of RTL insns that will initialize
     275              :    the hwasan_frame_base_ptr.  When the hwasan_frame_base_ptr is requested, we
     276              :    generate this sequence but do not emit it.  If the sequence was created it
     277              :    is emitted once the function body has been expanded.
     278              : 
     279              :    This delay is because the frame base pointer may be needed anywhere in the
     280              :    function body, or needed by the expand_used_vars function.  Emitting once in
     281              :    a known place is simpler than requiring the emission of the instructions to
     282              :    be know where it should go depending on the first place the hwasan frame
     283              :    base is needed.  */
     284              : static GTY(()) rtx_insn *hwasan_frame_base_init_seq = NULL;
     285              : 
     286              : /* Structure defining the extent of one object on the stack that HWASAN needs
     287              :    to tag in the corresponding shadow stack space.
     288              : 
     289              :    The range this object spans on the stack is between `untagged_base +
     290              :    nearest_offset` and `untagged_base + farthest_offset`.
     291              :    `tagged_base` is an rtx containing the same value as `untagged_base` but
     292              :    with a random tag stored in the top byte.  We record both `untagged_base`
     293              :    and `tagged_base` so that `hwasan_emit_prologue` can use both without having
     294              :    to emit RTL into the instruction stream to re-calculate one from the other.
     295              :    (`hwasan_emit_prologue` needs to use both bases since the
     296              :    __hwasan_tag_memory call it emits uses an untagged value, and it calculates
     297              :    the tag to store in shadow memory based on the tag_offset plus the tag in
     298              :    tagged_base).  */
     299              : struct hwasan_stack_var
     300              : {
     301              :   rtx untagged_base;
     302              :   rtx tagged_base;
     303              :   poly_int64 nearest_offset;
     304              :   poly_int64 farthest_offset;
     305              :   uint8_t tag_offset;
     306              : };
     307              : 
     308              : /* Variable recording all stack variables that HWASAN needs to tag.
     309              :    Does not need to be marked as GTY(()) since every use is in the cfgexpand
     310              :    pass and gcc_collect is not called in the middle of that pass.  */
     311              : static vec<hwasan_stack_var> hwasan_tagged_stack_vars;
     312              : 
     313              : 
     314              : /* Sets shadow offset to value in string VAL.  */
     315              : 
     316              : bool
     317           11 : set_asan_shadow_offset (const char *val)
     318              : {
     319           11 :   char *endp;
     320              : 
     321           11 :   errno = 0;
     322              : #ifdef HAVE_LONG_LONG
     323           11 :   asan_shadow_offset_value = strtoull (val, &endp, 0);
     324              : #else
     325              :   asan_shadow_offset_value = strtoul (val, &endp, 0);
     326              : #endif
     327           11 :   if (!(*val != '\0' && *endp == '\0' && errno == 0))
     328              :     return false;
     329              : 
     330           11 :   asan_shadow_offset_computed = true;
     331              : 
     332           11 :   return true;
     333              : }
     334              : 
     335              : /* Set list of user-defined sections that need to be sanitized.  */
     336              : 
     337              : void
     338           40 : set_sanitized_sections (const char *sections)
     339              : {
     340           40 :   char *pat;
     341           40 :   unsigned i;
     342           50 :   FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
     343           10 :     free (pat);
     344           40 :   sanitized_sections.truncate (0);
     345              : 
     346          130 :   for (const char *s = sections; *s; )
     347              :     {
     348              :       const char *end;
     349          220 :       for (end = s; *end && *end != ','; ++end);
     350           50 :       size_t len = end - s;
     351           50 :       sanitized_sections.safe_push (xstrndup (s, len));
     352           50 :       s = *end ? end + 1 : end;
     353              :     }
     354           40 : }
     355              : 
     356              : bool
     357       105907 : asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
     358              : {
     359       105907 :   return (gimple_call_internal_p (stmt, IFN_ASAN_MARK)
     360       105907 :           && tree_to_uhwi (gimple_call_arg (stmt, 0)) == flag);
     361              : }
     362              : 
     363              : bool
     364     21140649 : asan_sanitize_stack_p (void)
     365              : {
     366     21140649 :   return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_stack);
     367              : }
     368              : 
     369              : bool
     370      1516303 : asan_sanitize_allocas_p (void)
     371              : {
     372      1516303 :   return (asan_sanitize_stack_p () && param_asan_protect_allocas);
     373              : }
     374              : 
     375              : bool
     376        13734 : asan_instrument_reads (void)
     377              : {
     378        13734 :   return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_reads);
     379              : }
     380              : 
     381              : bool
     382        12691 : asan_instrument_writes (void)
     383              : {
     384        12691 :   return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_writes);
     385              : }
     386              : 
     387              : bool
     388         4409 : asan_memintrin (void)
     389              : {
     390         4409 :   return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_memintrin);
     391              : }
     392              : 
     393              : 
     394              : /* Support for --param asan-kernel-mem-intrinsic-prefix=1.  */
     395              : static GTY(()) rtx asan_memfn_rtls[3];
     396              : 
     397              : rtx
     398           42 : asan_memfn_rtl (tree fndecl)
     399              : {
     400           42 :   int i;
     401           42 :   const char *f, *p;
     402           42 :   char buf[sizeof ("__hwasan_memmove")];
     403              : 
     404           42 :   switch (DECL_FUNCTION_CODE (fndecl))
     405              :     {
     406              :     case BUILT_IN_MEMCPY: i = 0; f = "memcpy"; break;
     407           14 :     case BUILT_IN_MEMSET: i = 1; f = "memset"; break;
     408           14 :     case BUILT_IN_MEMMOVE: i = 2; f = "memmove"; break;
     409            0 :     default: gcc_unreachable ();
     410              :     }
     411           42 :   if (asan_memfn_rtls[i] == NULL_RTX)
     412              :     {
     413           42 :       tree save_name = DECL_NAME (fndecl);
     414           42 :       tree save_assembler_name = DECL_ASSEMBLER_NAME (fndecl);
     415           42 :       rtx save_rtl = DECL_RTL (fndecl);
     416           42 :       if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
     417              :         p = "__hwasan_";
     418              :       else
     419           42 :         p = "__asan_";
     420           42 :       strcpy (buf, p);
     421           42 :       strcat (buf, f);
     422           42 :       DECL_NAME (fndecl) = get_identifier (buf);
     423           42 :       DECL_ASSEMBLER_NAME_RAW (fndecl) = NULL_TREE;
     424           42 :       SET_DECL_RTL (fndecl, NULL_RTX);
     425           42 :       asan_memfn_rtls[i] = DECL_RTL (fndecl);
     426           42 :       DECL_NAME (fndecl) = save_name;
     427           42 :       DECL_ASSEMBLER_NAME_RAW (fndecl) = save_assembler_name;
     428           42 :       SET_DECL_RTL (fndecl, save_rtl);
     429              :     }
     430           42 :   return asan_memfn_rtls[i];
     431              : }
     432              : 
     433              : 
     434              : /* Checks whether section SEC should be sanitized.  */
     435              : 
     436              : static bool
     437          270 : section_sanitized_p (const char *sec)
     438              : {
     439          270 :   char *pat;
     440          270 :   unsigned i;
     441          420 :   FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
     442          330 :     if (fnmatch (pat, sec, FNM_PERIOD) == 0)
     443              :       return true;
     444              :   return false;
     445              : }
     446              : 
     447              : /* Returns Asan shadow offset.  */
     448              : 
     449              : static unsigned HOST_WIDE_INT
     450        23693 : asan_shadow_offset ()
     451              : {
     452        23693 :   if (!asan_shadow_offset_computed)
     453              :     {
     454         1751 :       asan_shadow_offset_computed = true;
     455         1751 :       asan_shadow_offset_value = targetm.asan_shadow_offset ();
     456              :     }
     457        23693 :   return asan_shadow_offset_value;
     458              : }
     459              : 
     460              : static bool
     461        30084 : asan_dynamic_shadow_offset_p ()
     462              : {
     463        30084 :   return (asan_shadow_offset_value == 0)
     464        30084 :          && targetm.asan_dynamic_shadow_offset_p ();
     465              : }
     466              : 
     467              : /* Returns Asan shadow offset has been set.  */
     468              : bool
     469            0 : asan_shadow_offset_set_p ()
     470              : {
     471            0 :   return asan_shadow_offset_computed;
     472              : }
     473              : 
     474              : alias_set_type asan_shadow_set = -1;
     475              : 
     476              : /* Pointer types to 1, 2 or 4 byte integers in shadow memory.  A separate
     477              :    alias set is used for all shadow memory accesses.  */
     478              : static GTY(()) tree shadow_ptr_types[3];
     479              : 
     480              : /* Decl for __asan_option_detect_stack_use_after_return.  */
     481              : static GTY(()) tree asan_detect_stack_use_after_return;
     482              : 
     483              : static GTY (()) tree asan_shadow_memory_dynamic_address;
     484              : 
     485              : /* Local copy for the asan_shadow_memory_dynamic_address within the
     486              :    function.  */
     487              : static GTY (()) tree asan_local_shadow_memory_dynamic_address;
     488              : 
     489              : static tree
     490            0 : get_asan_shadow_memory_dynamic_address_decl ()
     491              : {
     492            0 :   if (asan_shadow_memory_dynamic_address == NULL_TREE)
     493              :     {
     494            0 :       tree id, decl;
     495            0 :       id = get_identifier ("__asan_shadow_memory_dynamic_address");
     496            0 :       decl
     497            0 :         = build_decl (BUILTINS_LOCATION, VAR_DECL, id, pointer_sized_int_node);
     498            0 :       SET_DECL_ASSEMBLER_NAME (decl, id);
     499            0 :       TREE_ADDRESSABLE (decl) = 1;
     500            0 :       DECL_ARTIFICIAL (decl) = 1;
     501            0 :       DECL_IGNORED_P (decl) = 1;
     502            0 :       DECL_EXTERNAL (decl) = 1;
     503            0 :       TREE_STATIC (decl) = 1;
     504            0 :       TREE_PUBLIC (decl) = 1;
     505            0 :       TREE_USED (decl) = 1;
     506            0 :       asan_shadow_memory_dynamic_address = decl;
     507              :     }
     508              : 
     509            0 :   return asan_shadow_memory_dynamic_address;
     510              : }
     511              : 
     512              : void
     513         6391 : asan_maybe_insert_dynamic_shadow_at_function_entry (function *fun)
     514              : {
     515         6391 :   asan_local_shadow_memory_dynamic_address = NULL_TREE;
     516         6391 :   if (!asan_dynamic_shadow_offset_p ())
     517              :     return;
     518              : 
     519            0 :   gimple *g;
     520              : 
     521            0 :   tree lhs = create_tmp_var (pointer_sized_int_node,
     522              :                              "__local_asan_shadow_memory_dynamic_address");
     523              : 
     524            0 :   g = gimple_build_assign (lhs, get_asan_shadow_memory_dynamic_address_decl ());
     525            0 :   gimple_set_location (g, fun->function_start_locus);
     526            0 :   edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
     527            0 :   gsi_insert_on_edge_immediate (e, g);
     528              : 
     529            0 :   asan_local_shadow_memory_dynamic_address = lhs;
     530              : }
     531              : 
     532              : /* Hashtable support for memory references used by gimple
     533              :    statements.  */
     534              : 
     535              : /* This type represents a reference to a memory region.  */
     536              : struct asan_mem_ref
     537              : {
     538              :   /* The expression of the beginning of the memory region.  */
     539              :   tree start;
     540              : 
     541              :   /* The size of the access.  */
     542              :   HOST_WIDE_INT access_size;
     543              : };
     544              : 
     545              : object_allocator <asan_mem_ref> asan_mem_ref_pool ("asan_mem_ref");
     546              : 
     547              : /* Initializes an instance of asan_mem_ref.  */
     548              : 
     549              : static void
     550       159517 : asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size)
     551              : {
     552       159584 :   ref->start = start;
     553       159584 :   ref->access_size = access_size;
     554            0 : }
     555              : 
     556              : /* Allocates memory for an instance of asan_mem_ref into the memory
     557              :    pool returned by asan_mem_ref_get_alloc_pool and initialize it.
     558              :    START is the address of (or the expression pointing to) the
     559              :    beginning of memory reference.  ACCESS_SIZE is the size of the
     560              :    access to the referenced memory.  */
     561              : 
     562              : static asan_mem_ref*
     563        37486 : asan_mem_ref_new (tree start, HOST_WIDE_INT access_size)
     564              : {
     565            0 :   asan_mem_ref *ref = asan_mem_ref_pool.allocate ();
     566              : 
     567        37486 :   asan_mem_ref_init (ref, start, access_size);
     568        37486 :   return ref;
     569              : }
     570              : 
     571              : /* This builds and returns a pointer to the end of the memory region
     572              :    that starts at START and of length LEN.  */
     573              : 
     574              : tree
     575            0 : asan_mem_ref_get_end (tree start, tree len)
     576              : {
     577            0 :   if (len == NULL_TREE || integer_zerop (len))
     578              :     return start;
     579              : 
     580            0 :   if (!ptrofftype_p (len))
     581            0 :     len = convert_to_ptrofftype (len);
     582              : 
     583            0 :   return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len);
     584              : }
     585              : 
     586              : /*  Return a tree expression that represents the end of the referenced
     587              :     memory region.  Beware that this function can actually build a new
     588              :     tree expression.  */
     589              : 
     590              : tree
     591            0 : asan_mem_ref_get_end (const asan_mem_ref *ref, tree len)
     592              : {
     593            0 :   return asan_mem_ref_get_end (ref->start, len);
     594              : }
     595              : 
     596              : struct asan_mem_ref_hasher : nofree_ptr_hash <asan_mem_ref>
     597              : {
     598              :   static inline hashval_t hash (const asan_mem_ref *);
     599              :   static inline bool equal (const asan_mem_ref *, const asan_mem_ref *);
     600              : };
     601              : 
     602              : /* Hash a memory reference.  */
     603              : 
     604              : inline hashval_t
     605       254619 : asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref)
     606              : {
     607       254619 :   return iterative_hash_expr (mem_ref->start, 0);
     608              : }
     609              : 
     610              : /* Compare two memory references.  We accept the length of either
     611              :    memory references to be NULL_TREE.  */
     612              : 
     613              : inline bool
     614       192249 : asan_mem_ref_hasher::equal (const asan_mem_ref *m1,
     615              :                             const asan_mem_ref *m2)
     616              : {
     617       192249 :   return operand_equal_p (m1->start, m2->start, 0);
     618              : }
     619              : 
     620              : static hash_table<asan_mem_ref_hasher> *asan_mem_ref_ht;
     621              : 
     622              : /* Returns a reference to the hash table containing memory references.
     623              :    This function ensures that the hash table is created.  Note that
     624              :    this hash table is updated by the function
     625              :    update_mem_ref_hash_table.  */
     626              : 
     627              : static hash_table<asan_mem_ref_hasher> *
     628        83094 : get_mem_ref_hash_table ()
     629              : {
     630        83094 :   if (!asan_mem_ref_ht)
     631         3529 :     asan_mem_ref_ht = new hash_table<asan_mem_ref_hasher> (10);
     632              : 
     633        83094 :   return asan_mem_ref_ht;
     634              : }
     635              : 
     636              : /* Clear all entries from the memory references hash table.  */
     637              : 
     638              : static void
     639        37311 : empty_mem_ref_hash_table ()
     640              : {
     641        37311 :   if (asan_mem_ref_ht)
     642        20740 :     asan_mem_ref_ht->empty ();
     643        37311 : }
     644              : 
     645              : /* Free the memory references hash table.  */
     646              : 
     647              : static void
     648         6572 : free_mem_ref_resources ()
     649              : {
     650         6572 :   delete asan_mem_ref_ht;
     651         6572 :   asan_mem_ref_ht = NULL;
     652              : 
     653         6572 :   asan_mem_ref_pool.release ();
     654         6572 : }
     655              : 
     656              : /* Return true iff the memory reference REF has been instrumented.  */
     657              : 
     658              : static bool
     659        45596 : has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size)
     660              : {
     661        45596 :   asan_mem_ref r;
     662        45596 :   asan_mem_ref_init (&r, ref, access_size);
     663              : 
     664        45596 :   asan_mem_ref *saved_ref = get_mem_ref_hash_table ()->find (&r);
     665        45596 :   return saved_ref && saved_ref->access_size >= access_size;
     666              : }
     667              : 
     668              : /* Return true iff the memory reference REF has been instrumented.  */
     669              : 
     670              : static bool
     671        26692 : has_mem_ref_been_instrumented (const asan_mem_ref *ref)
     672              : {
     673            0 :   return has_mem_ref_been_instrumented (ref->start, ref->access_size);
     674              : }
     675              : 
     676              : /* Return true iff access to memory region starting at REF and of
     677              :    length LEN has been instrumented.  */
     678              : 
     679              : static bool
     680          963 : has_mem_ref_been_instrumented (const asan_mem_ref *ref, tree len)
     681              : {
     682          963 :   HOST_WIDE_INT size_in_bytes
     683          963 :     = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
     684              : 
     685          251 :   return size_in_bytes != -1
     686          251 :     && has_mem_ref_been_instrumented (ref->start, size_in_bytes);
     687              : }
     688              : 
     689              : /* Set REF to the memory reference present in a gimple assignment
     690              :    ASSIGNMENT.  Return true upon successful completion, false
     691              :    otherwise.  */
     692              : 
     693              : static bool
     694        30131 : get_mem_ref_of_assignment (const gassign *assignment,
     695              :                            asan_mem_ref *ref,
     696              :                            bool *ref_is_store)
     697              : {
     698        30131 :   gcc_assert (gimple_assign_single_p (assignment));
     699              : 
     700        30131 :   if (gimple_store_p (assignment)
     701        30131 :       && !gimple_clobber_p (assignment))
     702              :     {
     703        13055 :       ref->start = gimple_assign_lhs (assignment);
     704        13055 :       *ref_is_store = true;
     705              :     }
     706        17076 :   else if (gimple_assign_load_p (assignment))
     707              :     {
     708        13570 :       ref->start = gimple_assign_rhs1 (assignment);
     709        13570 :       *ref_is_store = false;
     710              :     }
     711              :   else
     712              :     return false;
     713              : 
     714        26625 :   ref->access_size = int_size_in_bytes (TREE_TYPE (ref->start));
     715        26625 :   return true;
     716              : }
     717              : 
     718              : /* Return address of last allocated dynamic alloca.  */
     719              : 
     720              : static tree
     721          400 : get_last_alloca_addr ()
     722              : {
     723          400 :   if (last_alloca_addr)
     724              :     return last_alloca_addr;
     725              : 
     726          187 :   last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr");
     727          187 :   gassign *g = gimple_build_assign (last_alloca_addr, null_pointer_node);
     728          187 :   edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
     729          187 :   gsi_insert_on_edge_immediate (e, g);
     730          187 :   return last_alloca_addr;
     731              : }
     732              : 
     733              : /* Insert __asan_allocas_unpoison (top, bottom) call before
     734              :    __builtin_stack_restore (new_sp) call.
     735              :    The pseudocode of this routine should look like this:
     736              :      top = last_alloca_addr;
     737              :      bot = new_sp;
     738              :      __asan_allocas_unpoison (top, bot);
     739              :      last_alloca_addr = new_sp;
     740              :      __builtin_stack_restore (new_sp);
     741              :    In general, we can't use new_sp as bot parameter because on some
     742              :    architectures SP has non zero offset from dynamic stack area.  Moreover, on
     743              :    some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each
     744              :    particular function only after all callees were expanded to rtl.
     745              :    The most noticeable example is PowerPC{,64}, see
     746              :    http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK.
     747              :    To overcome the issue we use following trick: pass new_sp as a second
     748              :    parameter to __asan_allocas_unpoison and rewrite it during expansion with
     749              :    new_sp + (virtual_dynamic_stack_rtx - sp) later in
     750              :    expand_asan_emit_allocas_unpoison function.
     751              : 
     752              :    HWASAN needs to do very similar, the eventual pseudocode should be:
     753              :       __hwasan_tag_memory (virtual_stack_dynamic_rtx,
     754              :                            0,
     755              :                            new_sp - sp);
     756              :       __builtin_stack_restore (new_sp)
     757              : 
     758              :    Need to use the same trick to handle STACK_DYNAMIC_OFFSET as described
     759              :    above.  */
     760              : 
     761              : static void
     762          410 : handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
     763              : {
     764          410 :   if (!iter
     765          412 :       || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()
     766            2 :            || memtag_sanitize_allocas_p ()))
     767              :     return;
     768              : 
     769          203 :   tree restored_stack = gimple_call_arg (call, 0);
     770              : 
     771          203 :   gimple *g;
     772              : 
     773          203 :   if (hwasan_sanitize_allocas_p () || memtag_sanitize_allocas_p ())
     774              :     {
     775            0 :       enum internal_fn fn = IFN_HWASAN_ALLOCA_UNPOISON;
     776              :       /* There is only one piece of information `expand_HWASAN_ALLOCA_UNPOISON`
     777              :          needs to work.  This is the length of the area that we're
     778              :          deallocating.  Since the stack pointer is known at expand time, the
     779              :          position of the new stack pointer after deallocation is enough
     780              :          information to calculate this length.  */
     781            0 :       g = gimple_build_call_internal (fn, 1, restored_stack);
     782              :     }
     783              :   else
     784              :     {
     785          203 :       tree last_alloca = get_last_alloca_addr ();
     786          203 :       tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
     787          203 :       g = gimple_build_call (fn, 2, last_alloca, restored_stack);
     788          203 :       gsi_insert_before (iter, g, GSI_SAME_STMT);
     789          203 :       g = gimple_build_assign (last_alloca, restored_stack);
     790              :     }
     791              : 
     792          203 :   gsi_insert_before (iter, g, GSI_SAME_STMT);
     793              : }
     794              : 
     795              : /* Deploy and poison redzones around __builtin_alloca call.  To do this, we
     796              :    should replace this call with another one with changed parameters and
     797              :    replace all its uses with new address, so
     798              :        addr = __builtin_alloca (old_size, align);
     799              :    is replaced by
     800              :        left_redzone_size = max (align, ASAN_RED_ZONE_SIZE);
     801              :    Following two statements are optimized out if we know that
     802              :    old_size & (ASAN_RED_ZONE_SIZE - 1) == 0, i.e. alloca doesn't need partial
     803              :    redzone.
     804              :        misalign = old_size & (ASAN_RED_ZONE_SIZE - 1);
     805              :        partial_redzone_size = ASAN_RED_ZONE_SIZE - misalign;
     806              :        right_redzone_size = ASAN_RED_ZONE_SIZE;
     807              :        additional_size = left_redzone_size + partial_redzone_size +
     808              :                          right_redzone_size;
     809              :        new_size = old_size + additional_size;
     810              :        new_alloca = __builtin_alloca (new_size, max (align, 32))
     811              :        __asan_alloca_poison (new_alloca, old_size)
     812              :        addr = new_alloca + max (align, ASAN_RED_ZONE_SIZE);
     813              :        last_alloca_addr = new_alloca;
     814              :    ADDITIONAL_SIZE is added to make new memory allocation contain not only
     815              :    requested memory, but also left, partial and right redzones as well as some
     816              :    additional space, required by alignment.  */
     817              : 
     818              : static void
     819          398 : handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
     820              : {
     821          398 :   if (!iter
     822          400 :       || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()
     823            2 :            || memtag_sanitize_allocas_p ()))
     824          201 :     return;
     825              : 
     826          197 :   gassign *g;
     827          197 :   gcall *gg;
     828          197 :   tree callee = gimple_call_fndecl (call);
     829          197 :   tree lhs = gimple_call_lhs (call);
     830          197 :   tree old_size = gimple_call_arg (call, 0);
     831          197 :   tree ptr_type = lhs ? TREE_TYPE (lhs) : ptr_type_node;
     832          197 :   tree partial_size = NULL_TREE;
     833          197 :   unsigned int align
     834          197 :     = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
     835          390 :       ? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
     836              : 
     837          197 :   bool throws = false;
     838          197 :   edge e = NULL;
     839          197 :   if (stmt_can_throw_internal (cfun, call))
     840              :     {
     841            9 :       if (!lhs)
     842              :         return;
     843            9 :       throws = true;
     844            9 :       e = find_fallthru_edge (gsi_bb (*iter)->succs);
     845              :     }
     846              : 
     847          197 :   if (hwasan_sanitize_allocas_p () || memtag_sanitize_allocas_p ())
     848              :     {
     849            0 :       gimple_seq stmts = NULL;
     850            0 :       location_t loc = gimple_location (gsi_stmt (*iter));
     851              :       /* HWASAN and MEMTAG need a different expansion.
     852              : 
     853              :          addr = __builtin_alloca (size, align);
     854              : 
     855              :          in case of HWASAN, should be replaced by
     856              : 
     857              :          new_size = size rounded up to HWASAN_TAG_GRANULE_SIZE byte alignment;
     858              :          untagged_addr = __builtin_alloca (new_size, align);
     859              :          tag = __hwasan_choose_alloca_tag ();
     860              :          addr = ifn_HWASAN_SET_TAG (untagged_addr, tag);
     861              :          __hwasan_tag_memory (untagged_addr, tag, new_size);
     862              : 
     863              :          in case of MEMTAG, should be replaced by
     864              : 
     865              :          new_size = size rounded up to HWASAN_TAG_GRANULE_SIZE byte alignment;
     866              :          untagged_addr = __builtin_alloca (new_size, align);
     867              :          addr = ifn_HWASAN_ALLOCA_POISON (untagged_addr, new_size);
     868              : 
     869              :          where a new tag is chosen and set on untagged_addr when
     870              :          HWASAN_ALLOCA_POISON is expanded.  */
     871              : 
     872              :       /* Ensure alignment at least HWASAN_TAG_GRANULE_SIZE bytes so we start on
     873              :          a tag granule.  */
     874            0 :       align = align > HWASAN_TAG_GRANULE_SIZE ? align : HWASAN_TAG_GRANULE_SIZE;
     875              : 
     876            0 :       tree old_size = gimple_call_arg (call, 0);
     877            0 :       tree new_size = gimple_build_round_up (&stmts, loc, size_type_node,
     878              :                                              old_size,
     879            0 :                                              HWASAN_TAG_GRANULE_SIZE);
     880              : 
     881              :       /* Make the alloca call */
     882            0 :       tree untagged_addr
     883            0 :         = gimple_build (&stmts, loc,
     884              :                         as_combined_fn (BUILT_IN_ALLOCA_WITH_ALIGN), ptr_type,
     885            0 :                         new_size, build_int_cst (size_type_node, align));
     886              : 
     887            0 :       tree addr;
     888              : 
     889            0 :       if (memtag_sanitize_p ())
     890            0 :         addr = gimple_build (&stmts, loc, CFN_HWASAN_ALLOCA_POISON, ptr_type,
     891              :                              untagged_addr, new_size);
     892              :       else
     893              :         {
     894              :           /* Choose the tag.
     895              :              Here we use an internal function so we can choose the tag at expand
     896              :              time.  We need the decision to be made after stack variables have been
     897              :              assigned their tag (i.e. once the hwasan_frame_tag_offset variable has
     898              :              been set to one after the last stack variables tag).  */
     899            0 :           tree tag = gimple_build (&stmts, loc, CFN_HWASAN_CHOOSE_TAG,
     900              :                                    unsigned_char_type_node);
     901              : 
     902              :           /* Add tag to pointer.  */
     903            0 :           addr = gimple_build (&stmts, loc, CFN_HWASAN_SET_TAG, ptr_type,
     904              :                                untagged_addr, tag);
     905              : 
     906              :           /* Tag shadow memory.
     907              :              NOTE: require using `untagged_addr` here for libhwasan API.  */
     908            0 :           gimple_build (&stmts, loc, as_combined_fn (BUILT_IN_HWASAN_TAG_MEM),
     909              :                         void_type_node, untagged_addr, tag, new_size);
     910              :         }
     911              : 
     912              :       /* Insert the built up code sequence into the original instruction stream
     913              :          the iterator points to.  */
     914            0 :       gsi_insert_seq_before (iter, stmts, GSI_SAME_STMT);
     915              : 
     916              :       /* Finally, replace old alloca ptr with NEW_ALLOCA.  */
     917            0 :       replace_call_with_value (iter, addr);
     918            0 :       return;
     919              :     }
     920              : 
     921          197 :   tree last_alloca = get_last_alloca_addr ();
     922          197 :   const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
     923              : 
     924              :   /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
     925              :      bytes of allocated space.  Otherwise, align alloca to ASAN_RED_ZONE_SIZE
     926              :      manually.  */
     927          197 :   align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
     928              : 
     929          197 :   tree alloca_rz_mask = build_int_cst (size_type_node, redzone_mask);
     930          197 :   tree redzone_size = build_int_cst (size_type_node, ASAN_RED_ZONE_SIZE);
     931              : 
     932              :   /* Extract lower bits from old_size.  */
     933          197 :   wide_int size_nonzero_bits = get_nonzero_bits (old_size);
     934          197 :   wide_int rz_mask
     935          197 :     = wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits));
     936          197 :   wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask);
     937              : 
     938              :   /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial
     939              :      redzone.  Otherwise, compute its size here.  */
     940          197 :   if (wi::ne_p (old_size_lower_bits, 0))
     941              :     {
     942              :       /* misalign = size & (ASAN_RED_ZONE_SIZE - 1)
     943              :          partial_size = ASAN_RED_ZONE_SIZE - misalign.  */
     944          194 :       g = gimple_build_assign (make_ssa_name (size_type_node, NULL),
     945              :                                BIT_AND_EXPR, old_size, alloca_rz_mask);
     946          194 :       gsi_insert_before (iter, g, GSI_SAME_STMT);
     947          194 :       tree misalign = gimple_assign_lhs (g);
     948          194 :       g = gimple_build_assign (make_ssa_name (size_type_node, NULL), MINUS_EXPR,
     949              :                                redzone_size, misalign);
     950          194 :       gsi_insert_before (iter, g, GSI_SAME_STMT);
     951          194 :       partial_size = gimple_assign_lhs (g);
     952              :     }
     953              : 
     954              :   /* additional_size = align + ASAN_RED_ZONE_SIZE.  */
     955          394 :   tree additional_size = build_int_cst (size_type_node, align / BITS_PER_UNIT
     956          197 :                                                         + ASAN_RED_ZONE_SIZE);
     957              :   /* If alloca has partial redzone, include it to additional_size too.  */
     958          197 :   if (partial_size)
     959              :     {
     960              :       /* additional_size += partial_size.  */
     961          194 :       g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR,
     962              :                                partial_size, additional_size);
     963          194 :       gsi_insert_before (iter, g, GSI_SAME_STMT);
     964          194 :       additional_size = gimple_assign_lhs (g);
     965              :     }
     966              : 
     967              :   /* new_size = old_size + additional_size.  */
     968          197 :   g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR, old_size,
     969              :                            additional_size);
     970          197 :   gsi_insert_before (iter, g, GSI_SAME_STMT);
     971          197 :   tree new_size = gimple_assign_lhs (g);
     972              : 
     973              :   /* Build new __builtin_alloca call:
     974              :        new_alloca_with_rz = __builtin_alloca (new_size, align).  */
     975          197 :   tree fn = builtin_decl_implicit (BUILT_IN_ALLOCA_WITH_ALIGN);
     976          197 :   gg = gimple_build_call (fn, 2, new_size,
     977          197 :                           build_int_cst (size_type_node, align));
     978          197 :   tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
     979          197 :   gimple_call_set_lhs (gg, new_alloca_with_rz);
     980          197 :   if (throws)
     981              :     {
     982            9 :       gimple_call_set_lhs (call, NULL);
     983            9 :       gsi_replace (iter, gg, true);
     984              :     }
     985              :   else
     986          188 :     gsi_insert_before (iter, gg, GSI_SAME_STMT);
     987              : 
     988              :   /* new_alloca = new_alloca_with_rz + align.  */
     989          197 :   g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
     990              :                            new_alloca_with_rz,
     991              :                            build_int_cst (size_type_node,
     992          197 :                                           align / BITS_PER_UNIT));
     993          197 :   gimple_stmt_iterator gsi = gsi_none ();
     994          197 :   if (throws)
     995              :     {
     996            9 :       gsi_insert_on_edge_immediate (e, g);
     997            9 :       gsi = gsi_for_stmt (g);
     998              :     }
     999              :   else
    1000          188 :     gsi_insert_before (iter, g, GSI_SAME_STMT);
    1001          197 :   tree new_alloca = gimple_assign_lhs (g);
    1002              : 
    1003              :   /* Poison newly created alloca redzones:
    1004              :       __asan_alloca_poison (new_alloca, old_size).  */
    1005          197 :   fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
    1006          197 :   gg = gimple_build_call (fn, 2, new_alloca, old_size);
    1007          197 :   if (throws)
    1008            9 :     gsi_insert_after (&gsi, gg, GSI_NEW_STMT);
    1009              :   else
    1010          188 :     gsi_insert_before (iter, gg, GSI_SAME_STMT);
    1011              : 
    1012              :   /* Save new_alloca_with_rz value into last_alloca to use it during
    1013              :      allocas unpoisoning.  */
    1014          197 :   g = gimple_build_assign (last_alloca, new_alloca_with_rz);
    1015          197 :   if (throws)
    1016            9 :     gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    1017              :   else
    1018          188 :     gsi_insert_before (iter, g, GSI_SAME_STMT);
    1019              : 
    1020              :   /* Finally, replace old alloca ptr with NEW_ALLOCA.  */
    1021          197 :   if (throws)
    1022              :     {
    1023            9 :       g = gimple_build_assign (lhs, new_alloca);
    1024            9 :       gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    1025              :     }
    1026              :   else
    1027          188 :     replace_call_with_value (iter, new_alloca);
    1028          197 : }
    1029              : 
    1030              : /* Return the memory references contained in a gimple statement
    1031              :    representing a builtin call that has to do with memory access.  */
    1032              : 
    1033              : static bool
    1034         8806 : get_mem_refs_of_builtin_call (gcall *call,
    1035              :                               asan_mem_ref *src0,
    1036              :                               tree *src0_len,
    1037              :                               bool *src0_is_store,
    1038              :                               asan_mem_ref *src1,
    1039              :                               tree *src1_len,
    1040              :                               bool *src1_is_store,
    1041              :                               asan_mem_ref *dst,
    1042              :                               tree *dst_len,
    1043              :                               bool *dst_is_store,
    1044              :                               bool *dest_is_deref,
    1045              :                               bool *intercepted_p,
    1046              :                               gimple_stmt_iterator *iter = NULL)
    1047              : {
    1048         8806 :   gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
    1049              : 
    1050         8806 :   tree callee = gimple_call_fndecl (call);
    1051         8806 :   tree source0 = NULL_TREE, source1 = NULL_TREE,
    1052         8806 :     dest = NULL_TREE, len = NULL_TREE;
    1053         8806 :   bool is_store = true, got_reference_p = false;
    1054         8806 :   HOST_WIDE_INT access_size = 1;
    1055              : 
    1056         8806 :   *intercepted_p = asan_intercepted_p ((DECL_FUNCTION_CODE (callee)));
    1057              : 
    1058         8806 :   switch (DECL_FUNCTION_CODE (callee))
    1059              :     {
    1060              :       /* (s, s, n) style memops.  */
    1061          112 :     case BUILT_IN_BCMP:
    1062          112 :     case BUILT_IN_MEMCMP:
    1063          112 :       source0 = gimple_call_arg (call, 0);
    1064          112 :       source1 = gimple_call_arg (call, 1);
    1065          112 :       len = gimple_call_arg (call, 2);
    1066          112 :       break;
    1067              : 
    1068              :       /* (src, dest, n) style memops.  */
    1069            0 :     case BUILT_IN_BCOPY:
    1070            0 :       source0 = gimple_call_arg (call, 0);
    1071            0 :       dest = gimple_call_arg (call, 1);
    1072            0 :       len = gimple_call_arg (call, 2);
    1073            0 :       break;
    1074              : 
    1075              :       /* (dest, src, n) style memops.  */
    1076         1250 :     case BUILT_IN_MEMCPY:
    1077         1250 :     case BUILT_IN_MEMCPY_CHK:
    1078         1250 :     case BUILT_IN_MEMMOVE:
    1079         1250 :     case BUILT_IN_MEMMOVE_CHK:
    1080         1250 :     case BUILT_IN_MEMPCPY:
    1081         1250 :     case BUILT_IN_MEMPCPY_CHK:
    1082         1250 :       dest = gimple_call_arg (call, 0);
    1083         1250 :       source0 = gimple_call_arg (call, 1);
    1084         1250 :       len = gimple_call_arg (call, 2);
    1085         1250 :       break;
    1086              : 
    1087              :       /* (dest, n) style memops.  */
    1088            0 :     case BUILT_IN_BZERO:
    1089            0 :       dest = gimple_call_arg (call, 0);
    1090            0 :       len = gimple_call_arg (call, 1);
    1091            0 :       break;
    1092              : 
    1093              :       /* (dest, x, n) style memops*/
    1094          388 :     case BUILT_IN_MEMSET:
    1095          388 :     case BUILT_IN_MEMSET_CHK:
    1096          388 :       dest = gimple_call_arg (call, 0);
    1097          388 :       len = gimple_call_arg (call, 2);
    1098          388 :       break;
    1099              : 
    1100          104 :     case BUILT_IN_STRLEN:
    1101              :       /* Special case strlen here since its length is taken from its return
    1102              :          value.
    1103              : 
    1104              :          The approach taken by the sanitizers is to check a memory access
    1105              :          before it's taken.  For ASAN strlen is intercepted by libasan, so no
    1106              :          check is inserted by the compiler.
    1107              : 
    1108              :          This function still returns `true` and provides a length to the rest
    1109              :          of the ASAN pass in order to record what areas have been checked,
    1110              :          avoiding superfluous checks later on.
    1111              : 
    1112              :          HWASAN does not intercept any of these internal functions.
    1113              :          This means that checks for memory accesses must be inserted by the
    1114              :          compiler.
    1115              :          strlen is a special case, because we can tell the length from the
    1116              :          return of the function, but that is not known until after the function
    1117              :          has returned.
    1118              : 
    1119              :          Hence we can't check the memory access before it happens.
    1120              :          We could check the memory access after it has already happened, but
    1121              :          for now we choose to just ignore `strlen` calls.
    1122              :          This decision was simply made because that means the special case is
    1123              :          limited to this one case of this one function.  */
    1124          104 :       if (hwassist_sanitize_p ())
    1125              :         return false;
    1126           72 :       source0 = gimple_call_arg (call, 0);
    1127           72 :       len = gimple_call_lhs (call);
    1128           72 :       break;
    1129              : 
    1130          410 :     case BUILT_IN_STACK_RESTORE:
    1131          410 :       handle_builtin_stack_restore (call, iter);
    1132          410 :       break;
    1133              : 
    1134          398 :     CASE_BUILT_IN_ALLOCA:
    1135          398 :       handle_builtin_alloca (call, iter);
    1136          398 :       break;
    1137              :     /* And now the __atomic* and __sync builtins.
    1138              :        These are handled differently from the classical memory
    1139              :        access builtins above.  */
    1140              : 
    1141            0 :     case BUILT_IN_ATOMIC_LOAD_1:
    1142            0 :       is_store = false;
    1143              :       /* FALLTHRU */
    1144            0 :     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
    1145            0 :     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
    1146            0 :     case BUILT_IN_SYNC_FETCH_AND_OR_1:
    1147            0 :     case BUILT_IN_SYNC_FETCH_AND_AND_1:
    1148            0 :     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
    1149            0 :     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
    1150            0 :     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
    1151            0 :     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
    1152            0 :     case BUILT_IN_SYNC_OR_AND_FETCH_1:
    1153            0 :     case BUILT_IN_SYNC_AND_AND_FETCH_1:
    1154            0 :     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
    1155            0 :     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
    1156            0 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
    1157            0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
    1158            0 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
    1159            0 :     case BUILT_IN_SYNC_LOCK_RELEASE_1:
    1160            0 :     case BUILT_IN_ATOMIC_EXCHANGE_1:
    1161            0 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
    1162            0 :     case BUILT_IN_ATOMIC_STORE_1:
    1163            0 :     case BUILT_IN_ATOMIC_ADD_FETCH_1:
    1164            0 :     case BUILT_IN_ATOMIC_SUB_FETCH_1:
    1165            0 :     case BUILT_IN_ATOMIC_AND_FETCH_1:
    1166            0 :     case BUILT_IN_ATOMIC_NAND_FETCH_1:
    1167            0 :     case BUILT_IN_ATOMIC_XOR_FETCH_1:
    1168            0 :     case BUILT_IN_ATOMIC_OR_FETCH_1:
    1169            0 :     case BUILT_IN_ATOMIC_FETCH_ADD_1:
    1170            0 :     case BUILT_IN_ATOMIC_FETCH_SUB_1:
    1171            0 :     case BUILT_IN_ATOMIC_FETCH_AND_1:
    1172            0 :     case BUILT_IN_ATOMIC_FETCH_NAND_1:
    1173            0 :     case BUILT_IN_ATOMIC_FETCH_XOR_1:
    1174            0 :     case BUILT_IN_ATOMIC_FETCH_OR_1:
    1175            0 :       access_size = 1;
    1176            0 :       goto do_atomic;
    1177              : 
    1178            0 :     case BUILT_IN_ATOMIC_LOAD_2:
    1179            0 :       is_store = false;
    1180              :       /* FALLTHRU */
    1181            0 :     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
    1182            0 :     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
    1183            0 :     case BUILT_IN_SYNC_FETCH_AND_OR_2:
    1184            0 :     case BUILT_IN_SYNC_FETCH_AND_AND_2:
    1185            0 :     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
    1186            0 :     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
    1187            0 :     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
    1188            0 :     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
    1189            0 :     case BUILT_IN_SYNC_OR_AND_FETCH_2:
    1190            0 :     case BUILT_IN_SYNC_AND_AND_FETCH_2:
    1191            0 :     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
    1192            0 :     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
    1193            0 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
    1194            0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
    1195            0 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
    1196            0 :     case BUILT_IN_SYNC_LOCK_RELEASE_2:
    1197            0 :     case BUILT_IN_ATOMIC_EXCHANGE_2:
    1198            0 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
    1199            0 :     case BUILT_IN_ATOMIC_STORE_2:
    1200            0 :     case BUILT_IN_ATOMIC_ADD_FETCH_2:
    1201            0 :     case BUILT_IN_ATOMIC_SUB_FETCH_2:
    1202            0 :     case BUILT_IN_ATOMIC_AND_FETCH_2:
    1203            0 :     case BUILT_IN_ATOMIC_NAND_FETCH_2:
    1204            0 :     case BUILT_IN_ATOMIC_XOR_FETCH_2:
    1205            0 :     case BUILT_IN_ATOMIC_OR_FETCH_2:
    1206            0 :     case BUILT_IN_ATOMIC_FETCH_ADD_2:
    1207            0 :     case BUILT_IN_ATOMIC_FETCH_SUB_2:
    1208            0 :     case BUILT_IN_ATOMIC_FETCH_AND_2:
    1209            0 :     case BUILT_IN_ATOMIC_FETCH_NAND_2:
    1210            0 :     case BUILT_IN_ATOMIC_FETCH_XOR_2:
    1211            0 :     case BUILT_IN_ATOMIC_FETCH_OR_2:
    1212            0 :       access_size = 2;
    1213            0 :       goto do_atomic;
    1214              : 
    1215            0 :     case BUILT_IN_ATOMIC_LOAD_4:
    1216            0 :       is_store = false;
    1217              :       /* FALLTHRU */
    1218           56 :     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
    1219           56 :     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
    1220           56 :     case BUILT_IN_SYNC_FETCH_AND_OR_4:
    1221           56 :     case BUILT_IN_SYNC_FETCH_AND_AND_4:
    1222           56 :     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
    1223           56 :     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
    1224           56 :     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
    1225           56 :     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
    1226           56 :     case BUILT_IN_SYNC_OR_AND_FETCH_4:
    1227           56 :     case BUILT_IN_SYNC_AND_AND_FETCH_4:
    1228           56 :     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
    1229           56 :     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
    1230           56 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
    1231           56 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
    1232           56 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
    1233           56 :     case BUILT_IN_SYNC_LOCK_RELEASE_4:
    1234           56 :     case BUILT_IN_ATOMIC_EXCHANGE_4:
    1235           56 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
    1236           56 :     case BUILT_IN_ATOMIC_STORE_4:
    1237           56 :     case BUILT_IN_ATOMIC_ADD_FETCH_4:
    1238           56 :     case BUILT_IN_ATOMIC_SUB_FETCH_4:
    1239           56 :     case BUILT_IN_ATOMIC_AND_FETCH_4:
    1240           56 :     case BUILT_IN_ATOMIC_NAND_FETCH_4:
    1241           56 :     case BUILT_IN_ATOMIC_XOR_FETCH_4:
    1242           56 :     case BUILT_IN_ATOMIC_OR_FETCH_4:
    1243           56 :     case BUILT_IN_ATOMIC_FETCH_ADD_4:
    1244           56 :     case BUILT_IN_ATOMIC_FETCH_SUB_4:
    1245           56 :     case BUILT_IN_ATOMIC_FETCH_AND_4:
    1246           56 :     case BUILT_IN_ATOMIC_FETCH_NAND_4:
    1247           56 :     case BUILT_IN_ATOMIC_FETCH_XOR_4:
    1248           56 :     case BUILT_IN_ATOMIC_FETCH_OR_4:
    1249           56 :       access_size = 4;
    1250           56 :       goto do_atomic;
    1251              : 
    1252            0 :     case BUILT_IN_ATOMIC_LOAD_8:
    1253            0 :       is_store = false;
    1254              :       /* FALLTHRU */
    1255            0 :     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
    1256            0 :     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
    1257            0 :     case BUILT_IN_SYNC_FETCH_AND_OR_8:
    1258            0 :     case BUILT_IN_SYNC_FETCH_AND_AND_8:
    1259            0 :     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
    1260            0 :     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
    1261            0 :     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
    1262            0 :     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
    1263            0 :     case BUILT_IN_SYNC_OR_AND_FETCH_8:
    1264            0 :     case BUILT_IN_SYNC_AND_AND_FETCH_8:
    1265            0 :     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
    1266            0 :     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
    1267            0 :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
    1268            0 :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
    1269            0 :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
    1270            0 :     case BUILT_IN_SYNC_LOCK_RELEASE_8:
    1271            0 :     case BUILT_IN_ATOMIC_EXCHANGE_8:
    1272            0 :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
    1273            0 :     case BUILT_IN_ATOMIC_STORE_8:
    1274            0 :     case BUILT_IN_ATOMIC_ADD_FETCH_8:
    1275            0 :     case BUILT_IN_ATOMIC_SUB_FETCH_8:
    1276            0 :     case BUILT_IN_ATOMIC_AND_FETCH_8:
    1277            0 :     case BUILT_IN_ATOMIC_NAND_FETCH_8:
    1278            0 :     case BUILT_IN_ATOMIC_XOR_FETCH_8:
    1279            0 :     case BUILT_IN_ATOMIC_OR_FETCH_8:
    1280            0 :     case BUILT_IN_ATOMIC_FETCH_ADD_8:
    1281            0 :     case BUILT_IN_ATOMIC_FETCH_SUB_8:
    1282            0 :     case BUILT_IN_ATOMIC_FETCH_AND_8:
    1283            0 :     case BUILT_IN_ATOMIC_FETCH_NAND_8:
    1284            0 :     case BUILT_IN_ATOMIC_FETCH_XOR_8:
    1285            0 :     case BUILT_IN_ATOMIC_FETCH_OR_8:
    1286            0 :       access_size = 8;
    1287            0 :       goto do_atomic;
    1288              : 
    1289            0 :     case BUILT_IN_ATOMIC_LOAD_16:
    1290            0 :       is_store = false;
    1291              :       /* FALLTHRU */
    1292              :     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
    1293              :     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
    1294              :     case BUILT_IN_SYNC_FETCH_AND_OR_16:
    1295              :     case BUILT_IN_SYNC_FETCH_AND_AND_16:
    1296              :     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
    1297              :     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
    1298              :     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
    1299              :     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
    1300              :     case BUILT_IN_SYNC_OR_AND_FETCH_16:
    1301              :     case BUILT_IN_SYNC_AND_AND_FETCH_16:
    1302              :     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
    1303              :     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
    1304              :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
    1305              :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
    1306              :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
    1307              :     case BUILT_IN_SYNC_LOCK_RELEASE_16:
    1308              :     case BUILT_IN_ATOMIC_EXCHANGE_16:
    1309              :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
    1310              :     case BUILT_IN_ATOMIC_STORE_16:
    1311              :     case BUILT_IN_ATOMIC_ADD_FETCH_16:
    1312              :     case BUILT_IN_ATOMIC_SUB_FETCH_16:
    1313              :     case BUILT_IN_ATOMIC_AND_FETCH_16:
    1314              :     case BUILT_IN_ATOMIC_NAND_FETCH_16:
    1315              :     case BUILT_IN_ATOMIC_XOR_FETCH_16:
    1316              :     case BUILT_IN_ATOMIC_OR_FETCH_16:
    1317              :     case BUILT_IN_ATOMIC_FETCH_ADD_16:
    1318              :     case BUILT_IN_ATOMIC_FETCH_SUB_16:
    1319              :     case BUILT_IN_ATOMIC_FETCH_AND_16:
    1320              :     case BUILT_IN_ATOMIC_FETCH_NAND_16:
    1321              :     case BUILT_IN_ATOMIC_FETCH_XOR_16:
    1322              :     case BUILT_IN_ATOMIC_FETCH_OR_16:
    1323              :       access_size = 16;
    1324              :       /* FALLTHRU */
    1325           56 :     do_atomic:
    1326           56 :       {
    1327           56 :         dest = gimple_call_arg (call, 0);
    1328              :         /* DEST represents the address of a memory location.
    1329              :            instrument_derefs wants the memory location, so lets
    1330              :            dereference the address DEST before handing it to
    1331              :            instrument_derefs.  */
    1332          112 :         tree type = build_nonstandard_integer_type (access_size
    1333           56 :                                                     * BITS_PER_UNIT, 1);
    1334           56 :         dest = build2 (MEM_REF, type, dest,
    1335              :                        build_int_cst (build_pointer_type (char_type_node), 0));
    1336           56 :         break;
    1337              :       }
    1338              : 
    1339              :     default:
    1340              :       /* The other builtins memory access are not instrumented in this
    1341              :          function because they either don't have any length parameter,
    1342              :          or their length parameter is just a limit.  */
    1343              :       break;
    1344              :     }
    1345              : 
    1346         2686 :   if (len != NULL_TREE)
    1347              :     {
    1348         1822 :       if (source0 != NULL_TREE)
    1349              :         {
    1350         1434 :           src0->start = source0;
    1351         1434 :           src0->access_size = access_size;
    1352         1434 :           *src0_len = len;
    1353         1434 :           *src0_is_store = false;
    1354              :         }
    1355              : 
    1356         1822 :       if (source1 != NULL_TREE)
    1357              :         {
    1358          112 :           src1->start = source1;
    1359          112 :           src1->access_size = access_size;
    1360          112 :           *src1_len = len;
    1361          112 :           *src1_is_store = false;
    1362              :         }
    1363              : 
    1364         1822 :       if (dest != NULL_TREE)
    1365              :         {
    1366         1638 :           dst->start = dest;
    1367         1638 :           dst->access_size = access_size;
    1368         1638 :           *dst_len = len;
    1369         1638 :           *dst_is_store = true;
    1370              :         }
    1371              : 
    1372              :       got_reference_p = true;
    1373              :     }
    1374         6952 :   else if (dest)
    1375              :     {
    1376           56 :       dst->start = dest;
    1377           56 :       dst->access_size = access_size;
    1378           56 :       *dst_len = NULL_TREE;
    1379           56 :       *dst_is_store = is_store;
    1380           56 :       *dest_is_deref = true;
    1381           56 :       got_reference_p = true;
    1382              :     }
    1383              : 
    1384              :   return got_reference_p;
    1385              : }
    1386              : 
    1387              : /* Return true iff a given gimple statement has been instrumented.
    1388              :    Note that the statement is "defined" by the memory references it
    1389              :    contains.  */
    1390              : 
    1391              : static bool
    1392       170118 : has_stmt_been_instrumented_p (gimple *stmt)
    1393              : {
    1394       170118 :   if (gimple_assign_single_p (stmt))
    1395              :     {
    1396        30131 :       bool r_is_store;
    1397        30131 :       asan_mem_ref r;
    1398        30131 :       asan_mem_ref_init (&r, NULL, 1);
    1399              : 
    1400        30131 :       if (get_mem_ref_of_assignment (as_a <gassign *> (stmt), &r,
    1401              :                                      &r_is_store))
    1402              :         {
    1403        26625 :           if (!has_mem_ref_been_instrumented (&r))
    1404        26625 :             return false;
    1405         1021 :           if (r_is_store && gimple_assign_load_p (stmt))
    1406              :             {
    1407            5 :               asan_mem_ref src;
    1408            5 :               asan_mem_ref_init (&src, NULL, 1);
    1409            5 :               src.start = gimple_assign_rhs1 (stmt);
    1410            5 :               src.access_size = int_size_in_bytes (TREE_TYPE (src.start));
    1411            5 :               if (!has_mem_ref_been_instrumented (&src))
    1412              :                 return false;
    1413              :             }
    1414         1016 :           return true;
    1415              :         }
    1416              :     }
    1417       139987 :   else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    1418              :     {
    1419         4421 :       asan_mem_ref src0, src1, dest;
    1420         4421 :       asan_mem_ref_init (&src0, NULL, 1);
    1421         4421 :       asan_mem_ref_init (&src1, NULL, 1);
    1422         4421 :       asan_mem_ref_init (&dest, NULL, 1);
    1423              : 
    1424         4421 :       tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
    1425         4421 :       bool src0_is_store = false, src1_is_store = false,
    1426              :         dest_is_store = false, dest_is_deref = false, intercepted_p = true;
    1427         4421 :       if (get_mem_refs_of_builtin_call (as_a <gcall *> (stmt),
    1428              :                                         &src0, &src0_len, &src0_is_store,
    1429              :                                         &src1, &src1_len, &src1_is_store,
    1430              :                                         &dest, &dest_len, &dest_is_store,
    1431              :                                         &dest_is_deref, &intercepted_p))
    1432              :         {
    1433          951 :           if (src0.start != NULL_TREE
    1434          951 :               && !has_mem_ref_been_instrumented (&src0, src0_len))
    1435          951 :             return false;
    1436              : 
    1437          240 :           if (src1.start != NULL_TREE
    1438          240 :               && !has_mem_ref_been_instrumented (&src1, src1_len))
    1439              :             return false;
    1440              : 
    1441          240 :           if (dest.start != NULL_TREE
    1442          240 :               && !has_mem_ref_been_instrumented (&dest, dest_len))
    1443          228 :             return false;
    1444              : 
    1445              :           return true;
    1446              :         }
    1447              :     }
    1448       135566 :   else if (is_gimple_call (stmt)
    1449        18367 :            && gimple_store_p (stmt)
    1450       135854 :            && (gimple_call_builtin_p (stmt)
    1451          288 :                || gimple_call_internal_p (stmt)
    1452          287 :                || !aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
    1453          287 :                                       gimple_call_fntype (stmt))))
    1454              :     {
    1455           62 :       asan_mem_ref r;
    1456           62 :       asan_mem_ref_init (&r, NULL, 1);
    1457              : 
    1458           62 :       r.start = gimple_call_lhs (stmt);
    1459           62 :       r.access_size = int_size_in_bytes (TREE_TYPE (r.start));
    1460           62 :       return has_mem_ref_been_instrumented (&r);
    1461              :     }
    1462              : 
    1463              :   return false;
    1464              : }
    1465              : 
    1466              : /*  Insert a memory reference into the hash table.  */
    1467              : 
    1468              : static void
    1469        37498 : update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size)
    1470              : {
    1471        37498 :   hash_table<asan_mem_ref_hasher> *ht = get_mem_ref_hash_table ();
    1472              : 
    1473        37498 :   asan_mem_ref r;
    1474        37498 :   asan_mem_ref_init (&r, ref, access_size);
    1475              : 
    1476        37498 :   asan_mem_ref **slot = ht->find_slot (&r, INSERT);
    1477        37498 :   if (*slot == NULL || (*slot)->access_size < access_size)
    1478        37486 :     *slot = asan_mem_ref_new (ref, access_size);
    1479        37498 : }
    1480              : 
    1481              : /* Initialize shadow_ptr_types array.  */
    1482              : 
    1483              : static void
    1484         2481 : asan_init_shadow_ptr_types (void)
    1485              : {
    1486         2481 :   asan_shadow_set = new_alias_set ();
    1487         2481 :   tree types[3] = { signed_char_type_node, short_integer_type_node,
    1488         2481 :                     integer_type_node };
    1489              : 
    1490         9924 :   for (unsigned i = 0; i < 3; i++)
    1491              :     {
    1492         7443 :       shadow_ptr_types[i] = build_distinct_type_copy (types[i]);
    1493         7443 :       TYPE_ALIAS_SET (shadow_ptr_types[i]) = asan_shadow_set;
    1494         7443 :       shadow_ptr_types[i] = build_pointer_type (shadow_ptr_types[i]);
    1495              :     }
    1496              : 
    1497         2481 :   initialize_sanitizer_builtins ();
    1498         2481 : }
    1499              : 
    1500              : /* Create ADDR_EXPR of STRING_CST with the PP pretty printer text.  */
    1501              : 
    1502              : static tree
    1503        12318 : asan_pp_string (pretty_printer *pp)
    1504              : {
    1505        12318 :   const char *buf = pp_formatted_text (pp);
    1506        12318 :   size_t len = strlen (buf);
    1507        12318 :   tree ret = build_string (len + 1, buf);
    1508        24636 :   TREE_TYPE (ret)
    1509        12318 :     = build_array_type (TREE_TYPE (shadow_ptr_types[0]),
    1510        12318 :                         build_index_type (size_int (len)));
    1511        12318 :   TREE_READONLY (ret) = 1;
    1512        12318 :   TREE_STATIC (ret) = 1;
    1513        12318 :   return build1 (ADDR_EXPR, shadow_ptr_types[0], ret);
    1514              : }
    1515              : 
    1516              : /* Clear shadow memory at SHADOW_MEM, LEN bytes.  Can't call a library call here
    1517              :    though.  */
    1518              : 
    1519              : static void
    1520         2396 : asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
    1521              : {
    1522         2396 :   rtx_insn *insn, *insns, *jump;
    1523         2396 :   rtx_code_label *top_label;
    1524         2396 :   rtx end, addr, tmp;
    1525              : 
    1526         2396 :   gcc_assert ((len & 3) == 0);
    1527         2396 :   start_sequence ();
    1528         2396 :   clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
    1529         2396 :   insns = end_sequence ();
    1530         8592 :   for (insn = insns; insn; insn = NEXT_INSN (insn))
    1531         3813 :     if (CALL_P (insn))
    1532              :       break;
    1533         2396 :   if (insn == NULL_RTX)
    1534              :     {
    1535         2383 :       emit_insn (insns);
    1536         2383 :       return;
    1537              :     }
    1538              : 
    1539           13 :   top_label = gen_label_rtx ();
    1540           13 :   addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
    1541           13 :   shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
    1542           13 :   end = force_reg (Pmode, plus_constant (Pmode, addr, len));
    1543           13 :   emit_label (top_label);
    1544              : 
    1545           13 :   emit_move_insn (shadow_mem, const0_rtx);
    1546           13 :   tmp = expand_simple_binop (Pmode, PLUS, addr, gen_int_mode (4, Pmode), addr,
    1547              :                              true, OPTAB_LIB_WIDEN);
    1548           13 :   if (tmp != addr)
    1549            0 :     emit_move_insn (addr, tmp);
    1550           13 :   emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
    1551           13 :   jump = get_last_insn ();
    1552           13 :   gcc_assert (JUMP_P (jump));
    1553           13 :   add_reg_br_prob_note (jump,
    1554           26 :                         profile_probability::guessed_always ()
    1555              :                            .apply_scale (80, 100));
    1556              : }
    1557              : 
    1558              : void
    1559         6345 : asan_function_start (void)
    1560              : {
    1561         6345 :   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC", current_function_funcdef_no);
    1562         6345 : }
    1563              : 
    1564              : /* Return number of shadow bytes that are occupied by a local variable
    1565              :    of SIZE bytes.  */
    1566              : 
    1567              : static unsigned HOST_WIDE_INT
    1568         2096 : shadow_mem_size (unsigned HOST_WIDE_INT size)
    1569              : {
    1570              :   /* It must be possible to align stack variables to granularity
    1571              :      of shadow memory.  */
    1572         2096 :   gcc_assert (BITS_PER_UNIT
    1573              :               * ASAN_SHADOW_GRANULARITY <= MAX_SUPPORTED_STACK_ALIGNMENT);
    1574              : 
    1575         2096 :   return ROUND_UP (size, ASAN_SHADOW_GRANULARITY) / ASAN_SHADOW_GRANULARITY;
    1576              : }
    1577              : 
    1578              : /* Always emit 4 bytes at a time.  */
    1579              : #define RZ_BUFFER_SIZE 4
    1580              : 
    1581              : /* ASAN redzone buffer container that handles emission of shadow bytes.  */
    1582         3442 : class asan_redzone_buffer
    1583              : {
    1584              : public:
    1585              :   /* Constructor.  */
    1586         1721 :   asan_redzone_buffer (rtx shadow_mem, HOST_WIDE_INT prev_offset):
    1587         1721 :     m_shadow_mem (shadow_mem), m_prev_offset (prev_offset),
    1588         1721 :     m_original_offset (prev_offset), m_shadow_bytes (RZ_BUFFER_SIZE)
    1589              :   {}
    1590              : 
    1591              :   /* Emit VALUE shadow byte at a given OFFSET.  */
    1592              :   void emit_redzone_byte (HOST_WIDE_INT offset, unsigned char value);
    1593              : 
    1594              :   /* Emit RTX emission of the content of the buffer.  */
    1595              :   void flush_redzone_payload (void);
    1596              : 
    1597              : private:
    1598              :   /* Flush if the content of the buffer is full
    1599              :      (equal to RZ_BUFFER_SIZE).  */
    1600              :   void flush_if_full (void);
    1601              : 
    1602              :   /* Memory where we last emitted a redzone payload.  */
    1603              :   rtx m_shadow_mem;
    1604              : 
    1605              :   /* Relative offset where we last emitted a redzone payload.  */
    1606              :   HOST_WIDE_INT m_prev_offset;
    1607              : 
    1608              :   /* Relative original offset.  Used for checking only.  */
    1609              :   HOST_WIDE_INT m_original_offset;
    1610              : 
    1611              : public:
    1612              :   /* Buffer with redzone payload.  */
    1613              :   auto_vec<unsigned char> m_shadow_bytes;
    1614              : };
    1615              : 
    1616              : /* Emit VALUE shadow byte at a given OFFSET.  */
    1617              : 
    1618              : void
    1619        22769 : asan_redzone_buffer::emit_redzone_byte (HOST_WIDE_INT offset,
    1620              :                                         unsigned char value)
    1621              : {
    1622        22769 :   gcc_assert ((offset & (ASAN_SHADOW_GRANULARITY - 1)) == 0);
    1623        22769 :   gcc_assert (offset >= m_prev_offset);
    1624              : 
    1625        22769 :   HOST_WIDE_INT off
    1626        22769 :     = m_prev_offset + ASAN_SHADOW_GRANULARITY * m_shadow_bytes.length ();
    1627        22769 :   if (off == offset)
    1628              :     /* Consecutive shadow memory byte.  */;
    1629         4719 :   else if (offset < m_prev_offset + (HOST_WIDE_INT) (ASAN_SHADOW_GRANULARITY
    1630              :                                                      * RZ_BUFFER_SIZE)
    1631         4719 :            && !m_shadow_bytes.is_empty ())
    1632              :     {
    1633              :       /* Shadow memory byte with a small gap.  */
    1634           68 :       for (; off < offset; off += ASAN_SHADOW_GRANULARITY)
    1635           34 :         m_shadow_bytes.safe_push (0);
    1636              :     }
    1637              :   else
    1638              :     {
    1639         4685 :       if (!m_shadow_bytes.is_empty ())
    1640          358 :         flush_redzone_payload ();
    1641              : 
    1642              :       /* Maybe start earlier in order to use aligned store.  */
    1643         4685 :       HOST_WIDE_INT align = (offset - m_prev_offset) % ASAN_RED_ZONE_SIZE;
    1644         4685 :       if (align)
    1645              :         {
    1646         1284 :           offset -= align;
    1647         3389 :           for (unsigned i = 0; i < align / BITS_PER_UNIT; i++)
    1648         2105 :             m_shadow_bytes.safe_push (0);
    1649              :         }
    1650              : 
    1651              :       /* Adjust m_prev_offset and m_shadow_mem.  */
    1652         4685 :       HOST_WIDE_INT diff = offset - m_prev_offset;
    1653         4685 :       m_shadow_mem = adjust_address (m_shadow_mem, VOIDmode,
    1654              :                                      diff >> ASAN_SHADOW_SHIFT);
    1655         4685 :       m_prev_offset = offset;
    1656              :     }
    1657        22769 :   m_shadow_bytes.safe_push (value);
    1658        22769 :   flush_if_full ();
    1659        22769 : }
    1660              : 
    1661              : /* Emit RTX emission of the content of the buffer.  */
    1662              : 
    1663              : void
    1664         6406 : asan_redzone_buffer::flush_redzone_payload (void)
    1665              : {
    1666         6406 :   gcc_assert (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN);
    1667              : 
    1668         6406 :   if (m_shadow_bytes.is_empty ())
    1669         6406 :     return;
    1670              : 
    1671              :   /* Be sure we always emit to an aligned address.  */
    1672         6406 :   gcc_assert (((m_prev_offset - m_original_offset)
    1673              :               & (ASAN_RED_ZONE_SIZE - 1)) == 0);
    1674              : 
    1675              :   /* Fill it to RZ_BUFFER_SIZE bytes with zeros if needed.  */
    1676              :   unsigned l = m_shadow_bytes.length ();
    1677        13528 :   for (unsigned i = 0; i <= RZ_BUFFER_SIZE - l; i++)
    1678         7122 :     m_shadow_bytes.safe_push (0);
    1679              : 
    1680         6406 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1681            0 :     fprintf (dump_file,
    1682              :              "Flushing rzbuffer at offset %" PRId64 " with: ", m_prev_offset);
    1683              : 
    1684         6406 :   unsigned HOST_WIDE_INT val = 0;
    1685        32030 :   for (unsigned i = 0; i < RZ_BUFFER_SIZE; i++)
    1686              :     {
    1687        25624 :       unsigned char v
    1688        25624 :         = m_shadow_bytes[BYTES_BIG_ENDIAN ? RZ_BUFFER_SIZE - i - 1 : i];
    1689        25624 :       val |= (unsigned HOST_WIDE_INT)v << (BITS_PER_UNIT * i);
    1690        25624 :       if (dump_file && (dump_flags & TDF_DETAILS))
    1691            0 :         fprintf (dump_file, "%02x ", v);
    1692              :     }
    1693              : 
    1694         6406 :   if (dump_file && (dump_flags & TDF_DETAILS))
    1695            0 :     fprintf (dump_file, "\n");
    1696              : 
    1697         6406 :   rtx c = gen_int_mode (val, SImode);
    1698         6406 :   m_shadow_mem = adjust_address (m_shadow_mem, SImode, 0);
    1699         6406 :   emit_move_insn (m_shadow_mem, c);
    1700         6406 :   m_shadow_bytes.truncate (0);
    1701              : }
    1702              : 
    1703              : /* Flush if the content of the buffer is full
    1704              :    (equal to RZ_BUFFER_SIZE).  */
    1705              : 
    1706              : void
    1707        22769 : asan_redzone_buffer::flush_if_full (void)
    1708              : {
    1709        22769 :   if (m_shadow_bytes.length () == RZ_BUFFER_SIZE)
    1710         6048 :     flush_redzone_payload ();
    1711        22769 : }
    1712              : 
    1713              : 
    1714              : /* HWAddressSanitizer (hwasan) is a probabilistic method for detecting
    1715              :    out-of-bounds and use-after-free bugs.
    1716              :    Read more:
    1717              :    http://code.google.com/p/address-sanitizer/
    1718              : 
    1719              :    Similar to AddressSanitizer (asan) it consists of two parts: the
    1720              :    instrumentation module in this file, and a run-time library.
    1721              : 
    1722              :    The instrumentation module adds a run-time check before every memory insn in
    1723              :    the same manner as asan (see the block comment for AddressSanitizer above).
    1724              :    Currently, hwasan only adds out-of-line instrumentation, where each check is
    1725              :    implemented as a function call to the run-time library.  Hence a check for a
    1726              :    load of N bytes from address X would be implemented with a function call to
    1727              :    __hwasan_loadN(X), and checking a store of N bytes from address X would be
    1728              :    implemented with a function call to __hwasan_storeN(X).
    1729              : 
    1730              :    The main difference between hwasan and asan is in the information stored to
    1731              :    help this checking.  Both sanitizers use a shadow memory area which stores
    1732              :    data recording the state of main memory at a corresponding address.
    1733              : 
    1734              :    For hwasan, each 16 byte granule in main memory has a corresponding 1 byte
    1735              :    in shadow memory.  This shadow address can be calculated with equation:
    1736              :      (addr >> log_2(HWASAN_TAG_GRANULE_SIZE))
    1737              :           + __hwasan_shadow_memory_dynamic_address;
    1738              :    The conversion between real and shadow memory for asan is given in the block
    1739              :    comment at the top of this file.
    1740              :    The description of how this shadow memory is laid out for asan is in the
    1741              :    block comment at the top of this file, here we describe how this shadow
    1742              :    memory is used for hwasan.
    1743              : 
    1744              :    For hwasan, each variable is assigned a byte-sized 'tag'.  The extent of
    1745              :    the shadow memory for that variable is filled with the assigned tag, and
    1746              :    every pointer referencing that variable has its top byte set to the same
    1747              :    tag.  The run-time library redefines malloc so that every allocation returns
    1748              :    a tagged pointer and tags the corresponding shadow memory with the same tag.
    1749              : 
    1750              :    On each pointer dereference the tag found in the pointer is compared to the
    1751              :    tag found in the shadow memory corresponding to the accessed memory address.
    1752              :    If these tags are found to differ then this memory access is judged to be
    1753              :    invalid and a report is generated.
    1754              : 
    1755              :    This method of bug detection is not perfect -- it can not catch every bad
    1756              :    access -- but catches them probabilistically instead.  There is always the
    1757              :    possibility that an invalid memory access will happen to access memory
    1758              :    tagged with the same tag as the pointer that this access used.
    1759              :    The chances of this are approx. 0.4% for any two uncorrelated objects.
    1760              : 
    1761              :    Random tag generation can mitigate this problem by decreasing the
    1762              :    probability that an invalid access will be missed in the same manner over
    1763              :    multiple runs.  i.e. if two objects are tagged the same in one run of the
    1764              :    binary they are unlikely to be tagged the same in the next run.
    1765              :    Both heap and stack allocated objects have random tags by default.
    1766              : 
    1767              :    [16 byte granule implications]
    1768              :     Since the shadow memory only has a resolution on real memory of 16 bytes,
    1769              :     invalid accesses that are within the same 16 byte granule as a valid
    1770              :     address will not be caught.
    1771              : 
    1772              :     There is a "short-granule" feature in the runtime library which does catch
    1773              :     such accesses, but this feature is not implemented for stack objects (since
    1774              :     stack objects are allocated and tagged by compiler instrumentation, and
    1775              :     this feature has not yet been implemented in GCC instrumentation).
    1776              : 
    1777              :     Another outcome of this 16 byte resolution is that each tagged object must
    1778              :     be 16 byte aligned.  If two objects were to share any 16 byte granule in
    1779              :     memory, then they both would have to be given the same tag, and invalid
    1780              :     accesses to one using a pointer to the other would be undetectable.
    1781              : 
    1782              :    [Compiler instrumentation]
    1783              :     Compiler instrumentation ensures that two adjacent buffers on the stack are
    1784              :     given different tags, this means an access to one buffer using a pointer
    1785              :     generated from the other (e.g. through buffer overrun) will have mismatched
    1786              :     tags and be caught by hwasan.
    1787              : 
    1788              :     We don't randomly tag every object on the stack, since that would require
    1789              :     keeping many registers to record each tag.  Instead we randomly generate a
    1790              :     tag for each function frame, and each new stack object uses a tag offset
    1791              :     from that frame tag.
    1792              :     i.e. each object is tagged as RFT + offset, where RFT is the "random frame
    1793              :     tag" generated for this frame.
    1794              :     This means that randomisation does not peturb the difference between tags
    1795              :     on tagged stack objects within a frame, but this is mitigated by the fact
    1796              :     that objects with the same tag within a frame are very far apart
    1797              :     (approx. 2^HWASAN_TAG_SIZE objects apart).
    1798              : 
    1799              :     As a demonstration, using the same example program as in the asan block
    1800              :     comment above:
    1801              : 
    1802              :      int
    1803              :      foo ()
    1804              :      {
    1805              :        char a[24] = {0};
    1806              :        int b[2] = {0};
    1807              : 
    1808              :        a[5] = 1;
    1809              :        b[1] = 2;
    1810              : 
    1811              :        return a[5] + b[1];
    1812              :      }
    1813              : 
    1814              :     On AArch64 the stack will be ordered as follows for the above function:
    1815              : 
    1816              :     Slot 1/ [24 bytes for variable 'a']
    1817              :     Slot 2/ [8 bytes padding for alignment]
    1818              :     Slot 3/ [8 bytes for variable 'b']
    1819              :     Slot 4/ [8 bytes padding for alignment]
    1820              : 
    1821              :     (The padding is there to ensure 16 byte alignment as described in the 16
    1822              :      byte granule implications).
    1823              : 
    1824              :     While the shadow memory will be ordered as follows:
    1825              : 
    1826              :     - 2 bytes (representing 32 bytes in real memory) tagged with RFT + 1.
    1827              :     - 1 byte (representing 16 bytes in real memory) tagged with RFT + 2.
    1828              : 
    1829              :     And any pointer to "a" will have the tag RFT + 1, and any pointer to "b"
    1830              :     will have the tag RFT + 2.
    1831              : 
    1832              :    [Top Byte Ignore requirements]
    1833              :     Hwasan requires the ability to store an 8 bit tag in every pointer.  There
    1834              :     is no instrumentation done to remove this tag from pointers before
    1835              :     dereferencing, which means the hardware must ignore this tag during memory
    1836              :     accesses.
    1837              : 
    1838              :     Architectures where this feature is available should indicate this using
    1839              :     the TARGET_MEMTAG_CAN_TAG_ADDRESSES hook.
    1840              : 
    1841              :    [Stack requires cleanup on unwinding]
    1842              :     During normal operation of a hwasan sanitized program more space in the
    1843              :     shadow memory becomes tagged as the stack grows.  As the stack shrinks this
    1844              :     shadow memory space must become untagged.  If it is not untagged then when
    1845              :     the stack grows again (during other function calls later on in the program)
    1846              :     objects on the stack that are usually not tagged (e.g. parameters passed on
    1847              :     the stack) can be placed in memory whose shadow space is tagged with
    1848              :     something else, and accesses can cause false positive reports.
    1849              : 
    1850              :     Hence we place untagging code on every epilogue of functions which tag some
    1851              :     stack objects.
    1852              : 
    1853              :     Moreover, the run-time library intercepts longjmp & setjmp to untag when
    1854              :     the stack is unwound this way.
    1855              : 
    1856              :     C++ exceptions are not yet handled, which means this sanitizer can not
    1857              :     handle C++ code that throws exceptions -- it will give false positives
    1858              :     after an exception has been thrown.  The implementation that the hwasan
    1859              :     library has for handling these relies on the frame pointer being after any
    1860              :     local variables.  This is not generally the case for GCC.  */
    1861              : 
    1862              : 
    1863              : /* Returns whether we are tagging pointers and checking those tags on memory
    1864              :    access.  */
    1865              : bool
    1866     30100309 : hwasan_sanitize_p ()
    1867              : {
    1868     30100309 :   return sanitize_flags_p (SANITIZE_HWADDRESS);
    1869              : }
    1870              : 
    1871              : /* Are we tagging the stack?  */
    1872              : bool
    1873     28226321 : hwasan_sanitize_stack_p ()
    1874              : {
    1875     28226321 :   return (hwasan_sanitize_p () && param_hwasan_instrument_stack);
    1876              : }
    1877              : 
    1878              : /* Are we tagging alloca objects?  */
    1879              : bool
    1880      1516125 : hwasan_sanitize_allocas_p (void)
    1881              : {
    1882      1516125 :   return (hwasan_sanitize_stack_p () && param_hwasan_instrument_allocas);
    1883              : }
    1884              : 
    1885              : /* Should we instrument reads?  */
    1886              : bool
    1887          370 : hwasan_instrument_reads (void)
    1888              : {
    1889          370 :   return (hwasan_sanitize_p () && param_hwasan_instrument_reads);
    1890              : }
    1891              : 
    1892              : /* Should we instrument writes?  */
    1893              : bool
    1894          212 : hwasan_instrument_writes (void)
    1895              : {
    1896          212 :   return (hwasan_sanitize_p () && param_hwasan_instrument_writes);
    1897              : }
    1898              : 
    1899              : /* Should we instrument builtin calls?  */
    1900              : bool
    1901           94 : hwasan_memintrin (void)
    1902              : {
    1903           94 :   return (hwasan_sanitize_p () && param_hwasan_instrument_mem_intrinsics);
    1904              : }
    1905              : 
    1906              : /* MEMoryTAGging sanitizer (MEMTAG) uses a hardware based capability known as
    1907              :    memory tagging to detect memory safety vulnerabilities.  Similar to HWASAN,
    1908              :    it is also a probabilistic method.
    1909              : 
    1910              :    MEMTAG relies on the optional extension in armv8.5a known as MTE (Memory
    1911              :    Tagging Extension).  The extension is available in AArch64 only and
    1912              :    introduces two types of tags:
    1913              :      - Logical Address Tag - bits 56-59 (TARGET_MEMTAG_TAG_BITSIZE) of the
    1914              :        virtual address.
    1915              :      - Allocation Tag - 4 bits for each tag granule (TARGET_MEMTAG_GRANULE_SIZE
    1916              :        set to 16 bytes), stored separately.
    1917              :    Load / store instructions raise an exception if tags differ, thereby
    1918              :    providing a faster way (than HWASAN) to detect memory safety issues.
    1919              :    Further, new instructions are available in MTE to manipulate (generate,
    1920              :    update address with) tags.  Load / store instructions with SP base register
    1921              :    and immediate offset do not check tags.
    1922              : 
    1923              :    PS: Currently, MEMTAG sanitizer is capable of stack (variable / memory)
    1924              :    tagging only.
    1925              : 
    1926              :    In general, detecting stack-related memory bugs requires the compiler to:
    1927              :      - ensure that each tag granule is only used by one variable at a time.
    1928              :        This includes alloca.
    1929              :      - Tag/Color: put tags into each stack variable pointer.
    1930              :      - Untag: the function epilogue will retag the memory.
    1931              : 
    1932              :    MEMTAG sanitizer is based off the HWASAN sanitizer implementation
    1933              :    internally.  Similar to HWASAN:
    1934              :      - Assigning an independently random tag to each variable is carried out by
    1935              :        keeping a tagged base pointer.  A tagged base pointer allows addressing
    1936              :        variables with (addr offset, tag offset).
    1937              :    */
    1938              : 
    1939              : /* Returns whether we are tagging pointers and checking those tags on memory
    1940              :    access.  */
    1941              : bool
    1942      3114263 : memtag_sanitize_p ()
    1943              : {
    1944      3114263 :   return sanitize_flags_p (SANITIZE_MEMTAG);
    1945              : }
    1946              : 
    1947              : /* Are we tagging the stack?  */
    1948              : bool
    1949     26692579 : memtag_sanitize_stack_p ()
    1950              : {
    1951     26692579 :   return (sanitize_flags_p (SANITIZE_MEMTAG_STACK));
    1952              : }
    1953              : 
    1954              : /* Are we tagging alloca objects?  */
    1955              : bool
    1956          404 : memtag_sanitize_allocas_p (void)
    1957              : {
    1958          404 :   return (memtag_sanitize_stack_p () && param_memtag_instrument_allocas);
    1959              : }
    1960              : 
    1961              : /* Are we taggin mem intrinsics?  */
    1962              : bool
    1963           24 : memtag_memintrin (void)
    1964              : {
    1965           24 :   return (memtag_sanitize_p () && param_memtag_instrument_mem_intrinsics);
    1966              : }
    1967              : 
    1968              : /* Returns whether we are tagging pointers and checking those tags on memory
    1969              :    access.  */
    1970              : bool
    1971        90719 : hwassist_sanitize_p ()
    1972              : {
    1973        90719 :   return (hwasan_sanitize_p () || memtag_sanitize_p ());
    1974              : }
    1975              : 
    1976              : /* Are we tagging stack objects for hwasan or memtag?  */
    1977              : bool
    1978     26696523 : hwassist_sanitize_stack_p ()
    1979              : {
    1980     26696523 :   return (hwasan_sanitize_stack_p () || memtag_sanitize_stack_p ());
    1981              : }
    1982              : 
    1983              : /* Insert code to protect stack vars.  The prologue sequence should be emitted
    1984              :    directly, epilogue sequence returned.  BASE is the register holding the
    1985              :    stack base, against which OFFSETS array offsets are relative to, OFFSETS
    1986              :    array contains pairs of offsets in reverse order, always the end offset
    1987              :    of some gap that needs protection followed by starting offset,
    1988              :    and DECLS is an array of representative decls for each var partition.
    1989              :    LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1
    1990              :    elements long (OFFSETS include gap before the first variable as well
    1991              :    as gaps after each stack variable).  PBASE is, if non-NULL, some pseudo
    1992              :    register which stack vars DECL_RTLs are based on.  Either BASE should be
    1993              :    assigned to PBASE, when not doing use after return protection, or
    1994              :    corresponding address based on __asan_stack_malloc* return value.  */
    1995              : 
    1996              : rtx_insn *
    1997         1721 : asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
    1998              :                             HOST_WIDE_INT *offsets, tree *decls, int length)
    1999              : {
    2000         1721 :   rtx shadow_base, shadow_mem, ret, mem, orig_base;
    2001         1721 :   rtx_code_label *lab;
    2002         1721 :   rtx_insn *insns;
    2003         1721 :   char buf[32];
    2004         1721 :   HOST_WIDE_INT base_offset = offsets[length - 1];
    2005         1721 :   HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
    2006         1721 :   HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
    2007         1721 :   HOST_WIDE_INT last_offset, last_size, last_size_aligned;
    2008         1721 :   int l;
    2009         1721 :   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
    2010         1721 :   tree str_cst, decl, id;
    2011         1721 :   int use_after_return_class = -1;
    2012              : 
    2013              :   /* Don't emit anything when doing error recovery, the assertions
    2014              :      might fail e.g. if a function had a frame offset overflow.  */
    2015         1721 :   if (seen_error ())
    2016              :     return NULL;
    2017              : 
    2018         1721 :   if (shadow_ptr_types[0] == NULL_TREE)
    2019            0 :     asan_init_shadow_ptr_types ();
    2020              : 
    2021         1721 :   expanded_location cfun_xloc
    2022         1721 :     = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
    2023              : 
    2024              :   /* First of all, prepare the description string.  */
    2025         1721 :   pretty_printer asan_pp;
    2026              : 
    2027         1721 :   pp_decimal_int (&asan_pp, length / 2 - 1);
    2028         1721 :   pp_space (&asan_pp);
    2029         5026 :   for (l = length - 2; l; l -= 2)
    2030              :     {
    2031         3305 :       tree decl = decls[l / 2 - 1];
    2032         3305 :       pp_wide_integer (&asan_pp, offsets[l] - base_offset);
    2033         3305 :       pp_space (&asan_pp);
    2034         3305 :       pp_wide_integer (&asan_pp, offsets[l - 1] - offsets[l]);
    2035         3305 :       pp_space (&asan_pp);
    2036              : 
    2037         3305 :       expanded_location xloc
    2038         3305 :         = expand_location (DECL_SOURCE_LOCATION (decl));
    2039         3305 :       char location[32];
    2040              : 
    2041         3305 :       if (xloc.file == cfun_xloc.file)
    2042         3081 :         sprintf (location, ":%d", xloc.line);
    2043              :       else
    2044          224 :         location[0] = '\0';
    2045              : 
    2046         3305 :       if (DECL_P (decl) && DECL_NAME (decl))
    2047              :         {
    2048         2757 :           unsigned idlen
    2049         2757 :             = IDENTIFIER_LENGTH (DECL_NAME (decl)) + strlen (location);
    2050         2757 :           pp_decimal_int (&asan_pp, idlen);
    2051         2757 :           pp_space (&asan_pp);
    2052         2757 :           pp_tree_identifier (&asan_pp, DECL_NAME (decl));
    2053         2757 :           pp_string (&asan_pp, location);
    2054              :         }
    2055              :       else
    2056          548 :         pp_string (&asan_pp, "9 <unknown>");
    2057              : 
    2058         3305 :       if (l > 2)
    2059         1584 :         pp_space (&asan_pp);
    2060              :     }
    2061         1721 :   str_cst = asan_pp_string (&asan_pp);
    2062              : 
    2063         3382 :   gcc_checking_assert (offsets[0] == (crtl->stack_protect_guard
    2064              :                                       ? -ASAN_RED_ZONE_SIZE : 0));
    2065              :   /* Emit the prologue sequence.  */
    2066         1721 :   if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase
    2067         1690 :       && param_asan_use_after_return)
    2068              :     {
    2069         1656 :       HOST_WIDE_INT adjusted_frame_size = asan_frame_size;
    2070              :       /* The stack protector guard is allocated at the top of the frame
    2071              :          and cfgexpand.cc then uses align_frame_offset (ASAN_RED_ZONE_SIZE);
    2072              :          while in that case we can still use asan_frame_size, we need to take
    2073              :          that into account when computing base_align_bias.  */
    2074         1656 :       if (alignb > ASAN_RED_ZONE_SIZE && crtl->stack_protect_guard)
    2075           28 :         adjusted_frame_size += ASAN_RED_ZONE_SIZE;
    2076         1656 :       use_after_return_class = floor_log2 (asan_frame_size - 1) - 5;
    2077              :       /* __asan_stack_malloc_N guarantees alignment
    2078              :          N < 6 ? (64 << N) : 4096 bytes.  */
    2079         1656 :       if (alignb > (use_after_return_class < 6
    2080         1656 :                     ? (64U << use_after_return_class) : 4096U))
    2081              :         use_after_return_class = -1;
    2082         1656 :       else if (alignb > ASAN_RED_ZONE_SIZE
    2083           54 :                && (adjusted_frame_size & (alignb - 1)))
    2084              :         {
    2085           28 :           base_align_bias
    2086           28 :             = ((adjusted_frame_size + alignb - 1)
    2087           28 :                & ~(alignb - HOST_WIDE_INT_1)) - adjusted_frame_size;
    2088           28 :           use_after_return_class
    2089           28 :             = floor_log2 (asan_frame_size + base_align_bias - 1) - 5;
    2090           28 :           if (use_after_return_class > 10)
    2091              :             {
    2092           65 :               base_align_bias = 0;
    2093           65 :               use_after_return_class = -1;
    2094              :             }
    2095              :         }
    2096              :     }
    2097              : 
    2098              :   /* Align base if target is STRICT_ALIGNMENT.  */
    2099         1721 :   if (STRICT_ALIGNMENT)
    2100              :     {
    2101              :       const HOST_WIDE_INT align
    2102              :         = (GET_MODE_ALIGNMENT (SImode) / BITS_PER_UNIT) << ASAN_SHADOW_SHIFT;
    2103              :       base = expand_binop (Pmode, and_optab, base, gen_int_mode (-align, Pmode),
    2104              :                            NULL_RTX, 1, OPTAB_DIRECT);
    2105              :     }
    2106              : 
    2107         1721 :   if (use_after_return_class == -1 && pbase)
    2108           65 :     emit_move_insn (pbase, base);
    2109              : 
    2110         1721 :   base = expand_binop (Pmode, add_optab, base,
    2111         1721 :                        gen_int_mode (base_offset - base_align_bias, Pmode),
    2112              :                        NULL_RTX, 1, OPTAB_DIRECT);
    2113         1721 :   orig_base = NULL_RTX;
    2114         1721 :   if (use_after_return_class != -1)
    2115              :     {
    2116         1656 :       if (asan_detect_stack_use_after_return == NULL_TREE)
    2117              :         {
    2118         1209 :           id = get_identifier ("__asan_option_detect_stack_use_after_return");
    2119         1209 :           decl = build_decl (BUILTINS_LOCATION, VAR_DECL, id,
    2120              :                              integer_type_node);
    2121         1209 :           SET_DECL_ASSEMBLER_NAME (decl, id);
    2122         1209 :           TREE_ADDRESSABLE (decl) = 1;
    2123         1209 :           DECL_ARTIFICIAL (decl) = 1;
    2124         1209 :           DECL_IGNORED_P (decl) = 1;
    2125         1209 :           DECL_EXTERNAL (decl) = 1;
    2126         1209 :           TREE_STATIC (decl) = 1;
    2127         1209 :           TREE_PUBLIC (decl) = 1;
    2128         1209 :           TREE_USED (decl) = 1;
    2129         1209 :           asan_detect_stack_use_after_return = decl;
    2130              :         }
    2131         1656 :       orig_base = gen_reg_rtx (Pmode);
    2132         1656 :       emit_move_insn (orig_base, base);
    2133         1656 :       ret = expand_normal (asan_detect_stack_use_after_return);
    2134         1656 :       lab = gen_label_rtx ();
    2135         1656 :       emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
    2136              :                                VOIDmode, 0, lab,
    2137              :                                profile_probability::very_likely ());
    2138         1656 :       snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
    2139              :                 use_after_return_class);
    2140         1656 :       ret = init_one_libfunc (buf);
    2141         1656 :       ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
    2142              :                                      GEN_INT (asan_frame_size
    2143              :                                               + base_align_bias),
    2144         1656 :                                      TYPE_MODE (pointer_sized_int_node));
    2145              :       /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
    2146              :          and NULL otherwise.  Check RET value is NULL here and jump over the
    2147              :          BASE reassignment in this case.  Otherwise, reassign BASE to RET.  */
    2148         1656 :       emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
    2149              :                                VOIDmode, 0, lab,
    2150              :                                profile_probability:: very_unlikely ());
    2151         1656 :       ret = convert_memory_address (Pmode, ret);
    2152         1656 :       emit_move_insn (base, ret);
    2153         1656 :       emit_label (lab);
    2154         1656 :       emit_move_insn (pbase, expand_binop (Pmode, add_optab, base,
    2155              :                                            gen_int_mode (base_align_bias
    2156         1656 :                                                          - base_offset, Pmode),
    2157              :                                            NULL_RTX, 1, OPTAB_DIRECT));
    2158              :     }
    2159         1721 :   mem = gen_rtx_MEM (ptr_mode, base);
    2160         1721 :   mem = adjust_address (mem, VOIDmode, base_align_bias);
    2161         1721 :   emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode));
    2162         3442 :   mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
    2163         1721 :   emit_move_insn (mem, expand_normal (str_cst));
    2164         3442 :   mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
    2165         1721 :   ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no);
    2166         1721 :   id = get_identifier (buf);
    2167         1721 :   decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
    2168              :                     VAR_DECL, id, char_type_node);
    2169         1721 :   SET_DECL_ASSEMBLER_NAME (decl, id);
    2170         1721 :   TREE_ADDRESSABLE (decl) = 1;
    2171         1721 :   TREE_READONLY (decl) = 1;
    2172         1721 :   DECL_ARTIFICIAL (decl) = 1;
    2173         1721 :   DECL_IGNORED_P (decl) = 1;
    2174         1721 :   TREE_STATIC (decl) = 1;
    2175         1721 :   TREE_PUBLIC (decl) = 0;
    2176         1721 :   TREE_USED (decl) = 1;
    2177         1721 :   DECL_INITIAL (decl) = decl;
    2178         1721 :   TREE_ASM_WRITTEN (decl) = 1;
    2179         1721 :   TREE_ASM_WRITTEN (id) = 1;
    2180         1721 :   DECL_ALIGN_RAW (decl) = DECL_ALIGN_RAW (current_function_decl);
    2181         1721 :   emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
    2182         1721 :   shadow_base = expand_binop (Pmode, lshr_optab, base,
    2183         1721 :                               gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT),
    2184              :                               NULL_RTX, 1, OPTAB_DIRECT);
    2185         1721 :   if (asan_dynamic_shadow_offset_p ())
    2186              :     {
    2187            0 :       ret = expand_normal (get_asan_shadow_memory_dynamic_address_decl ());
    2188            0 :       shadow_base
    2189            0 :         = expand_simple_binop (Pmode, PLUS, shadow_base, ret, NULL_RTX,
    2190              :                                /* unsignedp = */ 1, OPTAB_WIDEN);
    2191            0 :       shadow_base = plus_constant (Pmode, shadow_base,
    2192            0 :                                    (base_align_bias >> ASAN_SHADOW_SHIFT));
    2193              :     }
    2194              :   else
    2195              :     {
    2196         1721 :       shadow_base = plus_constant (Pmode, shadow_base,
    2197         1721 :                                    asan_shadow_offset ()
    2198         1721 :                                      + (base_align_bias >> ASAN_SHADOW_SHIFT));
    2199              :     }
    2200         1721 :   gcc_assert (asan_shadow_set != -1
    2201              :               && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
    2202         1721 :   shadow_mem = gen_rtx_MEM (SImode, shadow_base);
    2203         1721 :   set_mem_alias_set (shadow_mem, asan_shadow_set);
    2204         1721 :   if (STRICT_ALIGNMENT)
    2205              :     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
    2206         1721 :   prev_offset = base_offset;
    2207              : 
    2208         1721 :   asan_redzone_buffer rz_buffer (shadow_mem, prev_offset);
    2209         8468 :   for (l = length; l; l -= 2)
    2210              :     {
    2211         5026 :       if (l == 2)
    2212         1721 :         cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
    2213         5026 :       offset = offsets[l - 1];
    2214              : 
    2215         5026 :       bool extra_byte = (offset - base_offset) & (ASAN_SHADOW_GRANULARITY - 1);
    2216              :       /* If a red-zone is not aligned to ASAN_SHADOW_GRANULARITY then
    2217              :          the previous stack variable has size % ASAN_SHADOW_GRANULARITY != 0.
    2218              :          In that case we have to emit one extra byte that will describe
    2219              :          how many bytes (our of ASAN_SHADOW_GRANULARITY) can be accessed.  */
    2220         5026 :       if (extra_byte)
    2221              :         {
    2222         1498 :           HOST_WIDE_INT aoff
    2223         1498 :             = base_offset + ((offset - base_offset)
    2224         1498 :                              & ~(ASAN_SHADOW_GRANULARITY - HOST_WIDE_INT_1));
    2225         1498 :           rz_buffer.emit_redzone_byte (aoff, offset - aoff);
    2226         1498 :           offset = aoff + ASAN_SHADOW_GRANULARITY;
    2227              :         }
    2228              : 
    2229              :       /* Calculate size of red zone payload.  */
    2230        26297 :       while (offset < offsets[l - 2])
    2231              :         {
    2232        21271 :           rz_buffer.emit_redzone_byte (offset, cur_shadow_byte);
    2233        21271 :           offset += ASAN_SHADOW_GRANULARITY;
    2234              :         }
    2235              : 
    2236         5026 :       cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
    2237              :     }
    2238              : 
    2239              :   /* As the automatic variables are aligned to
    2240              :      ASAN_RED_ZONE_SIZE / ASAN_SHADOW_GRANULARITY, the buffer should be
    2241              :      flushed here.  */
    2242         1721 :   gcc_assert (rz_buffer.m_shadow_bytes.is_empty ());
    2243              : 
    2244         1721 :   do_pending_stack_adjust ();
    2245              : 
    2246              :   /* Construct epilogue sequence.  */
    2247         1721 :   start_sequence ();
    2248              : 
    2249         1721 :   lab = NULL;
    2250         1721 :   if (use_after_return_class != -1)
    2251              :     {
    2252         1656 :       rtx_code_label *lab2 = gen_label_rtx ();
    2253         1656 :       char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
    2254         1656 :       emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
    2255              :                                VOIDmode, 0, lab2,
    2256              :                                profile_probability::very_likely ());
    2257         1656 :       shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
    2258         1656 :       set_mem_alias_set (shadow_mem, asan_shadow_set);
    2259         1656 :       mem = gen_rtx_MEM (ptr_mode, base);
    2260         1656 :       mem = adjust_address (mem, VOIDmode, base_align_bias);
    2261         1656 :       emit_move_insn (mem, gen_int_mode (ASAN_STACK_RETIRED_MAGIC, ptr_mode));
    2262         1656 :       unsigned HOST_WIDE_INT sz = asan_frame_size >> ASAN_SHADOW_SHIFT;
    2263         1656 :       bool asan_stack_free_emitted_p = false;
    2264         1656 :       if (use_after_return_class < 5
    2265         1656 :           && can_store_by_pieces (sz, builtin_memset_read_str, &c,
    2266              :                                   BITS_PER_UNIT, true))
    2267              :         /* Emit memset (ShadowBase, kAsanStackAfterReturnMagic, ShadowSize).  */
    2268         1531 :         store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
    2269              :                          BITS_PER_UNIT, true, RETURN_BEGIN);
    2270          125 :       else if (use_after_return_class >= 5
    2271          142 :                || !set_storage_via_setmem (shadow_mem,
    2272              :                                            GEN_INT (sz),
    2273           17 :                                            gen_int_mode (c, QImode),
    2274              :                                            BITS_PER_UNIT, BITS_PER_UNIT,
    2275              :                                            -1, sz, sz, sz))
    2276              :         {
    2277          108 :           snprintf (buf, sizeof buf, "__asan_stack_free_%d",
    2278              :                     use_after_return_class);
    2279          108 :           ret = init_one_libfunc (buf);
    2280          108 :           rtx addr = convert_memory_address (ptr_mode, base);
    2281          108 :           rtx orig_addr = convert_memory_address (ptr_mode, orig_base);
    2282          216 :           emit_library_call (ret, LCT_NORMAL, ptr_mode, addr, ptr_mode,
    2283              :                              GEN_INT (asan_frame_size + base_align_bias),
    2284          108 :                              TYPE_MODE (pointer_sized_int_node),
    2285              :                              orig_addr, ptr_mode);
    2286          108 :           asan_stack_free_emitted_p = true;
    2287              :         }
    2288         1656 :       if (!asan_stack_free_emitted_p)
    2289              :         {
    2290              :           /* Emit **SavedFlagPtr (FakeStack, class_id) = 0.  */
    2291         1548 :           unsigned HOST_WIDE_INT offset = (1 << (use_after_return_class + 6));
    2292         1548 :           offset -= GET_MODE_SIZE (ptr_mode);
    2293         1548 :           mem = gen_rtx_MEM (ptr_mode, base);
    2294         1548 :           mem = adjust_address (mem, ptr_mode, offset);
    2295         1548 :           rtx addr = gen_reg_rtx (ptr_mode);
    2296         1548 :           emit_move_insn (addr, mem);
    2297         1548 :           addr = convert_memory_address (Pmode, addr);
    2298         1548 :           mem = gen_rtx_MEM (QImode, addr);
    2299         1548 :           emit_move_insn (mem, const0_rtx);
    2300              :         }
    2301         1656 :       lab = gen_label_rtx ();
    2302         1656 :       emit_jump (lab);
    2303         1656 :       emit_label (lab2);
    2304              :     }
    2305              : 
    2306         1721 :   shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
    2307         1721 :   set_mem_alias_set (shadow_mem, asan_shadow_set);
    2308              : 
    2309         1721 :   if (STRICT_ALIGNMENT)
    2310              :     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
    2311              : 
    2312         1721 :   prev_offset = base_offset;
    2313         1721 :   last_offset = base_offset;
    2314         1721 :   last_size = 0;
    2315         1721 :   last_size_aligned = 0;
    2316         8468 :   for (l = length; l; l -= 2)
    2317              :     {
    2318         5026 :       offset = base_offset + ((offsets[l - 1] - base_offset)
    2319         5026 :                               & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
    2320         5026 :       if (last_offset + last_size_aligned < offset)
    2321              :         {
    2322          675 :           shadow_mem = adjust_address (shadow_mem, VOIDmode,
    2323              :                                        (last_offset - prev_offset)
    2324              :                                        >> ASAN_SHADOW_SHIFT);
    2325          675 :           prev_offset = last_offset;
    2326          675 :           asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
    2327          675 :           last_offset = offset;
    2328          675 :           last_size = 0;
    2329              :         }
    2330              :       else
    2331         4351 :         last_size = offset - last_offset;
    2332         5026 :       last_size += base_offset + ((offsets[l - 2] - base_offset)
    2333         5026 :                                   & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
    2334         5026 :                    - offset;
    2335              : 
    2336              :       /* Unpoison shadow memory that corresponds to a variable that is
    2337              :          is subject of use-after-return sanitization.  */
    2338         5026 :       if (l > 2)
    2339              :         {
    2340         3305 :           decl = decls[l / 2 - 2];
    2341         3305 :           if (asan_handled_variables != NULL
    2342         3305 :               && asan_handled_variables->contains (decl))
    2343              :             {
    2344          871 :               HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
    2345          871 :               if (dump_file && (dump_flags & TDF_DETAILS))
    2346              :                 {
    2347            0 :                   const char *n = (DECL_NAME (decl)
    2348            0 :                                    ? IDENTIFIER_POINTER (DECL_NAME (decl))
    2349            0 :                                    : "<unknown>");
    2350            0 :                   fprintf (dump_file, "Unpoisoning shadow stack for variable: "
    2351              :                            "%s (%" PRId64 " B)\n", n, size);
    2352              :                 }
    2353              : 
    2354          871 :                 last_size += size & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
    2355              :             }
    2356              :         }
    2357         5026 :       last_size_aligned
    2358         5026 :         = ((last_size + (ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
    2359              :            & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
    2360              :     }
    2361         1721 :   if (last_size_aligned)
    2362              :     {
    2363         1721 :       shadow_mem = adjust_address (shadow_mem, VOIDmode,
    2364              :                                    (last_offset - prev_offset)
    2365              :                                    >> ASAN_SHADOW_SHIFT);
    2366         1721 :       asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
    2367              :     }
    2368              : 
    2369              :   /* Clean-up set with instrumented stack variables.  */
    2370         2108 :   delete asan_handled_variables;
    2371         1721 :   asan_handled_variables = NULL;
    2372         1816 :   delete asan_used_labels;
    2373         1721 :   asan_used_labels = NULL;
    2374              : 
    2375         1721 :   do_pending_stack_adjust ();
    2376         1721 :   if (lab)
    2377         1656 :     emit_label (lab);
    2378              : 
    2379         1721 :   insns = end_sequence ();
    2380         1721 :   return insns;
    2381         1721 : }
    2382              : 
    2383              : /* Emit __asan_allocas_unpoison (top, bot) call.  The BASE parameter corresponds
    2384              :    to BOT argument, for TOP virtual_stack_dynamic_rtx is used.  NEW_SEQUENCE
    2385              :    indicates whether we're emitting new instructions sequence or not.  */
    2386              : 
    2387              : rtx_insn *
    2388          178 : asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
    2389              : {
    2390          178 :   if (before)
    2391           38 :     push_to_sequence (before);
    2392              :   else
    2393          140 :     start_sequence ();
    2394          178 :   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
    2395          178 :   top = convert_memory_address (ptr_mode, top);
    2396          178 :   bot = convert_memory_address (ptr_mode, bot);
    2397          178 :   emit_library_call (ret, LCT_NORMAL, ptr_mode,
    2398              :                      top, ptr_mode, bot, ptr_mode);
    2399              : 
    2400          178 :   do_pending_stack_adjust ();
    2401          178 :   return end_sequence ();
    2402              : }
    2403              : 
    2404              : /* Return true if DECL, a global var, might be overridden and needs
    2405              :    therefore a local alias.  */
    2406              : 
    2407              : static bool
    2408         4158 : asan_needs_local_alias (tree decl)
    2409              : {
    2410         4158 :   return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
    2411              : }
    2412              : 
    2413              : /* Return true if DECL, a global var, is an artificial ODR indicator symbol
    2414              :    therefore doesn't need protection.  */
    2415              : 
    2416              : static bool
    2417         8659 : is_odr_indicator (tree decl)
    2418              : {
    2419         8659 :   return (DECL_ARTIFICIAL (decl)
    2420         8659 :           && lookup_attribute ("asan odr indicator", DECL_ATTRIBUTES (decl)));
    2421              : }
    2422              : 
    2423              : /* Return true if DECL is a VAR_DECL that should be protected
    2424              :    by Address Sanitizer, by appending a red zone with protected
    2425              :    shadow memory after it and aligning it to at least
    2426              :    ASAN_RED_ZONE_SIZE bytes.  */
    2427              : 
    2428              : bool
    2429        22850 : asan_protect_global (tree decl, bool ignore_decl_rtl_set_p)
    2430              : {
    2431        22850 :   if (!param_asan_globals)
    2432              :     return false;
    2433              : 
    2434        22687 :   rtx rtl, symbol;
    2435              : 
    2436        22687 :   if (TREE_CODE (decl) == STRING_CST)
    2437              :     {
    2438              :       /* Instrument all STRING_CSTs except those created
    2439              :          by asan_pp_string here.  */
    2440        13577 :       if (shadow_ptr_types[0] != NULL_TREE
    2441        13543 :           && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
    2442        27120 :           && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0]))
    2443              :         return false;
    2444         6822 :       return true;
    2445              :     }
    2446         9110 :   if (!VAR_P (decl)
    2447              :       /* TLS vars aren't statically protectable.  */
    2448         9110 :       || DECL_THREAD_LOCAL_P (decl)
    2449              :       /* Externs will be protected elsewhere.  */
    2450         9104 :       || DECL_EXTERNAL (decl)
    2451              :       /* PR sanitizer/81697: For architectures that use section anchors first
    2452              :          call to asan_protect_global may occur before DECL_RTL (decl) is set.
    2453              :          We should ignore DECL_RTL_SET_P then, because otherwise the first call
    2454              :          to asan_protect_global will return FALSE and the following calls on the
    2455              :          same decl after setting DECL_RTL (decl) will return TRUE and we'll end
    2456              :          up with inconsistency at runtime.  */
    2457         9104 :       || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p)
    2458              :       /* Comdat vars pose an ABI problem, we can't know if
    2459              :          the var that is selected by the linker will have
    2460              :          padding or not.  */
    2461         9092 :       || DECL_ONE_ONLY (decl)
    2462              :       /* Similarly for common vars.  People can use -fno-common.
    2463              :          Note: Linux kernel is built with -fno-common, so we do instrument
    2464              :          globals there even if it is C.  */
    2465         8809 :       || (DECL_COMMON (decl) && TREE_PUBLIC (decl))
    2466              :       /* Don't protect if using user section, often vars placed
    2467              :          into user section from multiple TUs are then assumed
    2468              :          to be an array of such vars, putting padding in there
    2469              :          breaks this assumption.  */
    2470         8809 :       || (DECL_SECTION_NAME (decl) != NULL
    2471          270 :           && !symtab_node::get (decl)->implicit_section
    2472          270 :           && !section_sanitized_p (DECL_SECTION_NAME (decl)))
    2473              :       /* Don't protect variables in non-generic address-space.  */
    2474         8719 :       || !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)))
    2475         8717 :       || DECL_SIZE (decl) == 0
    2476         8717 :       || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
    2477         8717 :       || TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
    2478         8717 :       || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
    2479         8717 :       || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
    2480         8659 :       || TREE_TYPE (decl) == ubsan_get_source_location_type ()
    2481        17769 :       || is_odr_indicator (decl))
    2482              :     return false;
    2483              : 
    2484         8659 :   if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl))
    2485              :     {
    2486              : 
    2487         8659 :       rtl = DECL_RTL (decl);
    2488         8659 :       if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF)
    2489              :         return false;
    2490         8659 :       symbol = XEXP (rtl, 0);
    2491              : 
    2492         8659 :       if (CONSTANT_POOL_ADDRESS_P (symbol)
    2493         8659 :           || TREE_CONSTANT_POOL_ADDRESS_P (symbol))
    2494              :         return false;
    2495              :     }
    2496              : 
    2497         8659 :   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
    2498            0 :     return false;
    2499              : 
    2500              :   if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl))
    2501              :     return false;
    2502              : 
    2503              :   return true;
    2504              : }
    2505              : 
    2506              : /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}.
    2507              :    IS_STORE is either 1 (for a store) or 0 (for a load).  */
    2508              : 
    2509              : static tree
    2510        18927 : report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
    2511              :                    int *nargs)
    2512              : {
    2513        18927 :   gcc_assert (!hwassist_sanitize_p ());
    2514              : 
    2515        18927 :   static enum built_in_function report[2][2][6]
    2516              :     = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
    2517              :             BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
    2518              :             BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
    2519              :           { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
    2520              :             BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
    2521              :             BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
    2522              :         { { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
    2523              :             BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
    2524              :             BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
    2525              :             BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
    2526              :             BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
    2527              :             BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
    2528              :           { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
    2529              :             BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
    2530              :             BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
    2531              :             BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
    2532              :             BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
    2533              :             BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
    2534        18927 :   if (size_in_bytes == -1)
    2535              :     {
    2536         1008 :       *nargs = 2;
    2537         1008 :       return builtin_decl_implicit (report[recover_p][is_store][5]);
    2538              :     }
    2539        17919 :   int size_log2 = exact_log2 (size_in_bytes);
    2540        17919 :   if (size_log2 == -1 || size_log2 >= 5)
    2541              :     {
    2542           28 :       *nargs = 2;
    2543           28 :       return builtin_decl_implicit (report[recover_p][is_store][5]);
    2544              :     }
    2545        17891 :   *nargs = 1;
    2546        17891 :   return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
    2547              : }
    2548              : 
    2549              : /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
    2550              :    IS_STORE is either 1 (for a store) or 0 (for a load).  */
    2551              : 
    2552              : static tree
    2553          103 : check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
    2554              :             int *nargs)
    2555              : {
    2556          103 :   static enum built_in_function check[2][2][6]
    2557              :     = { { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
    2558              :             BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
    2559              :             BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
    2560              :           { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
    2561              :             BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
    2562              :             BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } },
    2563              :         { { BUILT_IN_ASAN_LOAD1_NOABORT,
    2564              :             BUILT_IN_ASAN_LOAD2_NOABORT,
    2565              :             BUILT_IN_ASAN_LOAD4_NOABORT,
    2566              :             BUILT_IN_ASAN_LOAD8_NOABORT,
    2567              :             BUILT_IN_ASAN_LOAD16_NOABORT,
    2568              :             BUILT_IN_ASAN_LOADN_NOABORT },
    2569              :           { BUILT_IN_ASAN_STORE1_NOABORT,
    2570              :             BUILT_IN_ASAN_STORE2_NOABORT,
    2571              :             BUILT_IN_ASAN_STORE4_NOABORT,
    2572              :             BUILT_IN_ASAN_STORE8_NOABORT,
    2573              :             BUILT_IN_ASAN_STORE16_NOABORT,
    2574              :             BUILT_IN_ASAN_STOREN_NOABORT } } };
    2575          103 :   if (size_in_bytes == -1)
    2576              :     {
    2577           28 :       *nargs = 2;
    2578           28 :       return builtin_decl_implicit (check[recover_p][is_store][5]);
    2579              :     }
    2580           75 :   *nargs = 1;
    2581           75 :   int size_log2 = exact_log2 (size_in_bytes);
    2582           75 :   return builtin_decl_implicit (check[recover_p][is_store][size_log2]);
    2583              : }
    2584              : 
    2585              : /* Split the current basic block and create a condition statement
    2586              :    insertion point right before or after the statement pointed to by
    2587              :    ITER.  Return an iterator to the point at which the caller might
    2588              :    safely insert the condition statement.
    2589              : 
    2590              :    THEN_BLOCK must be set to the address of an uninitialized instance
    2591              :    of basic_block.  The function will then set *THEN_BLOCK to the
    2592              :    'then block' of the condition statement to be inserted by the
    2593              :    caller.
    2594              : 
    2595              :    If CREATE_THEN_FALLTHRU_EDGE is false, no edge will be created from
    2596              :    *THEN_BLOCK to *FALLTHROUGH_BLOCK.
    2597              : 
    2598              :    Similarly, the function will set *FALLTRHOUGH_BLOCK to the 'else
    2599              :    block' of the condition statement to be inserted by the caller.
    2600              : 
    2601              :    Note that *FALLTHROUGH_BLOCK is a new block that contains the
    2602              :    statements starting from *ITER, and *THEN_BLOCK is a new empty
    2603              :    block.
    2604              : 
    2605              :    *ITER is adjusted to point to always point to the first statement
    2606              :     of the basic block * FALLTHROUGH_BLOCK.  That statement is the
    2607              :     same as what ITER was pointing to prior to calling this function,
    2608              :     if BEFORE_P is true; otherwise, it is its following statement.  */
    2609              : 
    2610              : gimple_stmt_iterator
    2611        23123 : create_cond_insert_point (gimple_stmt_iterator *iter,
    2612              :                           bool before_p,
    2613              :                           bool then_more_likely_p,
    2614              :                           bool create_then_fallthru_edge,
    2615              :                           basic_block *then_block,
    2616              :                           basic_block *fallthrough_block)
    2617              : {
    2618        23123 :   gimple_stmt_iterator gsi = *iter;
    2619              : 
    2620        23123 :   if (!gsi_end_p (gsi) && before_p)
    2621         1275 :     gsi_prev (&gsi);
    2622              : 
    2623        23123 :   basic_block cur_bb = gsi_bb (*iter);
    2624              : 
    2625        23123 :   edge e = split_block (cur_bb, gsi_stmt (gsi));
    2626              : 
    2627              :   /* Get a hold on the 'condition block', the 'then block' and the
    2628              :      'else block'.  */
    2629        23123 :   basic_block cond_bb = e->src;
    2630        23123 :   basic_block fallthru_bb = e->dest;
    2631        23123 :   basic_block then_bb = create_empty_bb (cond_bb);
    2632        23123 :   if (current_loops)
    2633              :     {
    2634        23123 :       add_bb_to_loop (then_bb, cond_bb->loop_father);
    2635        23123 :       loops_state_set (LOOPS_NEED_FIXUP);
    2636              :     }
    2637              : 
    2638              :   /* Set up the newly created 'then block'.  */
    2639        23123 :   e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
    2640        23123 :   profile_probability fallthrough_probability
    2641              :     = then_more_likely_p
    2642        23123 :     ? profile_probability::very_unlikely ()
    2643        23123 :     : profile_probability::very_likely ();
    2644        23123 :   e->probability = fallthrough_probability.invert ();
    2645        23123 :   then_bb->count = e->count ();
    2646        23123 :   if (create_then_fallthru_edge)
    2647         4377 :     make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
    2648              : 
    2649              :   /* Set up the fallthrough basic block.  */
    2650        23123 :   e = find_edge (cond_bb, fallthru_bb);
    2651        23123 :   e->flags = EDGE_FALSE_VALUE;
    2652        23123 :   e->probability = fallthrough_probability;
    2653              : 
    2654              :   /* Update dominance info for the newly created then_bb; note that
    2655              :      fallthru_bb's dominance info has already been updated by
    2656              :      split_bock.  */
    2657        23123 :   if (dom_info_available_p (CDI_DOMINATORS))
    2658        21676 :     set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
    2659              : 
    2660        23123 :   *then_block = then_bb;
    2661        23123 :   *fallthrough_block = fallthru_bb;
    2662        23123 :   *iter = gsi_start_bb (fallthru_bb);
    2663              : 
    2664        23123 :   return gsi_last_bb (cond_bb);
    2665              : }
    2666              : 
    2667              : /* Insert an if condition followed by a 'then block' right before the
    2668              :    statement pointed to by ITER.  The fallthrough block -- which is the
    2669              :    else block of the condition as well as the destination of the
    2670              :    outcoming edge of the 'then block' -- starts with the statement
    2671              :    pointed to by ITER.
    2672              : 
    2673              :    COND is the condition of the if.
    2674              : 
    2675              :    If THEN_MORE_LIKELY_P is true, the probability of the edge to the
    2676              :    'then block' is higher than the probability of the edge to the
    2677              :    fallthrough block.
    2678              : 
    2679              :    Upon completion of the function, *THEN_BB is set to the newly
    2680              :    inserted 'then block' and similarly, *FALLTHROUGH_BB is set to the
    2681              :    fallthrough block.
    2682              : 
    2683              :    *ITER is adjusted to still point to the same statement it was
    2684              :    pointing to initially.  */
    2685              : 
    2686              : static void
    2687            0 : insert_if_then_before_iter (gcond *cond,
    2688              :                             gimple_stmt_iterator *iter,
    2689              :                             bool then_more_likely_p,
    2690              :                             basic_block *then_bb,
    2691              :                             basic_block *fallthrough_bb)
    2692              : {
    2693            0 :   gimple_stmt_iterator cond_insert_point =
    2694            0 :     create_cond_insert_point (iter,
    2695              :                               /*before_p=*/true,
    2696              :                               then_more_likely_p,
    2697              :                               /*create_then_fallthru_edge=*/true,
    2698              :                               then_bb,
    2699              :                               fallthrough_bb);
    2700            0 :   gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
    2701            0 : }
    2702              : 
    2703              : /* Build (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().
    2704              :    If RETURN_ADDRESS is set to true, return memory location instead
    2705              :    of a value in the shadow memory.  */
    2706              : 
    2707              : static tree
    2708        21972 : build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
    2709              :                          tree base_addr, tree shadow_ptr_type,
    2710              :                          bool return_address = false)
    2711              : {
    2712        21972 :   tree t, uintptr_type = TREE_TYPE (base_addr);
    2713        21972 :   tree shadow_type = TREE_TYPE (shadow_ptr_type);
    2714        21972 :   gimple *g;
    2715              : 
    2716        21972 :   t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
    2717        21972 :   g = gimple_build_assign (make_ssa_name (uintptr_type), RSHIFT_EXPR,
    2718              :                            base_addr, t);
    2719        21972 :   gimple_set_location (g, location);
    2720        21972 :   gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2721              : 
    2722        21972 :   if (asan_dynamic_shadow_offset_p ())
    2723            0 :     t = asan_local_shadow_memory_dynamic_address;
    2724              :   else
    2725        21972 :     t = build_int_cst (uintptr_type, asan_shadow_offset ());
    2726        21972 :   g = gimple_build_assign (make_ssa_name (uintptr_type), PLUS_EXPR,
    2727              :                            gimple_assign_lhs (g), t);
    2728        21972 :   gimple_set_location (g, location);
    2729        21972 :   gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2730              : 
    2731        21972 :   g = gimple_build_assign (make_ssa_name (shadow_ptr_type), NOP_EXPR,
    2732              :                            gimple_assign_lhs (g));
    2733        21972 :   gimple_set_location (g, location);
    2734        21972 :   gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2735              : 
    2736        21972 :   if (!return_address)
    2737              :     {
    2738        19876 :       t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
    2739              :                   build_int_cst (shadow_ptr_type, 0));
    2740        19876 :       g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
    2741        19876 :       gimple_set_location (g, location);
    2742        19876 :       gsi_insert_after (gsi, g, GSI_NEW_STMT);
    2743              :     }
    2744              : 
    2745        21972 :   return gimple_assign_lhs (g);
    2746              : }
    2747              : 
    2748              : /* BASE can already be an SSA_NAME; in that case, do not create a
    2749              :    new SSA_NAME for it.  */
    2750              : 
    2751              : static tree
    2752        18556 : maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
    2753              :                        bool before_p)
    2754              : {
    2755        18556 :   STRIP_USELESS_TYPE_CONVERSION (base);
    2756        18556 :   if (TREE_CODE (base) == SSA_NAME)
    2757              :     return base;
    2758        16469 :   gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (base)), base);
    2759        16469 :   gimple_set_location (g, loc);
    2760        16469 :   if (before_p)
    2761        16469 :     gsi_safe_insert_before (iter, g);
    2762              :   else
    2763            0 :     gsi_insert_after (iter, g, GSI_NEW_STMT);
    2764        16469 :   return gimple_assign_lhs (g);
    2765              : }
    2766              : 
    2767              : /* LEN can already have necessary size and precision;
    2768              :    in that case, do not create a new variable.  */
    2769              : 
    2770              : tree
    2771            0 : maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter,
    2772              :                        bool before_p)
    2773              : {
    2774            0 :   if (ptrofftype_p (len))
    2775              :     return len;
    2776            0 :   gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    2777              :                                    NOP_EXPR, len);
    2778            0 :   gimple_set_location (g, loc);
    2779            0 :   if (before_p)
    2780            0 :     gsi_safe_insert_before (iter, g);
    2781              :   else
    2782            0 :     gsi_insert_after (iter, g, GSI_NEW_STMT);
    2783            0 :   return gimple_assign_lhs (g);
    2784              : }
    2785              : 
    2786              : /* Instrument the memory access instruction BASE.  Insert new
    2787              :    statements before or after ITER.
    2788              : 
    2789              :    Note that the memory access represented by BASE can be either an
    2790              :    SSA_NAME, or a non-SSA expression.  LOCATION is the source code
    2791              :    location.  IS_STORE is TRUE for a store, FALSE for a load.
    2792              :    BEFORE_P is TRUE for inserting the instrumentation code before
    2793              :    ITER, FALSE for inserting it after ITER.  IS_SCALAR_ACCESS is TRUE
    2794              :    for a scalar memory access and FALSE for memory region access.
    2795              :    NON_ZERO_P is TRUE if memory region is guaranteed to have non-zero
    2796              :    length.  ALIGN tells alignment of accessed memory object.
    2797              : 
    2798              :    START_INSTRUMENTED and END_INSTRUMENTED are TRUE if start/end of
    2799              :    memory region have already been instrumented.
    2800              : 
    2801              :    If BEFORE_P is TRUE, *ITER is arranged to still point to the
    2802              :    statement it was pointing to prior to calling this function,
    2803              :    otherwise, it points to the statement logically following it.  */
    2804              : 
    2805              : static void
    2806        18556 : build_check_stmt (location_t loc, tree base, tree len,
    2807              :                   HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
    2808              :                   bool is_non_zero_len, bool before_p, bool is_store,
    2809              :                   bool is_scalar_access, unsigned int align = 0)
    2810              : {
    2811        18556 :   gimple *g;
    2812              : 
    2813        18556 :   gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
    2814        18556 :   gcc_assert (size_in_bytes == -1 || size_in_bytes >= 1);
    2815              : 
    2816        18556 :   base = unshare_expr (base);
    2817        18556 :   base = maybe_create_ssa_name (loc, base, iter, before_p);
    2818              : 
    2819        18556 :   if (len)
    2820              :     {
    2821            0 :       len = unshare_expr (len);
    2822            0 :       len = maybe_cast_to_ptrmode (loc, len, iter, before_p);
    2823              :     }
    2824              :   else
    2825              :     {
    2826        18556 :       gcc_assert (size_in_bytes != -1);
    2827        18556 :       len = build_int_cst (pointer_sized_int_node, size_in_bytes);
    2828              :     }
    2829              : 
    2830        18556 :   if (size_in_bytes > 1)
    2831              :     {
    2832        15811 :       if ((size_in_bytes & (size_in_bytes - 1)) != 0
    2833        15497 :           || size_in_bytes > 16)
    2834              :         is_scalar_access = false;
    2835        15134 :       else if (align && align < size_in_bytes * BITS_PER_UNIT)
    2836              :         {
    2837              :           /* On non-strict alignment targets, if
    2838              :              16-byte access is just 8-byte aligned,
    2839              :              this will result in misaligned shadow
    2840              :              memory 2 byte load, but otherwise can
    2841              :              be handled using one read.  */
    2842          282 :           if (size_in_bytes != 16
    2843              :               || STRICT_ALIGNMENT
    2844          149 :               || align < 8 * BITS_PER_UNIT)
    2845        18556 :             is_scalar_access = false;
    2846              :         }
    2847              :     }
    2848              : 
    2849        18556 :   HOST_WIDE_INT flags = 0;
    2850        18556 :   if (is_store)
    2851         9383 :     flags |= ASAN_CHECK_STORE;
    2852        18556 :   if (is_non_zero_len)
    2853        18556 :     flags |= ASAN_CHECK_NON_ZERO_LEN;
    2854        18556 :   if (is_scalar_access)
    2855        17737 :     flags |= ASAN_CHECK_SCALAR_ACCESS;
    2856              : 
    2857        18556 :   enum internal_fn fn = hwassist_sanitize_p ()
    2858        18556 :     ? IFN_HWASAN_CHECK
    2859        18180 :     : IFN_ASAN_CHECK;
    2860              : 
    2861        18556 :   g = gimple_build_call_internal (fn, 4,
    2862        18556 :                                   build_int_cst (integer_type_node, flags),
    2863              :                                   base, len,
    2864              :                                   build_int_cst (integer_type_node,
    2865        18556 :                                                  align / BITS_PER_UNIT));
    2866        18556 :   gimple_set_location (g, loc);
    2867        18556 :   if (before_p)
    2868        18556 :     gsi_safe_insert_before (iter, g);
    2869              :   else
    2870              :     {
    2871            0 :       gsi_insert_after (iter, g, GSI_NEW_STMT);
    2872            0 :       gsi_next (iter);
    2873              :     }
    2874        18556 : }
    2875              : 
    2876              : /* If T represents a memory access, add instrumentation code before ITER.
    2877              :    LOCATION is source code location.
    2878              :    IS_STORE is either TRUE (for a store) or FALSE (for a load).  */
    2879              : 
    2880              : static void
    2881        26425 : instrument_derefs (gimple_stmt_iterator *iter, tree t,
    2882              :                    location_t location, bool is_store)
    2883              : {
    2884        26425 :   if (is_store && !(asan_instrument_writes () || hwasan_instrument_writes ()))
    2885         7772 :     return;
    2886        26383 :   if (!is_store && !(asan_instrument_reads () || hwasan_instrument_reads ()))
    2887              :     return;
    2888              : 
    2889        26327 :   tree type, base;
    2890        26327 :   HOST_WIDE_INT size_in_bytes;
    2891        26327 :   if (location == UNKNOWN_LOCATION)
    2892          377 :     location = EXPR_LOCATION (t);
    2893              : 
    2894        26327 :   type = TREE_TYPE (t);
    2895        26327 :   switch (TREE_CODE (t))
    2896              :     {
    2897        26135 :     case ARRAY_REF:
    2898        26135 :     case COMPONENT_REF:
    2899        26135 :     case INDIRECT_REF:
    2900        26135 :     case MEM_REF:
    2901        26135 :     case VAR_DECL:
    2902        26135 :     case BIT_FIELD_REF:
    2903        26135 :       break;
    2904              :       /* FALLTHRU */
    2905              :     default:
    2906              :       return;
    2907              :     }
    2908              : 
    2909        26135 :   size_in_bytes = int_size_in_bytes (type);
    2910        26135 :   if (size_in_bytes <= 0)
    2911              :     return;
    2912              : 
    2913        26135 :   poly_int64 bitsize, bitpos;
    2914        26135 :   tree offset;
    2915        26135 :   machine_mode mode;
    2916        26135 :   int unsignedp, reversep, volatilep = 0;
    2917        26135 :   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
    2918              :                                     &unsignedp, &reversep, &volatilep);
    2919              : 
    2920        26135 :   if (TREE_CODE (t) == COMPONENT_REF
    2921        26135 :       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
    2922              :     {
    2923           72 :       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
    2924           72 :       instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr),
    2925           72 :                                        TREE_OPERAND (t, 0), repr,
    2926           72 :                                        TREE_OPERAND (t, 2)),
    2927              :                          location, is_store);
    2928           72 :       return;
    2929              :     }
    2930              : 
    2931        26063 :   if (!multiple_p (bitpos, BITS_PER_UNIT)
    2932        26063 :       || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
    2933              :     return;
    2934              : 
    2935        26063 :   if (VAR_P (inner) && DECL_HARD_REGISTER (inner))
    2936              :     return;
    2937              : 
    2938              :   /* Accesses to non-generic address-spaces should not be instrumented.  */
    2939        26057 :   if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (inner))))
    2940              :     return;
    2941              : 
    2942        26047 :   poly_int64 decl_size;
    2943        26047 :   if ((VAR_P (inner)
    2944        11086 :        || (TREE_CODE (inner) == RESULT_DECL
    2945          145 :            && !aggregate_value_p (inner, current_function_decl)))
    2946        14961 :       && offset == NULL_TREE
    2947        14371 :       && DECL_SIZE (inner)
    2948        14371 :       && poly_int_tree_p (DECL_SIZE (inner), &decl_size)
    2949        52094 :       && known_subrange_p (bitpos, bitsize, 0, decl_size))
    2950              :     {
    2951        14352 :       if (VAR_P (inner) && DECL_THREAD_LOCAL_P (inner))
    2952              :         return;
    2953              :       /* If we're not sanitizing globals and we can tell statically that this
    2954              :          access is inside a global variable, then there's no point adding
    2955              :          instrumentation to check the access.  N.b. hwasan currently never
    2956              :          sanitizes globals.  */
    2957        28528 :       if ((hwassist_sanitize_p () || !param_asan_globals)
    2958        14430 :           && is_global_var (inner))
    2959              :         return;
    2960        14166 :       if (!TREE_STATIC (inner))
    2961              :         {
    2962              :           /* Automatic vars in the current function will be always
    2963              :              accessible.  */
    2964         9285 :           if (decl_function_context (inner) == current_function_decl
    2965         9285 :               && (!asan_sanitize_use_after_scope ()
    2966         8493 :                   || !TREE_ADDRESSABLE (inner)))
    2967              :             return;
    2968              :         }
    2969              :       /* Always instrument external vars, they might be dynamically
    2970              :          initialized.  */
    2971         4881 :       else if (!DECL_EXTERNAL (inner))
    2972              :         {
    2973              :           /* For static vars if they are known not to be dynamically
    2974              :              initialized, they will be always accessible.  */
    2975         4872 :           varpool_node *vnode = varpool_node::get (inner);
    2976         4872 :           if (vnode && !vnode->dynamically_initialized)
    2977              :             return;
    2978              :         }
    2979              :     }
    2980              : 
    2981        18653 :   if (DECL_P (inner)
    2982         7738 :       && decl_function_context (inner) == current_function_decl
    2983        25697 :       && !TREE_ADDRESSABLE (inner))
    2984          110 :     mark_addressable (inner);
    2985              : 
    2986        18653 :   base = build_fold_addr_expr (t);
    2987        18653 :   if (!has_mem_ref_been_instrumented (base, size_in_bytes))
    2988              :     {
    2989        18556 :       unsigned int align = get_object_alignment (t);
    2990        18556 :       build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter,
    2991              :                         /*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true,
    2992              :                         is_store, /*is_scalar_access*/true, align);
    2993        18556 :       update_mem_ref_hash_table (base, size_in_bytes);
    2994        18556 :       update_mem_ref_hash_table (t, size_in_bytes);
    2995              :     }
    2996              : 
    2997              : }
    2998              : 
    2999              : /*  Insert a memory reference into the hash table if access length
    3000              :     can be determined in compile time.  */
    3001              : 
    3002              : static void
    3003         1574 : maybe_update_mem_ref_hash_table (tree base, tree len)
    3004              : {
    3005         1640 :   if (!POINTER_TYPE_P (TREE_TYPE (base))
    3006         1640 :       || !INTEGRAL_TYPE_P (TREE_TYPE (len)))
    3007              :     return;
    3008              : 
    3009         1574 :   HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
    3010              : 
    3011          386 :   if (size_in_bytes != -1)
    3012          386 :     update_mem_ref_hash_table (base, size_in_bytes);
    3013              : }
    3014              : 
    3015              : /* Instrument an access to a contiguous memory region that starts at
    3016              :    the address pointed to by BASE, over a length of LEN (expressed in
    3017              :    the sizeof (*BASE) bytes).  ITER points to the instruction before
    3018              :    which the instrumentation instructions must be inserted.  LOCATION
    3019              :    is the source location that the instrumentation instructions must
    3020              :    have.  If IS_STORE is true, then the memory access is a store;
    3021              :    otherwise, it's a load.  */
    3022              : 
    3023              : static void
    3024            0 : instrument_mem_region_access (tree base, tree len,
    3025              :                               gimple_stmt_iterator *iter,
    3026              :                               location_t location, bool is_store)
    3027              : {
    3028            0 :   if (!POINTER_TYPE_P (TREE_TYPE (base))
    3029            0 :       || !INTEGRAL_TYPE_P (TREE_TYPE (len))
    3030            0 :       || integer_zerop (len))
    3031              :     return;
    3032              : 
    3033            0 :   HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
    3034              : 
    3035            0 :   if ((size_in_bytes == -1)
    3036            0 :       || !has_mem_ref_been_instrumented (base, size_in_bytes))
    3037              :     {
    3038            0 :       build_check_stmt (location, base, len, size_in_bytes, iter,
    3039              :                         /*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true,
    3040              :                         is_store, /*is_scalar_access*/false, /*align*/0);
    3041              :     }
    3042              : 
    3043            0 :   maybe_update_mem_ref_hash_table (base, len);
    3044            0 :   *iter = gsi_for_stmt (gsi_stmt (*iter));
    3045              : }
    3046              : 
    3047              : /* Instrument the call to a built-in memory access function that is
    3048              :    pointed to by the iterator ITER.
    3049              : 
    3050              :    Upon completion, return TRUE iff *ITER has been advanced to the
    3051              :    statement following the one it was originally pointing to.  */
    3052              : 
    3053              : static bool
    3054         4409 : instrument_builtin_call (gimple_stmt_iterator *iter)
    3055              : {
    3056         4433 :   if (!(asan_memintrin () || hwasan_memintrin ()
    3057           24 :         || memtag_memintrin ()))
    3058              :     return false;
    3059              : 
    3060         4385 :   bool iter_advanced_p = false;
    3061         4385 :   gcall *call = as_a <gcall *> (gsi_stmt (*iter));
    3062              : 
    3063         4385 :   gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
    3064              : 
    3065         4385 :   location_t loc = gimple_location (call);
    3066              : 
    3067         4385 :   asan_mem_ref src0, src1, dest;
    3068         4385 :   asan_mem_ref_init (&src0, NULL, 1);
    3069         4385 :   asan_mem_ref_init (&src1, NULL, 1);
    3070         4385 :   asan_mem_ref_init (&dest, NULL, 1);
    3071              : 
    3072         4385 :   tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
    3073         4385 :   bool src0_is_store = false, src1_is_store = false, dest_is_store = false,
    3074         4385 :     dest_is_deref = false, intercepted_p = true;
    3075              : 
    3076         4385 :   if (get_mem_refs_of_builtin_call (call,
    3077              :                                     &src0, &src0_len, &src0_is_store,
    3078              :                                     &src1, &src1_len, &src1_is_store,
    3079              :                                     &dest, &dest_len, &dest_is_store,
    3080              :                                     &dest_is_deref, &intercepted_p, iter))
    3081              :     {
    3082          927 :       if (dest_is_deref)
    3083              :         {
    3084           28 :           instrument_derefs (iter, dest.start, loc, dest_is_store);
    3085           28 :           gsi_next (iter);
    3086           28 :           iter_advanced_p = true;
    3087              :         }
    3088          899 :       else if (!intercepted_p
    3089            0 :                && (src0_len || src1_len || dest_len))
    3090              :         {
    3091            0 :           if (src0.start != NULL_TREE)
    3092            0 :             instrument_mem_region_access (src0.start, src0_len,
    3093              :                                           iter, loc, /*is_store=*/false);
    3094            0 :           if (src1.start != NULL_TREE)
    3095            0 :             instrument_mem_region_access (src1.start, src1_len,
    3096              :                                           iter, loc, /*is_store=*/false);
    3097            0 :           if (dest.start != NULL_TREE)
    3098            0 :             instrument_mem_region_access (dest.start, dest_len,
    3099              :                                           iter, loc, /*is_store=*/true);
    3100              : 
    3101            0 :           *iter = gsi_for_stmt (call);
    3102            0 :           gsi_next (iter);
    3103            0 :           iter_advanced_p = true;
    3104              :         }
    3105              :       else
    3106              :         {
    3107          899 :           if (src0.start != NULL_TREE)
    3108          711 :             maybe_update_mem_ref_hash_table (src0.start, src0_len);
    3109          899 :           if (src1.start != NULL_TREE)
    3110           50 :             maybe_update_mem_ref_hash_table (src1.start, src1_len);
    3111          899 :           if (dest.start != NULL_TREE)
    3112          813 :             maybe_update_mem_ref_hash_table (dest.start, dest_len);
    3113              :         }
    3114              :     }
    3115              :   return iter_advanced_p;
    3116              : }
    3117              : 
    3118              : /*  Instrument the assignment statement ITER if it is subject to
    3119              :     instrumentation.  Return TRUE iff instrumentation actually
    3120              :     happened.  In that case, the iterator ITER is advanced to the next
    3121              :     logical expression following the one initially pointed to by ITER,
    3122              :     and the relevant memory reference that which access has been
    3123              :     instrumented is added to the memory references hash table.  */
    3124              : 
    3125              : static bool
    3126        28150 : maybe_instrument_assignment (gimple_stmt_iterator *iter)
    3127              : {
    3128        28150 :   gimple *s = gsi_stmt (*iter);
    3129              : 
    3130        28150 :   gcc_assert (gimple_assign_single_p (s));
    3131              : 
    3132        28150 :   tree ref_expr = NULL_TREE;
    3133        28150 :   bool is_store, is_instrumented = false;
    3134              : 
    3135        28150 :   if (gimple_store_p (s))
    3136              :     {
    3137        12594 :       ref_expr = gimple_assign_lhs (s);
    3138        12594 :       is_store = true;
    3139        12594 :       instrument_derefs (iter, ref_expr,
    3140              :                          gimple_location (s),
    3141              :                          is_store);
    3142        12594 :       is_instrumented = true;
    3143              :     }
    3144              : 
    3145        28150 :   if (gimple_assign_load_p (s))
    3146              :     {
    3147        13570 :       ref_expr = gimple_assign_rhs1 (s);
    3148        13570 :       is_store = false;
    3149        13570 :       instrument_derefs (iter, ref_expr,
    3150              :                          gimple_location (s),
    3151              :                          is_store);
    3152        13570 :       is_instrumented = true;
    3153              :     }
    3154              : 
    3155        28150 :   if (is_instrumented)
    3156        25609 :     gsi_next (iter);
    3157              : 
    3158        28150 :   return is_instrumented;
    3159              : }
    3160              : 
    3161              : /* Instrument the function call pointed to by the iterator ITER, if it
    3162              :    is subject to instrumentation.  At the moment, the only function
    3163              :    calls that are instrumented are some built-in functions that access
    3164              :    memory.  Look at instrument_builtin_call to learn more.
    3165              : 
    3166              :    Upon completion return TRUE iff *ITER was advanced to the statement
    3167              :    following the one it was originally pointing to.  */
    3168              : 
    3169              : static bool
    3170        22776 : maybe_instrument_call (gimple_stmt_iterator *iter)
    3171              : {
    3172        22776 :   gimple *stmt = gsi_stmt (*iter);
    3173        22776 :   bool is_builtin = gimple_call_builtin_p (stmt, BUILT_IN_NORMAL);
    3174              : 
    3175        22776 :   if (is_builtin && instrument_builtin_call (iter))
    3176              :     return true;
    3177              : 
    3178        22748 :   if (gimple_call_noreturn_p (stmt))
    3179              :     {
    3180         1136 :       if (is_builtin)
    3181              :         {
    3182          320 :           tree callee = gimple_call_fndecl (stmt);
    3183          320 :           switch (DECL_FUNCTION_CODE (callee))
    3184              :             {
    3185              :             case BUILT_IN_UNREACHABLE:
    3186              :             case BUILT_IN_UNREACHABLE_TRAP:
    3187              :             case BUILT_IN_TRAP:
    3188              :             case BUILT_IN_ASAN_REPORT_LOAD1:
    3189              :             case BUILT_IN_ASAN_REPORT_LOAD2:
    3190              :             case BUILT_IN_ASAN_REPORT_LOAD4:
    3191              :             case BUILT_IN_ASAN_REPORT_LOAD8:
    3192              :             case BUILT_IN_ASAN_REPORT_LOAD16:
    3193              :             case BUILT_IN_ASAN_REPORT_LOAD_N:
    3194              :             case BUILT_IN_ASAN_REPORT_STORE1:
    3195              :             case BUILT_IN_ASAN_REPORT_STORE2:
    3196              :             case BUILT_IN_ASAN_REPORT_STORE4:
    3197              :             case BUILT_IN_ASAN_REPORT_STORE8:
    3198              :             case BUILT_IN_ASAN_REPORT_STORE16:
    3199              :             case BUILT_IN_ASAN_REPORT_STORE_N:
    3200              :               /* Don't instrument these.  */
    3201              :               return false;
    3202              :             default:
    3203              :               break;
    3204              :             }
    3205              :         }
    3206          956 :       if (gimple_call_internal_p (stmt, IFN_ABNORMAL_DISPATCHER))
    3207              :         /* Don't instrument this.  */
    3208              :         return false;
    3209              :       /* If a function does not return, then we must handle clearing up the
    3210              :          shadow stack accordingly.  For ASAN we can simply set the entire stack
    3211              :          to "valid" for accesses by setting the shadow space to 0 and all
    3212              :          accesses will pass checks.  That means that some bad accesses may be
    3213              :          missed, but we will not report any false positives.
    3214              : 
    3215              :          This is not possible for HWASAN.  Since there is no "always valid" tag
    3216              :          we can not set any space to "always valid".  If we were to clear the
    3217              :          entire shadow stack then code resuming from `longjmp` or a caught
    3218              :          exception would trigger false positives when correctly accessing
    3219              :          variables on the stack.  Hence we need to handle things like
    3220              :          `longjmp`, thread exit, and exceptions in a different way.  These
    3221              :          problems must be handled externally to the compiler, e.g. in the
    3222              :          language runtime.  */
    3223          871 :       if (! hwassist_sanitize_p ())
    3224              :         {
    3225          837 :           tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
    3226          837 :           gimple *g = gimple_build_call (decl, 0);
    3227          837 :           gimple_set_location (g, gimple_location (stmt));
    3228          837 :           gsi_safe_insert_before (iter, g);
    3229              :         }
    3230              :     }
    3231              : 
    3232        22483 :   bool instrumented = false;
    3233        22483 :   if (gimple_store_p (stmt)
    3234        22483 :       && (gimple_call_builtin_p (stmt)
    3235          288 :           || gimple_call_internal_p (stmt)
    3236          287 :           || !aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
    3237          287 :                                  gimple_call_fntype (stmt))))
    3238              :     {
    3239           62 :       tree ref_expr = gimple_call_lhs (stmt);
    3240           62 :       instrument_derefs (iter, ref_expr,
    3241              :                          gimple_location (stmt),
    3242              :                          /*is_store=*/true);
    3243              : 
    3244           62 :       instrumented = true;
    3245              :     }
    3246              : 
    3247              :   /* Walk through gimple_call arguments and check them id needed.  */
    3248        22483 :   unsigned args_num = gimple_call_num_args (stmt);
    3249        92916 :   for (unsigned i = 0; i < args_num; ++i)
    3250              :     {
    3251        47950 :       tree arg = gimple_call_arg (stmt, i);
    3252              :       /* If ARG is not a non-aggregate register variable, compiler in general
    3253              :          creates temporary for it and pass it as argument to gimple call.
    3254              :          But in some cases, e.g. when we pass by value a small structure that
    3255              :          fits to register, compiler can avoid extra overhead by pulling out
    3256              :          these temporaries.  In this case, we should check the argument.  */
    3257        47950 :       if (!is_gimple_reg (arg) && !is_gimple_min_invariant (arg))
    3258              :         {
    3259           99 :           instrument_derefs (iter, arg,
    3260              :                              gimple_location (stmt),
    3261              :                              /*is_store=*/false);
    3262           99 :           instrumented = true;
    3263              :         }
    3264              :     }
    3265        22483 :   if (instrumented)
    3266          155 :     gsi_next (iter);
    3267              :   return instrumented;
    3268              : }
    3269              : 
    3270              : /* Walk each instruction of all basic block and instrument those that
    3271              :    represent memory references: loads, stores, or function calls.
    3272              :    In a given basic block, this function avoids instrumenting memory
    3273              :    references that have already been instrumented.  */
    3274              : 
    3275              : static void
    3276         6572 : transform_statements (void)
    3277              : {
    3278         6572 :   basic_block bb, last_bb = NULL;
    3279         6572 :   gimple_stmt_iterator i;
    3280         6572 :   int saved_last_basic_block = last_basic_block_for_fn (cfun);
    3281              : 
    3282        38074 :   FOR_EACH_BB_FN (bb, cfun)
    3283              :     {
    3284        31502 :       basic_block prev_bb = bb;
    3285              : 
    3286        31502 :       if (bb->index >= saved_last_basic_block) continue;
    3287              : 
    3288              :       /* Flush the mem ref hash table, if current bb doesn't have
    3289              :          exactly one predecessor, or if that predecessor (skipping
    3290              :          over asan created basic blocks) isn't the last processed
    3291              :          basic block.  Thus we effectively flush on extended basic
    3292              :          block boundaries.  */
    3293        31500 :       while (single_pred_p (prev_bb))
    3294              :         {
    3295        25551 :           prev_bb = single_pred (prev_bb);
    3296        25551 :           if (prev_bb->index < saved_last_basic_block)
    3297              :             break;
    3298              :         }
    3299        31494 :       if (prev_bb != last_bb)
    3300        21242 :         empty_mem_ref_hash_table ();
    3301        31494 :       last_bb = bb;
    3302              : 
    3303       233106 :       for (i = gsi_start_bb (bb); !gsi_end_p (i);)
    3304              :         {
    3305       170118 :           gimple *s = gsi_stmt (i);
    3306              : 
    3307       170118 :           if (has_stmt_been_instrumented_p (s))
    3308         1028 :             gsi_next (&i);
    3309       169090 :           else if (gimple_assign_single_p (s)
    3310        29115 :                    && !gimple_clobber_p (s)
    3311       197240 :                    && maybe_instrument_assignment (&i))
    3312              :             /*  Nothing to do as maybe_instrument_assignment advanced
    3313              :                 the iterator I.  */;
    3314       143481 :           else if (is_gimple_call (s) && maybe_instrument_call (&i))
    3315              :             /*  Nothing to do as maybe_instrument_call
    3316              :                 advanced the iterator I.  */;
    3317              :           else
    3318              :             {
    3319              :               /* No instrumentation happened.
    3320              : 
    3321              :                  If the current instruction is a function call that
    3322              :                  might free something, let's forget about the memory
    3323              :                  references that got instrumented.  Otherwise we might
    3324              :                  miss some instrumentation opportunities.  Do the same
    3325              :                  for a ASAN_MARK poisoning internal function.  */
    3326       143298 :               if (is_gimple_call (s)
    3327       143298 :                   && (!nonfreeing_call_p (s)
    3328         6524 :                       || asan_mark_p (s, ASAN_MARK_POISON)))
    3329        16069 :                 empty_mem_ref_hash_table ();
    3330              : 
    3331       143298 :               gsi_next (&i);
    3332              :             }
    3333              :         }
    3334              :     }
    3335         6572 :   free_mem_ref_resources ();
    3336         6572 : }
    3337              : 
    3338              : /* Build
    3339              :    __asan_before_dynamic_init (module_name)
    3340              :    or
    3341              :    __asan_after_dynamic_init ()
    3342              :    call.  */
    3343              : 
    3344              : tree
    3345           42 : asan_dynamic_init_call (bool after_p)
    3346              : {
    3347           42 :   if (shadow_ptr_types[0] == NULL_TREE)
    3348           21 :     asan_init_shadow_ptr_types ();
    3349              : 
    3350           63 :   tree fn = builtin_decl_implicit (after_p
    3351              :                                    ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT
    3352              :                                    : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT);
    3353           42 :   tree module_name_cst = NULL_TREE;
    3354           42 :   if (!after_p)
    3355              :     {
    3356           21 :       pretty_printer module_name_pp;
    3357           21 :       pp_string (&module_name_pp, main_input_filename);
    3358              : 
    3359           21 :       module_name_cst = asan_pp_string (&module_name_pp);
    3360           21 :       module_name_cst = fold_convert (const_ptr_type_node,
    3361              :                                       module_name_cst);
    3362           21 :     }
    3363              : 
    3364           42 :   return build_call_expr (fn, after_p ? 0 : 1, module_name_cst);
    3365              : }
    3366              : 
    3367              : /* Build
    3368              :    struct __asan_global
    3369              :    {
    3370              :      const void *__beg;
    3371              :      uptr __size;
    3372              :      uptr __size_with_redzone;
    3373              :      const void *__name;
    3374              :      const void *__module_name;
    3375              :      uptr __has_dynamic_init;
    3376              :      __asan_global_source_location *__location;
    3377              :      char *__odr_indicator;
    3378              :    } type.  */
    3379              : 
    3380              : static tree
    3381         1092 : asan_global_struct (void)
    3382              : {
    3383         1092 :   static const char *field_names[]
    3384              :     = { "__beg", "__size", "__size_with_redzone",
    3385              :         "__name", "__module_name", "__has_dynamic_init", "__location",
    3386              :         "__odr_indicator" };
    3387         1092 :   tree fields[ARRAY_SIZE (field_names)], ret;
    3388         1092 :   unsigned i;
    3389              : 
    3390         1092 :   ret = make_node (RECORD_TYPE);
    3391        10920 :   for (i = 0; i < ARRAY_SIZE (field_names); i++)
    3392              :     {
    3393         8736 :       fields[i]
    3394         8736 :         = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
    3395              :                       get_identifier (field_names[i]),
    3396         8736 :                       (i == 0 || i == 3) ? const_ptr_type_node
    3397              :                       : pointer_sized_int_node);
    3398         8736 :       DECL_CONTEXT (fields[i]) = ret;
    3399         8736 :       if (i)
    3400         7644 :         DECL_CHAIN (fields[i - 1]) = fields[i];
    3401              :     }
    3402         1092 :   tree type_decl = build_decl (input_location, TYPE_DECL,
    3403              :                                get_identifier ("__asan_global"), ret);
    3404         1092 :   DECL_IGNORED_P (type_decl) = 1;
    3405         1092 :   DECL_ARTIFICIAL (type_decl) = 1;
    3406         1092 :   TYPE_FIELDS (ret) = fields[0];
    3407         1092 :   TYPE_NAME (ret) = type_decl;
    3408         1092 :   TYPE_STUB_DECL (ret) = type_decl;
    3409         1092 :   TYPE_ARTIFICIAL (ret) = 1;
    3410         1092 :   layout_type (ret);
    3411         1092 :   return ret;
    3412              : }
    3413              : 
    3414              : /* Create and return odr indicator symbol for DECL.
    3415              :    TYPE is __asan_global struct type as returned by asan_global_struct.  */
    3416              : 
    3417              : static tree
    3418         1266 : create_odr_indicator (tree decl, tree type)
    3419              : {
    3420         1266 :   char *name;
    3421         1266 :   tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
    3422         1266 :   tree decl_name
    3423         1266 :     = (HAS_DECL_ASSEMBLER_NAME_P (decl) ? DECL_ASSEMBLER_NAME (decl)
    3424            0 :                                         : DECL_NAME (decl));
    3425              :   /* DECL_NAME theoretically might be NULL.  Bail out with 0 in this case.  */
    3426         1266 :   if (decl_name == NULL_TREE)
    3427            0 :     return build_int_cst (uptr, 0);
    3428         1266 :   const char *dname = IDENTIFIER_POINTER (decl_name);
    3429         1266 :   if (HAS_DECL_ASSEMBLER_NAME_P (decl))
    3430         1266 :     dname = targetm.strip_name_encoding (dname);
    3431         1266 :   size_t len = strlen (dname) + sizeof ("__odr_asan_");
    3432         1266 :   name = XALLOCAVEC (char, len);
    3433         1266 :   snprintf (name, len, "__odr_asan_%s", dname);
    3434              : #ifndef NO_DOT_IN_LABEL
    3435         1266 :   name[sizeof ("__odr_asan") - 1] = '.';
    3436              : #elif !defined(NO_DOLLAR_IN_LABEL)
    3437              :   name[sizeof ("__odr_asan") - 1] = '$';
    3438              : #endif
    3439         1266 :   tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name),
    3440              :                          char_type_node);
    3441         1266 :   TREE_ADDRESSABLE (var) = 1;
    3442         1266 :   TREE_READONLY (var) = 0;
    3443         1266 :   TREE_THIS_VOLATILE (var) = 1;
    3444         1266 :   DECL_ARTIFICIAL (var) = 1;
    3445         1266 :   DECL_IGNORED_P (var) = 1;
    3446         1266 :   TREE_STATIC (var) = 1;
    3447         1266 :   TREE_PUBLIC (var) = 1;
    3448         1266 :   DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
    3449         1266 :   DECL_VISIBILITY_SPECIFIED (var) = DECL_VISIBILITY_SPECIFIED (decl);
    3450              : 
    3451         1266 :   TREE_USED (var) = 1;
    3452         1266 :   tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
    3453              :                                     build_int_cst (unsigned_type_node, 0));
    3454         1266 :   TREE_CONSTANT (ctor) = 1;
    3455         1266 :   TREE_STATIC (ctor) = 1;
    3456         1266 :   DECL_INITIAL (var) = ctor;
    3457         1266 :   DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("asan odr indicator"),
    3458         1266 :                                      NULL, DECL_ATTRIBUTES (var));
    3459         1266 :   make_decl_rtl (var);
    3460         1266 :   varpool_node::finalize_decl (var);
    3461         1266 :   return fold_convert (uptr, build_fold_addr_expr (var));
    3462              : }
    3463              : 
    3464              : /* Return true if DECL, a global var, might be overridden and needs
    3465              :    an additional odr indicator symbol.  */
    3466              : 
    3467              : static bool
    3468         4158 : asan_needs_odr_indicator_p (tree decl)
    3469              : {
    3470              :   /* Don't emit ODR indicators for kernel because:
    3471              :      a) Kernel is written in C thus doesn't need ODR indicators.
    3472              :      b) Some kernel code may have assumptions about symbols containing specific
    3473              :         patterns in their names.  Since ODR indicators contain original names
    3474              :         of symbols they are emitted for, these assumptions would be broken for
    3475              :         ODR indicator symbols.  */
    3476         4158 :   return (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS)
    3477         4158 :           && !DECL_ARTIFICIAL (decl)
    3478         1678 :           && !DECL_WEAK (decl)
    3479         5836 :           && TREE_PUBLIC (decl));
    3480              : }
    3481              : 
    3482              : /* Append description of a single global DECL into vector V.
    3483              :    TYPE is __asan_global struct type as returned by asan_global_struct.  */
    3484              : 
    3485              : static void
    3486         4158 : asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
    3487              : {
    3488         4158 :   tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
    3489         4158 :   unsigned HOST_WIDE_INT size;
    3490         4158 :   tree str_cst, module_name_cst, refdecl = decl;
    3491         4158 :   vec<constructor_elt, va_gc> *vinner = NULL;
    3492              : 
    3493         4158 :   pretty_printer asan_pp, module_name_pp;
    3494              : 
    3495         4158 :   if (DECL_NAME (decl))
    3496         4158 :     pp_tree_identifier (&asan_pp, DECL_NAME (decl));
    3497              :   else
    3498            0 :     pp_string (&asan_pp, "<unknown>");
    3499         4158 :   str_cst = asan_pp_string (&asan_pp);
    3500              : 
    3501         4158 :   if (!in_lto_p)
    3502         3734 :     pp_string (&module_name_pp, main_input_filename);
    3503              :   else
    3504              :     {
    3505          424 :       const_tree tu = get_ultimate_context ((const_tree)decl);
    3506          424 :       if (tu != NULL_TREE)
    3507          291 :         pp_string (&module_name_pp, IDENTIFIER_POINTER (DECL_NAME (tu)));
    3508              :       else
    3509          133 :         pp_string (&module_name_pp, aux_base_name);
    3510              :     }
    3511              : 
    3512         4158 :   module_name_cst = asan_pp_string (&module_name_pp);
    3513              : 
    3514         4158 :   if (asan_needs_local_alias (decl))
    3515              :     {
    3516            0 :       char buf[20];
    3517            0 :       ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", vec_safe_length (v) + 1);
    3518            0 :       refdecl = build_decl (DECL_SOURCE_LOCATION (decl),
    3519            0 :                             VAR_DECL, get_identifier (buf), TREE_TYPE (decl));
    3520            0 :       TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
    3521            0 :       TREE_READONLY (refdecl) = TREE_READONLY (decl);
    3522            0 :       TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
    3523            0 :       DECL_NOT_GIMPLE_REG_P (refdecl) = DECL_NOT_GIMPLE_REG_P (decl);
    3524            0 :       DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
    3525            0 :       DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
    3526            0 :       TREE_STATIC (refdecl) = 1;
    3527            0 :       TREE_PUBLIC (refdecl) = 0;
    3528            0 :       TREE_USED (refdecl) = 1;
    3529            0 :       assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
    3530              :     }
    3531              : 
    3532         4158 :   tree odr_indicator_ptr
    3533         4158 :     = (asan_needs_odr_indicator_p (decl) ? create_odr_indicator (decl, type)
    3534         2892 :                                          : build_int_cst (uptr, 0));
    3535         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
    3536              :                           fold_convert (const_ptr_type_node,
    3537              :                                         build_fold_addr_expr (refdecl)));
    3538         4158 :   size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
    3539         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
    3540         4158 :   size += asan_red_zone_size (size);
    3541         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
    3542         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
    3543              :                           fold_convert (const_ptr_type_node, str_cst));
    3544         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
    3545              :                           fold_convert (const_ptr_type_node, module_name_cst));
    3546         4158 :   varpool_node *vnode = varpool_node::get (decl);
    3547         4158 :   int has_dynamic_init = 0;
    3548              :   /* FIXME: Enable initialization order fiasco detection in LTO mode once
    3549              :      proper fix for PR 79061 will be applied.  */
    3550         4158 :   if (!in_lto_p)
    3551         3734 :     has_dynamic_init = vnode ? vnode->dynamically_initialized : 0;
    3552         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
    3553              :                           build_int_cst (uptr, has_dynamic_init));
    3554         4158 :   tree locptr = NULL_TREE;
    3555         4158 :   location_t loc = DECL_SOURCE_LOCATION (decl);
    3556         4158 :   expanded_location xloc = expand_location (loc);
    3557         4158 :   if (xloc.file != NULL)
    3558              :     {
    3559         2260 :       static int lasanloccnt = 0;
    3560         2260 :       char buf[25];
    3561         2260 :       ASM_GENERATE_INTERNAL_LABEL (buf, "LASANLOC", ++lasanloccnt);
    3562         2260 :       tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
    3563              :                              ubsan_get_source_location_type ());
    3564         2260 :       TREE_STATIC (var) = 1;
    3565         2260 :       TREE_PUBLIC (var) = 0;
    3566         2260 :       DECL_ARTIFICIAL (var) = 1;
    3567         2260 :       DECL_IGNORED_P (var) = 1;
    3568         2260 :       pretty_printer filename_pp;
    3569         2260 :       pp_string (&filename_pp, xloc.file);
    3570         2260 :       tree str = asan_pp_string (&filename_pp);
    3571         2260 :       tree ctor = build_constructor_va (TREE_TYPE (var), 3,
    3572              :                                         NULL_TREE, str, NULL_TREE,
    3573              :                                         build_int_cst (unsigned_type_node,
    3574         2260 :                                                        xloc.line), NULL_TREE,
    3575              :                                         build_int_cst (unsigned_type_node,
    3576         2260 :                                                        xloc.column));
    3577         2260 :       TREE_CONSTANT (ctor) = 1;
    3578         2260 :       TREE_STATIC (ctor) = 1;
    3579         2260 :       DECL_INITIAL (var) = ctor;
    3580         2260 :       varpool_node::finalize_decl (var);
    3581         2260 :       locptr = fold_convert (uptr, build_fold_addr_expr (var));
    3582         2260 :     }
    3583              :   else
    3584         1898 :     locptr = build_int_cst (uptr, 0);
    3585         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
    3586         4158 :   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, odr_indicator_ptr);
    3587         4158 :   init = build_constructor (type, vinner);
    3588         4158 :   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
    3589         4158 : }
    3590              : 
    3591              : /* Initialize sanitizer.def builtins if the FE hasn't initialized them.  */
    3592              : void
    3593        38222 : initialize_sanitizer_builtins (void)
    3594              : {
    3595        38222 :   tree decl;
    3596              : 
    3597        38222 :   if (builtin_decl_implicit_p (BUILT_IN_ASAN_INIT))
    3598        38130 :     return;
    3599              : 
    3600           92 :   tree ptrmode_type = (*lang_hooks.types.type_for_mode) (ptr_mode, 0);
    3601           92 :   tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
    3602           92 :   tree BT_FN_VOID_PTR
    3603           92 :     = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
    3604           92 :   tree BT_FN_VOID_CONST_PTR
    3605           92 :     = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
    3606           92 :   tree BT_FN_VOID_PTR_PTR
    3607           92 :     = build_function_type_list (void_type_node, ptr_type_node,
    3608              :                                 ptr_type_node, NULL_TREE);
    3609           92 :   tree BT_FN_VOID_PTR_PTR_PTR
    3610           92 :     = build_function_type_list (void_type_node, ptr_type_node,
    3611              :                                 ptr_type_node, ptr_type_node, NULL_TREE);
    3612           92 :   tree BT_FN_VOID_PTR_PTRMODE
    3613           92 :     = build_function_type_list (void_type_node, ptr_type_node,
    3614              :                                 ptrmode_type, NULL_TREE);
    3615           92 :   tree BT_FN_VOID_INT
    3616           92 :     = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
    3617           92 :   tree BT_FN_SIZE_CONST_PTR_INT
    3618           92 :     = build_function_type_list (size_type_node, const_ptr_type_node,
    3619              :                                 integer_type_node, NULL_TREE);
    3620              : 
    3621           92 :   tree BT_FN_VOID_UINT8_UINT8
    3622           92 :     = build_function_type_list (void_type_node, unsigned_char_type_node,
    3623              :                                 unsigned_char_type_node, NULL_TREE);
    3624           92 :   tree BT_FN_VOID_UINT16_UINT16
    3625           92 :     = build_function_type_list (void_type_node, uint16_type_node,
    3626              :                                 uint16_type_node, NULL_TREE);
    3627           92 :   tree BT_FN_VOID_UINT32_UINT32
    3628           92 :     = build_function_type_list (void_type_node, uint32_type_node,
    3629              :                                 uint32_type_node, NULL_TREE);
    3630           92 :   tree BT_FN_VOID_UINT64_UINT64
    3631           92 :     = build_function_type_list (void_type_node, uint64_type_node,
    3632              :                                 uint64_type_node, NULL_TREE);
    3633           92 :   tree BT_FN_VOID_FLOAT_FLOAT
    3634           92 :     = build_function_type_list (void_type_node, float_type_node,
    3635              :                                 float_type_node, NULL_TREE);
    3636           92 :   tree BT_FN_VOID_DOUBLE_DOUBLE
    3637           92 :     = build_function_type_list (void_type_node, double_type_node,
    3638              :                                 double_type_node, NULL_TREE);
    3639           92 :   tree BT_FN_VOID_UINT64_PTR
    3640           92 :     = build_function_type_list (void_type_node, uint64_type_node,
    3641              :                                 ptr_type_node, NULL_TREE);
    3642              : 
    3643           92 :   tree BT_FN_PTR_CONST_PTR_UINT8
    3644           92 :     = build_function_type_list (ptr_type_node, const_ptr_type_node,
    3645              :                                 unsigned_char_type_node, NULL_TREE);
    3646           92 :   tree BT_FN_VOID_PTR_UINT8_PTRMODE
    3647           92 :     = build_function_type_list (void_type_node, ptr_type_node,
    3648              :                                 unsigned_char_type_node,
    3649              :                                 ptrmode_type, NULL_TREE);
    3650              : 
    3651           92 :   tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5];
    3652           92 :   tree BT_FN_IX_CONST_VPTR_INT[5];
    3653           92 :   tree BT_FN_IX_VPTR_IX_INT[5];
    3654           92 :   tree BT_FN_VOID_VPTR_IX_INT[5];
    3655           92 :   tree vptr
    3656           92 :     = build_pointer_type (build_qualified_type (void_type_node,
    3657              :                                                 TYPE_QUAL_VOLATILE));
    3658           92 :   tree cvptr
    3659           92 :     = build_pointer_type (build_qualified_type (void_type_node,
    3660              :                                                 TYPE_QUAL_VOLATILE
    3661              :                                                 |TYPE_QUAL_CONST));
    3662           92 :   tree boolt
    3663           92 :     = lang_hooks.types.type_for_size (BOOL_TYPE_SIZE, 1);
    3664           92 :   int i;
    3665          644 :   for (i = 0; i < 5; i++)
    3666              :     {
    3667          460 :       tree ix = build_nonstandard_integer_type (BITS_PER_UNIT * (1 << i), 1);
    3668          460 :       BT_FN_BOOL_VPTR_PTR_IX_INT_INT[i]
    3669          460 :         = build_function_type_list (boolt, vptr, ptr_type_node, ix,
    3670              :                                     integer_type_node, integer_type_node,
    3671              :                                     NULL_TREE);
    3672          460 :       BT_FN_IX_CONST_VPTR_INT[i]
    3673          460 :         = build_function_type_list (ix, cvptr, integer_type_node, NULL_TREE);
    3674          460 :       BT_FN_IX_VPTR_IX_INT[i]
    3675          460 :         = build_function_type_list (ix, vptr, ix, integer_type_node,
    3676              :                                     NULL_TREE);
    3677          460 :       BT_FN_VOID_VPTR_IX_INT[i]
    3678          460 :         = build_function_type_list (void_type_node, vptr, ix,
    3679              :                                     integer_type_node, NULL_TREE);
    3680              :     }
    3681              : #define BT_FN_BOOL_VPTR_PTR_I1_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[0]
    3682              : #define BT_FN_I1_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[0]
    3683              : #define BT_FN_I1_VPTR_I1_INT BT_FN_IX_VPTR_IX_INT[0]
    3684              : #define BT_FN_VOID_VPTR_I1_INT BT_FN_VOID_VPTR_IX_INT[0]
    3685              : #define BT_FN_BOOL_VPTR_PTR_I2_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[1]
    3686              : #define BT_FN_I2_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[1]
    3687              : #define BT_FN_I2_VPTR_I2_INT BT_FN_IX_VPTR_IX_INT[1]
    3688              : #define BT_FN_VOID_VPTR_I2_INT BT_FN_VOID_VPTR_IX_INT[1]
    3689              : #define BT_FN_BOOL_VPTR_PTR_I4_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[2]
    3690              : #define BT_FN_I4_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[2]
    3691              : #define BT_FN_I4_VPTR_I4_INT BT_FN_IX_VPTR_IX_INT[2]
    3692              : #define BT_FN_VOID_VPTR_I4_INT BT_FN_VOID_VPTR_IX_INT[2]
    3693              : #define BT_FN_BOOL_VPTR_PTR_I8_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[3]
    3694              : #define BT_FN_I8_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[3]
    3695              : #define BT_FN_I8_VPTR_I8_INT BT_FN_IX_VPTR_IX_INT[3]
    3696              : #define BT_FN_VOID_VPTR_I8_INT BT_FN_VOID_VPTR_IX_INT[3]
    3697              : #define BT_FN_BOOL_VPTR_PTR_I16_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[4]
    3698              : #define BT_FN_I16_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[4]
    3699              : #define BT_FN_I16_VPTR_I16_INT BT_FN_IX_VPTR_IX_INT[4]
    3700              : #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4]
    3701              : #undef ATTR_NOTHROW_LIST
    3702              : #define ATTR_NOTHROW_LIST ECF_NOTHROW
    3703              : #undef ATTR_NOTHROW_LEAF_LIST
    3704              : #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
    3705              : #undef ATTR_TMPURE_NOTHROW_LEAF_LIST
    3706              : #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST
    3707              : #undef ATTR_NORETURN_NOTHROW_LEAF_LIST
    3708              : #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST
    3709              : #undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
    3710              : #define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \
    3711              :   ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST
    3712              : #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST
    3713              : #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \
    3714              :   ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST
    3715              : #undef ATTR_COLD_NOTHROW_LEAF_LIST
    3716              : #define ATTR_COLD_NOTHROW_LEAF_LIST \
    3717              :   /* ECF_COLD missing */ ATTR_NOTHROW_LEAF_LIST
    3718              : #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST
    3719              : #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \
    3720              :   /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST
    3721              : #undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST
    3722              : #define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \
    3723              :   /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
    3724              : #undef ATTR_PURE_NOTHROW_LEAF_LIST
    3725              : #define ATTR_PURE_NOTHROW_LEAF_LIST ECF_PURE | ATTR_NOTHROW_LEAF_LIST
    3726              : #undef DEF_BUILTIN_STUB
    3727              : #define DEF_BUILTIN_STUB(ENUM, NAME)
    3728              : #undef DEF_SANITIZER_BUILTIN_1
    3729              : #define DEF_SANITIZER_BUILTIN_1(ENUM, NAME, TYPE, ATTRS)                \
    3730              :   do {                                                                  \
    3731              :     decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM,               \
    3732              :                                  BUILT_IN_NORMAL, NAME, NULL_TREE);     \
    3733              :     set_call_expr_flags (decl, ATTRS);                                  \
    3734              :     set_builtin_decl (ENUM, decl, true);                                \
    3735              :   } while (0)
    3736              : #undef DEF_SANITIZER_BUILTIN
    3737              : #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS)  \
    3738              :   DEF_SANITIZER_BUILTIN_1 (ENUM, NAME, TYPE, ATTRS);
    3739              : 
    3740              : #include "sanitizer.def"
    3741              : 
    3742              :   /* -fsanitize=object-size uses __builtin_dynamic_object_size and
    3743              :      __builtin_object_size, but they might not be available for e.g. Fortran at
    3744              :      this point.  We use DEF_SANITIZER_BUILTIN here only as a convenience
    3745              :      macro.  */
    3746           92 :   if (flag_sanitize & SANITIZE_OBJECT_SIZE)
    3747              :     {
    3748           21 :       if (!builtin_decl_implicit_p (BUILT_IN_OBJECT_SIZE))
    3749           15 :         DEF_SANITIZER_BUILTIN_1 (BUILT_IN_OBJECT_SIZE, "object_size",
    3750              :                                  BT_FN_SIZE_CONST_PTR_INT,
    3751              :                                  ATTR_PURE_NOTHROW_LEAF_LIST);
    3752          113 :       if (!builtin_decl_implicit_p (BUILT_IN_DYNAMIC_OBJECT_SIZE))
    3753           15 :         DEF_SANITIZER_BUILTIN_1 (BUILT_IN_DYNAMIC_OBJECT_SIZE,
    3754              :                                  "dynamic_object_size",
    3755              :                                  BT_FN_SIZE_CONST_PTR_INT,
    3756              :                                  ATTR_PURE_NOTHROW_LEAF_LIST);
    3757              :     }
    3758              : 
    3759              : #undef DEF_SANITIZER_BUILTIN_1
    3760              : #undef DEF_SANITIZER_BUILTIN
    3761              : #undef DEF_BUILTIN_STUB
    3762              : }
    3763              : 
    3764              : /* Called via htab_traverse.  Count number of emitted
    3765              :    STRING_CSTs in the constant hash table.  */
    3766              : 
    3767              : int
    3768         3402 : count_string_csts (constant_descriptor_tree **slot,
    3769              :                    unsigned HOST_WIDE_INT *data)
    3770              : {
    3771         3402 :   struct constant_descriptor_tree *desc = *slot;
    3772         3402 :   if (TREE_CODE (desc->value) == STRING_CST
    3773         3368 :       && TREE_ASM_WRITTEN (desc->value)
    3774         6770 :       && asan_protect_global (desc->value))
    3775         1698 :     ++*data;
    3776         3402 :   return 1;
    3777              : }
    3778              : 
    3779              : /* Helper structure to pass two parameters to
    3780              :    add_string_csts.  */
    3781              : 
    3782              : struct asan_add_string_csts_data
    3783              : {
    3784              :   tree type;
    3785              :   vec<constructor_elt, va_gc> *v;
    3786              : };
    3787              : 
    3788              : /* Called via hash_table::traverse.  Call asan_add_global
    3789              :    on emitted STRING_CSTs from the constant hash table.  */
    3790              : 
    3791              : int
    3792         3479 : add_string_csts (constant_descriptor_tree **slot,
    3793              :                  asan_add_string_csts_data *aascd)
    3794              : {
    3795         3479 :   struct constant_descriptor_tree *desc = *slot;
    3796         3479 :   if (TREE_CODE (desc->value) == STRING_CST
    3797         3452 :       && TREE_ASM_WRITTEN (desc->value)
    3798         6931 :       && asan_protect_global (desc->value))
    3799              :     {
    3800         1698 :       asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)),
    3801              :                        aascd->type, aascd->v);
    3802              :     }
    3803         3479 :   return 1;
    3804              : }
    3805              : 
    3806              : /* Needs to be GTY(()), because cgraph_build_static_cdtor may
    3807              :    invoke ggc_collect.  */
    3808              : static GTY(()) tree asan_ctor_statements;
    3809              : 
    3810              : /* Module-level instrumentation.
    3811              :    - Insert __asan_init_vN() into the list of CTORs.
    3812              :    - TODO: insert redzones around globals.
    3813              :  */
    3814              : 
    3815              : void
    3816         2478 : asan_finish_file (void)
    3817              : {
    3818         2478 :   varpool_node *vnode;
    3819         2478 :   unsigned HOST_WIDE_INT gcount = 0;
    3820              : 
    3821         2478 :   if (shadow_ptr_types[0] == NULL_TREE)
    3822          111 :     asan_init_shadow_ptr_types ();
    3823              :   /* Avoid instrumenting code in the asan ctors/dtors.
    3824              :      We don't need to insert padding after the description strings,
    3825              :      nor after .LASAN* array.  */
    3826         2478 :   flag_sanitize &= ~SANITIZE_ADDRESS;
    3827              : 
    3828              :   /* For user-space we want asan constructors to run first.
    3829              :      Linux kernel does not support priorities other than default, and the only
    3830              :      other user of constructors is coverage. So we run with the default
    3831              :      priority.  */
    3832          126 :   int priority = flag_sanitize & SANITIZE_USER_ADDRESS
    3833         2478 :                  ? MAX_RESERVED_INIT_PRIORITY - 1 : DEFAULT_INIT_PRIORITY;
    3834              : 
    3835         2478 :   if (flag_sanitize & SANITIZE_USER_ADDRESS)
    3836              :     {
    3837         2352 :       tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
    3838         2352 :       append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
    3839         2352 :       fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK);
    3840         2352 :       append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
    3841              :     }
    3842         5157 :   FOR_EACH_DEFINED_VARIABLE (vnode)
    3843         2679 :     if (TREE_ASM_WRITTEN (vnode->decl)
    3844         2679 :         && asan_protect_global (vnode->decl))
    3845         2460 :       ++gcount;
    3846         2478 :   hash_table<tree_descriptor_hasher> *const_desc_htab = constant_pool_htab ();
    3847         2478 :   const_desc_htab->traverse<unsigned HOST_WIDE_INT *, count_string_csts>
    3848         5880 :     (&gcount);
    3849         2478 :   if (gcount)
    3850              :     {
    3851         1092 :       tree type = asan_global_struct (), var, ctor;
    3852         1092 :       tree dtor_statements = NULL_TREE;
    3853         1092 :       vec<constructor_elt, va_gc> *v;
    3854         1092 :       char buf[20];
    3855              : 
    3856         1092 :       type = build_array_type_nelts (type, gcount);
    3857         1092 :       ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", 0);
    3858         1092 :       var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
    3859              :                         type);
    3860         1092 :       TREE_STATIC (var) = 1;
    3861         1092 :       TREE_PUBLIC (var) = 0;
    3862         1092 :       DECL_ARTIFICIAL (var) = 1;
    3863         1092 :       DECL_IGNORED_P (var) = 1;
    3864         1092 :       vec_alloc (v, gcount);
    3865         3689 :       FOR_EACH_DEFINED_VARIABLE (vnode)
    3866         2597 :         if (TREE_ASM_WRITTEN (vnode->decl)
    3867         2597 :             && asan_protect_global (vnode->decl))
    3868         2460 :           asan_add_global (vnode->decl, TREE_TYPE (type), v);
    3869         1092 :       struct asan_add_string_csts_data aascd;
    3870         1092 :       aascd.type = TREE_TYPE (type);
    3871         1092 :       aascd.v = v;
    3872         1092 :       const_desc_htab->traverse<asan_add_string_csts_data *, add_string_csts>
    3873         4571 :         (&aascd);
    3874         1092 :       ctor = build_constructor (type, v);
    3875         1092 :       TREE_CONSTANT (ctor) = 1;
    3876         1092 :       TREE_STATIC (ctor) = 1;
    3877         1092 :       DECL_INITIAL (var) = ctor;
    3878         1092 :       SET_DECL_ALIGN (var, MAX (DECL_ALIGN (var),
    3879              :                                 ASAN_SHADOW_GRANULARITY * BITS_PER_UNIT));
    3880              : 
    3881         1092 :       varpool_node::finalize_decl (var);
    3882              : 
    3883         1092 :       tree fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS);
    3884         1092 :       tree gcount_tree = build_int_cst (pointer_sized_int_node, gcount);
    3885         1092 :       append_to_statement_list (build_call_expr (fn, 2,
    3886              :                                                  build_fold_addr_expr (var),
    3887              :                                                  gcount_tree),
    3888              :                                 &asan_ctor_statements);
    3889              : 
    3890         1092 :       fn = builtin_decl_implicit (BUILT_IN_ASAN_UNREGISTER_GLOBALS);
    3891         1092 :       append_to_statement_list (build_call_expr (fn, 2,
    3892              :                                                  build_fold_addr_expr (var),
    3893              :                                                  gcount_tree),
    3894              :                                 &dtor_statements);
    3895         1092 :       cgraph_build_static_cdtor ('D', dtor_statements, priority);
    3896              :     }
    3897         2478 :   if (asan_ctor_statements)
    3898         2352 :     cgraph_build_static_cdtor ('I', asan_ctor_statements, priority);
    3899         2478 :   flag_sanitize |= SANITIZE_ADDRESS;
    3900         2478 : }
    3901              : 
    3902              : /* Poison or unpoison (depending on IS_CLOBBER variable) shadow memory based
    3903              :    on SHADOW address.  Newly added statements will be added to ITER with
    3904              :    given location LOC.  We mark SIZE bytes in shadow memory, where
    3905              :    LAST_CHUNK_SIZE is greater than zero in situation where we are at the
    3906              :    end of a variable.  */
    3907              : 
    3908              : static void
    3909         2193 : asan_store_shadow_bytes (gimple_stmt_iterator *iter, location_t loc,
    3910              :                          tree shadow,
    3911              :                          unsigned HOST_WIDE_INT base_addr_offset,
    3912              :                          bool is_clobber, unsigned size,
    3913              :                          unsigned last_chunk_size)
    3914              : {
    3915         2193 :   tree shadow_ptr_type;
    3916              : 
    3917         2193 :   switch (size)
    3918              :     {
    3919         1422 :     case 1:
    3920         1422 :       shadow_ptr_type = shadow_ptr_types[0];
    3921         1422 :       break;
    3922          272 :     case 2:
    3923          272 :       shadow_ptr_type = shadow_ptr_types[1];
    3924          272 :       break;
    3925          499 :     case 4:
    3926          499 :       shadow_ptr_type = shadow_ptr_types[2];
    3927          499 :       break;
    3928            0 :     default:
    3929            0 :       gcc_unreachable ();
    3930              :     }
    3931              : 
    3932         2193 :   unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0;
    3933         2193 :   unsigned HOST_WIDE_INT val = 0;
    3934         2193 :   unsigned last_pos = size;
    3935         2193 :   if (last_chunk_size && !is_clobber)
    3936          322 :     last_pos = BYTES_BIG_ENDIAN ? 0 : size - 1;
    3937         6155 :   for (unsigned i = 0; i < size; ++i)
    3938              :     {
    3939         3962 :       unsigned char shadow_c = c;
    3940         3962 :       if (i == last_pos)
    3941          322 :         shadow_c = last_chunk_size;
    3942         3962 :       val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i);
    3943              :     }
    3944              : 
    3945              :   /* Handle last chunk in unpoisoning.  */
    3946         2193 :   tree magic = build_int_cst (TREE_TYPE (shadow_ptr_type), val);
    3947              : 
    3948         2193 :   tree dest = build2 (MEM_REF, TREE_TYPE (shadow_ptr_type), shadow,
    3949         2193 :                       build_int_cst (shadow_ptr_type, base_addr_offset));
    3950              : 
    3951         2193 :   gimple *g = gimple_build_assign (dest, magic);
    3952         2193 :   gimple_set_location (g, loc);
    3953         2193 :   gsi_insert_after (iter, g, GSI_NEW_STMT);
    3954         2193 : }
    3955              : 
    3956              : /* Expand the ASAN_MARK builtins.  */
    3957              : 
    3958              : bool
    3959         2149 : asan_expand_mark_ifn (gimple_stmt_iterator *iter)
    3960              : {
    3961         2149 :   gimple *g = gsi_stmt (*iter);
    3962         2149 :   location_t loc = gimple_location (g);
    3963         2149 :   HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (g, 0));
    3964         2149 :   bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
    3965              : 
    3966         2149 :   tree base = gimple_call_arg (g, 1);
    3967         2149 :   gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
    3968         2149 :   tree decl = TREE_OPERAND (base, 0);
    3969              : 
    3970              :   /* For a nested function, we can have: ASAN_MARK (2, &FRAME.2.fp_input, 4) */
    3971         2149 :   if (TREE_CODE (decl) == COMPONENT_REF
    3972         2149 :       && DECL_NONLOCAL_FRAME (TREE_OPERAND (decl, 0)))
    3973            1 :     decl = TREE_OPERAND (decl, 0);
    3974              : 
    3975         2149 :   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
    3976              : 
    3977         2149 :   if (hwassist_sanitize_p ())
    3978              :     {
    3979            0 :       gcc_assert (param_hwasan_instrument_stack);
    3980            0 :       gimple_seq stmts = NULL;
    3981              :       /* Here we swap ASAN_MARK calls for HWASAN_MARK.
    3982              :          This is because we are using the approach of using ASAN_MARK as a
    3983              :          synonym until here.
    3984              :          That approach means we don't yet have to duplicate all the special
    3985              :          cases for ASAN_MARK and ASAN_POISON with the exact same handling but
    3986              :          called HWASAN_MARK etc.
    3987              : 
    3988              :          N.b. __asan_poison_stack_memory (which implements ASAN_MARK for ASAN)
    3989              :          rounds the size up to its shadow memory granularity, while
    3990              :          __hwasan_tag_memory (which implements the same for HWASAN) does not.
    3991              :          Hence we emit HWASAN_MARK with an aligned size unlike ASAN_MARK.  */
    3992            0 :       tree len = gimple_call_arg (g, 2);
    3993            0 :       tree new_len = gimple_build_round_up (&stmts, loc, size_type_node, len,
    3994            0 :                                             HWASAN_TAG_GRANULE_SIZE);
    3995            0 :       gimple_build (&stmts, loc, CFN_HWASAN_MARK,
    3996              :                     void_type_node, gimple_call_arg (g, 0),
    3997              :                     base, new_len);
    3998            0 :       gsi_replace_with_seq (iter, stmts, true);
    3999            0 :       return false;
    4000              :     }
    4001              : 
    4002         2149 :   if (is_poison)
    4003              :     {
    4004         1412 :       if (asan_handled_variables == NULL)
    4005          387 :         asan_handled_variables = new hash_set<tree> (16);
    4006         1412 :       asan_handled_variables->add (decl);
    4007              :     }
    4008         2149 :   tree len = gimple_call_arg (g, 2);
    4009              : 
    4010         2149 :   gcc_assert (poly_int_tree_p (len));
    4011              : 
    4012         2149 :   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4013              :                            NOP_EXPR, base);
    4014         2149 :   gimple_set_location (g, loc);
    4015         2149 :   gsi_replace (iter, g, false);
    4016         2149 :   tree base_addr = gimple_assign_lhs (g);
    4017              : 
    4018              :   /* Generate direct emission if size_in_bytes is small.  */
    4019         2149 :   unsigned threshold = param_use_after_scope_direct_emission_threshold;
    4020         2149 :   if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) <= threshold)
    4021              :     {
    4022         2096 :       unsigned HOST_WIDE_INT size_in_bytes = tree_to_uhwi (len);
    4023         2096 :       const unsigned HOST_WIDE_INT shadow_size
    4024         2096 :         = shadow_mem_size (size_in_bytes);
    4025         2096 :       const unsigned int shadow_align
    4026         2096 :         = (get_pointer_alignment (base) / BITS_PER_UNIT) >> ASAN_SHADOW_SHIFT;
    4027              : 
    4028         2096 :       tree shadow = build_shadow_mem_access (iter, loc, base_addr,
    4029              :                                              shadow_ptr_types[0], true);
    4030              : 
    4031         6385 :       for (unsigned HOST_WIDE_INT offset = 0; offset < shadow_size;)
    4032              :         {
    4033         2193 :           unsigned size = 1;
    4034         2193 :           if (shadow_size - offset >= 4
    4035              :               && (!STRICT_ALIGNMENT || shadow_align >= 4))
    4036              :             size = 4;
    4037         1694 :           else if (shadow_size - offset >= 2
    4038              :                    && (!STRICT_ALIGNMENT || shadow_align >= 2))
    4039          272 :             size = 2;
    4040              : 
    4041         2193 :           unsigned HOST_WIDE_INT last_chunk_size = 0;
    4042         2193 :           unsigned HOST_WIDE_INT s = (offset + size) * ASAN_SHADOW_GRANULARITY;
    4043         2193 :           if (s > size_in_bytes)
    4044         1152 :             last_chunk_size = ASAN_SHADOW_GRANULARITY - (s - size_in_bytes);
    4045              : 
    4046         2193 :           asan_store_shadow_bytes (iter, loc, shadow, offset, is_poison,
    4047              :                                    size, last_chunk_size);
    4048         2193 :           offset += size;
    4049              :         }
    4050              :     }
    4051              :   else
    4052              :     {
    4053           53 :       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4054              :                                NOP_EXPR, len);
    4055           53 :       gimple_set_location (g, loc);
    4056           53 :       gsi_safe_insert_before (iter, g);
    4057           53 :       tree sz_arg = gimple_assign_lhs (g);
    4058              : 
    4059           53 :       tree fun
    4060           71 :         = builtin_decl_implicit (is_poison ? BUILT_IN_ASAN_POISON_STACK_MEMORY
    4061              :                                  : BUILT_IN_ASAN_UNPOISON_STACK_MEMORY);
    4062           53 :       g = gimple_build_call (fun, 2, base_addr, sz_arg);
    4063           53 :       gimple_set_location (g, loc);
    4064           53 :       gsi_insert_after (iter, g, GSI_NEW_STMT);
    4065              :     }
    4066              : 
    4067              :   return false;
    4068              : }
    4069              : 
    4070              : /* Expand the ASAN_{LOAD,STORE} builtins.  */
    4071              : 
    4072              : bool
    4073        18971 : asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
    4074              : {
    4075        18971 :   gcc_assert (!hwassist_sanitize_p ());
    4076        18971 :   gimple *g = gsi_stmt (*iter);
    4077        18971 :   location_t loc = gimple_location (g);
    4078        18971 :   bool recover_p;
    4079        18971 :   if (flag_sanitize & SANITIZE_USER_ADDRESS)
    4080        18926 :     recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
    4081              :   else
    4082           45 :     recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
    4083              : 
    4084        18971 :   HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
    4085        18971 :   gcc_assert (flags < ASAN_CHECK_LAST);
    4086        18971 :   bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
    4087        18971 :   bool is_store = (flags & ASAN_CHECK_STORE) != 0;
    4088        18971 :   bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
    4089              : 
    4090        18971 :   tree base = gimple_call_arg (g, 1);
    4091        18971 :   tree len = gimple_call_arg (g, 2);
    4092        18971 :   HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3));
    4093              : 
    4094        36906 :   HOST_WIDE_INT size_in_bytes
    4095        18971 :     = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
    4096              : 
    4097        18971 :   if (use_calls)
    4098              :     {
    4099              :       /* Instrument using callbacks.  */
    4100          103 :       gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4101              :                                       NOP_EXPR, base);
    4102          103 :       gimple_set_location (g, loc);
    4103          103 :       gsi_insert_before (iter, g, GSI_SAME_STMT);
    4104          103 :       tree base_addr = gimple_assign_lhs (g);
    4105              : 
    4106          103 :       int nargs;
    4107          103 :       tree fun = check_func (is_store, recover_p, size_in_bytes, &nargs);
    4108          103 :       if (nargs == 1)
    4109           75 :         g = gimple_build_call (fun, 1, base_addr);
    4110              :       else
    4111              :         {
    4112           28 :           gcc_assert (nargs == 2);
    4113           28 :           g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4114              :                                    NOP_EXPR, len);
    4115           28 :           gimple_set_location (g, loc);
    4116           28 :           gsi_insert_before (iter, g, GSI_SAME_STMT);
    4117           28 :           tree sz_arg = gimple_assign_lhs (g);
    4118           28 :           g = gimple_build_call (fun, nargs, base_addr, sz_arg);
    4119              :         }
    4120          103 :       gimple_set_location (g, loc);
    4121          103 :       gsi_replace (iter, g, false);
    4122          103 :       return false;
    4123              :     }
    4124              : 
    4125        18868 :   HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
    4126              : 
    4127        17860 :   tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
    4128        18868 :   tree shadow_type = TREE_TYPE (shadow_ptr_type);
    4129              : 
    4130        18868 :   gimple_stmt_iterator gsi = *iter;
    4131              : 
    4132        18868 :   if (!is_non_zero_len)
    4133              :     {
    4134              :       /* So, the length of the memory area to asan-protect is
    4135              :          non-constant.  Let's guard the generated instrumentation code
    4136              :          like:
    4137              : 
    4138              :          if (len != 0)
    4139              :            {
    4140              :              //asan instrumentation code goes here.
    4141              :            }
    4142              :          // fallthrough instructions, starting with *ITER.  */
    4143              : 
    4144            0 :       g = gimple_build_cond (NE_EXPR,
    4145              :                             len,
    4146            0 :                             build_int_cst (TREE_TYPE (len), 0),
    4147              :                             NULL_TREE, NULL_TREE);
    4148            0 :       gimple_set_location (g, loc);
    4149              : 
    4150            0 :       basic_block then_bb, fallthrough_bb;
    4151            0 :       insert_if_then_before_iter (as_a <gcond *> (g), iter,
    4152              :                                   /*then_more_likely_p=*/true,
    4153              :                                   &then_bb, &fallthrough_bb);
    4154              :       /* Note that fallthrough_bb starts with the statement that was
    4155              :         pointed to by ITER.  */
    4156              : 
    4157              :       /* The 'then block' of the 'if (len != 0) condition is where
    4158              :         we'll generate the asan instrumentation code now.  */
    4159            0 :       gsi = gsi_last_bb (then_bb);
    4160              :     }
    4161              : 
    4162              :   /* Get an iterator on the point where we can add the condition
    4163              :      statement for the instrumentation.  */
    4164        18868 :   basic_block then_bb, else_bb;
    4165        18868 :   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
    4166              :                                   /*then_more_likely_p=*/false,
    4167              :                                   /*create_then_fallthru_edge*/recover_p,
    4168              :                                   &then_bb,
    4169              :                                   &else_bb);
    4170              : 
    4171        18868 :   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4172              :                            NOP_EXPR, base);
    4173        18868 :   gimple_set_location (g, loc);
    4174        18868 :   gsi_insert_before (&gsi, g, GSI_NEW_STMT);
    4175        18868 :   tree base_addr = gimple_assign_lhs (g);
    4176              : 
    4177        18868 :   tree t = NULL_TREE;
    4178        18868 :   if (real_size_in_bytes >= 8)
    4179              :     {
    4180        12244 :       tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
    4181              :                                              shadow_ptr_type);
    4182        12244 :       t = shadow;
    4183              :     }
    4184              :   else
    4185              :     {
    4186              :       /* Slow path for 1, 2 and 4 byte accesses.  */
    4187              :       /* Test (shadow != 0)
    4188              :          & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow).  */
    4189         6624 :       tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
    4190              :                                              shadow_ptr_type);
    4191         6624 :       gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
    4192         6624 :       gimple_seq seq = NULL;
    4193         6624 :       gimple_seq_add_stmt (&seq, shadow_test);
    4194              :       /* Aligned (>= 8 bytes) can test just
    4195              :          (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
    4196              :          to be 0.  */
    4197         6624 :       if (align < 8)
    4198              :         {
    4199         4660 :           gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
    4200              :                                                    base_addr, 7));
    4201         4660 :           gimple_seq_add_stmt (&seq,
    4202         9320 :                                build_type_cast (shadow_type,
    4203              :                                                 gimple_seq_last (seq)));
    4204         4660 :           if (real_size_in_bytes > 1)
    4205         1862 :             gimple_seq_add_stmt (&seq,
    4206         1862 :                                  build_assign (PLUS_EXPR,
    4207              :                                                gimple_seq_last (seq),
    4208         1862 :                                                real_size_in_bytes - 1));
    4209         9320 :           t = gimple_assign_lhs (gimple_seq_last_stmt (seq));
    4210              :         }
    4211              :       else
    4212         1964 :         t = build_int_cst (shadow_type, real_size_in_bytes - 1);
    4213         6624 :       gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, t, shadow));
    4214        13248 :       gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
    4215              :                                                gimple_seq_last (seq)));
    4216        13248 :       t = gimple_assign_lhs (gimple_seq_last (seq));
    4217         6624 :       gimple_seq_set_location (seq, loc);
    4218         6624 :       gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
    4219              : 
    4220              :       /* For non-constant, misaligned or otherwise weird access sizes,
    4221              :        check first and last byte.  */
    4222         6624 :       if (size_in_bytes == -1)
    4223              :         {
    4224         1008 :           g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4225              :                                    MINUS_EXPR, len,
    4226              :                                    build_int_cst (pointer_sized_int_node, 1));
    4227         1008 :           gimple_set_location (g, loc);
    4228         1008 :           gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    4229         1008 :           tree last = gimple_assign_lhs (g);
    4230         1008 :           g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
    4231              :                                    PLUS_EXPR, base_addr, last);
    4232         1008 :           gimple_set_location (g, loc);
    4233         1008 :           gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    4234         1008 :           tree base_end_addr = gimple_assign_lhs (g);
    4235              : 
    4236         1008 :           tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr,
    4237              :                                                  shadow_ptr_type);
    4238         1008 :           gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
    4239         1008 :           gimple_seq seq = NULL;
    4240         1008 :           gimple_seq_add_stmt (&seq, shadow_test);
    4241         1008 :           gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
    4242              :                                                    base_end_addr, 7));
    4243         2016 :           gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
    4244              :                                                       gimple_seq_last (seq)));
    4245         2016 :           gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
    4246              :                                                    gimple_seq_last (seq),
    4247              :                                                    shadow));
    4248         2016 :           gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
    4249              :                                                    gimple_seq_last (seq)));
    4250         2016 :           gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
    4251              :                                                    gimple_seq_last (seq)));
    4252         2016 :           t = gimple_assign_lhs (gimple_seq_last (seq));
    4253         1008 :           gimple_seq_set_location (seq, loc);
    4254         1008 :           gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
    4255              :         }
    4256              :     }
    4257              : 
    4258        18868 :   g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
    4259              :                          NULL_TREE, NULL_TREE);
    4260        18868 :   gimple_set_location (g, loc);
    4261        18868 :   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    4262              : 
    4263              :   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
    4264        18868 :   gsi = gsi_start_bb (then_bb);
    4265        18868 :   int nargs;
    4266        18868 :   tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
    4267        18868 :   g = gimple_build_call (fun, nargs, base_addr, len);
    4268        18868 :   gimple_set_location (g, loc);
    4269        18868 :   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    4270              : 
    4271        18868 :   gsi_remove (iter, true);
    4272        18868 :   *iter = gsi_start_bb (else_bb);
    4273              : 
    4274        18868 :   return true;
    4275              : }
    4276              : 
    4277              : /* Create ASAN shadow variable for a VAR_DECL which has been rewritten
    4278              :    into SSA.  Already seen VAR_DECLs are stored in SHADOW_VARS_MAPPING.  */
    4279              : 
    4280              : static tree
    4281           59 : create_asan_shadow_var (tree var_decl,
    4282              :                         hash_map<tree, tree> &shadow_vars_mapping)
    4283              : {
    4284           59 :   tree *slot = shadow_vars_mapping.get (var_decl);
    4285           59 :   if (slot == NULL)
    4286              :     {
    4287           59 :       tree shadow_var = copy_node (var_decl);
    4288              : 
    4289           59 :       copy_body_data id;
    4290           59 :       memset (&id, 0, sizeof (copy_body_data));
    4291           59 :       id.src_fn = id.dst_fn = current_function_decl;
    4292           59 :       copy_decl_for_dup_finish (&id, var_decl, shadow_var);
    4293              : 
    4294           59 :       DECL_ARTIFICIAL (shadow_var) = 1;
    4295           59 :       DECL_IGNORED_P (shadow_var) = 1;
    4296           59 :       DECL_SEEN_IN_BIND_EXPR_P (shadow_var) = 0;
    4297           59 :       gimple_add_tmp_var (shadow_var);
    4298              : 
    4299           59 :       shadow_vars_mapping.put (var_decl, shadow_var);
    4300           59 :       return shadow_var;
    4301              :     }
    4302              :   else
    4303            0 :     return *slot;
    4304              : }
    4305              : 
    4306              : /* Expand ASAN_POISON ifn.  */
    4307              : 
    4308              : bool
    4309           64 : asan_expand_poison_ifn (gimple_stmt_iterator *iter,
    4310              :                         bool *need_commit_edge_insert,
    4311              :                         hash_map<tree, tree> &shadow_vars_mapping)
    4312              : {
    4313           64 :   gimple *g = gsi_stmt (*iter);
    4314           64 :   tree poisoned_var = gimple_call_lhs (g);
    4315           64 :   if (!poisoned_var || has_zero_uses (poisoned_var))
    4316              :     {
    4317            5 :       gsi_remove (iter, true);
    4318            5 :       return true;
    4319              :     }
    4320              : 
    4321           59 :   if (SSA_NAME_VAR (poisoned_var) == NULL_TREE)
    4322            0 :     SET_SSA_NAME_VAR_OR_IDENTIFIER (poisoned_var,
    4323              :                                     create_tmp_var (TREE_TYPE (poisoned_var)));
    4324              : 
    4325           59 :   tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
    4326              :                                             shadow_vars_mapping);
    4327              : 
    4328           59 :   bool recover_p;
    4329           59 :   if (flag_sanitize & SANITIZE_USER_ADDRESS)
    4330           59 :     recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
    4331              :   else
    4332            0 :     recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
    4333           59 :   tree size = DECL_SIZE_UNIT (shadow_var);
    4334           59 :   gimple *poison_call
    4335           59 :     = gimple_build_call_internal (IFN_ASAN_MARK, 3,
    4336              :                                   build_int_cst (integer_type_node,
    4337              :                                                  ASAN_MARK_POISON),
    4338              :                                   build_fold_addr_expr (shadow_var), size);
    4339              : 
    4340           59 :   gimple *use;
    4341           59 :   imm_use_iterator imm_iter;
    4342          177 :   FOR_EACH_IMM_USE_STMT (use, imm_iter, poisoned_var)
    4343              :     {
    4344          118 :       if (is_gimple_debug (use))
    4345           59 :         continue;
    4346              : 
    4347           59 :       int nargs;
    4348           59 :       bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
    4349           59 :       gcall *call;
    4350           59 :       if (hwassist_sanitize_p ())
    4351              :         {
    4352            0 :           tree fun = builtin_decl_implicit (BUILT_IN_HWASAN_TAG_MISMATCH4);
    4353              :           /* NOTE: hwasan has no __hwasan_report_* functions like asan does.
    4354              :                 We use __hwasan_tag_mismatch4 with arguments that tell it the
    4355              :                 size of access and load to report all tag mismatches.
    4356              : 
    4357              :                 The arguments to this function are:
    4358              :                   Address of invalid access.
    4359              :                   Bitfield containing information about the access
    4360              :                     (access_info)
    4361              :                   Pointer to a frame of registers
    4362              :                     (for use in printing the contents of registers in a dump)
    4363              :                     Not used yet -- to be used by inline instrumentation.
    4364              :                   Size of access.
    4365              : 
    4366              :                 The access_info bitfield encodes the following pieces of
    4367              :                 information:
    4368              :                   - Is this a store or load?
    4369              :                     access_info & 0x10  =>  store
    4370              :                   - Should the program continue after reporting the error?
    4371              :                     access_info & 0x20  =>  recover
    4372              :                   - What size access is this (not used here since we can always
    4373              :                     pass the size in the last argument)
    4374              : 
    4375              :                     if (access_info & 0xf == 0xf)
    4376              :                       size is taken from last argument.
    4377              :                     else
    4378              :                       size == 1 << (access_info & 0xf)
    4379              : 
    4380              :                 The last argument contains the size of the access iff the
    4381              :                 access_info size indicator is 0xf (we always use this argument
    4382              :                 rather than storing the size in the access_info bitfield).
    4383              : 
    4384              :                 See the function definition `__hwasan_tag_mismatch4` in
    4385              :                 libsanitizer/hwasan for the full definition.
    4386              :                 */
    4387            0 :           unsigned access_info = (0x20 * recover_p)
    4388            0 :             + (0x10 * store_p)
    4389            0 :             + (0xf);
    4390            0 :           call = gimple_build_call (fun, 4,
    4391              :                                     build_fold_addr_expr (shadow_var),
    4392              :                                     build_int_cst (pointer_sized_int_node,
    4393            0 :                                                    access_info),
    4394              :                                     build_int_cst (pointer_sized_int_node, 0),
    4395              :                                     size);
    4396              :         }
    4397              :       else
    4398              :         {
    4399           59 :           tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
    4400              :                                         &nargs);
    4401           59 :           tree ptrmode_type
    4402           59 :             = (nargs == 2 ? (*lang_hooks.types.type_for_mode) (ptr_mode, 0)
    4403              :                : NULL_TREE);
    4404           87 :           call = gimple_build_call (fun, nargs,
    4405              :                                     build_fold_addr_expr (shadow_var),
    4406              :                                     nargs == 2
    4407           28 :                                     ? fold_convert (ptrmode_type, size)
    4408              :                                     : NULL_TREE);
    4409              :         }
    4410           59 :       gimple_set_location (call, gimple_location (use));
    4411           59 :       gimple *call_to_insert = call;
    4412              : 
    4413              :       /* The USE can be a gimple PHI node.  If so, insert the call on
    4414              :          all edges leading to the PHI node.  */
    4415           59 :       if (is_a <gphi *> (use))
    4416              :         {
    4417              :           gphi *phi = dyn_cast<gphi *> (use);
    4418           20 :           for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
    4419           15 :             if (gimple_phi_arg_def (phi, i) == poisoned_var)
    4420              :               {
    4421            5 :                 edge e = gimple_phi_arg_edge (phi, i);
    4422              : 
    4423              :                 /* Do not insert on an edge we can't split.  */
    4424            5 :                 if (e->flags & EDGE_ABNORMAL)
    4425            5 :                   continue;
    4426              : 
    4427            0 :                 if (call_to_insert == NULL)
    4428            0 :                   call_to_insert = gimple_copy (call);
    4429              : 
    4430            0 :                 gsi_insert_seq_on_edge (e, call_to_insert);
    4431            0 :                 *need_commit_edge_insert = true;
    4432            0 :                 call_to_insert = NULL;
    4433              :               }
    4434              :         }
    4435              :       else
    4436              :         {
    4437           54 :           gimple_stmt_iterator gsi = gsi_for_stmt (use);
    4438           54 :           if (store_p)
    4439           18 :             gsi_replace (&gsi, call, true);
    4440              :           else
    4441           36 :             gsi_insert_before (&gsi, call, GSI_NEW_STMT);
    4442              :         }
    4443           59 :     }
    4444              : 
    4445           59 :   SSA_NAME_IS_DEFAULT_DEF (poisoned_var) = true;
    4446           59 :   SSA_NAME_DEF_STMT (poisoned_var) = gimple_build_nop ();
    4447           59 :   gsi_replace (iter, poison_call, false);
    4448              : 
    4449           59 :   return true;
    4450              : }
    4451              : 
    4452              : /* Instrument the current function.  */
    4453              : 
    4454              : static unsigned int
    4455         6572 : asan_instrument (void)
    4456              : {
    4457         6572 :   if (hwassist_sanitize_p ())
    4458              :     {
    4459          448 :       initialize_sanitizer_builtins ();
    4460          448 :       transform_statements ();
    4461          448 :       return 0;
    4462              :     }
    4463              : 
    4464         6124 :   if (shadow_ptr_types[0] == NULL_TREE)
    4465         2349 :     asan_init_shadow_ptr_types ();
    4466         6124 :   transform_statements ();
    4467         6124 :   last_alloca_addr = NULL_TREE;
    4468         6124 :   return 0;
    4469              : }
    4470              : 
    4471              : static bool
    4472      1516027 : gate_asan (void)
    4473              : {
    4474       453231 :   return sanitize_flags_p (SANITIZE_ADDRESS);
    4475              : }
    4476              : 
    4477              : namespace {
    4478              : 
    4479              : const pass_data pass_data_asan =
    4480              : {
    4481              :   GIMPLE_PASS, /* type */
    4482              :   "asan", /* name */
    4483              :   OPTGROUP_NONE, /* optinfo_flags */
    4484              :   TV_NONE, /* tv_id */
    4485              :   ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
    4486              :   0, /* properties_provided */
    4487              :   0, /* properties_destroyed */
    4488              :   0, /* todo_flags_start */
    4489              :   TODO_update_ssa, /* todo_flags_finish */
    4490              : };
    4491              : 
    4492              : class pass_asan : public gimple_opt_pass
    4493              : {
    4494              : public:
    4495       588392 :   pass_asan (gcc::context *ctxt)
    4496      1176784 :     : gimple_opt_pass (pass_data_asan, ctxt)
    4497              :   {}
    4498              : 
    4499              :   /* opt_pass methods: */
    4500       294196 :   opt_pass * clone () final override { return new pass_asan (m_ctxt); }
    4501      1062796 :   bool gate (function *) final override
    4502              :   {
    4503      1062796 :     return gate_asan () || gate_hwasan () || gate_memtag ();
    4504              :   }
    4505         5181 :   unsigned int execute (function *) final override
    4506              :   {
    4507         5181 :     return asan_instrument ();
    4508              :   }
    4509              : 
    4510              : }; // class pass_asan
    4511              : 
    4512              : } // anon namespace
    4513              : 
    4514              : gimple_opt_pass *
    4515       294196 : make_pass_asan (gcc::context *ctxt)
    4516              : {
    4517       294196 :   return new pass_asan (ctxt);
    4518              : }
    4519              : 
    4520              : namespace {
    4521              : 
    4522              : const pass_data pass_data_asan_O0 =
    4523              : {
    4524              :   GIMPLE_PASS, /* type */
    4525              :   "asan0", /* name */
    4526              :   OPTGROUP_NONE, /* optinfo_flags */
    4527              :   TV_NONE, /* tv_id */
    4528              :   ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
    4529              :   0, /* properties_provided */
    4530              :   0, /* properties_destroyed */
    4531              :   0, /* todo_flags_start */
    4532              :   TODO_update_ssa, /* todo_flags_finish */
    4533              : };
    4534              : 
    4535              : class pass_asan_O0 : public gimple_opt_pass
    4536              : {
    4537              : public:
    4538       294196 :   pass_asan_O0 (gcc::context *ctxt)
    4539       588392 :     : gimple_opt_pass (pass_data_asan_O0, ctxt)
    4540              :   {}
    4541              : 
    4542              :   /* opt_pass methods: */
    4543      1515908 :   bool gate (function *) final override
    4544              :     {
    4545      1969139 :       return !optimize && (gate_asan () || gate_hwasan () || gate_memtag ());
    4546              :     }
    4547         1391 :   unsigned int execute (function *) final override
    4548              :   {
    4549         1391 :     return asan_instrument ();
    4550              :   }
    4551              : 
    4552              : }; // class pass_asan_O0
    4553              : 
    4554              : } // anon namespace
    4555              : 
    4556              : gimple_opt_pass *
    4557       294196 : make_pass_asan_O0 (gcc::context *ctxt)
    4558              : {
    4559       294196 :   return new pass_asan_O0 (ctxt);
    4560              : }
    4561              : 
    4562              : /*  HWASAN  */
    4563              : 
    4564              : /* For stack tagging:
    4565              : 
    4566              :    Return the offset from the frame base tag that the "next" expanded object
    4567              :    should have.  */
    4568              : uint8_t
    4569          176 : hwasan_current_frame_tag ()
    4570              : {
    4571          176 :   return hwasan_frame_tag_offset;
    4572              : }
    4573              : 
    4574              : /* For stack tagging:
    4575              : 
    4576              :    Return the 'base pointer' for this function.  If that base pointer has not
    4577              :    yet been created then we create a register to hold it and record the insns
    4578              :    to initialize the register in `hwasan_frame_base_init_seq` for later
    4579              :    emission.  */
    4580              : rtx
    4581           88 : hwasan_frame_base ()
    4582              : {
    4583           88 :   if (! hwasan_frame_base_ptr)
    4584              :     {
    4585           62 :       start_sequence ();
    4586           62 :       hwasan_frame_base_ptr
    4587           62 :         = force_reg (Pmode,
    4588           62 :                      targetm.memtag.insert_random_tag (virtual_stack_vars_rtx,
    4589              :                                                        NULL_RTX));
    4590           62 :       hwasan_frame_base_init_seq = end_sequence ();
    4591              :     }
    4592              : 
    4593           88 :   return hwasan_frame_base_ptr;
    4594              : }
    4595              : 
    4596              : /* For stack tagging:
    4597              : 
    4598              :    Check whether this RTX is a standard pointer addressing the base of the
    4599              :    stack variables for this frame.  Returns true if the RTX is either
    4600              :    virtual_stack_vars_rtx or hwasan_frame_base_ptr.  */
    4601              : bool
    4602      2028824 : stack_vars_base_reg_p (rtx base)
    4603              : {
    4604      2028824 :   return base == virtual_stack_vars_rtx || base == hwasan_frame_base_ptr;
    4605              : }
    4606              : 
    4607              : /* For stack tagging:
    4608              : 
    4609              :    Emit frame base initialisation.
    4610              :    If hwasan_frame_base has been used before here then
    4611              :    hwasan_frame_base_init_seq contains the sequence of instructions to
    4612              :    initialize it.  This must be put just before the hwasan prologue, so we emit
    4613              :    the insns before parm_birth_insn (which will point to the first instruction
    4614              :    of the hwasan prologue if it exists).
    4615              : 
    4616              :    We update `parm_birth_insn` to point to the start of this initialisation
    4617              :    since that represents the end of the initialisation done by
    4618              :    expand_function_{start,end} functions and we want to maintain that.  */
    4619              : void
    4620          364 : hwasan_maybe_emit_frame_base_init ()
    4621              : {
    4622          364 :   if (! hwasan_frame_base_init_seq)
    4623              :     return;
    4624           16 :   emit_insn_before (hwasan_frame_base_init_seq, parm_birth_insn);
    4625           16 :   parm_birth_insn = hwasan_frame_base_init_seq;
    4626              : }
    4627              : 
    4628              : /* Record a compile-time constant size stack variable that HWASAN will need to
    4629              :    tag.  This record of the range of a stack variable will be used by
    4630              :    `hwasan_emit_prologue` to emit the RTL at the start of each frame which will
    4631              :    set tags in the shadow memory according to the assigned tag for each object.
    4632              : 
    4633              :    The range that the object spans in stack space should be described by the
    4634              :    bounds `untagged_base + nearest_offset` and
    4635              :    `untagged_base + farthest_offset`.
    4636              :    `tagged_base` is the base address which contains the "base frame tag" for
    4637              :    this frame, and from which the value to address this object with will be
    4638              :    calculated.
    4639              : 
    4640              :    We record the `untagged_base` since the functions in the hwasan library we
    4641              :    use to tag memory take pointers without a tag.  */
    4642              : void
    4643           88 : hwasan_record_stack_var (rtx untagged_base, rtx tagged_base,
    4644              :                          poly_int64 nearest_offset, poly_int64 farthest_offset)
    4645              : {
    4646           88 :   hwasan_stack_var cur_var;
    4647           88 :   cur_var.untagged_base = untagged_base;
    4648           88 :   cur_var.tagged_base = tagged_base;
    4649           88 :   cur_var.nearest_offset = nearest_offset;
    4650           88 :   cur_var.farthest_offset = farthest_offset;
    4651           88 :   cur_var.tag_offset = hwasan_current_frame_tag ();
    4652              : 
    4653           88 :   hwasan_tagged_stack_vars.safe_push (cur_var);
    4654           88 : }
    4655              : 
    4656              : /* Return the RTX representing the farthest extent of the statically allocated
    4657              :    stack objects for this frame.  If hwasan_frame_base_ptr has not been
    4658              :    initialized then we are not storing any static variables on the stack in
    4659              :    this frame.  In this case we return NULL_RTX to represent that.
    4660              : 
    4661              :    Otherwise simply return virtual_stack_vars_rtx + frame_offset.  */
    4662              : rtx
    4663          364 : hwasan_get_frame_extent ()
    4664              : {
    4665          364 :   return (hwasan_frame_base_ptr
    4666          364 :           ? plus_constant (Pmode, virtual_stack_vars_rtx, frame_offset)
    4667          364 :           : NULL_RTX);
    4668              : }
    4669              : 
    4670              : /* For stack tagging:
    4671              : 
    4672              :    Increment the frame tag offset modulo the size a tag can represent.  */
    4673              : void
    4674           88 : hwasan_increment_frame_tag ()
    4675              : {
    4676           88 :   uint8_t tag_bits = HWASAN_TAG_SIZE;
    4677           88 :   gcc_assert (HWASAN_TAG_SIZE
    4678              :               <= sizeof (hwasan_frame_tag_offset) * CHAR_BIT);
    4679           88 :   hwasan_frame_tag_offset = (hwasan_frame_tag_offset + 1) % (1 << tag_bits);
    4680              :   /* The "background tag" of the stack is zero by definition.
    4681              :      This is the tag that objects like parameters passed on the stack and
    4682              :      spilled registers are given.  It is handy to avoid this tag for objects
    4683              :      whose tags we decide ourselves, partly to ensure that buffer overruns
    4684              :      can't affect these important variables (e.g. saved link register, saved
    4685              :      stack pointer etc) and partly to make debugging easier (everything with a
    4686              :      tag of zero is space allocated automatically by the compiler).
    4687              : 
    4688              :      This is not feasible when using random frame tags (the default
    4689              :      configuration for hwasan) since the tag for the given frame is randomly
    4690              :      chosen at runtime.  In order to avoid any tags matching the stack
    4691              :      background we would need to decide tag offsets at runtime instead of
    4692              :      compile time (and pay the resulting performance cost).
    4693              : 
    4694              :      When not using random base tags for each frame (i.e. when compiled with
    4695              :      `--param hwasan-random-frame-tag=0`) the base tag for each frame is zero.
    4696              :      This means the tag that each object gets is equal to the
    4697              :      hwasan_frame_tag_offset used in determining it.
    4698              :      When this is the case we *can* ensure no object gets the tag of zero by
    4699              :      simply ensuring no object has the hwasan_frame_tag_offset of zero.
    4700              : 
    4701              :      There is the extra complication that we only record the
    4702              :      hwasan_frame_tag_offset here (which is the offset from the tag stored in
    4703              :      the stack pointer).  In the kernel, the tag in the stack pointer is 0xff
    4704              :      rather than zero.  This does not cause problems since tags of 0xff are
    4705              :      never checked in the kernel.  As mentioned at the beginning of this
    4706              :      comment the background tag of the stack is zero by definition, which means
    4707              :      that for the kernel we should skip offsets of both 0 and 1 from the stack
    4708              :      pointer.  Avoiding the offset of 0 ensures we use a tag which will be
    4709              :      checked, avoiding the offset of 1 ensures we use a tag that is not the
    4710              :      same as the background.  */
    4711           88 :   if (hwasan_frame_tag_offset == 0 && ! param_hwasan_random_frame_tag)
    4712            0 :     hwasan_frame_tag_offset += 1;
    4713           16 :   if (hwasan_frame_tag_offset == 1 && ! param_hwasan_random_frame_tag
    4714           88 :       && sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS))
    4715            0 :     hwasan_frame_tag_offset += 1;
    4716           88 : }
    4717              : 
    4718              : /* Clear internal state for the next function.
    4719              :    This function is called before variables on the stack get expanded, in
    4720              :    `init_vars_expansion`.  */
    4721              : void
    4722         1108 : hwasan_record_frame_init ()
    4723              : {
    4724         1108 :   delete asan_used_labels;
    4725         1108 :   asan_used_labels = NULL;
    4726              : 
    4727              :   /* If this isn't the case then some stack variable was recorded *before*
    4728              :      hwasan_record_frame_init is called, yet *after* the hwasan prologue for
    4729              :      the previous frame was emitted.  Such stack variables would not have
    4730              :      their shadow stack filled in.  */
    4731         1108 :   gcc_assert (hwasan_tagged_stack_vars.is_empty ());
    4732         1108 :   hwasan_frame_base_ptr = NULL_RTX;
    4733         1108 :   hwasan_frame_base_init_seq = NULL;
    4734              : 
    4735              :   /* When not using a random frame tag we can avoid the background stack
    4736              :      color which gives the user a little better debug output upon a crash.
    4737              :      Meanwhile, when using a random frame tag it will be nice to avoid adding
    4738              :      tags for the first object since that is unnecessary extra work.
    4739              :      Hence set the initial hwasan_frame_tag_offset to be 0 if using a random
    4740              :      frame tag and 1 otherwise.
    4741              : 
    4742              :      As described in hwasan_increment_frame_tag, in the kernel the stack
    4743              :      pointer has the tag 0xff.  That means that to avoid 0xff and 0 (the tag
    4744              :      which the kernel does not check and the background tag respectively) we
    4745              :      start with a tag offset of 2.  */
    4746         2066 :   hwasan_frame_tag_offset = param_hwasan_random_frame_tag
    4747              :     ? 0
    4748          958 :     : sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS) ? 2 : 1;
    4749         1108 : }
    4750              : 
    4751              : /* For stack tagging:
    4752              :    (Emits HWASAN equivalent of what is emitted by
    4753              :    `asan_emit_stack_protection`).
    4754              : 
    4755              :    Emits the extra prologue code to set the shadow stack as required for HWASAN
    4756              :    stack instrumentation.
    4757              : 
    4758              :    Uses the vector of recorded stack variables hwasan_tagged_stack_vars.  When
    4759              :    this function has completed hwasan_tagged_stack_vars is empty and all
    4760              :    objects it had pointed to are deallocated.  */
    4761              : void
    4762          364 : hwasan_emit_prologue ()
    4763              : {
    4764              :   /* We need untagged base pointers since libhwasan only accepts untagged
    4765              :     pointers in __hwasan_tag_memory.  We need the tagged base pointer to obtain
    4766              :     the base tag for an offset.  */
    4767              : 
    4768          364 :   if (hwasan_tagged_stack_vars.is_empty ())
    4769          364 :     return;
    4770              : 
    4771           62 :   poly_int64 bot = 0, top = 0;
    4772          150 :   for (hwasan_stack_var &cur : hwasan_tagged_stack_vars)
    4773              :     {
    4774           88 :       poly_int64 nearest = cur.nearest_offset;
    4775           88 :       poly_int64 farthest = cur.farthest_offset;
    4776              : 
    4777           88 :       if (known_ge (nearest, farthest))
    4778              :         {
    4779              :           top = nearest;
    4780              :           bot = farthest;
    4781              :         }
    4782              :       else
    4783              :         {
    4784              :           /* Given how these values are calculated, one must be known greater
    4785              :              than the other.  */
    4786            0 :           gcc_assert (known_le (nearest, farthest));
    4787            0 :           top = farthest;
    4788            0 :           bot = nearest;
    4789              :         }
    4790           88 :       poly_int64 size = (top - bot);
    4791              : 
    4792              :       /* Assert the edge of each variable is aligned to the HWASAN tag granule
    4793              :          size.  */
    4794          176 :       gcc_assert (multiple_p (top, HWASAN_TAG_GRANULE_SIZE));
    4795          176 :       gcc_assert (multiple_p (bot, HWASAN_TAG_GRANULE_SIZE));
    4796          176 :       gcc_assert (multiple_p (size, HWASAN_TAG_GRANULE_SIZE));
    4797              : 
    4798           88 :       rtx base_tag = targetm.memtag.extract_tag (cur.tagged_base, NULL_RTX);
    4799              : 
    4800           88 :       rtx bottom = convert_memory_address (ptr_mode,
    4801              :                                            plus_constant (Pmode,
    4802              :                                                           cur.untagged_base,
    4803              :                                                           bot));
    4804           88 :       if (memtag_sanitize_p ())
    4805              :         {
    4806            0 :           expand_operand ops[3];
    4807            0 :           rtx tagged_addr = gen_reg_rtx (ptr_mode);
    4808              : 
    4809              :           /* Check if the required target instructions are present.  */
    4810            0 :           gcc_assert (targetm.have_compose_tag ());
    4811            0 :           gcc_assert (targetm.have_tag_memory ());
    4812              : 
    4813              :           /* The AArch64 has addg/subg instructions which are working directly
    4814              :              on a tagged pointer.  */
    4815            0 :           create_output_operand (&ops[0], tagged_addr, ptr_mode);
    4816            0 :           create_input_operand (&ops[1], base_tag, ptr_mode);
    4817            0 :           create_integer_operand (&ops[2], cur.tag_offset);
    4818            0 :           expand_insn (targetm.code_for_compose_tag, 3, ops);
    4819              : 
    4820            0 :           emit_insn (targetm.gen_tag_memory (bottom, tagged_addr,
    4821              :                                              gen_int_mode (size, ptr_mode)));
    4822              :         }
    4823              :       else
    4824              :         {
    4825           88 :           rtx fn = init_one_libfunc ("__hwasan_tag_memory");
    4826           88 :           rtx tag = plus_constant (QImode, base_tag, cur.tag_offset);
    4827           88 :           tag = hwasan_truncate_to_tag_size (tag, NULL_RTX);
    4828           88 :           emit_library_call (fn, LCT_NORMAL, VOIDmode,
    4829              :                              bottom, ptr_mode,
    4830              :                              tag, QImode,
    4831              :                              gen_int_mode (size, ptr_mode), ptr_mode);
    4832              :         }
    4833              :     }
    4834              :   /* Clear the stack vars, we've emitted the prologue for them all now.  */
    4835           62 :   hwasan_tagged_stack_vars.truncate (0);
    4836              : }
    4837              : 
    4838              : /* For stack tagging:
    4839              : 
    4840              :    Return RTL insns to clear the tags between DYNAMIC and VARS pointers
    4841              :    into the stack.  These instructions should be emitted at the end of
    4842              :    every function.
    4843              : 
    4844              :    If `dynamic` is NULL_RTX then no insns are returned.  */
    4845              : rtx_insn *
    4846          364 : hwasan_emit_untag_frame (rtx dynamic, rtx vars)
    4847              : {
    4848          364 :   if (! dynamic)
    4849              :     return NULL;
    4850              : 
    4851           62 :   start_sequence ();
    4852              : 
    4853           62 :   dynamic = convert_memory_address (ptr_mode, dynamic);
    4854           62 :   vars = convert_memory_address (ptr_mode, vars);
    4855              : 
    4856           62 :   rtx top_rtx;
    4857           62 :   rtx bot_rtx;
    4858           62 :   if (FRAME_GROWS_DOWNWARD)
    4859              :     {
    4860           62 :       top_rtx = vars;
    4861           62 :       bot_rtx = dynamic;
    4862              :     }
    4863              :   else
    4864              :     {
    4865              :       top_rtx = dynamic;
    4866              :       bot_rtx = vars;
    4867              :     }
    4868              : 
    4869           62 :   rtx size_rtx = simplify_gen_binary (MINUS, ptr_mode, top_rtx, bot_rtx);
    4870           62 :   if (!CONST_INT_P (size_rtx))
    4871            0 :     size_rtx = force_reg (ptr_mode, size_rtx);
    4872              : 
    4873           62 :   if (memtag_sanitize_p ())
    4874            0 :     emit_insn (targetm.gen_tag_memory (bot_rtx, HWASAN_STACK_BACKGROUND,
    4875              :                                        size_rtx));
    4876              :   else
    4877              :     {
    4878           62 :       rtx fn = init_one_libfunc ("__hwasan_tag_memory");
    4879           62 :       emit_library_call (fn, LCT_NORMAL, VOIDmode,
    4880              :                          bot_rtx, ptr_mode,
    4881              :                          HWASAN_STACK_BACKGROUND, QImode,
    4882              :                          size_rtx, ptr_mode);
    4883              :     }
    4884              : 
    4885           62 :   do_pending_stack_adjust ();
    4886           62 :   return end_sequence ();
    4887              : }
    4888              : 
    4889              : /* Needs to be GTY(()), because cgraph_build_static_cdtor may
    4890              :    invoke ggc_collect.  */
    4891              : static GTY(()) tree hwasan_ctor_statements;
    4892              : 
    4893              : /* Insert module initialization into this TU.  This initialization calls the
    4894              :    initialization code for libhwasan.  */
    4895              : void
    4896          250 : hwasan_finish_file (void)
    4897              : {
    4898              :   /* Do not emit constructor initialization for the kernel.
    4899              :      (the kernel has its own initialization already).  */
    4900          250 :   if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
    4901              :     return;
    4902              : 
    4903          236 :   initialize_sanitizer_builtins ();
    4904              : 
    4905              :   /* Avoid instrumenting code in the hwasan constructors/destructors.  */
    4906          236 :   flag_sanitize &= ~SANITIZE_HWADDRESS;
    4907          236 :   int priority = MAX_RESERVED_INIT_PRIORITY - 1;
    4908          236 :   tree fn = builtin_decl_implicit (BUILT_IN_HWASAN_INIT);
    4909          236 :   append_to_statement_list (build_call_expr (fn, 0), &hwasan_ctor_statements);
    4910          236 :   cgraph_build_static_cdtor ('I', hwasan_ctor_statements, priority);
    4911          236 :   flag_sanitize |= SANITIZE_HWADDRESS;
    4912              : }
    4913              : 
    4914              : /* For stack tagging:
    4915              : 
    4916              :    Truncate `tag` to the number of bits that a tag uses (i.e. to
    4917              :    HWASAN_TAG_SIZE).  Store the result in `target` if it's convenient.  */
    4918              : rtx
    4919           88 : hwasan_truncate_to_tag_size (rtx tag, rtx target)
    4920              : {
    4921           88 :   gcc_assert (GET_MODE (tag) == QImode);
    4922           88 :   if (HWASAN_TAG_SIZE != GET_MODE_PRECISION (QImode))
    4923              :     {
    4924           88 :       gcc_assert (GET_MODE_PRECISION (QImode) > HWASAN_TAG_SIZE);
    4925           88 :       rtx mask = gen_int_mode ((HOST_WIDE_INT_1U << HWASAN_TAG_SIZE) - 1,
    4926              :                                QImode);
    4927           88 :       tag = expand_simple_binop (QImode, AND, tag, mask, target,
    4928              :                                  /* unsignedp = */1, OPTAB_WIDEN);
    4929           88 :       gcc_assert (tag);
    4930              :     }
    4931           88 :   return tag;
    4932              : }
    4933              : 
    4934              : /* Construct a function tree for __hwasan_{load,store}{1,2,4,8,16,_n}.
    4935              :    IS_STORE is either 1 (for a store) or 0 (for a load).  */
    4936              : static combined_fn
    4937          376 : hwasan_check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
    4938              :                    int *nargs)
    4939              : {
    4940          376 :   static enum built_in_function check[2][2][6]
    4941              :     = { { { BUILT_IN_HWASAN_LOAD1, BUILT_IN_HWASAN_LOAD2,
    4942              :             BUILT_IN_HWASAN_LOAD4, BUILT_IN_HWASAN_LOAD8,
    4943              :             BUILT_IN_HWASAN_LOAD16, BUILT_IN_HWASAN_LOADN },
    4944              :           { BUILT_IN_HWASAN_STORE1, BUILT_IN_HWASAN_STORE2,
    4945              :             BUILT_IN_HWASAN_STORE4, BUILT_IN_HWASAN_STORE8,
    4946              :             BUILT_IN_HWASAN_STORE16, BUILT_IN_HWASAN_STOREN } },
    4947              :         { { BUILT_IN_HWASAN_LOAD1_NOABORT,
    4948              :             BUILT_IN_HWASAN_LOAD2_NOABORT,
    4949              :             BUILT_IN_HWASAN_LOAD4_NOABORT,
    4950              :             BUILT_IN_HWASAN_LOAD8_NOABORT,
    4951              :             BUILT_IN_HWASAN_LOAD16_NOABORT,
    4952              :             BUILT_IN_HWASAN_LOADN_NOABORT },
    4953              :           { BUILT_IN_HWASAN_STORE1_NOABORT,
    4954              :             BUILT_IN_HWASAN_STORE2_NOABORT,
    4955              :             BUILT_IN_HWASAN_STORE4_NOABORT,
    4956              :             BUILT_IN_HWASAN_STORE8_NOABORT,
    4957              :             BUILT_IN_HWASAN_STORE16_NOABORT,
    4958              :             BUILT_IN_HWASAN_STOREN_NOABORT } } };
    4959          376 :   if (size_in_bytes == -1)
    4960              :     {
    4961            0 :       *nargs = 2;
    4962            0 :       return as_combined_fn (check[recover_p][is_store][5]);
    4963              :     }
    4964          376 :   *nargs = 1;
    4965          376 :   int size_log2 = exact_log2 (size_in_bytes);
    4966          376 :   gcc_assert (size_log2 >= 0 && size_log2 <= 5);
    4967          376 :   return as_combined_fn (check[recover_p][is_store][size_log2]);
    4968              : }
    4969              : 
    4970              : /* Expand the HWASAN_{LOAD,STORE} builtins.  */
    4971              : bool
    4972          376 : hwasan_expand_check_ifn (gimple_stmt_iterator *iter, bool)
    4973              : {
    4974          376 :   gimple *g = gsi_stmt (*iter);
    4975          376 :   location_t loc = gimple_location (g);
    4976          376 :   bool recover_p;
    4977          376 :   if (flag_sanitize & SANITIZE_USER_HWADDRESS)
    4978          316 :     recover_p = (flag_sanitize_recover & SANITIZE_USER_HWADDRESS) != 0;
    4979              :   else
    4980           60 :     recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_HWADDRESS) != 0;
    4981              : 
    4982          376 :   HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
    4983          376 :   gcc_assert (flags < ASAN_CHECK_LAST);
    4984          376 :   bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
    4985          376 :   bool is_store = (flags & ASAN_CHECK_STORE) != 0;
    4986          376 :   bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
    4987              : 
    4988          376 :   tree base = gimple_call_arg (g, 1);
    4989          376 :   tree len = gimple_call_arg (g, 2);
    4990              : 
    4991              :   /* `align` is unused for HWASAN_CHECK, but we pass the argument anyway
    4992              :      since that way the arguments match ASAN_CHECK.  */
    4993              :   /* HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3));  */
    4994              : 
    4995         1128 :   unsigned HOST_WIDE_INT size_in_bytes
    4996          376 :     = is_scalar_access ? tree_to_shwi (len) : -1;
    4997              : 
    4998          376 :   gimple_stmt_iterator gsi = *iter;
    4999              : 
    5000          376 :   if (!is_non_zero_len)
    5001              :     {
    5002              :       /* So, the length of the memory area to hwasan-protect is
    5003              :          non-constant.  Let's guard the generated instrumentation code
    5004              :          like:
    5005              : 
    5006              :          if (len != 0)
    5007              :            {
    5008              :              // hwasan instrumentation code goes here.
    5009              :            }
    5010              :          // fallthrough instructions, starting with *ITER.  */
    5011              : 
    5012            0 :       g = gimple_build_cond (NE_EXPR,
    5013              :                             len,
    5014            0 :                             build_int_cst (TREE_TYPE (len), 0),
    5015              :                             NULL_TREE, NULL_TREE);
    5016            0 :       gimple_set_location (g, loc);
    5017              : 
    5018            0 :       basic_block then_bb, fallthrough_bb;
    5019            0 :       insert_if_then_before_iter (as_a <gcond *> (g), iter,
    5020              :                                   /*then_more_likely_p=*/true,
    5021              :                                   &then_bb, &fallthrough_bb);
    5022              :       /* Note that fallthrough_bb starts with the statement that was
    5023              :         pointed to by ITER.  */
    5024              : 
    5025              :       /* The 'then block' of the 'if (len != 0) condition is where
    5026              :         we'll generate the hwasan instrumentation code now.  */
    5027            0 :       gsi = gsi_last_bb (then_bb);
    5028              :     }
    5029              : 
    5030          376 :   gimple_seq stmts = NULL;
    5031          376 :   tree base_addr = gimple_build (&stmts, loc, NOP_EXPR,
    5032              :                                  pointer_sized_int_node, base);
    5033              : 
    5034          376 :   int nargs = 0;
    5035          376 :   combined_fn fn
    5036          376 :     = hwasan_check_func (is_store, recover_p, size_in_bytes, &nargs);
    5037          376 :   if (nargs == 1)
    5038          376 :     gimple_build (&stmts, loc, fn, void_type_node, base_addr);
    5039              :   else
    5040              :     {
    5041            0 :       gcc_assert (nargs == 2);
    5042            0 :       tree sz_arg = gimple_build (&stmts, loc, NOP_EXPR,
    5043              :                                   pointer_sized_int_node, len);
    5044            0 :       gimple_build (&stmts, loc, fn, void_type_node, base_addr, sz_arg);
    5045              :     }
    5046              : 
    5047          376 :   gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
    5048          376 :   gsi_remove (iter, true);
    5049          376 :   *iter = gsi;
    5050          376 :   return false;
    5051              : }
    5052              : 
    5053              : /* For stack tagging:
    5054              : 
    5055              :    Dummy: the HWASAN_MARK internal function should only ever be in the code
    5056              :    after the sanopt pass.  */
    5057              : bool
    5058            0 : hwasan_expand_mark_ifn (gimple_stmt_iterator *)
    5059              : {
    5060            0 :   gcc_unreachable ();
    5061              : }
    5062              : 
    5063              : bool
    5064      1747190 : gate_hwasan ()
    5065              : {
    5066      1747190 :   return hwasan_sanitize_p ();
    5067              : }
    5068              : 
    5069              : bool
    5070      1509455 : gate_memtag ()
    5071              : {
    5072      1509455 :   return memtag_sanitize_p ();
    5073              : }
    5074              : 
    5075              : #include "gt-asan.h"
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.