Instrument built-in memory access function calls
commit905d350be68641678a5f73b3742b2d0cba8afa7f
authorDodji Seketeli <dodji@redhat.com>
Fri, 26 Oct 2012 12:58:40 +0000 (26 12:58 +0000)
committerDodji Seketeli <dodji@seketeli.org>
Fri, 9 Nov 2012 17:03:55 +0000 (9 18:03 +0100)
treebffd88e394adf1da9811ee310a4da88dac68d37d
parentc6611936b722be2a1a4132af3b56d4ecbb306bb9
Instrument built-in memory access function calls

This patch instruments many memory access patterns through builtins.

Basically, for a call like:

     __builtin_memset (from, 0, n_bytes);

the patch would only instrument the accesses at the beginning and at
the end of the memory region [from, from + n_bytes].  This is the
strategy used by the llvm implementation of asan.

This instrumentation is done for all the memory access builtin
functions that expose a well specified memory region -- one that
explicitly states the number of bytes accessed in the region.

A special treatment is used for __builtin_strlen.  The patch
instruments the access to the first byte of its argument, as well as
the access to the byte (of the argument) at the offset returned by
strlen.

For the __sync_* and __atomic* calls the patch instruments the access
to the bytes pointed to by the argument.

While doing this, I have added a new parameter to build_check_stmt to
decide whether to insert the instrumentation code before or after the
statement iterator.  This allows us to do away with the
gsi_{next,prev} dance we were doing in the callers of this function.

Tested by running cc1 -fasan on variations of simple programs like:

    int
    foo ()
    {
      char foo[10] = {0};

      foo[0] = 't';
      foo[1] = 'e';
      foo[2] = 's';
      foo[3] = 't';
      int l = __builtin_strlen (foo);
      int n = sizeof (foo);
      __builtin_memset (&foo[4], 0, n - 4);
      __sync_fetch_and_add (&foo[11], 1);

      return l;
    }

