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