xref: /dflybsd-src/contrib/gcc-8.0/gcc/asan.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* AddressSanitizer, a fast memory error detector.
238fd1498Szrj    Copyright (C) 2012-2018 Free Software Foundation, Inc.
338fd1498Szrj    Contributed by Kostya Serebryany <kcc@google.com>
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj 
2238fd1498Szrj #include "config.h"
2338fd1498Szrj #include "system.h"
2438fd1498Szrj #include "coretypes.h"
2538fd1498Szrj #include "backend.h"
2638fd1498Szrj #include "target.h"
2738fd1498Szrj #include "rtl.h"
2838fd1498Szrj #include "tree.h"
2938fd1498Szrj #include "gimple.h"
3038fd1498Szrj #include "cfghooks.h"
3138fd1498Szrj #include "alloc-pool.h"
3238fd1498Szrj #include "tree-pass.h"
3338fd1498Szrj #include "memmodel.h"
3438fd1498Szrj #include "tm_p.h"
3538fd1498Szrj #include "ssa.h"
3638fd1498Szrj #include "stringpool.h"
3738fd1498Szrj #include "tree-ssanames.h"
3838fd1498Szrj #include "optabs.h"
3938fd1498Szrj #include "emit-rtl.h"
4038fd1498Szrj #include "cgraph.h"
4138fd1498Szrj #include "gimple-pretty-print.h"
4238fd1498Szrj #include "alias.h"
4338fd1498Szrj #include "fold-const.h"
4438fd1498Szrj #include "cfganal.h"
4538fd1498Szrj #include "gimplify.h"
4638fd1498Szrj #include "gimple-iterator.h"
4738fd1498Szrj #include "varasm.h"
4838fd1498Szrj #include "stor-layout.h"
4938fd1498Szrj #include "tree-iterator.h"
5038fd1498Szrj #include "stringpool.h"
5138fd1498Szrj #include "attribs.h"
5238fd1498Szrj #include "asan.h"
5338fd1498Szrj #include "dojump.h"
5438fd1498Szrj #include "explow.h"
5538fd1498Szrj #include "expr.h"
5638fd1498Szrj #include "output.h"
5738fd1498Szrj #include "langhooks.h"
5838fd1498Szrj #include "cfgloop.h"
5938fd1498Szrj #include "gimple-builder.h"
6038fd1498Szrj #include "gimple-fold.h"
6138fd1498Szrj #include "ubsan.h"
6238fd1498Szrj #include "params.h"
6338fd1498Szrj #include "builtins.h"
6438fd1498Szrj #include "fnmatch.h"
6538fd1498Szrj #include "tree-inline.h"
6638fd1498Szrj 
6738fd1498Szrj /* AddressSanitizer finds out-of-bounds and use-after-free bugs
6838fd1498Szrj    with <2x slowdown on average.
6938fd1498Szrj 
7038fd1498Szrj    The tool consists of two parts:
7138fd1498Szrj    instrumentation module (this file) and a run-time library.
7238fd1498Szrj    The instrumentation module adds a run-time check before every memory insn.
7338fd1498Szrj      For a 8- or 16- byte load accessing address X:
7438fd1498Szrj        ShadowAddr = (X >> 3) + Offset
7538fd1498Szrj        ShadowValue = *(char*)ShadowAddr;  // *(short*) for 16-byte access.
7638fd1498Szrj        if (ShadowValue)
7738fd1498Szrj 	 __asan_report_load8(X);
7838fd1498Szrj      For a load of N bytes (N=1, 2 or 4) from address X:
7938fd1498Szrj        ShadowAddr = (X >> 3) + Offset
8038fd1498Szrj        ShadowValue = *(char*)ShadowAddr;
8138fd1498Szrj        if (ShadowValue)
8238fd1498Szrj 	 if ((X & 7) + N - 1 > ShadowValue)
8338fd1498Szrj 	   __asan_report_loadN(X);
8438fd1498Szrj    Stores are instrumented similarly, but using __asan_report_storeN functions.
8538fd1498Szrj    A call too __asan_init_vN() is inserted to the list of module CTORs.
8638fd1498Szrj    N is the version number of the AddressSanitizer API. The changes between the
8738fd1498Szrj    API versions are listed in libsanitizer/asan/asan_interface_internal.h.
8838fd1498Szrj 
8938fd1498Szrj    The run-time library redefines malloc (so that redzone are inserted around
9038fd1498Szrj    the allocated memory) and free (so that reuse of free-ed memory is delayed),
9138fd1498Szrj    provides __asan_report* and __asan_init_vN functions.
9238fd1498Szrj 
9338fd1498Szrj    Read more:
9438fd1498Szrj    http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
9538fd1498Szrj 
9638fd1498Szrj    The current implementation supports detection of out-of-bounds and
9738fd1498Szrj    use-after-free in the heap, on the stack and for global variables.
9838fd1498Szrj 
9938fd1498Szrj    [Protection of stack variables]
10038fd1498Szrj 
10138fd1498Szrj    To understand how detection of out-of-bounds and use-after-free works
10238fd1498Szrj    for stack variables, lets look at this example on x86_64 where the
10338fd1498Szrj    stack grows downward:
10438fd1498Szrj 
10538fd1498Szrj      int
10638fd1498Szrj      foo ()
10738fd1498Szrj      {
10838fd1498Szrj        char a[23] = {0};
10938fd1498Szrj        int b[2] = {0};
11038fd1498Szrj 
11138fd1498Szrj        a[5] = 1;
11238fd1498Szrj        b[1] = 2;
11338fd1498Szrj 
11438fd1498Szrj        return a[5] + b[1];
11538fd1498Szrj      }
11638fd1498Szrj 
11738fd1498Szrj    For this function, the stack protected by asan will be organized as
11838fd1498Szrj    follows, from the top of the stack to the bottom:
11938fd1498Szrj 
12038fd1498Szrj    Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone']
12138fd1498Szrj 
12238fd1498Szrj    Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make
12338fd1498Szrj 	   the next slot be 32 bytes aligned; this one is called Partial
12438fd1498Szrj 	   Redzone; this 32 bytes alignment is an asan constraint]
12538fd1498Szrj 
12638fd1498Szrj    Slot 3/ [24 bytes for variable 'a']
12738fd1498Szrj 
12838fd1498Szrj    Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
12938fd1498Szrj 
13038fd1498Szrj    Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
13138fd1498Szrj 
13238fd1498Szrj    Slot 6/ [8 bytes for variable 'b']
13338fd1498Szrj 
13438fd1498Szrj    Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called
13538fd1498Szrj 	    'LEFT RedZone']
13638fd1498Szrj 
13738fd1498Szrj    The 32 bytes of LEFT red zone at the bottom of the stack can be
13838fd1498Szrj    decomposed as such:
13938fd1498Szrj 
14038fd1498Szrj      1/ The first 8 bytes contain a magical asan number that is always
14138fd1498Szrj      0x41B58AB3.
14238fd1498Szrj 
14338fd1498Szrj      2/ The following 8 bytes contains a pointer to a string (to be
14438fd1498Szrj      parsed at runtime by the runtime asan library), which format is
14538fd1498Szrj      the following:
14638fd1498Szrj 
14738fd1498Szrj       "<function-name> <space> <num-of-variables-on-the-stack>
14838fd1498Szrj       (<32-bytes-aligned-offset-in-bytes-of-variable> <space>
14938fd1498Szrj       <length-of-var-in-bytes> ){n} "
15038fd1498Szrj 
15138fd1498Szrj 	where '(...){n}' means the content inside the parenthesis occurs 'n'
15238fd1498Szrj 	times, with 'n' being the number of variables on the stack.
15338fd1498Szrj 
15438fd1498Szrj      3/ The following 8 bytes contain the PC of the current function which
15538fd1498Szrj      will be used by the run-time library to print an error message.
15638fd1498Szrj 
15738fd1498Szrj      4/ The following 8 bytes are reserved for internal use by the run-time.
15838fd1498Szrj 
15938fd1498Szrj    The shadow memory for that stack layout is going to look like this:
16038fd1498Szrj 
16138fd1498Szrj      - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1.
16238fd1498Szrj        The F1 byte pattern is a magic number called
16338fd1498Szrj        ASAN_STACK_MAGIC_LEFT and is a way for the runtime to know that
16438fd1498Szrj        the memory for that shadow byte is part of a the LEFT red zone
16538fd1498Szrj        intended to seat at the bottom of the variables on the stack.
16638fd1498Szrj 
16738fd1498Szrj      - content of shadow memory 8 bytes for slots 6 and 5:
16838fd1498Szrj        0xF4F4F400.  The F4 byte pattern is a magic number
16938fd1498Szrj        called ASAN_STACK_MAGIC_PARTIAL.  It flags the fact that the
17038fd1498Szrj        memory region for this shadow byte is a PARTIAL red zone
17138fd1498Szrj        intended to pad a variable A, so that the slot following
17238fd1498Szrj        {A,padding} is 32 bytes aligned.
17338fd1498Szrj 
17438fd1498Szrj        Note that the fact that the least significant byte of this
17538fd1498Szrj        shadow memory content is 00 means that 8 bytes of its
17638fd1498Szrj        corresponding memory (which corresponds to the memory of
17738fd1498Szrj        variable 'b') is addressable.
17838fd1498Szrj 
17938fd1498Szrj      - content of shadow memory 8 bytes for slot 4: 0xF2F2F2F2.
18038fd1498Szrj        The F2 byte pattern is a magic number called
18138fd1498Szrj        ASAN_STACK_MAGIC_MIDDLE.  It flags the fact that the memory
18238fd1498Szrj        region for this shadow byte is a MIDDLE red zone intended to
18338fd1498Szrj        seat between two 32 aligned slots of {variable,padding}.
18438fd1498Szrj 
18538fd1498Szrj      - content of shadow memory 8 bytes for slot 3 and 2:
18638fd1498Szrj        0xF4000000.  This represents is the concatenation of
18738fd1498Szrj        variable 'a' and the partial red zone following it, like what we
18838fd1498Szrj        had for variable 'b'.  The least significant 3 bytes being 00
18938fd1498Szrj        means that the 3 bytes of variable 'a' are addressable.
19038fd1498Szrj 
19138fd1498Szrj      - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3.
19238fd1498Szrj        The F3 byte pattern is a magic number called
19338fd1498Szrj        ASAN_STACK_MAGIC_RIGHT.  It flags the fact that the memory
19438fd1498Szrj        region for this shadow byte is a RIGHT red zone intended to seat
19538fd1498Szrj        at the top of the variables of the stack.
19638fd1498Szrj 
19738fd1498Szrj    Note that the real variable layout is done in expand_used_vars in
19838fd1498Szrj    cfgexpand.c.  As far as Address Sanitizer is concerned, it lays out
19938fd1498Szrj    stack variables as well as the different red zones, emits some
20038fd1498Szrj    prologue code to populate the shadow memory as to poison (mark as
20138fd1498Szrj    non-accessible) the regions of the red zones and mark the regions of
20238fd1498Szrj    stack variables as accessible, and emit some epilogue code to
20338fd1498Szrj    un-poison (mark as accessible) the regions of red zones right before
20438fd1498Szrj    the function exits.
20538fd1498Szrj 
20638fd1498Szrj    [Protection of global variables]
20738fd1498Szrj 
20838fd1498Szrj    The basic idea is to insert a red zone between two global variables
20938fd1498Szrj    and install a constructor function that calls the asan runtime to do
21038fd1498Szrj    the populating of the relevant shadow memory regions at load time.
21138fd1498Szrj 
21238fd1498Szrj    So the global variables are laid out as to insert a red zone between
21338fd1498Szrj    them. The size of the red zones is so that each variable starts on a
21438fd1498Szrj    32 bytes boundary.
21538fd1498Szrj 
21638fd1498Szrj    Then a constructor function is installed so that, for each global
21738fd1498Szrj    variable, it calls the runtime asan library function
21838fd1498Szrj    __asan_register_globals_with an instance of this type:
21938fd1498Szrj 
22038fd1498Szrj      struct __asan_global
22138fd1498Szrj      {
22238fd1498Szrj        // Address of the beginning of the global variable.
22338fd1498Szrj        const void *__beg;
22438fd1498Szrj 
22538fd1498Szrj        // Initial size of the global variable.
22638fd1498Szrj        uptr __size;
22738fd1498Szrj 
22838fd1498Szrj        // Size of the global variable + size of the red zone.  This
22938fd1498Szrj        //   size is 32 bytes aligned.
23038fd1498Szrj        uptr __size_with_redzone;
23138fd1498Szrj 
23238fd1498Szrj        // Name of the global variable.
23338fd1498Szrj        const void *__name;
23438fd1498Szrj 
23538fd1498Szrj        // Name of the module where the global variable is declared.
23638fd1498Szrj        const void *__module_name;
23738fd1498Szrj 
23838fd1498Szrj        // 1 if it has dynamic initialization, 0 otherwise.
23938fd1498Szrj        uptr __has_dynamic_init;
24038fd1498Szrj 
24138fd1498Szrj        // A pointer to struct that contains source location, could be NULL.
24238fd1498Szrj        __asan_global_source_location *__location;
24338fd1498Szrj      }
24438fd1498Szrj 
24538fd1498Szrj    A destructor function that calls the runtime asan library function
24638fd1498Szrj    _asan_unregister_globals is also installed.  */
24738fd1498Szrj 
24838fd1498Szrj static unsigned HOST_WIDE_INT asan_shadow_offset_value;
24938fd1498Szrj static bool asan_shadow_offset_computed;
25038fd1498Szrj static vec<char *> sanitized_sections;
25138fd1498Szrj static tree last_alloca_addr;
25238fd1498Szrj 
25338fd1498Szrj /* Set of variable declarations that are going to be guarded by
25438fd1498Szrj    use-after-scope sanitizer.  */
25538fd1498Szrj 
256*58e805e6Szrj hash_set<tree> *asan_handled_variables = NULL;
25738fd1498Szrj 
25838fd1498Szrj hash_set <tree> *asan_used_labels = NULL;
25938fd1498Szrj 
26038fd1498Szrj /* Sets shadow offset to value in string VAL.  */
26138fd1498Szrj 
26238fd1498Szrj bool
set_asan_shadow_offset(const char * val)26338fd1498Szrj set_asan_shadow_offset (const char *val)
26438fd1498Szrj {
26538fd1498Szrj   char *endp;
26638fd1498Szrj 
26738fd1498Szrj   errno = 0;
26838fd1498Szrj #ifdef HAVE_LONG_LONG
26938fd1498Szrj   asan_shadow_offset_value = strtoull (val, &endp, 0);
27038fd1498Szrj #else
27138fd1498Szrj   asan_shadow_offset_value = strtoul (val, &endp, 0);
27238fd1498Szrj #endif
27338fd1498Szrj   if (!(*val != '\0' && *endp == '\0' && errno == 0))
27438fd1498Szrj     return false;
27538fd1498Szrj 
27638fd1498Szrj   asan_shadow_offset_computed = true;
27738fd1498Szrj 
27838fd1498Szrj   return true;
27938fd1498Szrj }
28038fd1498Szrj 
28138fd1498Szrj /* Set list of user-defined sections that need to be sanitized.  */
28238fd1498Szrj 
28338fd1498Szrj void
set_sanitized_sections(const char * sections)28438fd1498Szrj set_sanitized_sections (const char *sections)
28538fd1498Szrj {
28638fd1498Szrj   char *pat;
28738fd1498Szrj   unsigned i;
28838fd1498Szrj   FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
28938fd1498Szrj     free (pat);
29038fd1498Szrj   sanitized_sections.truncate (0);
29138fd1498Szrj 
29238fd1498Szrj   for (const char *s = sections; *s; )
29338fd1498Szrj     {
29438fd1498Szrj       const char *end;
29538fd1498Szrj       for (end = s; *end && *end != ','; ++end);
29638fd1498Szrj       size_t len = end - s;
29738fd1498Szrj       sanitized_sections.safe_push (xstrndup (s, len));
29838fd1498Szrj       s = *end ? end + 1 : end;
29938fd1498Szrj     }
30038fd1498Szrj }
30138fd1498Szrj 
30238fd1498Szrj bool
asan_mark_p(gimple * stmt,enum asan_mark_flags flag)30338fd1498Szrj asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
30438fd1498Szrj {
30538fd1498Szrj   return (gimple_call_internal_p (stmt, IFN_ASAN_MARK)
30638fd1498Szrj 	  && tree_to_uhwi (gimple_call_arg (stmt, 0)) == flag);
30738fd1498Szrj }
30838fd1498Szrj 
30938fd1498Szrj bool
asan_sanitize_stack_p(void)31038fd1498Szrj asan_sanitize_stack_p (void)
31138fd1498Szrj {
31238fd1498Szrj   return (sanitize_flags_p (SANITIZE_ADDRESS) && ASAN_STACK);
31338fd1498Szrj }
31438fd1498Szrj 
31538fd1498Szrj bool
asan_sanitize_allocas_p(void)31638fd1498Szrj asan_sanitize_allocas_p (void)
31738fd1498Szrj {
31838fd1498Szrj   return (asan_sanitize_stack_p () && ASAN_PROTECT_ALLOCAS);
31938fd1498Szrj }
32038fd1498Szrj 
32138fd1498Szrj /* Checks whether section SEC should be sanitized.  */
32238fd1498Szrj 
32338fd1498Szrj static bool
section_sanitized_p(const char * sec)32438fd1498Szrj section_sanitized_p (const char *sec)
32538fd1498Szrj {
32638fd1498Szrj   char *pat;
32738fd1498Szrj   unsigned i;
32838fd1498Szrj   FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
32938fd1498Szrj     if (fnmatch (pat, sec, FNM_PERIOD) == 0)
33038fd1498Szrj       return true;
33138fd1498Szrj   return false;
33238fd1498Szrj }
33338fd1498Szrj 
33438fd1498Szrj /* Returns Asan shadow offset.  */
33538fd1498Szrj 
33638fd1498Szrj static unsigned HOST_WIDE_INT
asan_shadow_offset()33738fd1498Szrj asan_shadow_offset ()
33838fd1498Szrj {
33938fd1498Szrj   if (!asan_shadow_offset_computed)
34038fd1498Szrj     {
34138fd1498Szrj       asan_shadow_offset_computed = true;
34238fd1498Szrj       asan_shadow_offset_value = targetm.asan_shadow_offset ();
34338fd1498Szrj     }
34438fd1498Szrj   return asan_shadow_offset_value;
34538fd1498Szrj }
34638fd1498Szrj 
34738fd1498Szrj alias_set_type asan_shadow_set = -1;
34838fd1498Szrj 
34938fd1498Szrj /* Pointer types to 1, 2 or 4 byte integers in shadow memory.  A separate
35038fd1498Szrj    alias set is used for all shadow memory accesses.  */
35138fd1498Szrj static GTY(()) tree shadow_ptr_types[3];
35238fd1498Szrj 
35338fd1498Szrj /* Decl for __asan_option_detect_stack_use_after_return.  */
35438fd1498Szrj static GTY(()) tree asan_detect_stack_use_after_return;
35538fd1498Szrj 
35638fd1498Szrj /* Hashtable support for memory references used by gimple
35738fd1498Szrj    statements.  */
35838fd1498Szrj 
35938fd1498Szrj /* This type represents a reference to a memory region.  */
36038fd1498Szrj struct asan_mem_ref
36138fd1498Szrj {
36238fd1498Szrj   /* The expression of the beginning of the memory region.  */
36338fd1498Szrj   tree start;
36438fd1498Szrj 
36538fd1498Szrj   /* The size of the access.  */
36638fd1498Szrj   HOST_WIDE_INT access_size;
36738fd1498Szrj };
36838fd1498Szrj 
36938fd1498Szrj object_allocator <asan_mem_ref> asan_mem_ref_pool ("asan_mem_ref");
37038fd1498Szrj 
37138fd1498Szrj /* Initializes an instance of asan_mem_ref.  */
37238fd1498Szrj 
37338fd1498Szrj static void
asan_mem_ref_init(asan_mem_ref * ref,tree start,HOST_WIDE_INT access_size)37438fd1498Szrj asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size)
37538fd1498Szrj {
37638fd1498Szrj   ref->start = start;
37738fd1498Szrj   ref->access_size = access_size;
37838fd1498Szrj }
37938fd1498Szrj 
38038fd1498Szrj /* Allocates memory for an instance of asan_mem_ref into the memory
38138fd1498Szrj    pool returned by asan_mem_ref_get_alloc_pool and initialize it.
38238fd1498Szrj    START is the address of (or the expression pointing to) the
38338fd1498Szrj    beginning of memory reference.  ACCESS_SIZE is the size of the
38438fd1498Szrj    access to the referenced memory.  */
38538fd1498Szrj 
38638fd1498Szrj static asan_mem_ref*
asan_mem_ref_new(tree start,HOST_WIDE_INT access_size)38738fd1498Szrj asan_mem_ref_new (tree start, HOST_WIDE_INT access_size)
38838fd1498Szrj {
38938fd1498Szrj   asan_mem_ref *ref = asan_mem_ref_pool.allocate ();
39038fd1498Szrj 
39138fd1498Szrj   asan_mem_ref_init (ref, start, access_size);
39238fd1498Szrj   return ref;
39338fd1498Szrj }
39438fd1498Szrj 
39538fd1498Szrj /* This builds and returns a pointer to the end of the memory region
39638fd1498Szrj    that starts at START and of length LEN.  */
39738fd1498Szrj 
39838fd1498Szrj tree
asan_mem_ref_get_end(tree start,tree len)39938fd1498Szrj asan_mem_ref_get_end (tree start, tree len)
40038fd1498Szrj {
40138fd1498Szrj   if (len == NULL_TREE || integer_zerop (len))
40238fd1498Szrj     return start;
40338fd1498Szrj 
40438fd1498Szrj   if (!ptrofftype_p (len))
40538fd1498Szrj     len = convert_to_ptrofftype (len);
40638fd1498Szrj 
40738fd1498Szrj   return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len);
40838fd1498Szrj }
40938fd1498Szrj 
41038fd1498Szrj /*  Return a tree expression that represents the end of the referenced
41138fd1498Szrj     memory region.  Beware that this function can actually build a new
41238fd1498Szrj     tree expression.  */
41338fd1498Szrj 
41438fd1498Szrj tree
asan_mem_ref_get_end(const asan_mem_ref * ref,tree len)41538fd1498Szrj asan_mem_ref_get_end (const asan_mem_ref *ref, tree len)
41638fd1498Szrj {
41738fd1498Szrj   return asan_mem_ref_get_end (ref->start, len);
41838fd1498Szrj }
41938fd1498Szrj 
42038fd1498Szrj struct asan_mem_ref_hasher : nofree_ptr_hash <asan_mem_ref>
42138fd1498Szrj {
42238fd1498Szrj   static inline hashval_t hash (const asan_mem_ref *);
42338fd1498Szrj   static inline bool equal (const asan_mem_ref *, const asan_mem_ref *);
42438fd1498Szrj };
42538fd1498Szrj 
42638fd1498Szrj /* Hash a memory reference.  */
42738fd1498Szrj 
42838fd1498Szrj inline hashval_t
hash(const asan_mem_ref * mem_ref)42938fd1498Szrj asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref)
43038fd1498Szrj {
43138fd1498Szrj   return iterative_hash_expr (mem_ref->start, 0);
43238fd1498Szrj }
43338fd1498Szrj 
43438fd1498Szrj /* Compare two memory references.  We accept the length of either
43538fd1498Szrj    memory references to be NULL_TREE.  */
43638fd1498Szrj 
43738fd1498Szrj inline bool
equal(const asan_mem_ref * m1,const asan_mem_ref * m2)43838fd1498Szrj asan_mem_ref_hasher::equal (const asan_mem_ref *m1,
43938fd1498Szrj 			    const asan_mem_ref *m2)
44038fd1498Szrj {
44138fd1498Szrj   return operand_equal_p (m1->start, m2->start, 0);
44238fd1498Szrj }
44338fd1498Szrj 
44438fd1498Szrj static hash_table<asan_mem_ref_hasher> *asan_mem_ref_ht;
44538fd1498Szrj 
44638fd1498Szrj /* Returns a reference to the hash table containing memory references.
44738fd1498Szrj    This function ensures that the hash table is created.  Note that
44838fd1498Szrj    this hash table is updated by the function
44938fd1498Szrj    update_mem_ref_hash_table.  */
45038fd1498Szrj 
45138fd1498Szrj static hash_table<asan_mem_ref_hasher> *
get_mem_ref_hash_table()45238fd1498Szrj get_mem_ref_hash_table ()
45338fd1498Szrj {
45438fd1498Szrj   if (!asan_mem_ref_ht)
45538fd1498Szrj     asan_mem_ref_ht = new hash_table<asan_mem_ref_hasher> (10);
45638fd1498Szrj 
45738fd1498Szrj   return asan_mem_ref_ht;
45838fd1498Szrj }
45938fd1498Szrj 
46038fd1498Szrj /* Clear all entries from the memory references hash table.  */
46138fd1498Szrj 
46238fd1498Szrj static void
empty_mem_ref_hash_table()46338fd1498Szrj empty_mem_ref_hash_table ()
46438fd1498Szrj {
46538fd1498Szrj   if (asan_mem_ref_ht)
46638fd1498Szrj     asan_mem_ref_ht->empty ();
46738fd1498Szrj }
46838fd1498Szrj 
46938fd1498Szrj /* Free the memory references hash table.  */
47038fd1498Szrj 
47138fd1498Szrj static void
free_mem_ref_resources()47238fd1498Szrj free_mem_ref_resources ()
47338fd1498Szrj {
47438fd1498Szrj   delete asan_mem_ref_ht;
47538fd1498Szrj   asan_mem_ref_ht = NULL;
47638fd1498Szrj 
47738fd1498Szrj   asan_mem_ref_pool.release ();
47838fd1498Szrj }
47938fd1498Szrj 
48038fd1498Szrj /* Return true iff the memory reference REF has been instrumented.  */
48138fd1498Szrj 
48238fd1498Szrj static bool
has_mem_ref_been_instrumented(tree ref,HOST_WIDE_INT access_size)48338fd1498Szrj has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size)
48438fd1498Szrj {
48538fd1498Szrj   asan_mem_ref r;
48638fd1498Szrj   asan_mem_ref_init (&r, ref, access_size);
48738fd1498Szrj 
48838fd1498Szrj   asan_mem_ref *saved_ref = get_mem_ref_hash_table ()->find (&r);
48938fd1498Szrj   return saved_ref && saved_ref->access_size >= access_size;
49038fd1498Szrj }
49138fd1498Szrj 
49238fd1498Szrj /* Return true iff the memory reference REF has been instrumented.  */
49338fd1498Szrj 
49438fd1498Szrj static bool
has_mem_ref_been_instrumented(const asan_mem_ref * ref)49538fd1498Szrj has_mem_ref_been_instrumented (const asan_mem_ref *ref)
49638fd1498Szrj {
49738fd1498Szrj   return has_mem_ref_been_instrumented (ref->start, ref->access_size);
49838fd1498Szrj }
49938fd1498Szrj 
50038fd1498Szrj /* Return true iff access to memory region starting at REF and of
50138fd1498Szrj    length LEN has been instrumented.  */
50238fd1498Szrj 
50338fd1498Szrj static bool
has_mem_ref_been_instrumented(const asan_mem_ref * ref,tree len)50438fd1498Szrj has_mem_ref_been_instrumented (const asan_mem_ref *ref, tree len)
50538fd1498Szrj {
50638fd1498Szrj   HOST_WIDE_INT size_in_bytes
50738fd1498Szrj     = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
50838fd1498Szrj 
50938fd1498Szrj   return size_in_bytes != -1
51038fd1498Szrj     && has_mem_ref_been_instrumented (ref->start, size_in_bytes);
51138fd1498Szrj }
51238fd1498Szrj 
51338fd1498Szrj /* Set REF to the memory reference present in a gimple assignment
51438fd1498Szrj    ASSIGNMENT.  Return true upon successful completion, false
51538fd1498Szrj    otherwise.  */
51638fd1498Szrj 
51738fd1498Szrj static bool
get_mem_ref_of_assignment(const gassign * assignment,asan_mem_ref * ref,bool * ref_is_store)51838fd1498Szrj get_mem_ref_of_assignment (const gassign *assignment,
51938fd1498Szrj 			   asan_mem_ref *ref,
52038fd1498Szrj 			   bool *ref_is_store)
52138fd1498Szrj {
52238fd1498Szrj   gcc_assert (gimple_assign_single_p (assignment));
52338fd1498Szrj 
52438fd1498Szrj   if (gimple_store_p (assignment)
52538fd1498Szrj       && !gimple_clobber_p (assignment))
52638fd1498Szrj     {
52738fd1498Szrj       ref->start = gimple_assign_lhs (assignment);
52838fd1498Szrj       *ref_is_store = true;
52938fd1498Szrj     }
53038fd1498Szrj   else if (gimple_assign_load_p (assignment))
53138fd1498Szrj     {
53238fd1498Szrj       ref->start = gimple_assign_rhs1 (assignment);
53338fd1498Szrj       *ref_is_store = false;
53438fd1498Szrj     }
53538fd1498Szrj   else
53638fd1498Szrj     return false;
53738fd1498Szrj 
53838fd1498Szrj   ref->access_size = int_size_in_bytes (TREE_TYPE (ref->start));
53938fd1498Szrj   return true;
54038fd1498Szrj }
54138fd1498Szrj 
54238fd1498Szrj /* Return address of last allocated dynamic alloca.  */
54338fd1498Szrj 
54438fd1498Szrj static tree
get_last_alloca_addr()54538fd1498Szrj get_last_alloca_addr ()
54638fd1498Szrj {
54738fd1498Szrj   if (last_alloca_addr)
54838fd1498Szrj     return last_alloca_addr;
54938fd1498Szrj 
55038fd1498Szrj   last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr");
55138fd1498Szrj   gassign *g = gimple_build_assign (last_alloca_addr, null_pointer_node);
55238fd1498Szrj   edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
55338fd1498Szrj   gsi_insert_on_edge_immediate (e, g);
55438fd1498Szrj   return last_alloca_addr;
55538fd1498Szrj }
55638fd1498Szrj 
55738fd1498Szrj /* Insert __asan_allocas_unpoison (top, bottom) call before
55838fd1498Szrj    __builtin_stack_restore (new_sp) call.
55938fd1498Szrj    The pseudocode of this routine should look like this:
56038fd1498Szrj      top = last_alloca_addr;
56138fd1498Szrj      bot = new_sp;
56238fd1498Szrj      __asan_allocas_unpoison (top, bot);
56338fd1498Szrj      last_alloca_addr = new_sp;
56438fd1498Szrj      __builtin_stack_restore (new_sp);
56538fd1498Szrj    In general, we can't use new_sp as bot parameter because on some
56638fd1498Szrj    architectures SP has non zero offset from dynamic stack area.  Moreover, on
56738fd1498Szrj    some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each
56838fd1498Szrj    particular function only after all callees were expanded to rtl.
56938fd1498Szrj    The most noticeable example is PowerPC{,64}, see
57038fd1498Szrj    http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK.
57138fd1498Szrj    To overcome the issue we use following trick: pass new_sp as a second
57238fd1498Szrj    parameter to __asan_allocas_unpoison and rewrite it during expansion with
57338fd1498Szrj    new_sp + (virtual_dynamic_stack_rtx - sp) later in
57438fd1498Szrj    expand_asan_emit_allocas_unpoison function.  */
57538fd1498Szrj 
57638fd1498Szrj static void
handle_builtin_stack_restore(gcall * call,gimple_stmt_iterator * iter)57738fd1498Szrj handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
57838fd1498Szrj {
57938fd1498Szrj   if (!iter || !asan_sanitize_allocas_p ())
58038fd1498Szrj     return;
58138fd1498Szrj 
58238fd1498Szrj   tree last_alloca = get_last_alloca_addr ();
58338fd1498Szrj   tree restored_stack = gimple_call_arg (call, 0);
58438fd1498Szrj   tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
58538fd1498Szrj   gimple *g = gimple_build_call (fn, 2, last_alloca, restored_stack);
58638fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
58738fd1498Szrj   g = gimple_build_assign (last_alloca, restored_stack);
58838fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
58938fd1498Szrj }
59038fd1498Szrj 
59138fd1498Szrj /* Deploy and poison redzones around __builtin_alloca call.  To do this, we
59238fd1498Szrj    should replace this call with another one with changed parameters and
59338fd1498Szrj    replace all its uses with new address, so
59438fd1498Szrj        addr = __builtin_alloca (old_size, align);
59538fd1498Szrj    is replaced by
59638fd1498Szrj        left_redzone_size = max (align, ASAN_RED_ZONE_SIZE);
59738fd1498Szrj    Following two statements are optimized out if we know that
59838fd1498Szrj    old_size & (ASAN_RED_ZONE_SIZE - 1) == 0, i.e. alloca doesn't need partial
59938fd1498Szrj    redzone.
60038fd1498Szrj        misalign = old_size & (ASAN_RED_ZONE_SIZE - 1);
60138fd1498Szrj        partial_redzone_size = ASAN_RED_ZONE_SIZE - misalign;
60238fd1498Szrj        right_redzone_size = ASAN_RED_ZONE_SIZE;
60338fd1498Szrj        additional_size = left_redzone_size + partial_redzone_size +
60438fd1498Szrj                          right_redzone_size;
60538fd1498Szrj        new_size = old_size + additional_size;
60638fd1498Szrj        new_alloca = __builtin_alloca (new_size, max (align, 32))
60738fd1498Szrj        __asan_alloca_poison (new_alloca, old_size)
60838fd1498Szrj        addr = new_alloca + max (align, ASAN_RED_ZONE_SIZE);
60938fd1498Szrj        last_alloca_addr = new_alloca;
61038fd1498Szrj    ADDITIONAL_SIZE is added to make new memory allocation contain not only
61138fd1498Szrj    requested memory, but also left, partial and right redzones as well as some
61238fd1498Szrj    additional space, required by alignment.  */
61338fd1498Szrj 
61438fd1498Szrj static void
handle_builtin_alloca(gcall * call,gimple_stmt_iterator * iter)61538fd1498Szrj handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
61638fd1498Szrj {
61738fd1498Szrj   if (!iter || !asan_sanitize_allocas_p ())
61838fd1498Szrj     return;
61938fd1498Szrj 
62038fd1498Szrj   gassign *g;
62138fd1498Szrj   gcall *gg;
62238fd1498Szrj   const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
62338fd1498Szrj 
62438fd1498Szrj   tree last_alloca = get_last_alloca_addr ();
62538fd1498Szrj   tree callee = gimple_call_fndecl (call);
62638fd1498Szrj   tree old_size = gimple_call_arg (call, 0);
62738fd1498Szrj   tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
62838fd1498Szrj 					 : ptr_type_node;
62938fd1498Szrj   tree partial_size = NULL_TREE;
63038fd1498Szrj   unsigned int align
63138fd1498Szrj     = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
63238fd1498Szrj       ? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
63338fd1498Szrj 
63438fd1498Szrj   /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
63538fd1498Szrj      bytes of allocated space.  Otherwise, align alloca to ASAN_RED_ZONE_SIZE
63638fd1498Szrj      manually.  */
63738fd1498Szrj   align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
63838fd1498Szrj 
63938fd1498Szrj   tree alloca_rz_mask = build_int_cst (size_type_node, redzone_mask);
64038fd1498Szrj   tree redzone_size = build_int_cst (size_type_node, ASAN_RED_ZONE_SIZE);
64138fd1498Szrj 
64238fd1498Szrj   /* Extract lower bits from old_size.  */
64338fd1498Szrj   wide_int size_nonzero_bits = get_nonzero_bits (old_size);
64438fd1498Szrj   wide_int rz_mask
64538fd1498Szrj     = wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits));
64638fd1498Szrj   wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask);
64738fd1498Szrj 
64838fd1498Szrj   /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial
64938fd1498Szrj      redzone.  Otherwise, compute its size here.  */
65038fd1498Szrj   if (wi::ne_p (old_size_lower_bits, 0))
65138fd1498Szrj     {
65238fd1498Szrj       /* misalign = size & (ASAN_RED_ZONE_SIZE - 1)
65338fd1498Szrj          partial_size = ASAN_RED_ZONE_SIZE - misalign.  */
65438fd1498Szrj       g = gimple_build_assign (make_ssa_name (size_type_node, NULL),
65538fd1498Szrj 			       BIT_AND_EXPR, old_size, alloca_rz_mask);
65638fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
65738fd1498Szrj       tree misalign = gimple_assign_lhs (g);
65838fd1498Szrj       g = gimple_build_assign (make_ssa_name (size_type_node, NULL), MINUS_EXPR,
65938fd1498Szrj 			       redzone_size, misalign);
66038fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
66138fd1498Szrj       partial_size = gimple_assign_lhs (g);
66238fd1498Szrj     }
66338fd1498Szrj 
66438fd1498Szrj   /* additional_size = align + ASAN_RED_ZONE_SIZE.  */
66538fd1498Szrj   tree additional_size = build_int_cst (size_type_node, align / BITS_PER_UNIT
66638fd1498Szrj 							+ ASAN_RED_ZONE_SIZE);
66738fd1498Szrj   /* If alloca has partial redzone, include it to additional_size too.  */
66838fd1498Szrj   if (partial_size)
66938fd1498Szrj     {
67038fd1498Szrj       /* additional_size += partial_size.  */
67138fd1498Szrj       g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR,
67238fd1498Szrj 			       partial_size, additional_size);
67338fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
67438fd1498Szrj       additional_size = gimple_assign_lhs (g);
67538fd1498Szrj     }
67638fd1498Szrj 
67738fd1498Szrj   /* new_size = old_size + additional_size.  */
67838fd1498Szrj   g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR, old_size,
67938fd1498Szrj 			   additional_size);
68038fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
68138fd1498Szrj   tree new_size = gimple_assign_lhs (g);
68238fd1498Szrj 
68338fd1498Szrj   /* Build new __builtin_alloca call:
68438fd1498Szrj        new_alloca_with_rz = __builtin_alloca (new_size, align).  */
68538fd1498Szrj   tree fn = builtin_decl_implicit (BUILT_IN_ALLOCA_WITH_ALIGN);
68638fd1498Szrj   gg = gimple_build_call (fn, 2, new_size,
68738fd1498Szrj 			  build_int_cst (size_type_node, align));
68838fd1498Szrj   tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
68938fd1498Szrj   gimple_call_set_lhs (gg, new_alloca_with_rz);
69038fd1498Szrj   gsi_insert_before (iter, gg, GSI_SAME_STMT);
69138fd1498Szrj 
69238fd1498Szrj   /* new_alloca = new_alloca_with_rz + align.  */
69338fd1498Szrj   g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
69438fd1498Szrj 			   new_alloca_with_rz,
69538fd1498Szrj 			   build_int_cst (size_type_node,
69638fd1498Szrj 					  align / BITS_PER_UNIT));
69738fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
69838fd1498Szrj   tree new_alloca = gimple_assign_lhs (g);
69938fd1498Szrj 
70038fd1498Szrj   /* Poison newly created alloca redzones:
70138fd1498Szrj       __asan_alloca_poison (new_alloca, old_size).  */
70238fd1498Szrj   fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
70338fd1498Szrj   gg = gimple_build_call (fn, 2, new_alloca, old_size);
70438fd1498Szrj   gsi_insert_before (iter, gg, GSI_SAME_STMT);
70538fd1498Szrj 
70638fd1498Szrj   /* Save new_alloca_with_rz value into last_alloca to use it during
70738fd1498Szrj      allocas unpoisoning.  */
70838fd1498Szrj   g = gimple_build_assign (last_alloca, new_alloca_with_rz);
70938fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
71038fd1498Szrj 
71138fd1498Szrj   /* Finally, replace old alloca ptr with NEW_ALLOCA.  */
71238fd1498Szrj   replace_call_with_value (iter, new_alloca);
71338fd1498Szrj }
71438fd1498Szrj 
71538fd1498Szrj /* Return the memory references contained in a gimple statement
71638fd1498Szrj    representing a builtin call that has to do with memory access.  */
71738fd1498Szrj 
71838fd1498Szrj static bool
71938fd1498Szrj get_mem_refs_of_builtin_call (gcall *call,
72038fd1498Szrj 			      asan_mem_ref *src0,
72138fd1498Szrj 			      tree *src0_len,
72238fd1498Szrj 			      bool *src0_is_store,
72338fd1498Szrj 			      asan_mem_ref *src1,
72438fd1498Szrj 			      tree *src1_len,
72538fd1498Szrj 			      bool *src1_is_store,
72638fd1498Szrj 			      asan_mem_ref *dst,
72738fd1498Szrj 			      tree *dst_len,
72838fd1498Szrj 			      bool *dst_is_store,
72938fd1498Szrj 			      bool *dest_is_deref,
73038fd1498Szrj 			      bool *intercepted_p,
73138fd1498Szrj 			      gimple_stmt_iterator *iter = NULL)
73238fd1498Szrj {
73338fd1498Szrj   gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
73438fd1498Szrj 
73538fd1498Szrj   tree callee = gimple_call_fndecl (call);
73638fd1498Szrj   tree source0 = NULL_TREE, source1 = NULL_TREE,
73738fd1498Szrj     dest = NULL_TREE, len = NULL_TREE;
73838fd1498Szrj   bool is_store = true, got_reference_p = false;
73938fd1498Szrj   HOST_WIDE_INT access_size = 1;
74038fd1498Szrj 
74138fd1498Szrj   *intercepted_p = asan_intercepted_p ((DECL_FUNCTION_CODE (callee)));
74238fd1498Szrj 
74338fd1498Szrj   switch (DECL_FUNCTION_CODE (callee))
74438fd1498Szrj     {
74538fd1498Szrj       /* (s, s, n) style memops.  */
74638fd1498Szrj     case BUILT_IN_BCMP:
74738fd1498Szrj     case BUILT_IN_MEMCMP:
74838fd1498Szrj       source0 = gimple_call_arg (call, 0);
74938fd1498Szrj       source1 = gimple_call_arg (call, 1);
75038fd1498Szrj       len = gimple_call_arg (call, 2);
75138fd1498Szrj       break;
75238fd1498Szrj 
75338fd1498Szrj       /* (src, dest, n) style memops.  */
75438fd1498Szrj     case BUILT_IN_BCOPY:
75538fd1498Szrj       source0 = gimple_call_arg (call, 0);
75638fd1498Szrj       dest = gimple_call_arg (call, 1);
75738fd1498Szrj       len = gimple_call_arg (call, 2);
75838fd1498Szrj       break;
75938fd1498Szrj 
76038fd1498Szrj       /* (dest, src, n) style memops.  */
76138fd1498Szrj     case BUILT_IN_MEMCPY:
76238fd1498Szrj     case BUILT_IN_MEMCPY_CHK:
76338fd1498Szrj     case BUILT_IN_MEMMOVE:
76438fd1498Szrj     case BUILT_IN_MEMMOVE_CHK:
76538fd1498Szrj     case BUILT_IN_MEMPCPY:
76638fd1498Szrj     case BUILT_IN_MEMPCPY_CHK:
76738fd1498Szrj       dest = gimple_call_arg (call, 0);
76838fd1498Szrj       source0 = gimple_call_arg (call, 1);
76938fd1498Szrj       len = gimple_call_arg (call, 2);
77038fd1498Szrj       break;
77138fd1498Szrj 
77238fd1498Szrj       /* (dest, n) style memops.  */
77338fd1498Szrj     case BUILT_IN_BZERO:
77438fd1498Szrj       dest = gimple_call_arg (call, 0);
77538fd1498Szrj       len = gimple_call_arg (call, 1);
77638fd1498Szrj       break;
77738fd1498Szrj 
77838fd1498Szrj       /* (dest, x, n) style memops*/
77938fd1498Szrj     case BUILT_IN_MEMSET:
78038fd1498Szrj     case BUILT_IN_MEMSET_CHK:
78138fd1498Szrj       dest = gimple_call_arg (call, 0);
78238fd1498Szrj       len = gimple_call_arg (call, 2);
78338fd1498Szrj       break;
78438fd1498Szrj 
78538fd1498Szrj     case BUILT_IN_STRLEN:
78638fd1498Szrj       source0 = gimple_call_arg (call, 0);
78738fd1498Szrj       len = gimple_call_lhs (call);
78838fd1498Szrj       break;
78938fd1498Szrj 
79038fd1498Szrj     case BUILT_IN_STACK_RESTORE:
79138fd1498Szrj       handle_builtin_stack_restore (call, iter);
79238fd1498Szrj       break;
79338fd1498Szrj 
79438fd1498Szrj     CASE_BUILT_IN_ALLOCA:
79538fd1498Szrj       handle_builtin_alloca (call, iter);
79638fd1498Szrj       break;
79738fd1498Szrj     /* And now the __atomic* and __sync builtins.
79838fd1498Szrj        These are handled differently from the classical memory memory
79938fd1498Szrj        access builtins above.  */
80038fd1498Szrj 
80138fd1498Szrj     case BUILT_IN_ATOMIC_LOAD_1:
80238fd1498Szrj       is_store = false;
80338fd1498Szrj       /* FALLTHRU */
80438fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_ADD_1:
80538fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_SUB_1:
80638fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_OR_1:
80738fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_AND_1:
80838fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_XOR_1:
80938fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_NAND_1:
81038fd1498Szrj     case BUILT_IN_SYNC_ADD_AND_FETCH_1:
81138fd1498Szrj     case BUILT_IN_SYNC_SUB_AND_FETCH_1:
81238fd1498Szrj     case BUILT_IN_SYNC_OR_AND_FETCH_1:
81338fd1498Szrj     case BUILT_IN_SYNC_AND_AND_FETCH_1:
81438fd1498Szrj     case BUILT_IN_SYNC_XOR_AND_FETCH_1:
81538fd1498Szrj     case BUILT_IN_SYNC_NAND_AND_FETCH_1:
81638fd1498Szrj     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
81738fd1498Szrj     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
81838fd1498Szrj     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
81938fd1498Szrj     case BUILT_IN_SYNC_LOCK_RELEASE_1:
82038fd1498Szrj     case BUILT_IN_ATOMIC_EXCHANGE_1:
82138fd1498Szrj     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
82238fd1498Szrj     case BUILT_IN_ATOMIC_STORE_1:
82338fd1498Szrj     case BUILT_IN_ATOMIC_ADD_FETCH_1:
82438fd1498Szrj     case BUILT_IN_ATOMIC_SUB_FETCH_1:
82538fd1498Szrj     case BUILT_IN_ATOMIC_AND_FETCH_1:
82638fd1498Szrj     case BUILT_IN_ATOMIC_NAND_FETCH_1:
82738fd1498Szrj     case BUILT_IN_ATOMIC_XOR_FETCH_1:
82838fd1498Szrj     case BUILT_IN_ATOMIC_OR_FETCH_1:
82938fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_ADD_1:
83038fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_SUB_1:
83138fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_AND_1:
83238fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_NAND_1:
83338fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_XOR_1:
83438fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_OR_1:
83538fd1498Szrj       access_size = 1;
83638fd1498Szrj       goto do_atomic;
83738fd1498Szrj 
83838fd1498Szrj     case BUILT_IN_ATOMIC_LOAD_2:
83938fd1498Szrj       is_store = false;
84038fd1498Szrj       /* FALLTHRU */
84138fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_ADD_2:
84238fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_SUB_2:
84338fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_OR_2:
84438fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_AND_2:
84538fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_XOR_2:
84638fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_NAND_2:
84738fd1498Szrj     case BUILT_IN_SYNC_ADD_AND_FETCH_2:
84838fd1498Szrj     case BUILT_IN_SYNC_SUB_AND_FETCH_2:
84938fd1498Szrj     case BUILT_IN_SYNC_OR_AND_FETCH_2:
85038fd1498Szrj     case BUILT_IN_SYNC_AND_AND_FETCH_2:
85138fd1498Szrj     case BUILT_IN_SYNC_XOR_AND_FETCH_2:
85238fd1498Szrj     case BUILT_IN_SYNC_NAND_AND_FETCH_2:
85338fd1498Szrj     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
85438fd1498Szrj     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
85538fd1498Szrj     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
85638fd1498Szrj     case BUILT_IN_SYNC_LOCK_RELEASE_2:
85738fd1498Szrj     case BUILT_IN_ATOMIC_EXCHANGE_2:
85838fd1498Szrj     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
85938fd1498Szrj     case BUILT_IN_ATOMIC_STORE_2:
86038fd1498Szrj     case BUILT_IN_ATOMIC_ADD_FETCH_2:
86138fd1498Szrj     case BUILT_IN_ATOMIC_SUB_FETCH_2:
86238fd1498Szrj     case BUILT_IN_ATOMIC_AND_FETCH_2:
86338fd1498Szrj     case BUILT_IN_ATOMIC_NAND_FETCH_2:
86438fd1498Szrj     case BUILT_IN_ATOMIC_XOR_FETCH_2:
86538fd1498Szrj     case BUILT_IN_ATOMIC_OR_FETCH_2:
86638fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_ADD_2:
86738fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_SUB_2:
86838fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_AND_2:
86938fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_NAND_2:
87038fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_XOR_2:
87138fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_OR_2:
87238fd1498Szrj       access_size = 2;
87338fd1498Szrj       goto do_atomic;
87438fd1498Szrj 
87538fd1498Szrj     case BUILT_IN_ATOMIC_LOAD_4:
87638fd1498Szrj       is_store = false;
87738fd1498Szrj       /* FALLTHRU */
87838fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_ADD_4:
87938fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_SUB_4:
88038fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_OR_4:
88138fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_AND_4:
88238fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_XOR_4:
88338fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_NAND_4:
88438fd1498Szrj     case BUILT_IN_SYNC_ADD_AND_FETCH_4:
88538fd1498Szrj     case BUILT_IN_SYNC_SUB_AND_FETCH_4:
88638fd1498Szrj     case BUILT_IN_SYNC_OR_AND_FETCH_4:
88738fd1498Szrj     case BUILT_IN_SYNC_AND_AND_FETCH_4:
88838fd1498Szrj     case BUILT_IN_SYNC_XOR_AND_FETCH_4:
88938fd1498Szrj     case BUILT_IN_SYNC_NAND_AND_FETCH_4:
89038fd1498Szrj     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
89138fd1498Szrj     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
89238fd1498Szrj     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
89338fd1498Szrj     case BUILT_IN_SYNC_LOCK_RELEASE_4:
89438fd1498Szrj     case BUILT_IN_ATOMIC_EXCHANGE_4:
89538fd1498Szrj     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
89638fd1498Szrj     case BUILT_IN_ATOMIC_STORE_4:
89738fd1498Szrj     case BUILT_IN_ATOMIC_ADD_FETCH_4:
89838fd1498Szrj     case BUILT_IN_ATOMIC_SUB_FETCH_4:
89938fd1498Szrj     case BUILT_IN_ATOMIC_AND_FETCH_4:
90038fd1498Szrj     case BUILT_IN_ATOMIC_NAND_FETCH_4:
90138fd1498Szrj     case BUILT_IN_ATOMIC_XOR_FETCH_4:
90238fd1498Szrj     case BUILT_IN_ATOMIC_OR_FETCH_4:
90338fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_ADD_4:
90438fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_SUB_4:
90538fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_AND_4:
90638fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_NAND_4:
90738fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_XOR_4:
90838fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_OR_4:
90938fd1498Szrj       access_size = 4;
91038fd1498Szrj       goto do_atomic;
91138fd1498Szrj 
91238fd1498Szrj     case BUILT_IN_ATOMIC_LOAD_8:
91338fd1498Szrj       is_store = false;
91438fd1498Szrj       /* FALLTHRU */
91538fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_ADD_8:
91638fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_SUB_8:
91738fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_OR_8:
91838fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_AND_8:
91938fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_XOR_8:
92038fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_NAND_8:
92138fd1498Szrj     case BUILT_IN_SYNC_ADD_AND_FETCH_8:
92238fd1498Szrj     case BUILT_IN_SYNC_SUB_AND_FETCH_8:
92338fd1498Szrj     case BUILT_IN_SYNC_OR_AND_FETCH_8:
92438fd1498Szrj     case BUILT_IN_SYNC_AND_AND_FETCH_8:
92538fd1498Szrj     case BUILT_IN_SYNC_XOR_AND_FETCH_8:
92638fd1498Szrj     case BUILT_IN_SYNC_NAND_AND_FETCH_8:
92738fd1498Szrj     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
92838fd1498Szrj     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
92938fd1498Szrj     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
93038fd1498Szrj     case BUILT_IN_SYNC_LOCK_RELEASE_8:
93138fd1498Szrj     case BUILT_IN_ATOMIC_EXCHANGE_8:
93238fd1498Szrj     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
93338fd1498Szrj     case BUILT_IN_ATOMIC_STORE_8:
93438fd1498Szrj     case BUILT_IN_ATOMIC_ADD_FETCH_8:
93538fd1498Szrj     case BUILT_IN_ATOMIC_SUB_FETCH_8:
93638fd1498Szrj     case BUILT_IN_ATOMIC_AND_FETCH_8:
93738fd1498Szrj     case BUILT_IN_ATOMIC_NAND_FETCH_8:
93838fd1498Szrj     case BUILT_IN_ATOMIC_XOR_FETCH_8:
93938fd1498Szrj     case BUILT_IN_ATOMIC_OR_FETCH_8:
94038fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_ADD_8:
94138fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_SUB_8:
94238fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_AND_8:
94338fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_NAND_8:
94438fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_XOR_8:
94538fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_OR_8:
94638fd1498Szrj       access_size = 8;
94738fd1498Szrj       goto do_atomic;
94838fd1498Szrj 
94938fd1498Szrj     case BUILT_IN_ATOMIC_LOAD_16:
95038fd1498Szrj       is_store = false;
95138fd1498Szrj       /* FALLTHRU */
95238fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_ADD_16:
95338fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_SUB_16:
95438fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_OR_16:
95538fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_AND_16:
95638fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_XOR_16:
95738fd1498Szrj     case BUILT_IN_SYNC_FETCH_AND_NAND_16:
95838fd1498Szrj     case BUILT_IN_SYNC_ADD_AND_FETCH_16:
95938fd1498Szrj     case BUILT_IN_SYNC_SUB_AND_FETCH_16:
96038fd1498Szrj     case BUILT_IN_SYNC_OR_AND_FETCH_16:
96138fd1498Szrj     case BUILT_IN_SYNC_AND_AND_FETCH_16:
96238fd1498Szrj     case BUILT_IN_SYNC_XOR_AND_FETCH_16:
96338fd1498Szrj     case BUILT_IN_SYNC_NAND_AND_FETCH_16:
96438fd1498Szrj     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
96538fd1498Szrj     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
96638fd1498Szrj     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
96738fd1498Szrj     case BUILT_IN_SYNC_LOCK_RELEASE_16:
96838fd1498Szrj     case BUILT_IN_ATOMIC_EXCHANGE_16:
96938fd1498Szrj     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
97038fd1498Szrj     case BUILT_IN_ATOMIC_STORE_16:
97138fd1498Szrj     case BUILT_IN_ATOMIC_ADD_FETCH_16:
97238fd1498Szrj     case BUILT_IN_ATOMIC_SUB_FETCH_16:
97338fd1498Szrj     case BUILT_IN_ATOMIC_AND_FETCH_16:
97438fd1498Szrj     case BUILT_IN_ATOMIC_NAND_FETCH_16:
97538fd1498Szrj     case BUILT_IN_ATOMIC_XOR_FETCH_16:
97638fd1498Szrj     case BUILT_IN_ATOMIC_OR_FETCH_16:
97738fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_ADD_16:
97838fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_SUB_16:
97938fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_AND_16:
98038fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_NAND_16:
98138fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_XOR_16:
98238fd1498Szrj     case BUILT_IN_ATOMIC_FETCH_OR_16:
98338fd1498Szrj       access_size = 16;
98438fd1498Szrj       /* FALLTHRU */
98538fd1498Szrj     do_atomic:
98638fd1498Szrj       {
98738fd1498Szrj 	dest = gimple_call_arg (call, 0);
98838fd1498Szrj 	/* DEST represents the address of a memory location.
98938fd1498Szrj 	   instrument_derefs wants the memory location, so lets
99038fd1498Szrj 	   dereference the address DEST before handing it to
99138fd1498Szrj 	   instrument_derefs.  */
99238fd1498Szrj 	tree type = build_nonstandard_integer_type (access_size
99338fd1498Szrj 						    * BITS_PER_UNIT, 1);
99438fd1498Szrj 	dest = build2 (MEM_REF, type, dest,
99538fd1498Szrj 		       build_int_cst (build_pointer_type (char_type_node), 0));
99638fd1498Szrj 	break;
99738fd1498Szrj       }
99838fd1498Szrj 
99938fd1498Szrj     default:
100038fd1498Szrj       /* The other builtins memory access are not instrumented in this
100138fd1498Szrj 	 function because they either don't have any length parameter,
100238fd1498Szrj 	 or their length parameter is just a limit.  */
100338fd1498Szrj       break;
100438fd1498Szrj     }
100538fd1498Szrj 
100638fd1498Szrj   if (len != NULL_TREE)
100738fd1498Szrj     {
100838fd1498Szrj       if (source0 != NULL_TREE)
100938fd1498Szrj 	{
101038fd1498Szrj 	  src0->start = source0;
101138fd1498Szrj 	  src0->access_size = access_size;
101238fd1498Szrj 	  *src0_len = len;
101338fd1498Szrj 	  *src0_is_store = false;
101438fd1498Szrj 	}
101538fd1498Szrj 
101638fd1498Szrj       if (source1 != NULL_TREE)
101738fd1498Szrj 	{
101838fd1498Szrj 	  src1->start = source1;
101938fd1498Szrj 	  src1->access_size = access_size;
102038fd1498Szrj 	  *src1_len = len;
102138fd1498Szrj 	  *src1_is_store = false;
102238fd1498Szrj 	}
102338fd1498Szrj 
102438fd1498Szrj       if (dest != NULL_TREE)
102538fd1498Szrj 	{
102638fd1498Szrj 	  dst->start = dest;
102738fd1498Szrj 	  dst->access_size = access_size;
102838fd1498Szrj 	  *dst_len = len;
102938fd1498Szrj 	  *dst_is_store = true;
103038fd1498Szrj 	}
103138fd1498Szrj 
103238fd1498Szrj       got_reference_p = true;
103338fd1498Szrj     }
103438fd1498Szrj   else if (dest)
103538fd1498Szrj     {
103638fd1498Szrj       dst->start = dest;
103738fd1498Szrj       dst->access_size = access_size;
103838fd1498Szrj       *dst_len = NULL_TREE;
103938fd1498Szrj       *dst_is_store = is_store;
104038fd1498Szrj       *dest_is_deref = true;
104138fd1498Szrj       got_reference_p = true;
104238fd1498Szrj     }
104338fd1498Szrj 
104438fd1498Szrj   return got_reference_p;
104538fd1498Szrj }
104638fd1498Szrj 
104738fd1498Szrj /* Return true iff a given gimple statement has been instrumented.
104838fd1498Szrj    Note that the statement is "defined" by the memory references it
104938fd1498Szrj    contains.  */
105038fd1498Szrj 
105138fd1498Szrj static bool
has_stmt_been_instrumented_p(gimple * stmt)105238fd1498Szrj has_stmt_been_instrumented_p (gimple *stmt)
105338fd1498Szrj {
105438fd1498Szrj   if (gimple_assign_single_p (stmt))
105538fd1498Szrj     {
105638fd1498Szrj       bool r_is_store;
105738fd1498Szrj       asan_mem_ref r;
105838fd1498Szrj       asan_mem_ref_init (&r, NULL, 1);
105938fd1498Szrj 
106038fd1498Szrj       if (get_mem_ref_of_assignment (as_a <gassign *> (stmt), &r,
106138fd1498Szrj 				     &r_is_store))
106238fd1498Szrj 	return has_mem_ref_been_instrumented (&r);
106338fd1498Szrj     }
106438fd1498Szrj   else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
106538fd1498Szrj     {
106638fd1498Szrj       asan_mem_ref src0, src1, dest;
106738fd1498Szrj       asan_mem_ref_init (&src0, NULL, 1);
106838fd1498Szrj       asan_mem_ref_init (&src1, NULL, 1);
106938fd1498Szrj       asan_mem_ref_init (&dest, NULL, 1);
107038fd1498Szrj 
107138fd1498Szrj       tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
107238fd1498Szrj       bool src0_is_store = false, src1_is_store = false,
107338fd1498Szrj 	dest_is_store = false, dest_is_deref = false, intercepted_p = true;
107438fd1498Szrj       if (get_mem_refs_of_builtin_call (as_a <gcall *> (stmt),
107538fd1498Szrj 					&src0, &src0_len, &src0_is_store,
107638fd1498Szrj 					&src1, &src1_len, &src1_is_store,
107738fd1498Szrj 					&dest, &dest_len, &dest_is_store,
107838fd1498Szrj 					&dest_is_deref, &intercepted_p))
107938fd1498Szrj 	{
108038fd1498Szrj 	  if (src0.start != NULL_TREE
108138fd1498Szrj 	      && !has_mem_ref_been_instrumented (&src0, src0_len))
108238fd1498Szrj 	    return false;
108338fd1498Szrj 
108438fd1498Szrj 	  if (src1.start != NULL_TREE
108538fd1498Szrj 	      && !has_mem_ref_been_instrumented (&src1, src1_len))
108638fd1498Szrj 	    return false;
108738fd1498Szrj 
108838fd1498Szrj 	  if (dest.start != NULL_TREE
108938fd1498Szrj 	      && !has_mem_ref_been_instrumented (&dest, dest_len))
109038fd1498Szrj 	    return false;
109138fd1498Szrj 
109238fd1498Szrj 	  return true;
109338fd1498Szrj 	}
109438fd1498Szrj     }
109538fd1498Szrj   else if (is_gimple_call (stmt) && gimple_store_p (stmt))
109638fd1498Szrj     {
109738fd1498Szrj       asan_mem_ref r;
109838fd1498Szrj       asan_mem_ref_init (&r, NULL, 1);
109938fd1498Szrj 
110038fd1498Szrj       r.start = gimple_call_lhs (stmt);
110138fd1498Szrj       r.access_size = int_size_in_bytes (TREE_TYPE (r.start));
110238fd1498Szrj       return has_mem_ref_been_instrumented (&r);
110338fd1498Szrj     }
110438fd1498Szrj 
110538fd1498Szrj   return false;
110638fd1498Szrj }
110738fd1498Szrj 
110838fd1498Szrj /*  Insert a memory reference into the hash table.  */
110938fd1498Szrj 
111038fd1498Szrj static void
update_mem_ref_hash_table(tree ref,HOST_WIDE_INT access_size)111138fd1498Szrj update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size)
111238fd1498Szrj {
111338fd1498Szrj   hash_table<asan_mem_ref_hasher> *ht = get_mem_ref_hash_table ();
111438fd1498Szrj 
111538fd1498Szrj   asan_mem_ref r;
111638fd1498Szrj   asan_mem_ref_init (&r, ref, access_size);
111738fd1498Szrj 
111838fd1498Szrj   asan_mem_ref **slot = ht->find_slot (&r, INSERT);
111938fd1498Szrj   if (*slot == NULL || (*slot)->access_size < access_size)
112038fd1498Szrj     *slot = asan_mem_ref_new (ref, access_size);
112138fd1498Szrj }
112238fd1498Szrj 
112338fd1498Szrj /* Initialize shadow_ptr_types array.  */
112438fd1498Szrj 
112538fd1498Szrj static void
asan_init_shadow_ptr_types(void)112638fd1498Szrj asan_init_shadow_ptr_types (void)
112738fd1498Szrj {
112838fd1498Szrj   asan_shadow_set = new_alias_set ();
112938fd1498Szrj   tree types[3] = { signed_char_type_node, short_integer_type_node,
113038fd1498Szrj 		    integer_type_node };
113138fd1498Szrj 
113238fd1498Szrj   for (unsigned i = 0; i < 3; i++)
113338fd1498Szrj     {
113438fd1498Szrj       shadow_ptr_types[i] = build_distinct_type_copy (types[i]);
113538fd1498Szrj       TYPE_ALIAS_SET (shadow_ptr_types[i]) = asan_shadow_set;
113638fd1498Szrj       shadow_ptr_types[i] = build_pointer_type (shadow_ptr_types[i]);
113738fd1498Szrj     }
113838fd1498Szrj 
113938fd1498Szrj   initialize_sanitizer_builtins ();
114038fd1498Szrj }
114138fd1498Szrj 
114238fd1498Szrj /* Create ADDR_EXPR of STRING_CST with the PP pretty printer text.  */
114338fd1498Szrj 
114438fd1498Szrj static tree
asan_pp_string(pretty_printer * pp)114538fd1498Szrj asan_pp_string (pretty_printer *pp)
114638fd1498Szrj {
114738fd1498Szrj   const char *buf = pp_formatted_text (pp);
114838fd1498Szrj   size_t len = strlen (buf);
114938fd1498Szrj   tree ret = build_string (len + 1, buf);
115038fd1498Szrj   TREE_TYPE (ret)
115138fd1498Szrj     = build_array_type (TREE_TYPE (shadow_ptr_types[0]),
115238fd1498Szrj 			build_index_type (size_int (len)));
115338fd1498Szrj   TREE_READONLY (ret) = 1;
115438fd1498Szrj   TREE_STATIC (ret) = 1;
115538fd1498Szrj   return build1 (ADDR_EXPR, shadow_ptr_types[0], ret);
115638fd1498Szrj }
115738fd1498Szrj 
115838fd1498Szrj /* Return a CONST_INT representing 4 subsequent shadow memory bytes.  */
115938fd1498Szrj 
116038fd1498Szrj static rtx
asan_shadow_cst(unsigned char shadow_bytes[4])116138fd1498Szrj asan_shadow_cst (unsigned char shadow_bytes[4])
116238fd1498Szrj {
116338fd1498Szrj   int i;
116438fd1498Szrj   unsigned HOST_WIDE_INT val = 0;
116538fd1498Szrj   gcc_assert (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN);
116638fd1498Szrj   for (i = 0; i < 4; i++)
116738fd1498Szrj     val |= (unsigned HOST_WIDE_INT) shadow_bytes[BYTES_BIG_ENDIAN ? 3 - i : i]
116838fd1498Szrj 	   << (BITS_PER_UNIT * i);
116938fd1498Szrj   return gen_int_mode (val, SImode);
117038fd1498Szrj }
117138fd1498Szrj 
117238fd1498Szrj /* Clear shadow memory at SHADOW_MEM, LEN bytes.  Can't call a library call here
117338fd1498Szrj    though.  */
117438fd1498Szrj 
117538fd1498Szrj static void
asan_clear_shadow(rtx shadow_mem,HOST_WIDE_INT len)117638fd1498Szrj asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
117738fd1498Szrj {
117838fd1498Szrj   rtx_insn *insn, *insns, *jump;
117938fd1498Szrj   rtx_code_label *top_label;
118038fd1498Szrj   rtx end, addr, tmp;
118138fd1498Szrj 
118238fd1498Szrj   start_sequence ();
118338fd1498Szrj   clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
118438fd1498Szrj   insns = get_insns ();
118538fd1498Szrj   end_sequence ();
118638fd1498Szrj   for (insn = insns; insn; insn = NEXT_INSN (insn))
118738fd1498Szrj     if (CALL_P (insn))
118838fd1498Szrj       break;
118938fd1498Szrj   if (insn == NULL_RTX)
119038fd1498Szrj     {
119138fd1498Szrj       emit_insn (insns);
119238fd1498Szrj       return;
119338fd1498Szrj     }
119438fd1498Szrj 
119538fd1498Szrj   gcc_assert ((len & 3) == 0);
119638fd1498Szrj   top_label = gen_label_rtx ();
119738fd1498Szrj   addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
119838fd1498Szrj   shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
119938fd1498Szrj   end = force_reg (Pmode, plus_constant (Pmode, addr, len));
120038fd1498Szrj   emit_label (top_label);
120138fd1498Szrj 
120238fd1498Szrj   emit_move_insn (shadow_mem, const0_rtx);
120338fd1498Szrj   tmp = expand_simple_binop (Pmode, PLUS, addr, gen_int_mode (4, Pmode), addr,
120438fd1498Szrj 			     true, OPTAB_LIB_WIDEN);
120538fd1498Szrj   if (tmp != addr)
120638fd1498Szrj     emit_move_insn (addr, tmp);
120738fd1498Szrj   emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
120838fd1498Szrj   jump = get_last_insn ();
120938fd1498Szrj   gcc_assert (JUMP_P (jump));
121038fd1498Szrj   add_reg_br_prob_note (jump,
121138fd1498Szrj 			profile_probability::guessed_always ()
121238fd1498Szrj 			   .apply_scale (80, 100));
121338fd1498Szrj }
121438fd1498Szrj 
121538fd1498Szrj void
asan_function_start(void)121638fd1498Szrj asan_function_start (void)
121738fd1498Szrj {
121838fd1498Szrj   section *fnsec = function_section (current_function_decl);
121938fd1498Szrj   switch_to_section (fnsec);
122038fd1498Szrj   ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC",
122138fd1498Szrj 			 current_function_funcdef_no);
122238fd1498Szrj }
122338fd1498Szrj 
122438fd1498Szrj /* Return number of shadow bytes that are occupied by a local variable
122538fd1498Szrj    of SIZE bytes.  */
122638fd1498Szrj 
122738fd1498Szrj static unsigned HOST_WIDE_INT
shadow_mem_size(unsigned HOST_WIDE_INT size)122838fd1498Szrj shadow_mem_size (unsigned HOST_WIDE_INT size)
122938fd1498Szrj {
123038fd1498Szrj   /* It must be possible to align stack variables to granularity
123138fd1498Szrj      of shadow memory.  */
123238fd1498Szrj   gcc_assert (BITS_PER_UNIT
123338fd1498Szrj 	      * ASAN_SHADOW_GRANULARITY <= MAX_SUPPORTED_STACK_ALIGNMENT);
123438fd1498Szrj 
123538fd1498Szrj   return ROUND_UP (size, ASAN_SHADOW_GRANULARITY) / ASAN_SHADOW_GRANULARITY;
123638fd1498Szrj }
123738fd1498Szrj 
123838fd1498Szrj /* Insert code to protect stack vars.  The prologue sequence should be emitted
123938fd1498Szrj    directly, epilogue sequence returned.  BASE is the register holding the
124038fd1498Szrj    stack base, against which OFFSETS array offsets are relative to, OFFSETS
124138fd1498Szrj    array contains pairs of offsets in reverse order, always the end offset
124238fd1498Szrj    of some gap that needs protection followed by starting offset,
124338fd1498Szrj    and DECLS is an array of representative decls for each var partition.
124438fd1498Szrj    LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1
124538fd1498Szrj    elements long (OFFSETS include gap before the first variable as well
124638fd1498Szrj    as gaps after each stack variable).  PBASE is, if non-NULL, some pseudo
124738fd1498Szrj    register which stack vars DECL_RTLs are based on.  Either BASE should be
124838fd1498Szrj    assigned to PBASE, when not doing use after return protection, or
124938fd1498Szrj    corresponding address based on __asan_stack_malloc* return value.  */
125038fd1498Szrj 
125138fd1498Szrj rtx_insn *
asan_emit_stack_protection(rtx base,rtx pbase,unsigned int alignb,HOST_WIDE_INT * offsets,tree * decls,int length)125238fd1498Szrj asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
125338fd1498Szrj 			    HOST_WIDE_INT *offsets, tree *decls, int length)
125438fd1498Szrj {
125538fd1498Szrj   rtx shadow_base, shadow_mem, ret, mem, orig_base;
125638fd1498Szrj   rtx_code_label *lab;
125738fd1498Szrj   rtx_insn *insns;
125838fd1498Szrj   char buf[32];
125938fd1498Szrj   unsigned char shadow_bytes[4];
126038fd1498Szrj   HOST_WIDE_INT base_offset = offsets[length - 1];
126138fd1498Szrj   HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
126238fd1498Szrj   HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
126338fd1498Szrj   HOST_WIDE_INT last_offset, last_size;
126438fd1498Szrj   int l;
126538fd1498Szrj   unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
126638fd1498Szrj   tree str_cst, decl, id;
126738fd1498Szrj   int use_after_return_class = -1;
126838fd1498Szrj 
126938fd1498Szrj   if (shadow_ptr_types[0] == NULL_TREE)
127038fd1498Szrj     asan_init_shadow_ptr_types ();
127138fd1498Szrj 
127238fd1498Szrj   /* First of all, prepare the description string.  */
127338fd1498Szrj   pretty_printer asan_pp;
127438fd1498Szrj 
127538fd1498Szrj   pp_decimal_int (&asan_pp, length / 2 - 1);
127638fd1498Szrj   pp_space (&asan_pp);
127738fd1498Szrj   for (l = length - 2; l; l -= 2)
127838fd1498Szrj     {
127938fd1498Szrj       tree decl = decls[l / 2 - 1];
128038fd1498Szrj       pp_wide_integer (&asan_pp, offsets[l] - base_offset);
128138fd1498Szrj       pp_space (&asan_pp);
128238fd1498Szrj       pp_wide_integer (&asan_pp, offsets[l - 1] - offsets[l]);
128338fd1498Szrj       pp_space (&asan_pp);
128438fd1498Szrj       if (DECL_P (decl) && DECL_NAME (decl))
128538fd1498Szrj 	{
128638fd1498Szrj 	  pp_decimal_int (&asan_pp, IDENTIFIER_LENGTH (DECL_NAME (decl)));
128738fd1498Szrj 	  pp_space (&asan_pp);
128838fd1498Szrj 	  pp_tree_identifier (&asan_pp, DECL_NAME (decl));
128938fd1498Szrj 	}
129038fd1498Szrj       else
129138fd1498Szrj 	pp_string (&asan_pp, "9 <unknown>");
129238fd1498Szrj       pp_space (&asan_pp);
129338fd1498Szrj     }
129438fd1498Szrj   str_cst = asan_pp_string (&asan_pp);
129538fd1498Szrj 
129638fd1498Szrj   /* Emit the prologue sequence.  */
129738fd1498Szrj   if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase
129838fd1498Szrj       && ASAN_USE_AFTER_RETURN)
129938fd1498Szrj     {
130038fd1498Szrj       use_after_return_class = floor_log2 (asan_frame_size - 1) - 5;
130138fd1498Szrj       /* __asan_stack_malloc_N guarantees alignment
130238fd1498Szrj 	 N < 6 ? (64 << N) : 4096 bytes.  */
130338fd1498Szrj       if (alignb > (use_after_return_class < 6
130438fd1498Szrj 		    ? (64U << use_after_return_class) : 4096U))
130538fd1498Szrj 	use_after_return_class = -1;
130638fd1498Szrj       else if (alignb > ASAN_RED_ZONE_SIZE && (asan_frame_size & (alignb - 1)))
130738fd1498Szrj 	base_align_bias = ((asan_frame_size + alignb - 1)
130838fd1498Szrj 			   & ~(alignb - HOST_WIDE_INT_1)) - asan_frame_size;
130938fd1498Szrj     }
131038fd1498Szrj   /* Align base if target is STRICT_ALIGNMENT.  */
131138fd1498Szrj   if (STRICT_ALIGNMENT)
131238fd1498Szrj     base = expand_binop (Pmode, and_optab, base,
131338fd1498Szrj 			 gen_int_mode (-((GET_MODE_ALIGNMENT (SImode)
131438fd1498Szrj 					  << ASAN_SHADOW_SHIFT)
131538fd1498Szrj 					 / BITS_PER_UNIT), Pmode), NULL_RTX,
131638fd1498Szrj 			 1, OPTAB_DIRECT);
131738fd1498Szrj 
131838fd1498Szrj   if (use_after_return_class == -1 && pbase)
131938fd1498Szrj     emit_move_insn (pbase, base);
132038fd1498Szrj 
132138fd1498Szrj   base = expand_binop (Pmode, add_optab, base,
132238fd1498Szrj 		       gen_int_mode (base_offset - base_align_bias, Pmode),
132338fd1498Szrj 		       NULL_RTX, 1, OPTAB_DIRECT);
132438fd1498Szrj   orig_base = NULL_RTX;
132538fd1498Szrj   if (use_after_return_class != -1)
132638fd1498Szrj     {
132738fd1498Szrj       if (asan_detect_stack_use_after_return == NULL_TREE)
132838fd1498Szrj 	{
132938fd1498Szrj 	  id = get_identifier ("__asan_option_detect_stack_use_after_return");
133038fd1498Szrj 	  decl = build_decl (BUILTINS_LOCATION, VAR_DECL, id,
133138fd1498Szrj 			     integer_type_node);
133238fd1498Szrj 	  SET_DECL_ASSEMBLER_NAME (decl, id);
133338fd1498Szrj 	  TREE_ADDRESSABLE (decl) = 1;
133438fd1498Szrj 	  DECL_ARTIFICIAL (decl) = 1;
133538fd1498Szrj 	  DECL_IGNORED_P (decl) = 1;
133638fd1498Szrj 	  DECL_EXTERNAL (decl) = 1;
133738fd1498Szrj 	  TREE_STATIC (decl) = 1;
133838fd1498Szrj 	  TREE_PUBLIC (decl) = 1;
133938fd1498Szrj 	  TREE_USED (decl) = 1;
134038fd1498Szrj 	  asan_detect_stack_use_after_return = decl;
134138fd1498Szrj 	}
134238fd1498Szrj       orig_base = gen_reg_rtx (Pmode);
134338fd1498Szrj       emit_move_insn (orig_base, base);
134438fd1498Szrj       ret = expand_normal (asan_detect_stack_use_after_return);
134538fd1498Szrj       lab = gen_label_rtx ();
134638fd1498Szrj       emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
134738fd1498Szrj 			       VOIDmode, 0, lab,
134838fd1498Szrj 			       profile_probability::very_likely ());
134938fd1498Szrj       snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
135038fd1498Szrj 		use_after_return_class);
135138fd1498Szrj       ret = init_one_libfunc (buf);
135238fd1498Szrj       ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
135338fd1498Szrj 				     GEN_INT (asan_frame_size
135438fd1498Szrj 					      + base_align_bias),
135538fd1498Szrj 				     TYPE_MODE (pointer_sized_int_node));
135638fd1498Szrj       /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
135738fd1498Szrj 	 and NULL otherwise.  Check RET value is NULL here and jump over the
135838fd1498Szrj 	 BASE reassignment in this case.  Otherwise, reassign BASE to RET.  */
135938fd1498Szrj       emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
136038fd1498Szrj 			       VOIDmode, 0, lab,
136138fd1498Szrj 			       profile_probability:: very_unlikely ());
136238fd1498Szrj       ret = convert_memory_address (Pmode, ret);
136338fd1498Szrj       emit_move_insn (base, ret);
136438fd1498Szrj       emit_label (lab);
136538fd1498Szrj       emit_move_insn (pbase, expand_binop (Pmode, add_optab, base,
136638fd1498Szrj 					   gen_int_mode (base_align_bias
136738fd1498Szrj 							 - base_offset, Pmode),
136838fd1498Szrj 					   NULL_RTX, 1, OPTAB_DIRECT));
136938fd1498Szrj     }
137038fd1498Szrj   mem = gen_rtx_MEM (ptr_mode, base);
137138fd1498Szrj   mem = adjust_address (mem, VOIDmode, base_align_bias);
137238fd1498Szrj   emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode));
137338fd1498Szrj   mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
137438fd1498Szrj   emit_move_insn (mem, expand_normal (str_cst));
137538fd1498Szrj   mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
137638fd1498Szrj   ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no);
137738fd1498Szrj   id = get_identifier (buf);
137838fd1498Szrj   decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
137938fd1498Szrj 		    VAR_DECL, id, char_type_node);
138038fd1498Szrj   SET_DECL_ASSEMBLER_NAME (decl, id);
138138fd1498Szrj   TREE_ADDRESSABLE (decl) = 1;
138238fd1498Szrj   TREE_READONLY (decl) = 1;
138338fd1498Szrj   DECL_ARTIFICIAL (decl) = 1;
138438fd1498Szrj   DECL_IGNORED_P (decl) = 1;
138538fd1498Szrj   TREE_STATIC (decl) = 1;
138638fd1498Szrj   TREE_PUBLIC (decl) = 0;
138738fd1498Szrj   TREE_USED (decl) = 1;
138838fd1498Szrj   DECL_INITIAL (decl) = decl;
138938fd1498Szrj   TREE_ASM_WRITTEN (decl) = 1;
139038fd1498Szrj   TREE_ASM_WRITTEN (id) = 1;
139138fd1498Szrj   emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
139238fd1498Szrj   shadow_base = expand_binop (Pmode, lshr_optab, base,
139338fd1498Szrj 			      gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT),
139438fd1498Szrj 			      NULL_RTX, 1, OPTAB_DIRECT);
139538fd1498Szrj   shadow_base
139638fd1498Szrj     = plus_constant (Pmode, shadow_base,
139738fd1498Szrj 		     asan_shadow_offset ()
139838fd1498Szrj 		     + (base_align_bias >> ASAN_SHADOW_SHIFT));
139938fd1498Szrj   gcc_assert (asan_shadow_set != -1
140038fd1498Szrj 	      && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
140138fd1498Szrj   shadow_mem = gen_rtx_MEM (SImode, shadow_base);
140238fd1498Szrj   set_mem_alias_set (shadow_mem, asan_shadow_set);
140338fd1498Szrj   if (STRICT_ALIGNMENT)
140438fd1498Szrj     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
140538fd1498Szrj   prev_offset = base_offset;
140638fd1498Szrj   for (l = length; l; l -= 2)
140738fd1498Szrj     {
140838fd1498Szrj       if (l == 2)
140938fd1498Szrj 	cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
141038fd1498Szrj       offset = offsets[l - 1];
141138fd1498Szrj       if ((offset - base_offset) & (ASAN_RED_ZONE_SIZE - 1))
141238fd1498Szrj 	{
141338fd1498Szrj 	  int i;
141438fd1498Szrj 	  HOST_WIDE_INT aoff
141538fd1498Szrj 	    = base_offset + ((offset - base_offset)
141638fd1498Szrj 			     & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
141738fd1498Szrj 	  shadow_mem = adjust_address (shadow_mem, VOIDmode,
141838fd1498Szrj 				       (aoff - prev_offset)
141938fd1498Szrj 				       >> ASAN_SHADOW_SHIFT);
142038fd1498Szrj 	  prev_offset = aoff;
142138fd1498Szrj 	  for (i = 0; i < 4; i++, aoff += ASAN_SHADOW_GRANULARITY)
142238fd1498Szrj 	    if (aoff < offset)
142338fd1498Szrj 	      {
142438fd1498Szrj 		if (aoff < offset - (HOST_WIDE_INT)ASAN_SHADOW_GRANULARITY + 1)
142538fd1498Szrj 		  shadow_bytes[i] = 0;
142638fd1498Szrj 		else
142738fd1498Szrj 		  shadow_bytes[i] = offset - aoff;
142838fd1498Szrj 	      }
142938fd1498Szrj 	    else
143038fd1498Szrj 	      shadow_bytes[i] = ASAN_STACK_MAGIC_MIDDLE;
143138fd1498Szrj 	  emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
143238fd1498Szrj 	  offset = aoff;
143338fd1498Szrj 	}
143438fd1498Szrj       while (offset <= offsets[l - 2] - ASAN_RED_ZONE_SIZE)
143538fd1498Szrj 	{
143638fd1498Szrj 	  shadow_mem = adjust_address (shadow_mem, VOIDmode,
143738fd1498Szrj 				       (offset - prev_offset)
143838fd1498Szrj 				       >> ASAN_SHADOW_SHIFT);
143938fd1498Szrj 	  prev_offset = offset;
144038fd1498Szrj 	  memset (shadow_bytes, cur_shadow_byte, 4);
144138fd1498Szrj 	  emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
144238fd1498Szrj 	  offset += ASAN_RED_ZONE_SIZE;
144338fd1498Szrj 	}
144438fd1498Szrj       cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
144538fd1498Szrj     }
144638fd1498Szrj   do_pending_stack_adjust ();
144738fd1498Szrj 
144838fd1498Szrj   /* Construct epilogue sequence.  */
144938fd1498Szrj   start_sequence ();
145038fd1498Szrj 
145138fd1498Szrj   lab = NULL;
145238fd1498Szrj   if (use_after_return_class != -1)
145338fd1498Szrj     {
145438fd1498Szrj       rtx_code_label *lab2 = gen_label_rtx ();
145538fd1498Szrj       char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
145638fd1498Szrj       emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
145738fd1498Szrj 			       VOIDmode, 0, lab2,
145838fd1498Szrj 			       profile_probability::very_likely ());
145938fd1498Szrj       shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
146038fd1498Szrj       set_mem_alias_set (shadow_mem, asan_shadow_set);
146138fd1498Szrj       mem = gen_rtx_MEM (ptr_mode, base);
146238fd1498Szrj       mem = adjust_address (mem, VOIDmode, base_align_bias);
146338fd1498Szrj       emit_move_insn (mem, gen_int_mode (ASAN_STACK_RETIRED_MAGIC, ptr_mode));
146438fd1498Szrj       unsigned HOST_WIDE_INT sz = asan_frame_size >> ASAN_SHADOW_SHIFT;
146538fd1498Szrj       if (use_after_return_class < 5
146638fd1498Szrj 	  && can_store_by_pieces (sz, builtin_memset_read_str, &c,
146738fd1498Szrj 				  BITS_PER_UNIT, true))
146838fd1498Szrj 	store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
146938fd1498Szrj 			 BITS_PER_UNIT, true, 0);
147038fd1498Szrj       else if (use_after_return_class >= 5
147138fd1498Szrj 	       || !set_storage_via_setmem (shadow_mem,
147238fd1498Szrj 					   GEN_INT (sz),
147338fd1498Szrj 					   gen_int_mode (c, QImode),
147438fd1498Szrj 					   BITS_PER_UNIT, BITS_PER_UNIT,
147538fd1498Szrj 					   -1, sz, sz, sz))
147638fd1498Szrj 	{
147738fd1498Szrj 	  snprintf (buf, sizeof buf, "__asan_stack_free_%d",
147838fd1498Szrj 		    use_after_return_class);
147938fd1498Szrj 	  ret = init_one_libfunc (buf);
148038fd1498Szrj 	  rtx addr = convert_memory_address (ptr_mode, base);
148138fd1498Szrj 	  rtx orig_addr = convert_memory_address (ptr_mode, orig_base);
148238fd1498Szrj 	  emit_library_call (ret, LCT_NORMAL, ptr_mode, addr, ptr_mode,
148338fd1498Szrj 			     GEN_INT (asan_frame_size + base_align_bias),
148438fd1498Szrj 			     TYPE_MODE (pointer_sized_int_node),
148538fd1498Szrj 			     orig_addr, ptr_mode);
148638fd1498Szrj 	}
148738fd1498Szrj       lab = gen_label_rtx ();
148838fd1498Szrj       emit_jump (lab);
148938fd1498Szrj       emit_label (lab2);
149038fd1498Szrj     }
149138fd1498Szrj 
149238fd1498Szrj   shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
149338fd1498Szrj   set_mem_alias_set (shadow_mem, asan_shadow_set);
149438fd1498Szrj 
149538fd1498Szrj   if (STRICT_ALIGNMENT)
149638fd1498Szrj     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
149738fd1498Szrj 
149838fd1498Szrj   prev_offset = base_offset;
149938fd1498Szrj   last_offset = base_offset;
150038fd1498Szrj   last_size = 0;
150138fd1498Szrj   for (l = length; l; l -= 2)
150238fd1498Szrj     {
150338fd1498Szrj       offset = base_offset + ((offsets[l - 1] - base_offset)
150438fd1498Szrj 			     & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
150538fd1498Szrj       if (last_offset + last_size != offset)
150638fd1498Szrj 	{
150738fd1498Szrj 	  shadow_mem = adjust_address (shadow_mem, VOIDmode,
150838fd1498Szrj 				       (last_offset - prev_offset)
150938fd1498Szrj 				       >> ASAN_SHADOW_SHIFT);
151038fd1498Szrj 	  prev_offset = last_offset;
151138fd1498Szrj 	  asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
151238fd1498Szrj 	  last_offset = offset;
151338fd1498Szrj 	  last_size = 0;
151438fd1498Szrj 	}
151538fd1498Szrj       last_size += base_offset + ((offsets[l - 2] - base_offset)
151638fd1498Szrj 				  & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
151738fd1498Szrj 		   - offset;
151838fd1498Szrj 
151938fd1498Szrj       /* Unpoison shadow memory that corresponds to a variable that is
152038fd1498Szrj 	 is subject of use-after-return sanitization.  */
152138fd1498Szrj       if (l > 2)
152238fd1498Szrj 	{
152338fd1498Szrj 	  decl = decls[l / 2 - 2];
152438fd1498Szrj 	  if (asan_handled_variables != NULL
152538fd1498Szrj 	      && asan_handled_variables->contains (decl))
152638fd1498Szrj 	    {
152738fd1498Szrj 	      HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
152838fd1498Szrj 	      if (dump_file && (dump_flags & TDF_DETAILS))
152938fd1498Szrj 		{
153038fd1498Szrj 		  const char *n = (DECL_NAME (decl)
153138fd1498Szrj 				   ? IDENTIFIER_POINTER (DECL_NAME (decl))
153238fd1498Szrj 				   : "<unknown>");
153338fd1498Szrj 		  fprintf (dump_file, "Unpoisoning shadow stack for variable: "
153438fd1498Szrj 			   "%s (%" PRId64 " B)\n", n, size);
153538fd1498Szrj 		}
153638fd1498Szrj 
153738fd1498Szrj 		last_size += size & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
153838fd1498Szrj 	    }
153938fd1498Szrj 	}
154038fd1498Szrj     }
154138fd1498Szrj   if (last_size)
154238fd1498Szrj     {
154338fd1498Szrj       shadow_mem = adjust_address (shadow_mem, VOIDmode,
154438fd1498Szrj 				   (last_offset - prev_offset)
154538fd1498Szrj 				   >> ASAN_SHADOW_SHIFT);
154638fd1498Szrj       asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
154738fd1498Szrj     }
154838fd1498Szrj 
154938fd1498Szrj   /* Clean-up set with instrumented stack variables.  */
155038fd1498Szrj   delete asan_handled_variables;
155138fd1498Szrj   asan_handled_variables = NULL;
155238fd1498Szrj   delete asan_used_labels;
155338fd1498Szrj   asan_used_labels = NULL;
155438fd1498Szrj 
155538fd1498Szrj   do_pending_stack_adjust ();
155638fd1498Szrj   if (lab)
155738fd1498Szrj     emit_label (lab);
155838fd1498Szrj 
155938fd1498Szrj   insns = get_insns ();
156038fd1498Szrj   end_sequence ();
156138fd1498Szrj   return insns;
156238fd1498Szrj }
156338fd1498Szrj 
156438fd1498Szrj /* Emit __asan_allocas_unpoison (top, bot) call.  The BASE parameter corresponds
156538fd1498Szrj    to BOT argument, for TOP virtual_stack_dynamic_rtx is used.  NEW_SEQUENCE
156638fd1498Szrj    indicates whether we're emitting new instructions sequence or not.  */
156738fd1498Szrj 
156838fd1498Szrj rtx_insn *
asan_emit_allocas_unpoison(rtx top,rtx bot,rtx_insn * before)156938fd1498Szrj asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
157038fd1498Szrj {
157138fd1498Szrj   if (before)
157238fd1498Szrj     push_to_sequence (before);
157338fd1498Szrj   else
157438fd1498Szrj     start_sequence ();
157538fd1498Szrj   rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
157638fd1498Szrj   top = convert_memory_address (ptr_mode, top);
157738fd1498Szrj   bot = convert_memory_address (ptr_mode, bot);
157838fd1498Szrj   ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
157938fd1498Szrj 				 top, ptr_mode, bot, ptr_mode);
158038fd1498Szrj 
158138fd1498Szrj   do_pending_stack_adjust ();
158238fd1498Szrj   rtx_insn *insns = get_insns ();
158338fd1498Szrj   end_sequence ();
158438fd1498Szrj   return insns;
158538fd1498Szrj }
158638fd1498Szrj 
158738fd1498Szrj /* Return true if DECL, a global var, might be overridden and needs
158838fd1498Szrj    therefore a local alias.  */
158938fd1498Szrj 
159038fd1498Szrj static bool
asan_needs_local_alias(tree decl)159138fd1498Szrj asan_needs_local_alias (tree decl)
159238fd1498Szrj {
159338fd1498Szrj   return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
159438fd1498Szrj }
159538fd1498Szrj 
159638fd1498Szrj /* Return true if DECL, a global var, is an artificial ODR indicator symbol
159738fd1498Szrj    therefore doesn't need protection.  */
159838fd1498Szrj 
159938fd1498Szrj static bool
is_odr_indicator(tree decl)160038fd1498Szrj is_odr_indicator (tree decl)
160138fd1498Szrj {
160238fd1498Szrj   return (DECL_ARTIFICIAL (decl)
160338fd1498Szrj 	  && lookup_attribute ("asan odr indicator", DECL_ATTRIBUTES (decl)));
160438fd1498Szrj }
160538fd1498Szrj 
160638fd1498Szrj /* Return true if DECL is a VAR_DECL that should be protected
160738fd1498Szrj    by Address Sanitizer, by appending a red zone with protected
160838fd1498Szrj    shadow memory after it and aligning it to at least
160938fd1498Szrj    ASAN_RED_ZONE_SIZE bytes.  */
161038fd1498Szrj 
161138fd1498Szrj bool
asan_protect_global(tree decl,bool ignore_decl_rtl_set_p)161238fd1498Szrj asan_protect_global (tree decl, bool ignore_decl_rtl_set_p)
161338fd1498Szrj {
161438fd1498Szrj   if (!ASAN_GLOBALS)
161538fd1498Szrj     return false;
161638fd1498Szrj 
161738fd1498Szrj   rtx rtl, symbol;
161838fd1498Szrj 
161938fd1498Szrj   if (TREE_CODE (decl) == STRING_CST)
162038fd1498Szrj     {
162138fd1498Szrj       /* Instrument all STRING_CSTs except those created
162238fd1498Szrj 	 by asan_pp_string here.  */
162338fd1498Szrj       if (shadow_ptr_types[0] != NULL_TREE
162438fd1498Szrj 	  && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
162538fd1498Szrj 	  && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0]))
162638fd1498Szrj 	return false;
162738fd1498Szrj       return true;
162838fd1498Szrj     }
162938fd1498Szrj   if (!VAR_P (decl)
163038fd1498Szrj       /* TLS vars aren't statically protectable.  */
163138fd1498Szrj       || DECL_THREAD_LOCAL_P (decl)
163238fd1498Szrj       /* Externs will be protected elsewhere.  */
163338fd1498Szrj       || DECL_EXTERNAL (decl)
163438fd1498Szrj       /* PR sanitizer/81697: For architectures that use section anchors first
163538fd1498Szrj 	 call to asan_protect_global may occur before DECL_RTL (decl) is set.
163638fd1498Szrj 	 We should ignore DECL_RTL_SET_P then, because otherwise the first call
163738fd1498Szrj 	 to asan_protect_global will return FALSE and the following calls on the
163838fd1498Szrj 	 same decl after setting DECL_RTL (decl) will return TRUE and we'll end
163938fd1498Szrj 	 up with inconsistency at runtime.  */
164038fd1498Szrj       || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p)
164138fd1498Szrj       /* Comdat vars pose an ABI problem, we can't know if
164238fd1498Szrj 	 the var that is selected by the linker will have
164338fd1498Szrj 	 padding or not.  */
164438fd1498Szrj       || DECL_ONE_ONLY (decl)
164538fd1498Szrj       /* Similarly for common vars.  People can use -fno-common.
164638fd1498Szrj 	 Note: Linux kernel is built with -fno-common, so we do instrument
164738fd1498Szrj 	 globals there even if it is C.  */
164838fd1498Szrj       || (DECL_COMMON (decl) && TREE_PUBLIC (decl))
164938fd1498Szrj       /* Don't protect if using user section, often vars placed
165038fd1498Szrj 	 into user section from multiple TUs are then assumed
165138fd1498Szrj 	 to be an array of such vars, putting padding in there
165238fd1498Szrj 	 breaks this assumption.  */
165338fd1498Szrj       || (DECL_SECTION_NAME (decl) != NULL
165438fd1498Szrj 	  && !symtab_node::get (decl)->implicit_section
165538fd1498Szrj 	  && !section_sanitized_p (DECL_SECTION_NAME (decl)))
165638fd1498Szrj       || DECL_SIZE (decl) == 0
165738fd1498Szrj       || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
165838fd1498Szrj       || TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
165938fd1498Szrj       || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
166038fd1498Szrj       || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
166138fd1498Szrj       || TREE_TYPE (decl) == ubsan_get_source_location_type ()
166238fd1498Szrj       || is_odr_indicator (decl))
166338fd1498Szrj     return false;
166438fd1498Szrj 
166538fd1498Szrj   if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl))
166638fd1498Szrj     {
166738fd1498Szrj 
166838fd1498Szrj       rtl = DECL_RTL (decl);
166938fd1498Szrj       if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF)
167038fd1498Szrj 	return false;
167138fd1498Szrj       symbol = XEXP (rtl, 0);
167238fd1498Szrj 
167338fd1498Szrj       if (CONSTANT_POOL_ADDRESS_P (symbol)
167438fd1498Szrj 	  || TREE_CONSTANT_POOL_ADDRESS_P (symbol))
167538fd1498Szrj 	return false;
167638fd1498Szrj     }
167738fd1498Szrj 
167838fd1498Szrj   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
167938fd1498Szrj     return false;
168038fd1498Szrj 
168138fd1498Szrj   if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl))
168238fd1498Szrj     return false;
168338fd1498Szrj 
168438fd1498Szrj   return true;
168538fd1498Szrj }
168638fd1498Szrj 
168738fd1498Szrj /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}.
168838fd1498Szrj    IS_STORE is either 1 (for a store) or 0 (for a load).  */
168938fd1498Szrj 
169038fd1498Szrj static tree
report_error_func(bool is_store,bool recover_p,HOST_WIDE_INT size_in_bytes,int * nargs)169138fd1498Szrj report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
169238fd1498Szrj 		   int *nargs)
169338fd1498Szrj {
169438fd1498Szrj   static enum built_in_function report[2][2][6]
169538fd1498Szrj     = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
169638fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
169738fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
169838fd1498Szrj 	  { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
169938fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
170038fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
170138fd1498Szrj 	{ { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
170238fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
170338fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
170438fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
170538fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
170638fd1498Szrj 	    BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
170738fd1498Szrj 	  { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
170838fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
170938fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
171038fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
171138fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
171238fd1498Szrj 	    BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
171338fd1498Szrj   if (size_in_bytes == -1)
171438fd1498Szrj     {
171538fd1498Szrj       *nargs = 2;
171638fd1498Szrj       return builtin_decl_implicit (report[recover_p][is_store][5]);
171738fd1498Szrj     }
171838fd1498Szrj   *nargs = 1;
171938fd1498Szrj   int size_log2 = exact_log2 (size_in_bytes);
172038fd1498Szrj   return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
172138fd1498Szrj }
172238fd1498Szrj 
172338fd1498Szrj /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
172438fd1498Szrj    IS_STORE is either 1 (for a store) or 0 (for a load).  */
172538fd1498Szrj 
172638fd1498Szrj static tree
check_func(bool is_store,bool recover_p,HOST_WIDE_INT size_in_bytes,int * nargs)172738fd1498Szrj check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
172838fd1498Szrj 	    int *nargs)
172938fd1498Szrj {
173038fd1498Szrj   static enum built_in_function check[2][2][6]
173138fd1498Szrj     = { { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
173238fd1498Szrj 	    BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
173338fd1498Szrj 	    BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
173438fd1498Szrj 	  { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
173538fd1498Szrj 	    BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
173638fd1498Szrj 	    BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } },
173738fd1498Szrj 	{ { BUILT_IN_ASAN_LOAD1_NOABORT,
173838fd1498Szrj 	    BUILT_IN_ASAN_LOAD2_NOABORT,
173938fd1498Szrj 	    BUILT_IN_ASAN_LOAD4_NOABORT,
174038fd1498Szrj 	    BUILT_IN_ASAN_LOAD8_NOABORT,
174138fd1498Szrj 	    BUILT_IN_ASAN_LOAD16_NOABORT,
174238fd1498Szrj 	    BUILT_IN_ASAN_LOADN_NOABORT },
174338fd1498Szrj 	  { BUILT_IN_ASAN_STORE1_NOABORT,
174438fd1498Szrj 	    BUILT_IN_ASAN_STORE2_NOABORT,
174538fd1498Szrj 	    BUILT_IN_ASAN_STORE4_NOABORT,
174638fd1498Szrj 	    BUILT_IN_ASAN_STORE8_NOABORT,
174738fd1498Szrj 	    BUILT_IN_ASAN_STORE16_NOABORT,
174838fd1498Szrj 	    BUILT_IN_ASAN_STOREN_NOABORT } } };
174938fd1498Szrj   if (size_in_bytes == -1)
175038fd1498Szrj     {
175138fd1498Szrj       *nargs = 2;
175238fd1498Szrj       return builtin_decl_implicit (check[recover_p][is_store][5]);
175338fd1498Szrj     }
175438fd1498Szrj   *nargs = 1;
175538fd1498Szrj   int size_log2 = exact_log2 (size_in_bytes);
175638fd1498Szrj   return builtin_decl_implicit (check[recover_p][is_store][size_log2]);
175738fd1498Szrj }
175838fd1498Szrj 
175938fd1498Szrj /* Split the current basic block and create a condition statement
176038fd1498Szrj    insertion point right before or after the statement pointed to by
176138fd1498Szrj    ITER.  Return an iterator to the point at which the caller might
176238fd1498Szrj    safely insert the condition statement.
176338fd1498Szrj 
176438fd1498Szrj    THEN_BLOCK must be set to the address of an uninitialized instance
176538fd1498Szrj    of basic_block.  The function will then set *THEN_BLOCK to the
176638fd1498Szrj    'then block' of the condition statement to be inserted by the
176738fd1498Szrj    caller.
176838fd1498Szrj 
176938fd1498Szrj    If CREATE_THEN_FALLTHRU_EDGE is false, no edge will be created from
177038fd1498Szrj    *THEN_BLOCK to *FALLTHROUGH_BLOCK.
177138fd1498Szrj 
177238fd1498Szrj    Similarly, the function will set *FALLTRHOUGH_BLOCK to the 'else
177338fd1498Szrj    block' of the condition statement to be inserted by the caller.
177438fd1498Szrj 
177538fd1498Szrj    Note that *FALLTHROUGH_BLOCK is a new block that contains the
177638fd1498Szrj    statements starting from *ITER, and *THEN_BLOCK is a new empty
177738fd1498Szrj    block.
177838fd1498Szrj 
177938fd1498Szrj    *ITER is adjusted to point to always point to the first statement
178038fd1498Szrj     of the basic block * FALLTHROUGH_BLOCK.  That statement is the
178138fd1498Szrj     same as what ITER was pointing to prior to calling this function,
178238fd1498Szrj     if BEFORE_P is true; otherwise, it is its following statement.  */
178338fd1498Szrj 
178438fd1498Szrj gimple_stmt_iterator
create_cond_insert_point(gimple_stmt_iterator * iter,bool before_p,bool then_more_likely_p,bool create_then_fallthru_edge,basic_block * then_block,basic_block * fallthrough_block)178538fd1498Szrj create_cond_insert_point (gimple_stmt_iterator *iter,
178638fd1498Szrj 			  bool before_p,
178738fd1498Szrj 			  bool then_more_likely_p,
178838fd1498Szrj 			  bool create_then_fallthru_edge,
178938fd1498Szrj 			  basic_block *then_block,
179038fd1498Szrj 			  basic_block *fallthrough_block)
179138fd1498Szrj {
179238fd1498Szrj   gimple_stmt_iterator gsi = *iter;
179338fd1498Szrj 
179438fd1498Szrj   if (!gsi_end_p (gsi) && before_p)
179538fd1498Szrj     gsi_prev (&gsi);
179638fd1498Szrj 
179738fd1498Szrj   basic_block cur_bb = gsi_bb (*iter);
179838fd1498Szrj 
179938fd1498Szrj   edge e = split_block (cur_bb, gsi_stmt (gsi));
180038fd1498Szrj 
180138fd1498Szrj   /* Get a hold on the 'condition block', the 'then block' and the
180238fd1498Szrj      'else block'.  */
180338fd1498Szrj   basic_block cond_bb = e->src;
180438fd1498Szrj   basic_block fallthru_bb = e->dest;
180538fd1498Szrj   basic_block then_bb = create_empty_bb (cond_bb);
180638fd1498Szrj   if (current_loops)
180738fd1498Szrj     {
180838fd1498Szrj       add_bb_to_loop (then_bb, cond_bb->loop_father);
180938fd1498Szrj       loops_state_set (LOOPS_NEED_FIXUP);
181038fd1498Szrj     }
181138fd1498Szrj 
181238fd1498Szrj   /* Set up the newly created 'then block'.  */
181338fd1498Szrj   e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
181438fd1498Szrj   profile_probability fallthrough_probability
181538fd1498Szrj     = then_more_likely_p
181638fd1498Szrj     ? profile_probability::very_unlikely ()
181738fd1498Szrj     : profile_probability::very_likely ();
181838fd1498Szrj   e->probability = fallthrough_probability.invert ();
181938fd1498Szrj   then_bb->count = e->count ();
182038fd1498Szrj   if (create_then_fallthru_edge)
182138fd1498Szrj     make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
182238fd1498Szrj 
182338fd1498Szrj   /* Set up the fallthrough basic block.  */
182438fd1498Szrj   e = find_edge (cond_bb, fallthru_bb);
182538fd1498Szrj   e->flags = EDGE_FALSE_VALUE;
182638fd1498Szrj   e->probability = fallthrough_probability;
182738fd1498Szrj 
182838fd1498Szrj   /* Update dominance info for the newly created then_bb; note that
182938fd1498Szrj      fallthru_bb's dominance info has already been updated by
183038fd1498Szrj      split_bock.  */
183138fd1498Szrj   if (dom_info_available_p (CDI_DOMINATORS))
183238fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
183338fd1498Szrj 
183438fd1498Szrj   *then_block = then_bb;
183538fd1498Szrj   *fallthrough_block = fallthru_bb;
183638fd1498Szrj   *iter = gsi_start_bb (fallthru_bb);
183738fd1498Szrj 
183838fd1498Szrj   return gsi_last_bb (cond_bb);
183938fd1498Szrj }
184038fd1498Szrj 
184138fd1498Szrj /* Insert an if condition followed by a 'then block' right before the
184238fd1498Szrj    statement pointed to by ITER.  The fallthrough block -- which is the
184338fd1498Szrj    else block of the condition as well as the destination of the
184438fd1498Szrj    outcoming edge of the 'then block' -- starts with the statement
184538fd1498Szrj    pointed to by ITER.
184638fd1498Szrj 
184738fd1498Szrj    COND is the condition of the if.
184838fd1498Szrj 
184938fd1498Szrj    If THEN_MORE_LIKELY_P is true, the probability of the edge to the
185038fd1498Szrj    'then block' is higher than the probability of the edge to the
185138fd1498Szrj    fallthrough block.
185238fd1498Szrj 
185338fd1498Szrj    Upon completion of the function, *THEN_BB is set to the newly
185438fd1498Szrj    inserted 'then block' and similarly, *FALLTHROUGH_BB is set to the
185538fd1498Szrj    fallthrough block.
185638fd1498Szrj 
185738fd1498Szrj    *ITER is adjusted to still point to the same statement it was
185838fd1498Szrj    pointing to initially.  */
185938fd1498Szrj 
186038fd1498Szrj static void
insert_if_then_before_iter(gcond * cond,gimple_stmt_iterator * iter,bool then_more_likely_p,basic_block * then_bb,basic_block * fallthrough_bb)186138fd1498Szrj insert_if_then_before_iter (gcond *cond,
186238fd1498Szrj 			    gimple_stmt_iterator *iter,
186338fd1498Szrj 			    bool then_more_likely_p,
186438fd1498Szrj 			    basic_block *then_bb,
186538fd1498Szrj 			    basic_block *fallthrough_bb)
186638fd1498Szrj {
186738fd1498Szrj   gimple_stmt_iterator cond_insert_point =
186838fd1498Szrj     create_cond_insert_point (iter,
186938fd1498Szrj 			      /*before_p=*/true,
187038fd1498Szrj 			      then_more_likely_p,
187138fd1498Szrj 			      /*create_then_fallthru_edge=*/true,
187238fd1498Szrj 			      then_bb,
187338fd1498Szrj 			      fallthrough_bb);
187438fd1498Szrj   gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
187538fd1498Szrj }
187638fd1498Szrj 
187738fd1498Szrj /* Build (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().
187838fd1498Szrj    If RETURN_ADDRESS is set to true, return memory location instread
187938fd1498Szrj    of a value in the shadow memory.  */
188038fd1498Szrj 
188138fd1498Szrj static tree
188238fd1498Szrj build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
188338fd1498Szrj 			 tree base_addr, tree shadow_ptr_type,
188438fd1498Szrj 			 bool return_address = false)
188538fd1498Szrj {
188638fd1498Szrj   tree t, uintptr_type = TREE_TYPE (base_addr);
188738fd1498Szrj   tree shadow_type = TREE_TYPE (shadow_ptr_type);
188838fd1498Szrj   gimple *g;
188938fd1498Szrj 
189038fd1498Szrj   t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
189138fd1498Szrj   g = gimple_build_assign (make_ssa_name (uintptr_type), RSHIFT_EXPR,
189238fd1498Szrj 			   base_addr, t);
189338fd1498Szrj   gimple_set_location (g, location);
189438fd1498Szrj   gsi_insert_after (gsi, g, GSI_NEW_STMT);
189538fd1498Szrj 
189638fd1498Szrj   t = build_int_cst (uintptr_type, asan_shadow_offset ());
189738fd1498Szrj   g = gimple_build_assign (make_ssa_name (uintptr_type), PLUS_EXPR,
189838fd1498Szrj 			   gimple_assign_lhs (g), t);
189938fd1498Szrj   gimple_set_location (g, location);
190038fd1498Szrj   gsi_insert_after (gsi, g, GSI_NEW_STMT);
190138fd1498Szrj 
190238fd1498Szrj   g = gimple_build_assign (make_ssa_name (shadow_ptr_type), NOP_EXPR,
190338fd1498Szrj 			   gimple_assign_lhs (g));
190438fd1498Szrj   gimple_set_location (g, location);
190538fd1498Szrj   gsi_insert_after (gsi, g, GSI_NEW_STMT);
190638fd1498Szrj 
190738fd1498Szrj   if (!return_address)
190838fd1498Szrj     {
190938fd1498Szrj       t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
191038fd1498Szrj 		  build_int_cst (shadow_ptr_type, 0));
191138fd1498Szrj       g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
191238fd1498Szrj       gimple_set_location (g, location);
191338fd1498Szrj       gsi_insert_after (gsi, g, GSI_NEW_STMT);
191438fd1498Szrj     }
191538fd1498Szrj 
191638fd1498Szrj   return gimple_assign_lhs (g);
191738fd1498Szrj }
191838fd1498Szrj 
191938fd1498Szrj /* BASE can already be an SSA_NAME; in that case, do not create a
192038fd1498Szrj    new SSA_NAME for it.  */
192138fd1498Szrj 
192238fd1498Szrj static tree
maybe_create_ssa_name(location_t loc,tree base,gimple_stmt_iterator * iter,bool before_p)192338fd1498Szrj maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
192438fd1498Szrj 		       bool before_p)
192538fd1498Szrj {
192638fd1498Szrj   if (TREE_CODE (base) == SSA_NAME)
192738fd1498Szrj     return base;
192838fd1498Szrj   gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (base)),
192938fd1498Szrj 				  TREE_CODE (base), base);
193038fd1498Szrj   gimple_set_location (g, loc);
193138fd1498Szrj   if (before_p)
193238fd1498Szrj     gsi_insert_before (iter, g, GSI_SAME_STMT);
193338fd1498Szrj   else
193438fd1498Szrj     gsi_insert_after (iter, g, GSI_NEW_STMT);
193538fd1498Szrj   return gimple_assign_lhs (g);
193638fd1498Szrj }
193738fd1498Szrj 
193838fd1498Szrj /* LEN can already have necessary size and precision;
193938fd1498Szrj    in that case, do not create a new variable.  */
194038fd1498Szrj 
194138fd1498Szrj tree
maybe_cast_to_ptrmode(location_t loc,tree len,gimple_stmt_iterator * iter,bool before_p)194238fd1498Szrj maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter,
194338fd1498Szrj 		       bool before_p)
194438fd1498Szrj {
194538fd1498Szrj   if (ptrofftype_p (len))
194638fd1498Szrj     return len;
194738fd1498Szrj   gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
194838fd1498Szrj 				  NOP_EXPR, len);
194938fd1498Szrj   gimple_set_location (g, loc);
195038fd1498Szrj   if (before_p)
195138fd1498Szrj     gsi_insert_before (iter, g, GSI_SAME_STMT);
195238fd1498Szrj   else
195338fd1498Szrj     gsi_insert_after (iter, g, GSI_NEW_STMT);
195438fd1498Szrj   return gimple_assign_lhs (g);
195538fd1498Szrj }
195638fd1498Szrj 
195738fd1498Szrj /* Instrument the memory access instruction BASE.  Insert new
195838fd1498Szrj    statements before or after ITER.
195938fd1498Szrj 
196038fd1498Szrj    Note that the memory access represented by BASE can be either an
196138fd1498Szrj    SSA_NAME, or a non-SSA expression.  LOCATION is the source code
196238fd1498Szrj    location.  IS_STORE is TRUE for a store, FALSE for a load.
196338fd1498Szrj    BEFORE_P is TRUE for inserting the instrumentation code before
196438fd1498Szrj    ITER, FALSE for inserting it after ITER.  IS_SCALAR_ACCESS is TRUE
196538fd1498Szrj    for a scalar memory access and FALSE for memory region access.
196638fd1498Szrj    NON_ZERO_P is TRUE if memory region is guaranteed to have non-zero
196738fd1498Szrj    length.  ALIGN tells alignment of accessed memory object.
196838fd1498Szrj 
196938fd1498Szrj    START_INSTRUMENTED and END_INSTRUMENTED are TRUE if start/end of
197038fd1498Szrj    memory region have already been instrumented.
197138fd1498Szrj 
197238fd1498Szrj    If BEFORE_P is TRUE, *ITER is arranged to still point to the
197338fd1498Szrj    statement it was pointing to prior to calling this function,
197438fd1498Szrj    otherwise, it points to the statement logically following it.  */
197538fd1498Szrj 
197638fd1498Szrj static void
197738fd1498Szrj build_check_stmt (location_t loc, tree base, tree len,
197838fd1498Szrj 		  HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
197938fd1498Szrj 		  bool is_non_zero_len, bool before_p, bool is_store,
198038fd1498Szrj 		  bool is_scalar_access, unsigned int align = 0)
198138fd1498Szrj {
198238fd1498Szrj   gimple_stmt_iterator gsi = *iter;
198338fd1498Szrj   gimple *g;
198438fd1498Szrj 
198538fd1498Szrj   gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
198638fd1498Szrj 
198738fd1498Szrj   gsi = *iter;
198838fd1498Szrj 
198938fd1498Szrj   base = unshare_expr (base);
199038fd1498Szrj   base = maybe_create_ssa_name (loc, base, &gsi, before_p);
199138fd1498Szrj 
199238fd1498Szrj   if (len)
199338fd1498Szrj     {
199438fd1498Szrj       len = unshare_expr (len);
199538fd1498Szrj       len = maybe_cast_to_ptrmode (loc, len, iter, before_p);
199638fd1498Szrj     }
199738fd1498Szrj   else
199838fd1498Szrj     {
199938fd1498Szrj       gcc_assert (size_in_bytes != -1);
200038fd1498Szrj       len = build_int_cst (pointer_sized_int_node, size_in_bytes);
200138fd1498Szrj     }
200238fd1498Szrj 
200338fd1498Szrj   if (size_in_bytes > 1)
200438fd1498Szrj     {
200538fd1498Szrj       if ((size_in_bytes & (size_in_bytes - 1)) != 0
200638fd1498Szrj 	  || size_in_bytes > 16)
200738fd1498Szrj 	is_scalar_access = false;
200838fd1498Szrj       else if (align && align < size_in_bytes * BITS_PER_UNIT)
200938fd1498Szrj 	{
201038fd1498Szrj 	  /* On non-strict alignment targets, if
201138fd1498Szrj 	     16-byte access is just 8-byte aligned,
201238fd1498Szrj 	     this will result in misaligned shadow
201338fd1498Szrj 	     memory 2 byte load, but otherwise can
201438fd1498Szrj 	     be handled using one read.  */
201538fd1498Szrj 	  if (size_in_bytes != 16
201638fd1498Szrj 	      || STRICT_ALIGNMENT
201738fd1498Szrj 	      || align < 8 * BITS_PER_UNIT)
201838fd1498Szrj 	    is_scalar_access = false;
201938fd1498Szrj 	}
202038fd1498Szrj     }
202138fd1498Szrj 
202238fd1498Szrj   HOST_WIDE_INT flags = 0;
202338fd1498Szrj   if (is_store)
202438fd1498Szrj     flags |= ASAN_CHECK_STORE;
202538fd1498Szrj   if (is_non_zero_len)
202638fd1498Szrj     flags |= ASAN_CHECK_NON_ZERO_LEN;
202738fd1498Szrj   if (is_scalar_access)
202838fd1498Szrj     flags |= ASAN_CHECK_SCALAR_ACCESS;
202938fd1498Szrj 
203038fd1498Szrj   g = gimple_build_call_internal (IFN_ASAN_CHECK, 4,
203138fd1498Szrj 				  build_int_cst (integer_type_node, flags),
203238fd1498Szrj 				  base, len,
203338fd1498Szrj 				  build_int_cst (integer_type_node,
203438fd1498Szrj 						 align / BITS_PER_UNIT));
203538fd1498Szrj   gimple_set_location (g, loc);
203638fd1498Szrj   if (before_p)
203738fd1498Szrj     gsi_insert_before (&gsi, g, GSI_SAME_STMT);
203838fd1498Szrj   else
203938fd1498Szrj     {
204038fd1498Szrj       gsi_insert_after (&gsi, g, GSI_NEW_STMT);
204138fd1498Szrj       gsi_next (&gsi);
204238fd1498Szrj       *iter = gsi;
204338fd1498Szrj     }
204438fd1498Szrj }
204538fd1498Szrj 
204638fd1498Szrj /* If T represents a memory access, add instrumentation code before ITER.
204738fd1498Szrj    LOCATION is source code location.
204838fd1498Szrj    IS_STORE is either TRUE (for a store) or FALSE (for a load).  */
204938fd1498Szrj 
205038fd1498Szrj static void
instrument_derefs(gimple_stmt_iterator * iter,tree t,location_t location,bool is_store)205138fd1498Szrj instrument_derefs (gimple_stmt_iterator *iter, tree t,
205238fd1498Szrj 		   location_t location, bool is_store)
205338fd1498Szrj {
205438fd1498Szrj   if (is_store && !ASAN_INSTRUMENT_WRITES)
205538fd1498Szrj     return;
205638fd1498Szrj   if (!is_store && !ASAN_INSTRUMENT_READS)
205738fd1498Szrj     return;
205838fd1498Szrj 
205938fd1498Szrj   tree type, base;
206038fd1498Szrj   HOST_WIDE_INT size_in_bytes;
206138fd1498Szrj   if (location == UNKNOWN_LOCATION)
206238fd1498Szrj     location = EXPR_LOCATION (t);
206338fd1498Szrj 
206438fd1498Szrj   type = TREE_TYPE (t);
206538fd1498Szrj   switch (TREE_CODE (t))
206638fd1498Szrj     {
206738fd1498Szrj     case ARRAY_REF:
206838fd1498Szrj     case COMPONENT_REF:
206938fd1498Szrj     case INDIRECT_REF:
207038fd1498Szrj     case MEM_REF:
207138fd1498Szrj     case VAR_DECL:
207238fd1498Szrj     case BIT_FIELD_REF:
207338fd1498Szrj       break;
207438fd1498Szrj       /* FALLTHRU */
207538fd1498Szrj     default:
207638fd1498Szrj       return;
207738fd1498Szrj     }
207838fd1498Szrj 
207938fd1498Szrj   size_in_bytes = int_size_in_bytes (type);
208038fd1498Szrj   if (size_in_bytes <= 0)
208138fd1498Szrj     return;
208238fd1498Szrj 
208338fd1498Szrj   poly_int64 bitsize, bitpos;
208438fd1498Szrj   tree offset;
208538fd1498Szrj   machine_mode mode;
208638fd1498Szrj   int unsignedp, reversep, volatilep = 0;
208738fd1498Szrj   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
208838fd1498Szrj 				    &unsignedp, &reversep, &volatilep);
208938fd1498Szrj 
209038fd1498Szrj   if (TREE_CODE (t) == COMPONENT_REF
209138fd1498Szrj       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
209238fd1498Szrj     {
209338fd1498Szrj       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
209438fd1498Szrj       instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr),
209538fd1498Szrj 				       TREE_OPERAND (t, 0), repr,
209638fd1498Szrj 				       TREE_OPERAND (t, 2)),
209738fd1498Szrj 			 location, is_store);
209838fd1498Szrj       return;
209938fd1498Szrj     }
210038fd1498Szrj 
210138fd1498Szrj   if (!multiple_p (bitpos, BITS_PER_UNIT)
210238fd1498Szrj       || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
210338fd1498Szrj     return;
210438fd1498Szrj 
210538fd1498Szrj   if (VAR_P (inner) && DECL_HARD_REGISTER (inner))
210638fd1498Szrj     return;
210738fd1498Szrj 
210838fd1498Szrj   poly_int64 decl_size;
210938fd1498Szrj   if (VAR_P (inner)
211038fd1498Szrj       && offset == NULL_TREE
211138fd1498Szrj       && DECL_SIZE (inner)
211238fd1498Szrj       && poly_int_tree_p (DECL_SIZE (inner), &decl_size)
211338fd1498Szrj       && known_subrange_p (bitpos, bitsize, 0, decl_size))
211438fd1498Szrj     {
211538fd1498Szrj       if (DECL_THREAD_LOCAL_P (inner))
211638fd1498Szrj 	return;
211738fd1498Szrj       if (!ASAN_GLOBALS && is_global_var (inner))
211838fd1498Szrj         return;
211938fd1498Szrj       if (!TREE_STATIC (inner))
212038fd1498Szrj 	{
212138fd1498Szrj 	  /* Automatic vars in the current function will be always
212238fd1498Szrj 	     accessible.  */
212338fd1498Szrj 	  if (decl_function_context (inner) == current_function_decl
212438fd1498Szrj 	      && (!asan_sanitize_use_after_scope ()
212538fd1498Szrj 		  || !TREE_ADDRESSABLE (inner)))
212638fd1498Szrj 	    return;
212738fd1498Szrj 	}
212838fd1498Szrj       /* Always instrument external vars, they might be dynamically
212938fd1498Szrj 	 initialized.  */
213038fd1498Szrj       else if (!DECL_EXTERNAL (inner))
213138fd1498Szrj 	{
213238fd1498Szrj 	  /* For static vars if they are known not to be dynamically
213338fd1498Szrj 	     initialized, they will be always accessible.  */
213438fd1498Szrj 	  varpool_node *vnode = varpool_node::get (inner);
213538fd1498Szrj 	  if (vnode && !vnode->dynamically_initialized)
213638fd1498Szrj 	    return;
213738fd1498Szrj 	}
213838fd1498Szrj     }
213938fd1498Szrj 
214038fd1498Szrj   base = build_fold_addr_expr (t);
214138fd1498Szrj   if (!has_mem_ref_been_instrumented (base, size_in_bytes))
214238fd1498Szrj     {
214338fd1498Szrj       unsigned int align = get_object_alignment (t);
214438fd1498Szrj       build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter,
214538fd1498Szrj 			/*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true,
214638fd1498Szrj 			is_store, /*is_scalar_access*/true, align);
214738fd1498Szrj       update_mem_ref_hash_table (base, size_in_bytes);
214838fd1498Szrj       update_mem_ref_hash_table (t, size_in_bytes);
214938fd1498Szrj     }
215038fd1498Szrj 
215138fd1498Szrj }
215238fd1498Szrj 
215338fd1498Szrj /*  Insert a memory reference into the hash table if access length
215438fd1498Szrj     can be determined in compile time.  */
215538fd1498Szrj 
215638fd1498Szrj static void
maybe_update_mem_ref_hash_table(tree base,tree len)215738fd1498Szrj maybe_update_mem_ref_hash_table (tree base, tree len)
215838fd1498Szrj {
215938fd1498Szrj   if (!POINTER_TYPE_P (TREE_TYPE (base))
216038fd1498Szrj       || !INTEGRAL_TYPE_P (TREE_TYPE (len)))
216138fd1498Szrj     return;
216238fd1498Szrj 
216338fd1498Szrj   HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
216438fd1498Szrj 
216538fd1498Szrj   if (size_in_bytes != -1)
216638fd1498Szrj     update_mem_ref_hash_table (base, size_in_bytes);
216738fd1498Szrj }
216838fd1498Szrj 
216938fd1498Szrj /* Instrument an access to a contiguous memory region that starts at
217038fd1498Szrj    the address pointed to by BASE, over a length of LEN (expressed in
217138fd1498Szrj    the sizeof (*BASE) bytes).  ITER points to the instruction before
217238fd1498Szrj    which the instrumentation instructions must be inserted.  LOCATION
217338fd1498Szrj    is the source location that the instrumentation instructions must
217438fd1498Szrj    have.  If IS_STORE is true, then the memory access is a store;
217538fd1498Szrj    otherwise, it's a load.  */
217638fd1498Szrj 
217738fd1498Szrj static void
instrument_mem_region_access(tree base,tree len,gimple_stmt_iterator * iter,location_t location,bool is_store)217838fd1498Szrj instrument_mem_region_access (tree base, tree len,
217938fd1498Szrj 			      gimple_stmt_iterator *iter,
218038fd1498Szrj 			      location_t location, bool is_store)
218138fd1498Szrj {
218238fd1498Szrj   if (!POINTER_TYPE_P (TREE_TYPE (base))
218338fd1498Szrj       || !INTEGRAL_TYPE_P (TREE_TYPE (len))
218438fd1498Szrj       || integer_zerop (len))
218538fd1498Szrj     return;
218638fd1498Szrj 
218738fd1498Szrj   HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
218838fd1498Szrj 
218938fd1498Szrj   if ((size_in_bytes == -1)
219038fd1498Szrj       || !has_mem_ref_been_instrumented (base, size_in_bytes))
219138fd1498Szrj     {
219238fd1498Szrj       build_check_stmt (location, base, len, size_in_bytes, iter,
219338fd1498Szrj 			/*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true,
219438fd1498Szrj 			is_store, /*is_scalar_access*/false, /*align*/0);
219538fd1498Szrj     }
219638fd1498Szrj 
219738fd1498Szrj   maybe_update_mem_ref_hash_table (base, len);
219838fd1498Szrj   *iter = gsi_for_stmt (gsi_stmt (*iter));
219938fd1498Szrj }
220038fd1498Szrj 
220138fd1498Szrj /* Instrument the call to a built-in memory access function that is
220238fd1498Szrj    pointed to by the iterator ITER.
220338fd1498Szrj 
220438fd1498Szrj    Upon completion, return TRUE iff *ITER has been advanced to the
220538fd1498Szrj    statement following the one it was originally pointing to.  */
220638fd1498Szrj 
220738fd1498Szrj static bool
instrument_builtin_call(gimple_stmt_iterator * iter)220838fd1498Szrj instrument_builtin_call (gimple_stmt_iterator *iter)
220938fd1498Szrj {
221038fd1498Szrj   if (!ASAN_MEMINTRIN)
221138fd1498Szrj     return false;
221238fd1498Szrj 
221338fd1498Szrj   bool iter_advanced_p = false;
221438fd1498Szrj   gcall *call = as_a <gcall *> (gsi_stmt (*iter));
221538fd1498Szrj 
221638fd1498Szrj   gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
221738fd1498Szrj 
221838fd1498Szrj   location_t loc = gimple_location (call);
221938fd1498Szrj 
222038fd1498Szrj   asan_mem_ref src0, src1, dest;
222138fd1498Szrj   asan_mem_ref_init (&src0, NULL, 1);
222238fd1498Szrj   asan_mem_ref_init (&src1, NULL, 1);
222338fd1498Szrj   asan_mem_ref_init (&dest, NULL, 1);
222438fd1498Szrj 
222538fd1498Szrj   tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
222638fd1498Szrj   bool src0_is_store = false, src1_is_store = false, dest_is_store = false,
222738fd1498Szrj     dest_is_deref = false, intercepted_p = true;
222838fd1498Szrj 
222938fd1498Szrj   if (get_mem_refs_of_builtin_call (call,
223038fd1498Szrj 				    &src0, &src0_len, &src0_is_store,
223138fd1498Szrj 				    &src1, &src1_len, &src1_is_store,
223238fd1498Szrj 				    &dest, &dest_len, &dest_is_store,
223338fd1498Szrj 				    &dest_is_deref, &intercepted_p, iter))
223438fd1498Szrj     {
223538fd1498Szrj       if (dest_is_deref)
223638fd1498Szrj 	{
223738fd1498Szrj 	  instrument_derefs (iter, dest.start, loc, dest_is_store);
223838fd1498Szrj 	  gsi_next (iter);
223938fd1498Szrj 	  iter_advanced_p = true;
224038fd1498Szrj 	}
224138fd1498Szrj       else if (!intercepted_p
224238fd1498Szrj 	       && (src0_len || src1_len || dest_len))
224338fd1498Szrj 	{
224438fd1498Szrj 	  if (src0.start != NULL_TREE)
224538fd1498Szrj 	    instrument_mem_region_access (src0.start, src0_len,
224638fd1498Szrj 					  iter, loc, /*is_store=*/false);
224738fd1498Szrj 	  if (src1.start != NULL_TREE)
224838fd1498Szrj 	    instrument_mem_region_access (src1.start, src1_len,
224938fd1498Szrj 					  iter, loc, /*is_store=*/false);
225038fd1498Szrj 	  if (dest.start != NULL_TREE)
225138fd1498Szrj 	    instrument_mem_region_access (dest.start, dest_len,
225238fd1498Szrj 					  iter, loc, /*is_store=*/true);
225338fd1498Szrj 
225438fd1498Szrj 	  *iter = gsi_for_stmt (call);
225538fd1498Szrj 	  gsi_next (iter);
225638fd1498Szrj 	  iter_advanced_p = true;
225738fd1498Szrj 	}
225838fd1498Szrj       else
225938fd1498Szrj 	{
226038fd1498Szrj 	  if (src0.start != NULL_TREE)
226138fd1498Szrj 	    maybe_update_mem_ref_hash_table (src0.start, src0_len);
226238fd1498Szrj 	  if (src1.start != NULL_TREE)
226338fd1498Szrj 	    maybe_update_mem_ref_hash_table (src1.start, src1_len);
226438fd1498Szrj 	  if (dest.start != NULL_TREE)
226538fd1498Szrj 	    maybe_update_mem_ref_hash_table (dest.start, dest_len);
226638fd1498Szrj 	}
226738fd1498Szrj     }
226838fd1498Szrj   return iter_advanced_p;
226938fd1498Szrj }
227038fd1498Szrj 
227138fd1498Szrj /*  Instrument the assignment statement ITER if it is subject to
227238fd1498Szrj     instrumentation.  Return TRUE iff instrumentation actually
227338fd1498Szrj     happened.  In that case, the iterator ITER is advanced to the next
227438fd1498Szrj     logical expression following the one initially pointed to by ITER,
227538fd1498Szrj     and the relevant memory reference that which access has been
227638fd1498Szrj     instrumented is added to the memory references hash table.  */
227738fd1498Szrj 
227838fd1498Szrj static bool
maybe_instrument_assignment(gimple_stmt_iterator * iter)227938fd1498Szrj maybe_instrument_assignment (gimple_stmt_iterator *iter)
228038fd1498Szrj {
228138fd1498Szrj   gimple *s = gsi_stmt (*iter);
228238fd1498Szrj 
228338fd1498Szrj   gcc_assert (gimple_assign_single_p (s));
228438fd1498Szrj 
228538fd1498Szrj   tree ref_expr = NULL_TREE;
228638fd1498Szrj   bool is_store, is_instrumented = false;
228738fd1498Szrj 
228838fd1498Szrj   if (gimple_store_p (s))
228938fd1498Szrj     {
229038fd1498Szrj       ref_expr = gimple_assign_lhs (s);
229138fd1498Szrj       is_store = true;
229238fd1498Szrj       instrument_derefs (iter, ref_expr,
229338fd1498Szrj 			 gimple_location (s),
229438fd1498Szrj 			 is_store);
229538fd1498Szrj       is_instrumented = true;
229638fd1498Szrj     }
229738fd1498Szrj 
229838fd1498Szrj   if (gimple_assign_load_p (s))
229938fd1498Szrj     {
230038fd1498Szrj       ref_expr = gimple_assign_rhs1 (s);
230138fd1498Szrj       is_store = false;
230238fd1498Szrj       instrument_derefs (iter, ref_expr,
230338fd1498Szrj 			 gimple_location (s),
230438fd1498Szrj 			 is_store);
230538fd1498Szrj       is_instrumented = true;
230638fd1498Szrj     }
230738fd1498Szrj 
230838fd1498Szrj   if (is_instrumented)
230938fd1498Szrj     gsi_next (iter);
231038fd1498Szrj 
231138fd1498Szrj   return is_instrumented;
231238fd1498Szrj }
231338fd1498Szrj 
231438fd1498Szrj /* Instrument the function call pointed to by the iterator ITER, if it
231538fd1498Szrj    is subject to instrumentation.  At the moment, the only function
231638fd1498Szrj    calls that are instrumented are some built-in functions that access
231738fd1498Szrj    memory.  Look at instrument_builtin_call to learn more.
231838fd1498Szrj 
231938fd1498Szrj    Upon completion return TRUE iff *ITER was advanced to the statement
232038fd1498Szrj    following the one it was originally pointing to.  */
232138fd1498Szrj 
232238fd1498Szrj static bool
maybe_instrument_call(gimple_stmt_iterator * iter)232338fd1498Szrj maybe_instrument_call (gimple_stmt_iterator *iter)
232438fd1498Szrj {
232538fd1498Szrj   gimple *stmt = gsi_stmt (*iter);
232638fd1498Szrj   bool is_builtin = gimple_call_builtin_p (stmt, BUILT_IN_NORMAL);
232738fd1498Szrj 
232838fd1498Szrj   if (is_builtin && instrument_builtin_call (iter))
232938fd1498Szrj     return true;
233038fd1498Szrj 
233138fd1498Szrj   if (gimple_call_noreturn_p (stmt))
233238fd1498Szrj     {
233338fd1498Szrj       if (is_builtin)
233438fd1498Szrj 	{
233538fd1498Szrj 	  tree callee = gimple_call_fndecl (stmt);
233638fd1498Szrj 	  switch (DECL_FUNCTION_CODE (callee))
233738fd1498Szrj 	    {
233838fd1498Szrj 	    case BUILT_IN_UNREACHABLE:
233938fd1498Szrj 	    case BUILT_IN_TRAP:
234038fd1498Szrj 	      /* Don't instrument these.  */
234138fd1498Szrj 	      return false;
234238fd1498Szrj 	    default:
234338fd1498Szrj 	      break;
234438fd1498Szrj 	    }
234538fd1498Szrj 	}
234638fd1498Szrj       tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
234738fd1498Szrj       gimple *g = gimple_build_call (decl, 0);
234838fd1498Szrj       gimple_set_location (g, gimple_location (stmt));
234938fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
235038fd1498Szrj     }
235138fd1498Szrj 
235238fd1498Szrj   bool instrumented = false;
235338fd1498Szrj   if (gimple_store_p (stmt))
235438fd1498Szrj     {
235538fd1498Szrj       tree ref_expr = gimple_call_lhs (stmt);
235638fd1498Szrj       instrument_derefs (iter, ref_expr,
235738fd1498Szrj 			 gimple_location (stmt),
235838fd1498Szrj 			 /*is_store=*/true);
235938fd1498Szrj 
236038fd1498Szrj       instrumented = true;
236138fd1498Szrj     }
236238fd1498Szrj 
236338fd1498Szrj   /* Walk through gimple_call arguments and check them id needed.  */
236438fd1498Szrj   unsigned args_num = gimple_call_num_args (stmt);
236538fd1498Szrj   for (unsigned i = 0; i < args_num; ++i)
236638fd1498Szrj     {
236738fd1498Szrj       tree arg = gimple_call_arg (stmt, i);
236838fd1498Szrj       /* If ARG is not a non-aggregate register variable, compiler in general
236938fd1498Szrj 	 creates temporary for it and pass it as argument to gimple call.
237038fd1498Szrj 	 But in some cases, e.g. when we pass by value a small structure that
237138fd1498Szrj 	 fits to register, compiler can avoid extra overhead by pulling out
237238fd1498Szrj 	 these temporaries.  In this case, we should check the argument.  */
237338fd1498Szrj       if (!is_gimple_reg (arg) && !is_gimple_min_invariant (arg))
237438fd1498Szrj 	{
237538fd1498Szrj 	  instrument_derefs (iter, arg,
237638fd1498Szrj 			     gimple_location (stmt),
237738fd1498Szrj 			     /*is_store=*/false);
237838fd1498Szrj 	  instrumented = true;
237938fd1498Szrj 	}
238038fd1498Szrj     }
238138fd1498Szrj   if (instrumented)
238238fd1498Szrj     gsi_next (iter);
238338fd1498Szrj   return instrumented;
238438fd1498Szrj }
238538fd1498Szrj 
238638fd1498Szrj /* Walk each instruction of all basic block and instrument those that
238738fd1498Szrj    represent memory references: loads, stores, or function calls.
238838fd1498Szrj    In a given basic block, this function avoids instrumenting memory
238938fd1498Szrj    references that have already been instrumented.  */
239038fd1498Szrj 
239138fd1498Szrj static void
transform_statements(void)239238fd1498Szrj transform_statements (void)
239338fd1498Szrj {
239438fd1498Szrj   basic_block bb, last_bb = NULL;
239538fd1498Szrj   gimple_stmt_iterator i;
239638fd1498Szrj   int saved_last_basic_block = last_basic_block_for_fn (cfun);
239738fd1498Szrj 
239838fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
239938fd1498Szrj     {
240038fd1498Szrj       basic_block prev_bb = bb;
240138fd1498Szrj 
240238fd1498Szrj       if (bb->index >= saved_last_basic_block) continue;
240338fd1498Szrj 
240438fd1498Szrj       /* Flush the mem ref hash table, if current bb doesn't have
240538fd1498Szrj 	 exactly one predecessor, or if that predecessor (skipping
240638fd1498Szrj 	 over asan created basic blocks) isn't the last processed
240738fd1498Szrj 	 basic block.  Thus we effectively flush on extended basic
240838fd1498Szrj 	 block boundaries.  */
240938fd1498Szrj       while (single_pred_p (prev_bb))
241038fd1498Szrj 	{
241138fd1498Szrj 	  prev_bb = single_pred (prev_bb);
241238fd1498Szrj 	  if (prev_bb->index < saved_last_basic_block)
241338fd1498Szrj 	    break;
241438fd1498Szrj 	}
241538fd1498Szrj       if (prev_bb != last_bb)
241638fd1498Szrj 	empty_mem_ref_hash_table ();
241738fd1498Szrj       last_bb = bb;
241838fd1498Szrj 
241938fd1498Szrj       for (i = gsi_start_bb (bb); !gsi_end_p (i);)
242038fd1498Szrj 	{
242138fd1498Szrj 	  gimple *s = gsi_stmt (i);
242238fd1498Szrj 
242338fd1498Szrj 	  if (has_stmt_been_instrumented_p (s))
242438fd1498Szrj 	    gsi_next (&i);
242538fd1498Szrj 	  else if (gimple_assign_single_p (s)
242638fd1498Szrj 		   && !gimple_clobber_p (s)
242738fd1498Szrj 		   && maybe_instrument_assignment (&i))
242838fd1498Szrj 	    /*  Nothing to do as maybe_instrument_assignment advanced
242938fd1498Szrj 		the iterator I.  */;
243038fd1498Szrj 	  else if (is_gimple_call (s) && maybe_instrument_call (&i))
243138fd1498Szrj 	    /*  Nothing to do as maybe_instrument_call
243238fd1498Szrj 		advanced the iterator I.  */;
243338fd1498Szrj 	  else
243438fd1498Szrj 	    {
243538fd1498Szrj 	      /* No instrumentation happened.
243638fd1498Szrj 
243738fd1498Szrj 		 If the current instruction is a function call that
243838fd1498Szrj 		 might free something, let's forget about the memory
243938fd1498Szrj 		 references that got instrumented.  Otherwise we might
244038fd1498Szrj 		 miss some instrumentation opportunities.  Do the same
244138fd1498Szrj 		 for a ASAN_MARK poisoning internal function.  */
244238fd1498Szrj 	      if (is_gimple_call (s)
244338fd1498Szrj 		  && (!nonfreeing_call_p (s)
244438fd1498Szrj 		      || asan_mark_p (s, ASAN_MARK_POISON)))
244538fd1498Szrj 		empty_mem_ref_hash_table ();
244638fd1498Szrj 
244738fd1498Szrj 	      gsi_next (&i);
244838fd1498Szrj 	    }
244938fd1498Szrj 	}
245038fd1498Szrj     }
245138fd1498Szrj   free_mem_ref_resources ();
245238fd1498Szrj }
245338fd1498Szrj 
245438fd1498Szrj /* Build
245538fd1498Szrj    __asan_before_dynamic_init (module_name)
245638fd1498Szrj    or
245738fd1498Szrj    __asan_after_dynamic_init ()
245838fd1498Szrj    call.  */
245938fd1498Szrj 
246038fd1498Szrj tree
asan_dynamic_init_call(bool after_p)246138fd1498Szrj asan_dynamic_init_call (bool after_p)
246238fd1498Szrj {
246338fd1498Szrj   if (shadow_ptr_types[0] == NULL_TREE)
246438fd1498Szrj     asan_init_shadow_ptr_types ();
246538fd1498Szrj 
246638fd1498Szrj   tree fn = builtin_decl_implicit (after_p
246738fd1498Szrj 				   ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT
246838fd1498Szrj 				   : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT);
246938fd1498Szrj   tree module_name_cst = NULL_TREE;
247038fd1498Szrj   if (!after_p)
247138fd1498Szrj     {
247238fd1498Szrj       pretty_printer module_name_pp;
247338fd1498Szrj       pp_string (&module_name_pp, main_input_filename);
247438fd1498Szrj 
247538fd1498Szrj       module_name_cst = asan_pp_string (&module_name_pp);
247638fd1498Szrj       module_name_cst = fold_convert (const_ptr_type_node,
247738fd1498Szrj 				      module_name_cst);
247838fd1498Szrj     }
247938fd1498Szrj 
248038fd1498Szrj   return build_call_expr (fn, after_p ? 0 : 1, module_name_cst);
248138fd1498Szrj }
248238fd1498Szrj 
248338fd1498Szrj /* Build
248438fd1498Szrj    struct __asan_global
248538fd1498Szrj    {
248638fd1498Szrj      const void *__beg;
248738fd1498Szrj      uptr __size;
248838fd1498Szrj      uptr __size_with_redzone;
248938fd1498Szrj      const void *__name;
249038fd1498Szrj      const void *__module_name;
249138fd1498Szrj      uptr __has_dynamic_init;
249238fd1498Szrj      __asan_global_source_location *__location;
249338fd1498Szrj      char *__odr_indicator;
249438fd1498Szrj    } type.  */
249538fd1498Szrj 
249638fd1498Szrj static tree
asan_global_struct(void)249738fd1498Szrj asan_global_struct (void)
249838fd1498Szrj {
249938fd1498Szrj   static const char *field_names[]
250038fd1498Szrj     = { "__beg", "__size", "__size_with_redzone",
250138fd1498Szrj 	"__name", "__module_name", "__has_dynamic_init", "__location",
250238fd1498Szrj 	"__odr_indicator" };
250338fd1498Szrj   tree fields[ARRAY_SIZE (field_names)], ret;
250438fd1498Szrj   unsigned i;
250538fd1498Szrj 
250638fd1498Szrj   ret = make_node (RECORD_TYPE);
250738fd1498Szrj   for (i = 0; i < ARRAY_SIZE (field_names); i++)
250838fd1498Szrj     {
250938fd1498Szrj       fields[i]
251038fd1498Szrj 	= build_decl (UNKNOWN_LOCATION, FIELD_DECL,
251138fd1498Szrj 		      get_identifier (field_names[i]),
251238fd1498Szrj 		      (i == 0 || i == 3) ? const_ptr_type_node
251338fd1498Szrj 		      : pointer_sized_int_node);
251438fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
251538fd1498Szrj       if (i)
251638fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
251738fd1498Szrj     }
251838fd1498Szrj   tree type_decl = build_decl (input_location, TYPE_DECL,
251938fd1498Szrj 			       get_identifier ("__asan_global"), ret);
252038fd1498Szrj   DECL_IGNORED_P (type_decl) = 1;
252138fd1498Szrj   DECL_ARTIFICIAL (type_decl) = 1;
252238fd1498Szrj   TYPE_FIELDS (ret) = fields[0];
252338fd1498Szrj   TYPE_NAME (ret) = type_decl;
252438fd1498Szrj   TYPE_STUB_DECL (ret) = type_decl;
252538fd1498Szrj   layout_type (ret);
252638fd1498Szrj   return ret;
252738fd1498Szrj }
252838fd1498Szrj 
252938fd1498Szrj /* Create and return odr indicator symbol for DECL.
253038fd1498Szrj    TYPE is __asan_global struct type as returned by asan_global_struct.  */
253138fd1498Szrj 
253238fd1498Szrj static tree
create_odr_indicator(tree decl,tree type)253338fd1498Szrj create_odr_indicator (tree decl, tree type)
253438fd1498Szrj {
253538fd1498Szrj   char *name;
253638fd1498Szrj   tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
253738fd1498Szrj   tree decl_name
253838fd1498Szrj     = (HAS_DECL_ASSEMBLER_NAME_P (decl) ? DECL_ASSEMBLER_NAME (decl)
253938fd1498Szrj 					: DECL_NAME (decl));
254038fd1498Szrj   /* DECL_NAME theoretically might be NULL.  Bail out with 0 in this case.  */
254138fd1498Szrj   if (decl_name == NULL_TREE)
254238fd1498Szrj     return build_int_cst (uptr, 0);
254338fd1498Szrj   const char *dname = IDENTIFIER_POINTER (decl_name);
254438fd1498Szrj   if (HAS_DECL_ASSEMBLER_NAME_P (decl))
254538fd1498Szrj     dname = targetm.strip_name_encoding (dname);
254638fd1498Szrj   size_t len = strlen (dname) + sizeof ("__odr_asan_");
254738fd1498Szrj   name = XALLOCAVEC (char, len);
254838fd1498Szrj   snprintf (name, len, "__odr_asan_%s", dname);
254938fd1498Szrj #ifndef NO_DOT_IN_LABEL
255038fd1498Szrj   name[sizeof ("__odr_asan") - 1] = '.';
255138fd1498Szrj #elif !defined(NO_DOLLAR_IN_LABEL)
255238fd1498Szrj   name[sizeof ("__odr_asan") - 1] = '$';
255338fd1498Szrj #endif
255438fd1498Szrj   tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name),
255538fd1498Szrj 			 char_type_node);
255638fd1498Szrj   TREE_ADDRESSABLE (var) = 1;
255738fd1498Szrj   TREE_READONLY (var) = 0;
255838fd1498Szrj   TREE_THIS_VOLATILE (var) = 1;
255938fd1498Szrj   DECL_GIMPLE_REG_P (var) = 0;
256038fd1498Szrj   DECL_ARTIFICIAL (var) = 1;
256138fd1498Szrj   DECL_IGNORED_P (var) = 1;
256238fd1498Szrj   TREE_STATIC (var) = 1;
256338fd1498Szrj   TREE_PUBLIC (var) = 1;
256438fd1498Szrj   DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
256538fd1498Szrj   DECL_VISIBILITY_SPECIFIED (var) = DECL_VISIBILITY_SPECIFIED (decl);
256638fd1498Szrj 
256738fd1498Szrj   TREE_USED (var) = 1;
256838fd1498Szrj   tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
256938fd1498Szrj 				    build_int_cst (unsigned_type_node, 0));
257038fd1498Szrj   TREE_CONSTANT (ctor) = 1;
257138fd1498Szrj   TREE_STATIC (ctor) = 1;
257238fd1498Szrj   DECL_INITIAL (var) = ctor;
257338fd1498Szrj   DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("asan odr indicator"),
257438fd1498Szrj 				     NULL, DECL_ATTRIBUTES (var));
257538fd1498Szrj   make_decl_rtl (var);
257638fd1498Szrj   varpool_node::finalize_decl (var);
257738fd1498Szrj   return fold_convert (uptr, build_fold_addr_expr (var));
257838fd1498Szrj }
257938fd1498Szrj 
258038fd1498Szrj /* Return true if DECL, a global var, might be overridden and needs
258138fd1498Szrj    an additional odr indicator symbol.  */
258238fd1498Szrj 
258338fd1498Szrj static bool
asan_needs_odr_indicator_p(tree decl)258438fd1498Szrj asan_needs_odr_indicator_p (tree decl)
258538fd1498Szrj {
258638fd1498Szrj   /* Don't emit ODR indicators for kernel because:
258738fd1498Szrj      a) Kernel is written in C thus doesn't need ODR indicators.
258838fd1498Szrj      b) Some kernel code may have assumptions about symbols containing specific
258938fd1498Szrj         patterns in their names.  Since ODR indicators contain original names
259038fd1498Szrj         of symbols they are emitted for, these assumptions would be broken for
259138fd1498Szrj         ODR indicator symbols.  */
259238fd1498Szrj   return (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS)
259338fd1498Szrj 	  && !DECL_ARTIFICIAL (decl)
259438fd1498Szrj 	  && !DECL_WEAK (decl)
259538fd1498Szrj 	  && TREE_PUBLIC (decl));
259638fd1498Szrj }
259738fd1498Szrj 
259838fd1498Szrj /* Append description of a single global DECL into vector V.
259938fd1498Szrj    TYPE is __asan_global struct type as returned by asan_global_struct.  */
260038fd1498Szrj 
260138fd1498Szrj static void
asan_add_global(tree decl,tree type,vec<constructor_elt,va_gc> * v)260238fd1498Szrj asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
260338fd1498Szrj {
260438fd1498Szrj   tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
260538fd1498Szrj   unsigned HOST_WIDE_INT size;
260638fd1498Szrj   tree str_cst, module_name_cst, refdecl = decl;
260738fd1498Szrj   vec<constructor_elt, va_gc> *vinner = NULL;
260838fd1498Szrj 
260938fd1498Szrj   pretty_printer asan_pp, module_name_pp;
261038fd1498Szrj 
261138fd1498Szrj   if (DECL_NAME (decl))
261238fd1498Szrj     pp_tree_identifier (&asan_pp, DECL_NAME (decl));
261338fd1498Szrj   else
261438fd1498Szrj     pp_string (&asan_pp, "<unknown>");
261538fd1498Szrj   str_cst = asan_pp_string (&asan_pp);
261638fd1498Szrj 
261738fd1498Szrj   pp_string (&module_name_pp, main_input_filename);
261838fd1498Szrj   module_name_cst = asan_pp_string (&module_name_pp);
261938fd1498Szrj 
262038fd1498Szrj   if (asan_needs_local_alias (decl))
262138fd1498Szrj     {
262238fd1498Szrj       char buf[20];
262338fd1498Szrj       ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", vec_safe_length (v) + 1);
262438fd1498Szrj       refdecl = build_decl (DECL_SOURCE_LOCATION (decl),
262538fd1498Szrj 			    VAR_DECL, get_identifier (buf), TREE_TYPE (decl));
262638fd1498Szrj       TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
262738fd1498Szrj       TREE_READONLY (refdecl) = TREE_READONLY (decl);
262838fd1498Szrj       TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
262938fd1498Szrj       DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl);
263038fd1498Szrj       DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
263138fd1498Szrj       DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
263238fd1498Szrj       TREE_STATIC (refdecl) = 1;
263338fd1498Szrj       TREE_PUBLIC (refdecl) = 0;
263438fd1498Szrj       TREE_USED (refdecl) = 1;
263538fd1498Szrj       assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
263638fd1498Szrj     }
263738fd1498Szrj 
263838fd1498Szrj   tree odr_indicator_ptr
263938fd1498Szrj     = (asan_needs_odr_indicator_p (decl) ? create_odr_indicator (decl, type)
264038fd1498Szrj 					 : build_int_cst (uptr, 0));
264138fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
264238fd1498Szrj 			  fold_convert (const_ptr_type_node,
264338fd1498Szrj 					build_fold_addr_expr (refdecl)));
264438fd1498Szrj   size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
264538fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
264638fd1498Szrj   size += asan_red_zone_size (size);
264738fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
264838fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
264938fd1498Szrj 			  fold_convert (const_ptr_type_node, str_cst));
265038fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
265138fd1498Szrj 			  fold_convert (const_ptr_type_node, module_name_cst));
265238fd1498Szrj   varpool_node *vnode = varpool_node::get (decl);
265338fd1498Szrj   int has_dynamic_init = 0;
265438fd1498Szrj   /* FIXME: Enable initialization order fiasco detection in LTO mode once
265538fd1498Szrj      proper fix for PR 79061 will be applied.  */
265638fd1498Szrj   if (!in_lto_p)
265738fd1498Szrj     has_dynamic_init = vnode ? vnode->dynamically_initialized : 0;
265838fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
265938fd1498Szrj 			  build_int_cst (uptr, has_dynamic_init));
266038fd1498Szrj   tree locptr = NULL_TREE;
266138fd1498Szrj   location_t loc = DECL_SOURCE_LOCATION (decl);
266238fd1498Szrj   expanded_location xloc = expand_location (loc);
266338fd1498Szrj   if (xloc.file != NULL)
266438fd1498Szrj     {
266538fd1498Szrj       static int lasanloccnt = 0;
266638fd1498Szrj       char buf[25];
266738fd1498Szrj       ASM_GENERATE_INTERNAL_LABEL (buf, "LASANLOC", ++lasanloccnt);
266838fd1498Szrj       tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
266938fd1498Szrj 			     ubsan_get_source_location_type ());
267038fd1498Szrj       TREE_STATIC (var) = 1;
267138fd1498Szrj       TREE_PUBLIC (var) = 0;
267238fd1498Szrj       DECL_ARTIFICIAL (var) = 1;
267338fd1498Szrj       DECL_IGNORED_P (var) = 1;
267438fd1498Szrj       pretty_printer filename_pp;
267538fd1498Szrj       pp_string (&filename_pp, xloc.file);
267638fd1498Szrj       tree str = asan_pp_string (&filename_pp);
267738fd1498Szrj       tree ctor = build_constructor_va (TREE_TYPE (var), 3,
267838fd1498Szrj 					NULL_TREE, str, NULL_TREE,
267938fd1498Szrj 					build_int_cst (unsigned_type_node,
268038fd1498Szrj 						       xloc.line), NULL_TREE,
268138fd1498Szrj 					build_int_cst (unsigned_type_node,
268238fd1498Szrj 						       xloc.column));
268338fd1498Szrj       TREE_CONSTANT (ctor) = 1;
268438fd1498Szrj       TREE_STATIC (ctor) = 1;
268538fd1498Szrj       DECL_INITIAL (var) = ctor;
268638fd1498Szrj       varpool_node::finalize_decl (var);
268738fd1498Szrj       locptr = fold_convert (uptr, build_fold_addr_expr (var));
268838fd1498Szrj     }
268938fd1498Szrj   else
269038fd1498Szrj     locptr = build_int_cst (uptr, 0);
269138fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
269238fd1498Szrj   CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, odr_indicator_ptr);
269338fd1498Szrj   init = build_constructor (type, vinner);
269438fd1498Szrj   CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
269538fd1498Szrj }
269638fd1498Szrj 
269738fd1498Szrj /* Initialize sanitizer.def builtins if the FE hasn't initialized them.  */
269838fd1498Szrj void
initialize_sanitizer_builtins(void)269938fd1498Szrj initialize_sanitizer_builtins (void)
270038fd1498Szrj {
270138fd1498Szrj   tree decl;
270238fd1498Szrj 
270338fd1498Szrj   if (builtin_decl_implicit_p (BUILT_IN_ASAN_INIT))
270438fd1498Szrj     return;
270538fd1498Szrj 
270638fd1498Szrj   tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
270738fd1498Szrj   tree BT_FN_VOID_PTR
270838fd1498Szrj     = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
270938fd1498Szrj   tree BT_FN_VOID_CONST_PTR
271038fd1498Szrj     = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
271138fd1498Szrj   tree BT_FN_VOID_PTR_PTR
271238fd1498Szrj     = build_function_type_list (void_type_node, ptr_type_node,
271338fd1498Szrj 				ptr_type_node, NULL_TREE);
271438fd1498Szrj   tree BT_FN_VOID_PTR_PTR_PTR
271538fd1498Szrj     = build_function_type_list (void_type_node, ptr_type_node,
271638fd1498Szrj 				ptr_type_node, ptr_type_node, NULL_TREE);
271738fd1498Szrj   tree BT_FN_VOID_PTR_PTRMODE
271838fd1498Szrj     = build_function_type_list (void_type_node, ptr_type_node,
271938fd1498Szrj 				pointer_sized_int_node, NULL_TREE);
272038fd1498Szrj   tree BT_FN_VOID_INT
272138fd1498Szrj     = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
272238fd1498Szrj   tree BT_FN_SIZE_CONST_PTR_INT
272338fd1498Szrj     = build_function_type_list (size_type_node, const_ptr_type_node,
272438fd1498Szrj 				integer_type_node, NULL_TREE);
272538fd1498Szrj 
272638fd1498Szrj   tree BT_FN_VOID_UINT8_UINT8
272738fd1498Szrj     = build_function_type_list (void_type_node, unsigned_char_type_node,
272838fd1498Szrj 				unsigned_char_type_node, NULL_TREE);
272938fd1498Szrj   tree BT_FN_VOID_UINT16_UINT16
273038fd1498Szrj     = build_function_type_list (void_type_node, uint16_type_node,
273138fd1498Szrj 				uint16_type_node, NULL_TREE);
273238fd1498Szrj   tree BT_FN_VOID_UINT32_UINT32
273338fd1498Szrj     = build_function_type_list (void_type_node, uint32_type_node,
273438fd1498Szrj 				uint32_type_node, NULL_TREE);
273538fd1498Szrj   tree BT_FN_VOID_UINT64_UINT64
273638fd1498Szrj     = build_function_type_list (void_type_node, uint64_type_node,
273738fd1498Szrj 				uint64_type_node, NULL_TREE);
273838fd1498Szrj   tree BT_FN_VOID_FLOAT_FLOAT
273938fd1498Szrj     = build_function_type_list (void_type_node, float_type_node,
274038fd1498Szrj 				float_type_node, NULL_TREE);
274138fd1498Szrj   tree BT_FN_VOID_DOUBLE_DOUBLE
274238fd1498Szrj     = build_function_type_list (void_type_node, double_type_node,
274338fd1498Szrj 				double_type_node, NULL_TREE);
274438fd1498Szrj   tree BT_FN_VOID_UINT64_PTR
274538fd1498Szrj     = build_function_type_list (void_type_node, uint64_type_node,
274638fd1498Szrj 				ptr_type_node, NULL_TREE);
274738fd1498Szrj 
274838fd1498Szrj   tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5];
274938fd1498Szrj   tree BT_FN_IX_CONST_VPTR_INT[5];
275038fd1498Szrj   tree BT_FN_IX_VPTR_IX_INT[5];
275138fd1498Szrj   tree BT_FN_VOID_VPTR_IX_INT[5];
275238fd1498Szrj   tree vptr
275338fd1498Szrj     = build_pointer_type (build_qualified_type (void_type_node,
275438fd1498Szrj 						TYPE_QUAL_VOLATILE));
275538fd1498Szrj   tree cvptr
275638fd1498Szrj     = build_pointer_type (build_qualified_type (void_type_node,
275738fd1498Szrj 						TYPE_QUAL_VOLATILE
275838fd1498Szrj 						|TYPE_QUAL_CONST));
275938fd1498Szrj   tree boolt
276038fd1498Szrj     = lang_hooks.types.type_for_size (BOOL_TYPE_SIZE, 1);
276138fd1498Szrj   int i;
276238fd1498Szrj   for (i = 0; i < 5; i++)
276338fd1498Szrj     {
276438fd1498Szrj       tree ix = build_nonstandard_integer_type (BITS_PER_UNIT * (1 << i), 1);
276538fd1498Szrj       BT_FN_BOOL_VPTR_PTR_IX_INT_INT[i]
276638fd1498Szrj 	= build_function_type_list (boolt, vptr, ptr_type_node, ix,
276738fd1498Szrj 				    integer_type_node, integer_type_node,
276838fd1498Szrj 				    NULL_TREE);
276938fd1498Szrj       BT_FN_IX_CONST_VPTR_INT[i]
277038fd1498Szrj 	= build_function_type_list (ix, cvptr, integer_type_node, NULL_TREE);
277138fd1498Szrj       BT_FN_IX_VPTR_IX_INT[i]
277238fd1498Szrj 	= build_function_type_list (ix, vptr, ix, integer_type_node,
277338fd1498Szrj 				    NULL_TREE);
277438fd1498Szrj       BT_FN_VOID_VPTR_IX_INT[i]
277538fd1498Szrj 	= build_function_type_list (void_type_node, vptr, ix,
277638fd1498Szrj 				    integer_type_node, NULL_TREE);
277738fd1498Szrj     }
277838fd1498Szrj #define BT_FN_BOOL_VPTR_PTR_I1_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[0]
277938fd1498Szrj #define BT_FN_I1_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[0]
278038fd1498Szrj #define BT_FN_I1_VPTR_I1_INT BT_FN_IX_VPTR_IX_INT[0]
278138fd1498Szrj #define BT_FN_VOID_VPTR_I1_INT BT_FN_VOID_VPTR_IX_INT[0]
278238fd1498Szrj #define BT_FN_BOOL_VPTR_PTR_I2_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[1]
278338fd1498Szrj #define BT_FN_I2_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[1]
278438fd1498Szrj #define BT_FN_I2_VPTR_I2_INT BT_FN_IX_VPTR_IX_INT[1]
278538fd1498Szrj #define BT_FN_VOID_VPTR_I2_INT BT_FN_VOID_VPTR_IX_INT[1]
278638fd1498Szrj #define BT_FN_BOOL_VPTR_PTR_I4_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[2]
278738fd1498Szrj #define BT_FN_I4_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[2]
278838fd1498Szrj #define BT_FN_I4_VPTR_I4_INT BT_FN_IX_VPTR_IX_INT[2]
278938fd1498Szrj #define BT_FN_VOID_VPTR_I4_INT BT_FN_VOID_VPTR_IX_INT[2]
279038fd1498Szrj #define BT_FN_BOOL_VPTR_PTR_I8_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[3]
279138fd1498Szrj #define BT_FN_I8_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[3]
279238fd1498Szrj #define BT_FN_I8_VPTR_I8_INT BT_FN_IX_VPTR_IX_INT[3]
279338fd1498Szrj #define BT_FN_VOID_VPTR_I8_INT BT_FN_VOID_VPTR_IX_INT[3]
279438fd1498Szrj #define BT_FN_BOOL_VPTR_PTR_I16_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[4]
279538fd1498Szrj #define BT_FN_I16_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[4]
279638fd1498Szrj #define BT_FN_I16_VPTR_I16_INT BT_FN_IX_VPTR_IX_INT[4]
279738fd1498Szrj #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4]
279838fd1498Szrj #undef ATTR_NOTHROW_LEAF_LIST
279938fd1498Szrj #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
280038fd1498Szrj #undef ATTR_TMPURE_NOTHROW_LEAF_LIST
280138fd1498Szrj #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST
280238fd1498Szrj #undef ATTR_NORETURN_NOTHROW_LEAF_LIST
280338fd1498Szrj #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST
280438fd1498Szrj #undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
280538fd1498Szrj #define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \
280638fd1498Szrj   ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST
280738fd1498Szrj #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST
280838fd1498Szrj #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \
280938fd1498Szrj   ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST
281038fd1498Szrj #undef ATTR_COLD_NOTHROW_LEAF_LIST
281138fd1498Szrj #define ATTR_COLD_NOTHROW_LEAF_LIST \
281238fd1498Szrj   /* ECF_COLD missing */ ATTR_NOTHROW_LEAF_LIST
281338fd1498Szrj #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST
281438fd1498Szrj #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \
281538fd1498Szrj   /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST
281638fd1498Szrj #undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST
281738fd1498Szrj #define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \
281838fd1498Szrj   /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
281938fd1498Szrj #undef ATTR_PURE_NOTHROW_LEAF_LIST
282038fd1498Szrj #define ATTR_PURE_NOTHROW_LEAF_LIST ECF_PURE | ATTR_NOTHROW_LEAF_LIST
282138fd1498Szrj #undef DEF_BUILTIN_STUB
282238fd1498Szrj #define DEF_BUILTIN_STUB(ENUM, NAME)
282338fd1498Szrj #undef DEF_SANITIZER_BUILTIN_1
282438fd1498Szrj #define DEF_SANITIZER_BUILTIN_1(ENUM, NAME, TYPE, ATTRS)		\
282538fd1498Szrj   do {									\
282638fd1498Szrj     decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM,		\
282738fd1498Szrj 				 BUILT_IN_NORMAL, NAME, NULL_TREE);	\
282838fd1498Szrj     set_call_expr_flags (decl, ATTRS);					\
282938fd1498Szrj     set_builtin_decl (ENUM, decl, true);				\
283038fd1498Szrj   } while (0)
283138fd1498Szrj #undef DEF_SANITIZER_BUILTIN
283238fd1498Szrj #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS)	\
283338fd1498Szrj   DEF_SANITIZER_BUILTIN_1 (ENUM, NAME, TYPE, ATTRS);
283438fd1498Szrj 
283538fd1498Szrj #include "sanitizer.def"
283638fd1498Szrj 
283738fd1498Szrj   /* -fsanitize=object-size uses __builtin_object_size, but that might
283838fd1498Szrj      not be available for e.g. Fortran at this point.  We use
283938fd1498Szrj      DEF_SANITIZER_BUILTIN here only as a convenience macro.  */
284038fd1498Szrj   if ((flag_sanitize & SANITIZE_OBJECT_SIZE)
284138fd1498Szrj       && !builtin_decl_implicit_p (BUILT_IN_OBJECT_SIZE))
284238fd1498Szrj     DEF_SANITIZER_BUILTIN_1 (BUILT_IN_OBJECT_SIZE, "object_size",
284338fd1498Szrj 			     BT_FN_SIZE_CONST_PTR_INT,
284438fd1498Szrj 			     ATTR_PURE_NOTHROW_LEAF_LIST);
284538fd1498Szrj 
284638fd1498Szrj #undef DEF_SANITIZER_BUILTIN_1
284738fd1498Szrj #undef DEF_SANITIZER_BUILTIN
284838fd1498Szrj #undef DEF_BUILTIN_STUB
284938fd1498Szrj }
285038fd1498Szrj 
285138fd1498Szrj /* Called via htab_traverse.  Count number of emitted
285238fd1498Szrj    STRING_CSTs in the constant hash table.  */
285338fd1498Szrj 
285438fd1498Szrj int
count_string_csts(constant_descriptor_tree ** slot,unsigned HOST_WIDE_INT * data)285538fd1498Szrj count_string_csts (constant_descriptor_tree **slot,
285638fd1498Szrj 		   unsigned HOST_WIDE_INT *data)
285738fd1498Szrj {
285838fd1498Szrj   struct constant_descriptor_tree *desc = *slot;
285938fd1498Szrj   if (TREE_CODE (desc->value) == STRING_CST
286038fd1498Szrj       && TREE_ASM_WRITTEN (desc->value)
286138fd1498Szrj       && asan_protect_global (desc->value))
286238fd1498Szrj     ++*data;
286338fd1498Szrj   return 1;
286438fd1498Szrj }
286538fd1498Szrj 
286638fd1498Szrj /* Helper structure to pass two parameters to
286738fd1498Szrj    add_string_csts.  */
286838fd1498Szrj 
286938fd1498Szrj struct asan_add_string_csts_data
287038fd1498Szrj {
287138fd1498Szrj   tree type;
287238fd1498Szrj   vec<constructor_elt, va_gc> *v;
287338fd1498Szrj };
287438fd1498Szrj 
287538fd1498Szrj /* Called via hash_table::traverse.  Call asan_add_global
287638fd1498Szrj    on emitted STRING_CSTs from the constant hash table.  */
287738fd1498Szrj 
287838fd1498Szrj int
add_string_csts(constant_descriptor_tree ** slot,asan_add_string_csts_data * aascd)287938fd1498Szrj add_string_csts (constant_descriptor_tree **slot,
288038fd1498Szrj 		 asan_add_string_csts_data *aascd)
288138fd1498Szrj {
288238fd1498Szrj   struct constant_descriptor_tree *desc = *slot;
288338fd1498Szrj   if (TREE_CODE (desc->value) == STRING_CST
288438fd1498Szrj       && TREE_ASM_WRITTEN (desc->value)
288538fd1498Szrj       && asan_protect_global (desc->value))
288638fd1498Szrj     {
288738fd1498Szrj       asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)),
288838fd1498Szrj 		       aascd->type, aascd->v);
288938fd1498Szrj     }
289038fd1498Szrj   return 1;
289138fd1498Szrj }
289238fd1498Szrj 
289338fd1498Szrj /* Needs to be GTY(()), because cgraph_build_static_cdtor may
289438fd1498Szrj    invoke ggc_collect.  */
289538fd1498Szrj static GTY(()) tree asan_ctor_statements;
289638fd1498Szrj 
289738fd1498Szrj /* Module-level instrumentation.
289838fd1498Szrj    - Insert __asan_init_vN() into the list of CTORs.
289938fd1498Szrj    - TODO: insert redzones around globals.
290038fd1498Szrj  */
290138fd1498Szrj 
290238fd1498Szrj void
asan_finish_file(void)290338fd1498Szrj asan_finish_file (void)
290438fd1498Szrj {
290538fd1498Szrj   varpool_node *vnode;
290638fd1498Szrj   unsigned HOST_WIDE_INT gcount = 0;
290738fd1498Szrj 
290838fd1498Szrj   if (shadow_ptr_types[0] == NULL_TREE)
290938fd1498Szrj     asan_init_shadow_ptr_types ();
291038fd1498Szrj   /* Avoid instrumenting code in the asan ctors/dtors.
291138fd1498Szrj      We don't need to insert padding after the description strings,
291238fd1498Szrj      nor after .LASAN* array.  */
291338fd1498Szrj   flag_sanitize &= ~SANITIZE_ADDRESS;
291438fd1498Szrj 
291538fd1498Szrj   /* For user-space we want asan constructors to run first.
291638fd1498Szrj      Linux kernel does not support priorities other than default, and the only
291738fd1498Szrj      other user of constructors is coverage. So we run with the default
291838fd1498Szrj      priority.  */
291938fd1498Szrj   int priority = flag_sanitize & SANITIZE_USER_ADDRESS
292038fd1498Szrj                  ? MAX_RESERVED_INIT_PRIORITY - 1 : DEFAULT_INIT_PRIORITY;
292138fd1498Szrj 
292238fd1498Szrj   if (flag_sanitize & SANITIZE_USER_ADDRESS)
292338fd1498Szrj     {
292438fd1498Szrj       tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
292538fd1498Szrj       append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
292638fd1498Szrj       fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK);
292738fd1498Szrj       append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
292838fd1498Szrj     }
292938fd1498Szrj   FOR_EACH_DEFINED_VARIABLE (vnode)
293038fd1498Szrj     if (TREE_ASM_WRITTEN (vnode->decl)
293138fd1498Szrj 	&& asan_protect_global (vnode->decl))
293238fd1498Szrj       ++gcount;
293338fd1498Szrj   hash_table<tree_descriptor_hasher> *const_desc_htab = constant_pool_htab ();
293438fd1498Szrj   const_desc_htab->traverse<unsigned HOST_WIDE_INT *, count_string_csts>
293538fd1498Szrj     (&gcount);
293638fd1498Szrj   if (gcount)
293738fd1498Szrj     {
293838fd1498Szrj       tree type = asan_global_struct (), var, ctor;
293938fd1498Szrj       tree dtor_statements = NULL_TREE;
294038fd1498Szrj       vec<constructor_elt, va_gc> *v;
294138fd1498Szrj       char buf[20];
294238fd1498Szrj 
294338fd1498Szrj       type = build_array_type_nelts (type, gcount);
294438fd1498Szrj       ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", 0);
294538fd1498Szrj       var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
294638fd1498Szrj 			type);
294738fd1498Szrj       TREE_STATIC (var) = 1;
294838fd1498Szrj       TREE_PUBLIC (var) = 0;
294938fd1498Szrj       DECL_ARTIFICIAL (var) = 1;
295038fd1498Szrj       DECL_IGNORED_P (var) = 1;
295138fd1498Szrj       vec_alloc (v, gcount);
295238fd1498Szrj       FOR_EACH_DEFINED_VARIABLE (vnode)
295338fd1498Szrj 	if (TREE_ASM_WRITTEN (vnode->decl)
295438fd1498Szrj 	    && asan_protect_global (vnode->decl))
295538fd1498Szrj 	  asan_add_global (vnode->decl, TREE_TYPE (type), v);
295638fd1498Szrj       struct asan_add_string_csts_data aascd;
295738fd1498Szrj       aascd.type = TREE_TYPE (type);
295838fd1498Szrj       aascd.v = v;
295938fd1498Szrj       const_desc_htab->traverse<asan_add_string_csts_data *, add_string_csts>
296038fd1498Szrj        	(&aascd);
296138fd1498Szrj       ctor = build_constructor (type, v);
296238fd1498Szrj       TREE_CONSTANT (ctor) = 1;
296338fd1498Szrj       TREE_STATIC (ctor) = 1;
296438fd1498Szrj       DECL_INITIAL (var) = ctor;
296538fd1498Szrj       SET_DECL_ALIGN (var, MAX (DECL_ALIGN (var),
296638fd1498Szrj 				ASAN_SHADOW_GRANULARITY * BITS_PER_UNIT));
296738fd1498Szrj 
296838fd1498Szrj       varpool_node::finalize_decl (var);
296938fd1498Szrj 
297038fd1498Szrj       tree fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS);
297138fd1498Szrj       tree gcount_tree = build_int_cst (pointer_sized_int_node, gcount);
297238fd1498Szrj       append_to_statement_list (build_call_expr (fn, 2,
297338fd1498Szrj 						 build_fold_addr_expr (var),
297438fd1498Szrj 						 gcount_tree),
297538fd1498Szrj 				&asan_ctor_statements);
297638fd1498Szrj 
297738fd1498Szrj       fn = builtin_decl_implicit (BUILT_IN_ASAN_UNREGISTER_GLOBALS);
297838fd1498Szrj       append_to_statement_list (build_call_expr (fn, 2,
297938fd1498Szrj 						 build_fold_addr_expr (var),
298038fd1498Szrj 						 gcount_tree),
298138fd1498Szrj 				&dtor_statements);
298238fd1498Szrj       cgraph_build_static_cdtor ('D', dtor_statements, priority);
298338fd1498Szrj     }
298438fd1498Szrj   if (asan_ctor_statements)
298538fd1498Szrj     cgraph_build_static_cdtor ('I', asan_ctor_statements, priority);
298638fd1498Szrj   flag_sanitize |= SANITIZE_ADDRESS;
298738fd1498Szrj }
298838fd1498Szrj 
298938fd1498Szrj /* Poison or unpoison (depending on IS_CLOBBER variable) shadow memory based
299038fd1498Szrj    on SHADOW address.  Newly added statements will be added to ITER with
299138fd1498Szrj    given location LOC.  We mark SIZE bytes in shadow memory, where
299238fd1498Szrj    LAST_CHUNK_SIZE is greater than zero in situation where we are at the
299338fd1498Szrj    end of a variable.  */
299438fd1498Szrj 
299538fd1498Szrj static void
asan_store_shadow_bytes(gimple_stmt_iterator * iter,location_t loc,tree shadow,unsigned HOST_WIDE_INT base_addr_offset,bool is_clobber,unsigned size,unsigned last_chunk_size)299638fd1498Szrj asan_store_shadow_bytes (gimple_stmt_iterator *iter, location_t loc,
299738fd1498Szrj 			 tree shadow,
299838fd1498Szrj 			 unsigned HOST_WIDE_INT base_addr_offset,
299938fd1498Szrj 			 bool is_clobber, unsigned size,
300038fd1498Szrj 			 unsigned last_chunk_size)
300138fd1498Szrj {
300238fd1498Szrj   tree shadow_ptr_type;
300338fd1498Szrj 
300438fd1498Szrj   switch (size)
300538fd1498Szrj     {
300638fd1498Szrj     case 1:
300738fd1498Szrj       shadow_ptr_type = shadow_ptr_types[0];
300838fd1498Szrj       break;
300938fd1498Szrj     case 2:
301038fd1498Szrj       shadow_ptr_type = shadow_ptr_types[1];
301138fd1498Szrj       break;
301238fd1498Szrj     case 4:
301338fd1498Szrj       shadow_ptr_type = shadow_ptr_types[2];
301438fd1498Szrj       break;
301538fd1498Szrj     default:
301638fd1498Szrj       gcc_unreachable ();
301738fd1498Szrj     }
301838fd1498Szrj 
301938fd1498Szrj   unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0;
302038fd1498Szrj   unsigned HOST_WIDE_INT val = 0;
302138fd1498Szrj   unsigned last_pos = size;
302238fd1498Szrj   if (last_chunk_size && !is_clobber)
302338fd1498Szrj     last_pos = BYTES_BIG_ENDIAN ? 0 : size - 1;
302438fd1498Szrj   for (unsigned i = 0; i < size; ++i)
302538fd1498Szrj     {
302638fd1498Szrj       unsigned char shadow_c = c;
302738fd1498Szrj       if (i == last_pos)
302838fd1498Szrj 	shadow_c = last_chunk_size;
302938fd1498Szrj       val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i);
303038fd1498Szrj     }
303138fd1498Szrj 
303238fd1498Szrj   /* Handle last chunk in unpoisoning.  */
303338fd1498Szrj   tree magic = build_int_cst (TREE_TYPE (shadow_ptr_type), val);
303438fd1498Szrj 
303538fd1498Szrj   tree dest = build2 (MEM_REF, TREE_TYPE (shadow_ptr_type), shadow,
303638fd1498Szrj 		      build_int_cst (shadow_ptr_type, base_addr_offset));
303738fd1498Szrj 
303838fd1498Szrj   gimple *g = gimple_build_assign (dest, magic);
303938fd1498Szrj   gimple_set_location (g, loc);
304038fd1498Szrj   gsi_insert_after (iter, g, GSI_NEW_STMT);
304138fd1498Szrj }
304238fd1498Szrj 
304338fd1498Szrj /* Expand the ASAN_MARK builtins.  */
304438fd1498Szrj 
304538fd1498Szrj bool
asan_expand_mark_ifn(gimple_stmt_iterator * iter)304638fd1498Szrj asan_expand_mark_ifn (gimple_stmt_iterator *iter)
304738fd1498Szrj {
304838fd1498Szrj   gimple *g = gsi_stmt (*iter);
304938fd1498Szrj   location_t loc = gimple_location (g);
305038fd1498Szrj   HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (g, 0));
305138fd1498Szrj   bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
305238fd1498Szrj 
305338fd1498Szrj   tree base = gimple_call_arg (g, 1);
305438fd1498Szrj   gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
305538fd1498Szrj   tree decl = TREE_OPERAND (base, 0);
305638fd1498Szrj 
305738fd1498Szrj   /* For a nested function, we can have: ASAN_MARK (2, &FRAME.2.fp_input, 4) */
305838fd1498Szrj   if (TREE_CODE (decl) == COMPONENT_REF
305938fd1498Szrj       && DECL_NONLOCAL_FRAME (TREE_OPERAND (decl, 0)))
306038fd1498Szrj     decl = TREE_OPERAND (decl, 0);
306138fd1498Szrj 
306238fd1498Szrj   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
306338fd1498Szrj 
306438fd1498Szrj   if (is_poison)
306538fd1498Szrj     {
306638fd1498Szrj       if (asan_handled_variables == NULL)
306738fd1498Szrj 	asan_handled_variables = new hash_set<tree> (16);
306838fd1498Szrj       asan_handled_variables->add (decl);
306938fd1498Szrj     }
307038fd1498Szrj   tree len = gimple_call_arg (g, 2);
307138fd1498Szrj 
307238fd1498Szrj   gcc_assert (tree_fits_shwi_p (len));
307338fd1498Szrj   unsigned HOST_WIDE_INT size_in_bytes = tree_to_shwi (len);
307438fd1498Szrj   gcc_assert (size_in_bytes);
307538fd1498Szrj 
307638fd1498Szrj   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
307738fd1498Szrj 			   NOP_EXPR, base);
307838fd1498Szrj   gimple_set_location (g, loc);
307938fd1498Szrj   gsi_replace (iter, g, false);
308038fd1498Szrj   tree base_addr = gimple_assign_lhs (g);
308138fd1498Szrj 
308238fd1498Szrj   /* Generate direct emission if size_in_bytes is small.  */
308338fd1498Szrj   if (size_in_bytes <= ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD)
308438fd1498Szrj     {
308538fd1498Szrj       unsigned HOST_WIDE_INT shadow_size = shadow_mem_size (size_in_bytes);
308638fd1498Szrj 
308738fd1498Szrj       tree shadow = build_shadow_mem_access (iter, loc, base_addr,
308838fd1498Szrj 					     shadow_ptr_types[0], true);
308938fd1498Szrj 
309038fd1498Szrj       for (unsigned HOST_WIDE_INT offset = 0; offset < shadow_size;)
309138fd1498Szrj 	{
309238fd1498Szrj 	  unsigned size = 1;
309338fd1498Szrj 	  if (shadow_size - offset >= 4)
309438fd1498Szrj 	    size = 4;
309538fd1498Szrj 	  else if (shadow_size - offset >= 2)
309638fd1498Szrj 	    size = 2;
309738fd1498Szrj 
309838fd1498Szrj 	  unsigned HOST_WIDE_INT last_chunk_size = 0;
309938fd1498Szrj 	  unsigned HOST_WIDE_INT s = (offset + size) * ASAN_SHADOW_GRANULARITY;
310038fd1498Szrj 	  if (s > size_in_bytes)
310138fd1498Szrj 	    last_chunk_size = ASAN_SHADOW_GRANULARITY - (s - size_in_bytes);
310238fd1498Szrj 
310338fd1498Szrj 	  asan_store_shadow_bytes (iter, loc, shadow, offset, is_poison,
310438fd1498Szrj 				   size, last_chunk_size);
310538fd1498Szrj 	  offset += size;
310638fd1498Szrj 	}
310738fd1498Szrj     }
310838fd1498Szrj   else
310938fd1498Szrj     {
311038fd1498Szrj       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
311138fd1498Szrj 			       NOP_EXPR, len);
311238fd1498Szrj       gimple_set_location (g, loc);
311338fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
311438fd1498Szrj       tree sz_arg = gimple_assign_lhs (g);
311538fd1498Szrj 
311638fd1498Szrj       tree fun
311738fd1498Szrj 	= builtin_decl_implicit (is_poison ? BUILT_IN_ASAN_POISON_STACK_MEMORY
311838fd1498Szrj 				 : BUILT_IN_ASAN_UNPOISON_STACK_MEMORY);
311938fd1498Szrj       g = gimple_build_call (fun, 2, base_addr, sz_arg);
312038fd1498Szrj       gimple_set_location (g, loc);
312138fd1498Szrj       gsi_insert_after (iter, g, GSI_NEW_STMT);
312238fd1498Szrj     }
312338fd1498Szrj 
312438fd1498Szrj   return false;
312538fd1498Szrj }
312638fd1498Szrj 
312738fd1498Szrj /* Expand the ASAN_{LOAD,STORE} builtins.  */
312838fd1498Szrj 
312938fd1498Szrj bool
asan_expand_check_ifn(gimple_stmt_iterator * iter,bool use_calls)313038fd1498Szrj asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
313138fd1498Szrj {
313238fd1498Szrj   gimple *g = gsi_stmt (*iter);
313338fd1498Szrj   location_t loc = gimple_location (g);
313438fd1498Szrj   bool recover_p;
313538fd1498Szrj   if (flag_sanitize & SANITIZE_USER_ADDRESS)
313638fd1498Szrj     recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
313738fd1498Szrj   else
313838fd1498Szrj     recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
313938fd1498Szrj 
314038fd1498Szrj   HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
314138fd1498Szrj   gcc_assert (flags < ASAN_CHECK_LAST);
314238fd1498Szrj   bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
314338fd1498Szrj   bool is_store = (flags & ASAN_CHECK_STORE) != 0;
314438fd1498Szrj   bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
314538fd1498Szrj 
314638fd1498Szrj   tree base = gimple_call_arg (g, 1);
314738fd1498Szrj   tree len = gimple_call_arg (g, 2);
314838fd1498Szrj   HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3));
314938fd1498Szrj 
315038fd1498Szrj   HOST_WIDE_INT size_in_bytes
315138fd1498Szrj     = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
315238fd1498Szrj 
315338fd1498Szrj   if (use_calls)
315438fd1498Szrj     {
315538fd1498Szrj       /* Instrument using callbacks.  */
315638fd1498Szrj       gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
315738fd1498Szrj 				      NOP_EXPR, base);
315838fd1498Szrj       gimple_set_location (g, loc);
315938fd1498Szrj       gsi_insert_before (iter, g, GSI_SAME_STMT);
316038fd1498Szrj       tree base_addr = gimple_assign_lhs (g);
316138fd1498Szrj 
316238fd1498Szrj       int nargs;
316338fd1498Szrj       tree fun = check_func (is_store, recover_p, size_in_bytes, &nargs);
316438fd1498Szrj       if (nargs == 1)
316538fd1498Szrj 	g = gimple_build_call (fun, 1, base_addr);
316638fd1498Szrj       else
316738fd1498Szrj 	{
316838fd1498Szrj 	  gcc_assert (nargs == 2);
316938fd1498Szrj 	  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
317038fd1498Szrj 				   NOP_EXPR, len);
317138fd1498Szrj 	  gimple_set_location (g, loc);
317238fd1498Szrj 	  gsi_insert_before (iter, g, GSI_SAME_STMT);
317338fd1498Szrj 	  tree sz_arg = gimple_assign_lhs (g);
317438fd1498Szrj 	  g = gimple_build_call (fun, nargs, base_addr, sz_arg);
317538fd1498Szrj 	}
317638fd1498Szrj       gimple_set_location (g, loc);
317738fd1498Szrj       gsi_replace (iter, g, false);
317838fd1498Szrj       return false;
317938fd1498Szrj     }
318038fd1498Szrj 
318138fd1498Szrj   HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
318238fd1498Szrj 
318338fd1498Szrj   tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
318438fd1498Szrj   tree shadow_type = TREE_TYPE (shadow_ptr_type);
318538fd1498Szrj 
318638fd1498Szrj   gimple_stmt_iterator gsi = *iter;
318738fd1498Szrj 
318838fd1498Szrj   if (!is_non_zero_len)
318938fd1498Szrj     {
319038fd1498Szrj       /* So, the length of the memory area to asan-protect is
319138fd1498Szrj 	 non-constant.  Let's guard the generated instrumentation code
319238fd1498Szrj 	 like:
319338fd1498Szrj 
319438fd1498Szrj 	 if (len != 0)
319538fd1498Szrj 	   {
319638fd1498Szrj 	     //asan instrumentation code goes here.
319738fd1498Szrj 	   }
319838fd1498Szrj 	 // falltrough instructions, starting with *ITER.  */
319938fd1498Szrj 
320038fd1498Szrj       g = gimple_build_cond (NE_EXPR,
320138fd1498Szrj 			    len,
320238fd1498Szrj 			    build_int_cst (TREE_TYPE (len), 0),
320338fd1498Szrj 			    NULL_TREE, NULL_TREE);
320438fd1498Szrj       gimple_set_location (g, loc);
320538fd1498Szrj 
320638fd1498Szrj       basic_block then_bb, fallthrough_bb;
320738fd1498Szrj       insert_if_then_before_iter (as_a <gcond *> (g), iter,
320838fd1498Szrj 				  /*then_more_likely_p=*/true,
320938fd1498Szrj 				  &then_bb, &fallthrough_bb);
321038fd1498Szrj       /* Note that fallthrough_bb starts with the statement that was
321138fd1498Szrj 	pointed to by ITER.  */
321238fd1498Szrj 
321338fd1498Szrj       /* The 'then block' of the 'if (len != 0) condition is where
321438fd1498Szrj 	we'll generate the asan instrumentation code now.  */
321538fd1498Szrj       gsi = gsi_last_bb (then_bb);
321638fd1498Szrj     }
321738fd1498Szrj 
321838fd1498Szrj   /* Get an iterator on the point where we can add the condition
321938fd1498Szrj      statement for the instrumentation.  */
322038fd1498Szrj   basic_block then_bb, else_bb;
322138fd1498Szrj   gsi = create_cond_insert_point (&gsi, /*before_p*/false,
322238fd1498Szrj 				  /*then_more_likely_p=*/false,
322338fd1498Szrj 				  /*create_then_fallthru_edge*/recover_p,
322438fd1498Szrj 				  &then_bb,
322538fd1498Szrj 				  &else_bb);
322638fd1498Szrj 
322738fd1498Szrj   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
322838fd1498Szrj 			   NOP_EXPR, base);
322938fd1498Szrj   gimple_set_location (g, loc);
323038fd1498Szrj   gsi_insert_before (&gsi, g, GSI_NEW_STMT);
323138fd1498Szrj   tree base_addr = gimple_assign_lhs (g);
323238fd1498Szrj 
323338fd1498Szrj   tree t = NULL_TREE;
323438fd1498Szrj   if (real_size_in_bytes >= 8)
323538fd1498Szrj     {
323638fd1498Szrj       tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
323738fd1498Szrj 					     shadow_ptr_type);
323838fd1498Szrj       t = shadow;
323938fd1498Szrj     }
324038fd1498Szrj   else
324138fd1498Szrj     {
324238fd1498Szrj       /* Slow path for 1, 2 and 4 byte accesses.  */
324338fd1498Szrj       /* Test (shadow != 0)
324438fd1498Szrj 	 & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow).  */
324538fd1498Szrj       tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
324638fd1498Szrj 					     shadow_ptr_type);
324738fd1498Szrj       gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
324838fd1498Szrj       gimple_seq seq = NULL;
324938fd1498Szrj       gimple_seq_add_stmt (&seq, shadow_test);
325038fd1498Szrj       /* Aligned (>= 8 bytes) can test just
325138fd1498Szrj 	 (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
325238fd1498Szrj 	 to be 0.  */
325338fd1498Szrj       if (align < 8)
325438fd1498Szrj 	{
325538fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
325638fd1498Szrj 						   base_addr, 7));
325738fd1498Szrj 	  gimple_seq_add_stmt (&seq,
325838fd1498Szrj 			       build_type_cast (shadow_type,
325938fd1498Szrj 						gimple_seq_last (seq)));
326038fd1498Szrj 	  if (real_size_in_bytes > 1)
326138fd1498Szrj 	    gimple_seq_add_stmt (&seq,
326238fd1498Szrj 				 build_assign (PLUS_EXPR,
326338fd1498Szrj 					       gimple_seq_last (seq),
326438fd1498Szrj 					       real_size_in_bytes - 1));
326538fd1498Szrj 	  t = gimple_assign_lhs (gimple_seq_last_stmt (seq));
326638fd1498Szrj 	}
326738fd1498Szrj       else
326838fd1498Szrj 	t = build_int_cst (shadow_type, real_size_in_bytes - 1);
326938fd1498Szrj       gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, t, shadow));
327038fd1498Szrj       gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
327138fd1498Szrj 					       gimple_seq_last (seq)));
327238fd1498Szrj       t = gimple_assign_lhs (gimple_seq_last (seq));
327338fd1498Szrj       gimple_seq_set_location (seq, loc);
327438fd1498Szrj       gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
327538fd1498Szrj 
327638fd1498Szrj       /* For non-constant, misaligned or otherwise weird access sizes,
327738fd1498Szrj        check first and last byte.  */
327838fd1498Szrj       if (size_in_bytes == -1)
327938fd1498Szrj 	{
328038fd1498Szrj 	  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
328138fd1498Szrj 				   MINUS_EXPR, len,
328238fd1498Szrj 				   build_int_cst (pointer_sized_int_node, 1));
328338fd1498Szrj 	  gimple_set_location (g, loc);
328438fd1498Szrj 	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
328538fd1498Szrj 	  tree last = gimple_assign_lhs (g);
328638fd1498Szrj 	  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
328738fd1498Szrj 				   PLUS_EXPR, base_addr, last);
328838fd1498Szrj 	  gimple_set_location (g, loc);
328938fd1498Szrj 	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
329038fd1498Szrj 	  tree base_end_addr = gimple_assign_lhs (g);
329138fd1498Szrj 
329238fd1498Szrj 	  tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr,
329338fd1498Szrj 						 shadow_ptr_type);
329438fd1498Szrj 	  gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
329538fd1498Szrj 	  gimple_seq seq = NULL;
329638fd1498Szrj 	  gimple_seq_add_stmt (&seq, shadow_test);
329738fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
329838fd1498Szrj 						   base_end_addr, 7));
329938fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
330038fd1498Szrj 						      gimple_seq_last (seq)));
330138fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
330238fd1498Szrj 						   gimple_seq_last (seq),
330338fd1498Szrj 						   shadow));
330438fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
330538fd1498Szrj 						   gimple_seq_last (seq)));
330638fd1498Szrj 	  gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
330738fd1498Szrj 						   gimple_seq_last (seq)));
330838fd1498Szrj 	  t = gimple_assign_lhs (gimple_seq_last (seq));
330938fd1498Szrj 	  gimple_seq_set_location (seq, loc);
331038fd1498Szrj 	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
331138fd1498Szrj 	}
331238fd1498Szrj     }
331338fd1498Szrj 
331438fd1498Szrj   g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
331538fd1498Szrj 			 NULL_TREE, NULL_TREE);
331638fd1498Szrj   gimple_set_location (g, loc);
331738fd1498Szrj   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
331838fd1498Szrj 
331938fd1498Szrj   /* Generate call to the run-time library (e.g. __asan_report_load8).  */
332038fd1498Szrj   gsi = gsi_start_bb (then_bb);
332138fd1498Szrj   int nargs;
332238fd1498Szrj   tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
332338fd1498Szrj   g = gimple_build_call (fun, nargs, base_addr, len);
332438fd1498Szrj   gimple_set_location (g, loc);
332538fd1498Szrj   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
332638fd1498Szrj 
332738fd1498Szrj   gsi_remove (iter, true);
332838fd1498Szrj   *iter = gsi_start_bb (else_bb);
332938fd1498Szrj 
333038fd1498Szrj   return true;
333138fd1498Szrj }
333238fd1498Szrj 
333338fd1498Szrj /* Create ASAN shadow variable for a VAR_DECL which has been rewritten
333438fd1498Szrj    into SSA.  Already seen VAR_DECLs are stored in SHADOW_VARS_MAPPING.  */
333538fd1498Szrj 
333638fd1498Szrj static tree
create_asan_shadow_var(tree var_decl,hash_map<tree,tree> & shadow_vars_mapping)333738fd1498Szrj create_asan_shadow_var (tree var_decl,
333838fd1498Szrj 			hash_map<tree, tree> &shadow_vars_mapping)
333938fd1498Szrj {
334038fd1498Szrj   tree *slot = shadow_vars_mapping.get (var_decl);
334138fd1498Szrj   if (slot == NULL)
334238fd1498Szrj     {
334338fd1498Szrj       tree shadow_var = copy_node (var_decl);
334438fd1498Szrj 
334538fd1498Szrj       copy_body_data id;
334638fd1498Szrj       memset (&id, 0, sizeof (copy_body_data));
334738fd1498Szrj       id.src_fn = id.dst_fn = current_function_decl;
334838fd1498Szrj       copy_decl_for_dup_finish (&id, var_decl, shadow_var);
334938fd1498Szrj 
335038fd1498Szrj       DECL_ARTIFICIAL (shadow_var) = 1;
335138fd1498Szrj       DECL_IGNORED_P (shadow_var) = 1;
335238fd1498Szrj       DECL_SEEN_IN_BIND_EXPR_P (shadow_var) = 0;
335338fd1498Szrj       gimple_add_tmp_var (shadow_var);
335438fd1498Szrj 
335538fd1498Szrj       shadow_vars_mapping.put (var_decl, shadow_var);
335638fd1498Szrj       return shadow_var;
335738fd1498Szrj     }
335838fd1498Szrj   else
335938fd1498Szrj     return *slot;
336038fd1498Szrj }
336138fd1498Szrj 
336238fd1498Szrj /* Expand ASAN_POISON ifn.  */
336338fd1498Szrj 
336438fd1498Szrj bool
asan_expand_poison_ifn(gimple_stmt_iterator * iter,bool * need_commit_edge_insert,hash_map<tree,tree> & shadow_vars_mapping)336538fd1498Szrj asan_expand_poison_ifn (gimple_stmt_iterator *iter,
336638fd1498Szrj 			bool *need_commit_edge_insert,
336738fd1498Szrj 			hash_map<tree, tree> &shadow_vars_mapping)
336838fd1498Szrj {
336938fd1498Szrj   gimple *g = gsi_stmt (*iter);
337038fd1498Szrj   tree poisoned_var = gimple_call_lhs (g);
337138fd1498Szrj   if (!poisoned_var || has_zero_uses (poisoned_var))
337238fd1498Szrj     {
337338fd1498Szrj       gsi_remove (iter, true);
337438fd1498Szrj       return true;
337538fd1498Szrj     }
337638fd1498Szrj 
337738fd1498Szrj   if (SSA_NAME_VAR (poisoned_var) == NULL_TREE)
337838fd1498Szrj     SET_SSA_NAME_VAR_OR_IDENTIFIER (poisoned_var,
337938fd1498Szrj 				    create_tmp_var (TREE_TYPE (poisoned_var)));
338038fd1498Szrj 
338138fd1498Szrj   tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
338238fd1498Szrj 					    shadow_vars_mapping);
338338fd1498Szrj 
338438fd1498Szrj   bool recover_p;
338538fd1498Szrj   if (flag_sanitize & SANITIZE_USER_ADDRESS)
338638fd1498Szrj     recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
338738fd1498Szrj   else
338838fd1498Szrj     recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
338938fd1498Szrj   tree size = DECL_SIZE_UNIT (shadow_var);
339038fd1498Szrj   gimple *poison_call
339138fd1498Szrj     = gimple_build_call_internal (IFN_ASAN_MARK, 3,
339238fd1498Szrj 				  build_int_cst (integer_type_node,
339338fd1498Szrj 						 ASAN_MARK_POISON),
339438fd1498Szrj 				  build_fold_addr_expr (shadow_var), size);
339538fd1498Szrj 
339638fd1498Szrj   gimple *use;
339738fd1498Szrj   imm_use_iterator imm_iter;
339838fd1498Szrj   FOR_EACH_IMM_USE_STMT (use, imm_iter, poisoned_var)
339938fd1498Szrj     {
340038fd1498Szrj       if (is_gimple_debug (use))
340138fd1498Szrj 	continue;
340238fd1498Szrj 
340338fd1498Szrj       int nargs;
340438fd1498Szrj       bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
340538fd1498Szrj       tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
340638fd1498Szrj 				    &nargs);
340738fd1498Szrj 
340838fd1498Szrj       gcall *call = gimple_build_call (fun, 1,
340938fd1498Szrj 				       build_fold_addr_expr (shadow_var));
341038fd1498Szrj       gimple_set_location (call, gimple_location (use));
341138fd1498Szrj       gimple *call_to_insert = call;
341238fd1498Szrj 
341338fd1498Szrj       /* The USE can be a gimple PHI node.  If so, insert the call on
341438fd1498Szrj 	 all edges leading to the PHI node.  */
341538fd1498Szrj       if (is_a <gphi *> (use))
341638fd1498Szrj 	{
341738fd1498Szrj 	  gphi *phi = dyn_cast<gphi *> (use);
341838fd1498Szrj 	  for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
341938fd1498Szrj 	    if (gimple_phi_arg_def (phi, i) == poisoned_var)
342038fd1498Szrj 	      {
342138fd1498Szrj 		edge e = gimple_phi_arg_edge (phi, i);
342238fd1498Szrj 
342338fd1498Szrj 		/* Do not insert on an edge we can't split.  */
342438fd1498Szrj 		if (e->flags & EDGE_ABNORMAL)
342538fd1498Szrj 		  continue;
342638fd1498Szrj 
342738fd1498Szrj 		if (call_to_insert == NULL)
342838fd1498Szrj 		  call_to_insert = gimple_copy (call);
342938fd1498Szrj 
343038fd1498Szrj 		gsi_insert_seq_on_edge (e, call_to_insert);
343138fd1498Szrj 		*need_commit_edge_insert = true;
343238fd1498Szrj 		call_to_insert = NULL;
343338fd1498Szrj 	      }
343438fd1498Szrj 	}
343538fd1498Szrj       else
343638fd1498Szrj 	{
343738fd1498Szrj 	  gimple_stmt_iterator gsi = gsi_for_stmt (use);
343838fd1498Szrj 	  if (store_p)
343938fd1498Szrj 	    gsi_replace (&gsi, call, true);
344038fd1498Szrj 	  else
344138fd1498Szrj 	    gsi_insert_before (&gsi, call, GSI_NEW_STMT);
344238fd1498Szrj 	}
344338fd1498Szrj     }
344438fd1498Szrj 
344538fd1498Szrj   SSA_NAME_IS_DEFAULT_DEF (poisoned_var) = true;
344638fd1498Szrj   SSA_NAME_DEF_STMT (poisoned_var) = gimple_build_nop ();
344738fd1498Szrj   gsi_replace (iter, poison_call, false);
344838fd1498Szrj 
344938fd1498Szrj   return true;
345038fd1498Szrj }
345138fd1498Szrj 
345238fd1498Szrj /* Instrument the current function.  */
345338fd1498Szrj 
345438fd1498Szrj static unsigned int
asan_instrument(void)345538fd1498Szrj asan_instrument (void)
345638fd1498Szrj {
345738fd1498Szrj   if (shadow_ptr_types[0] == NULL_TREE)
345838fd1498Szrj     asan_init_shadow_ptr_types ();
345938fd1498Szrj   transform_statements ();
346038fd1498Szrj   last_alloca_addr = NULL_TREE;
346138fd1498Szrj   return 0;
346238fd1498Szrj }
346338fd1498Szrj 
346438fd1498Szrj static bool
gate_asan(void)346538fd1498Szrj gate_asan (void)
346638fd1498Szrj {
346738fd1498Szrj   return sanitize_flags_p (SANITIZE_ADDRESS);
346838fd1498Szrj }
346938fd1498Szrj 
347038fd1498Szrj namespace {
347138fd1498Szrj 
347238fd1498Szrj const pass_data pass_data_asan =
347338fd1498Szrj {
347438fd1498Szrj   GIMPLE_PASS, /* type */
347538fd1498Szrj   "asan", /* name */
347638fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
347738fd1498Szrj   TV_NONE, /* tv_id */
347838fd1498Szrj   ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
347938fd1498Szrj   0, /* properties_provided */
348038fd1498Szrj   0, /* properties_destroyed */
348138fd1498Szrj   0, /* todo_flags_start */
348238fd1498Szrj   TODO_update_ssa, /* todo_flags_finish */
348338fd1498Szrj };
348438fd1498Szrj 
348538fd1498Szrj class pass_asan : public gimple_opt_pass
348638fd1498Szrj {
348738fd1498Szrj public:
pass_asan(gcc::context * ctxt)348838fd1498Szrj   pass_asan (gcc::context *ctxt)
348938fd1498Szrj     : gimple_opt_pass (pass_data_asan, ctxt)
349038fd1498Szrj   {}
349138fd1498Szrj 
349238fd1498Szrj   /* opt_pass methods: */
clone()349338fd1498Szrj   opt_pass * clone () { return new pass_asan (m_ctxt); }
gate(function *)349438fd1498Szrj   virtual bool gate (function *) { return gate_asan (); }
execute(function *)349538fd1498Szrj   virtual unsigned int execute (function *) { return asan_instrument (); }
349638fd1498Szrj 
349738fd1498Szrj }; // class pass_asan
349838fd1498Szrj 
349938fd1498Szrj } // anon namespace
350038fd1498Szrj 
350138fd1498Szrj gimple_opt_pass *
make_pass_asan(gcc::context * ctxt)350238fd1498Szrj make_pass_asan (gcc::context *ctxt)
350338fd1498Szrj {
350438fd1498Szrj   return new pass_asan (ctxt);
350538fd1498Szrj }
350638fd1498Szrj 
350738fd1498Szrj namespace {
350838fd1498Szrj 
350938fd1498Szrj const pass_data pass_data_asan_O0 =
351038fd1498Szrj {
351138fd1498Szrj   GIMPLE_PASS, /* type */
351238fd1498Szrj   "asan0", /* name */
351338fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
351438fd1498Szrj   TV_NONE, /* tv_id */
351538fd1498Szrj   ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
351638fd1498Szrj   0, /* properties_provided */
351738fd1498Szrj   0, /* properties_destroyed */
351838fd1498Szrj   0, /* todo_flags_start */
351938fd1498Szrj   TODO_update_ssa, /* todo_flags_finish */
352038fd1498Szrj };
352138fd1498Szrj 
352238fd1498Szrj class pass_asan_O0 : public gimple_opt_pass
352338fd1498Szrj {
352438fd1498Szrj public:
pass_asan_O0(gcc::context * ctxt)352538fd1498Szrj   pass_asan_O0 (gcc::context *ctxt)
352638fd1498Szrj     : gimple_opt_pass (pass_data_asan_O0, ctxt)
352738fd1498Szrj   {}
352838fd1498Szrj 
352938fd1498Szrj   /* opt_pass methods: */
gate(function *)353038fd1498Szrj   virtual bool gate (function *) { return !optimize && gate_asan (); }
execute(function *)353138fd1498Szrj   virtual unsigned int execute (function *) { return asan_instrument (); }
353238fd1498Szrj 
353338fd1498Szrj }; // class pass_asan_O0
353438fd1498Szrj 
353538fd1498Szrj } // anon namespace
353638fd1498Szrj 
353738fd1498Szrj gimple_opt_pass *
make_pass_asan_O0(gcc::context * ctxt)353838fd1498Szrj make_pass_asan_O0 (gcc::context *ctxt)
353938fd1498Szrj {
354038fd1498Szrj   return new pass_asan_O0 (ctxt);
354138fd1498Szrj }
354238fd1498Szrj 
354338fd1498Szrj #include "gt-asan.h"
3544