and by starring at the gimple output which for this function is:

    ;; Function foo (foo, funcdef_no=0, decl_uid=1714, cgraph_uid=0)

    foo ()
    {
      int n;
      int l;
      char foo[10];
      int D.1725;
      char * D.1724;
      int D.1723;
      long unsigned int D.1722;
      int D.1721;
      long unsigned int D.1720;
      long unsigned int _1;
      int _4;
      long unsigned int _5;
      int _6;
      char * _7;
      int _8;
      char * _9;
      unsigned long _10;
      unsigned long _11;
      unsigned long _12;
      signed char * _13;
      signed char _14;
      _Bool _15;
      unsigned long _16;
      signed char _17;
      _Bool _18;
      _Bool _19;
      char * _20;
      unsigned long _21;
      unsigned long _22;
      unsigned long _23;
      signed char * _24;
      signed char _25;
      _Bool _26;
      unsigned long _27;
      signed char _28;
      _Bool _29;
      _Bool _30;
      char * _31;
      unsigned long _32;
      unsigned long _33;
      unsigned long _34;
      signed char * _35;
      signed char _36;
      _Bool _37;
      unsigned long _38;
      signed char _39;
      _Bool _40;
      _Bool _41;
      char * _42;
      unsigned long _43;
      unsigned long _44;
      unsigned long _45;
      signed char * _46;
      signed char _47;
      _Bool _48;
      unsigned long _49;
      signed char _50;
      _Bool _51;
      _Bool _52;
      char * _53;
      unsigned long _54;
      unsigned long _55;
      unsigned long _56;
      signed char * _57;
      signed char _58;
      _Bool _59;
      unsigned long _60;
      signed char _61;
      _Bool _62;
      _Bool _63;
      char[10] * _64;
      unsigned long _65;
      unsigned long _66;
      unsigned long _67;
      signed char * _68;
      signed char _69;
      _Bool _70;
      unsigned long _71;
      signed char _72;
      _Bool _73;
      _Bool _74;
      unsigned long _75;
      unsigned long _76;
      unsigned long _77;
      signed char * _78;
      signed char _79;
      _Bool _80;
      unsigned long _81;
      signed char _82;
      _Bool _83;
      _Bool _84;
      long unsigned int _85;
      long unsigned int _86;
      char * _87;
      char * _88;
      unsigned long _89;
      unsigned long _90;
      unsigned long _91;
      signed char * _92;
      signed char _93;
      _Bool _94;
      unsigned long _95;
      signed char _96;
      _Bool _97;
      _Bool _98;
      char * _99;
      unsigned long _100;
      unsigned long _101;
      unsigned long _102;
      signed char * _103;
      signed char _104;
      _Bool _105;
      unsigned long _106;
      signed char _107;
      _Bool _108;
      _Bool _109;

      <bb 2>:
      foo = {};
      _9 = &foo[0];
      _10 = (unsigned long) _9;
      _11 = _10 >> 3;
      _12 = _11 + 17592186044416;
      _13 = (signed char *) _12;
      _14 = *_13;
      _15 = _14 != 0;
      _16 = _10 & 7;
      _17 = (signed char) _16;
      _18 = _17 >= _14;
      _19 = _15 & _18;
      if (_19 != 0)
goto <bb 5>;
      else
goto <bb 4>;

      <bb 5>:
      __asan_report_store1 (_10);

      <bb 4>:
      foo[0] = 116;
      _20 = &foo[1];
      _21 = (unsigned long) _20;
      _22 = _21 >> 3;
      _23 = _22 + 17592186044416;
      _24 = (signed char *) _23;
      _25 = *_24;
      _26 = _25 != 0;
      _27 = _21 & 7;
      _28 = (signed char) _27;
      _29 = _28 >= _25;
      _30 = _26 & _29;
      if (_30 != 0)
goto <bb 7>;
      else
goto <bb 6>;

      <bb 7>:
      __asan_report_store1 (_21);

      <bb 6>:
      foo[1] = 101;
      _31 = &foo[2];
      _32 = (unsigned long) _31;
      _33 = _32 >> 3;
      _34 = _33 + 17592186044416;
      _35 = (signed char *) _34;
      _36 = *_35;
      _37 = _36 != 0;
      _38 = _32 & 7;
      _39 = (signed char) _38;
      _40 = _39 >= _36;
      _41 = _37 & _40;
      if (_41 != 0)
goto <bb 9>;
      else
goto <bb 8>;

      <bb 9>:
      __asan_report_store1 (_32);

      <bb 8>:
      foo[2] = 115;
      _42 = &foo[3];
      _43 = (unsigned long) _42;
      _44 = _43 >> 3;
      _45 = _44 + 17592186044416;
      _46 = (signed char *) _45;
      _47 = *_46;
      _48 = _47 != 0;
      _49 = _43 & 7;
      _50 = (signed char) _49;
      _51 = _50 >= _47;
      _52 = _48 & _51;
      if (_52 != 0)
goto <bb 11>;
      else
goto <bb 10>;

      <bb 11>:
      __asan_report_store1 (_43);

      <bb 10>:
      foo[3] = 116;
      _53 = (char *) &foo;
      _54 = (unsigned long) _53;
      _55 = _54 >> 3;
      _56 = _55 + 17592186044416;
      _57 = (signed char *) _56;
      _58 = *_57;
      _59 = _58 != 0;
      _60 = _54 & 7;
      _61 = (signed char) _60;
      _62 = _61 >= _58;
      _63 = _59 & _62;
      if (_63 != 0)
goto <bb 13>;
      else
goto <bb 12>;

      <bb 13>:
      __asan_report_load1 (_54);

      <bb 12>:
      _1 = __builtin_strlen (&foo);
      _64 = _53 + _1;
      _65 = (unsigned long) _64;
      _66 = _65 >> 3;
      _67 = _66 + 17592186044416;
      _68 = (signed char *) _67;
      _69 = *_68;
      _70 = _69 != 0;
      _71 = _65 & 7;
      _72 = (signed char) _71;
      _73 = _72 >= _69;
      _74 = _70 & _73;
      if (_74 != 0)
goto <bb 15>;
      else
goto <bb 14>;

      <bb 15>:
      __asan_report_load1 (_65);

      <bb 14>:
      l_2 = (int) _1;
      n_3 = 10;
      _4 = n_3 + -4;
      _5 = (long unsigned int) _4;
      _6 = l_2 + 1;
      _7 = &foo[_6];
      if (_5 != 0)
goto <bb 17>;
      else
goto <bb 16>;

      <bb 17>:
      _75 = (unsigned long) _7;
      _76 = _75 >> 3;
      _77 = _76 + 17592186044416;
      _78 = (signed char *) _77;
      _79 = *_78;
      _80 = _79 != 0;
      _81 = _75 & 7;
      _82 = (signed char) _81;
      _83 = _82 >= _79;
      _84 = _80 & _83;
      _85 = _5;
      _86 = _85 - 1;
      _87 = _7;
      _88 = _87 + _86;
      _89 = (unsigned long) _88;
      _90 = _89 >> 3;
      _91 = _90 + 17592186044416;
      _92 = (signed char *) _91;
      _93 = *_92;
      _94 = _93 != 0;
      _95 = _89 & 7;
      _96 = (signed char) _95;
      _97 = _96 >= _93;
      _98 = _94 & _97;
      if (_98 != 0)
goto <bb 21>;
      else
goto <bb 20>;

      <bb 21>:
      __asan_report_store1 (_89);

      <bb 20>:
      if (_84 != 0)
goto <bb 19>;
      else
goto <bb 18>;

      <bb 19>:
      __asan_report_store1 (_75);

      <bb 18>:

      <bb 16>:
      __builtin_memset (_7, 0, _5);
      _99 = &foo[11];
      _100 = (unsigned long) _99;
      _101 = _100 >> 3;
      _102 = _101 + 17592186044416;
      _103 = (signed char *) _102;
      _104 = *_103;
      _105 = _104 != 0;
      _106 = _100 & 7;
      _107 = (signed char) _106;
      _108 = _107 >= _104;
      _109 = _105 & _108;
      if (_109 != 0)
goto <bb 23>;
      else
goto <bb 22>;

      <bb 23>:
      __asan_report_store1 (_100);

      <bb 22>:
      __sync_fetch_and_add_1 (&foo[11], 1);
      _8 = l_2;
      foo ={v} {CLOBBER};

    <L1>:
      return _8;

    }

    ;; Function _GLOBAL__sub_I_00099_0_foo (_GLOBAL__sub_I_00099_0_foo, funcdef_no=1, decl_uid=1752, cgraph_uid=4)

    _GLOBAL__sub_I_00099_0_foo ()
    {
      <bb 2>:
      __asan_init ();
      return;

    }

gcc/
* gimple.h (is_gimple_builtin_call): Declare ...
* gimple.c (is_gimple_builtin_call): ... New public function.
* asan.c (insert_if_then_before_iter, instrument_mem_region_access,
instrument_strlen_call, maybe_instrument_builtin_call,
instrument_call): New static functions.
(create_cond_insert_point): Renamed
create_cond_insert_point_before_iter into this.  Add a new
parameter to decide whether to insert the condition before or
after the statement iterator.
(build_check_stmt): Adjust for the new create_cond_insert_point.
Add a new parameter to decide whether to add the instrumentation
code before or after the statement iterator.
(instrument_assignment): Factorize from ...
(transform_statements): ... here.  Use maybe_instrument_call to
instrument builtin function calls as well.
(instrument_derefs): Adjust for the new parameter of
build_check_stmt.  Fix detection of bit-field access.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/asan@192845 138bc75d-0d04-0410-961f-82ee72b054a4

fixup! Instrument built-in memory access function calls
gcc/ChangeLog.asan
gcc/asan.c
gcc/gimple.c
gcc/gimple.h