* asan.c: Formatting cleanups.

From-SVN: r193442
This commit is contained in:
Jakub Jelinek 2012-11-12 17:18:59 +01:00
parent f35db108b9
commit 497a1c6692
2 changed files with 98 additions and 96 deletions

View File

@ -1,4 +1,8 @@
2012-11-12 Wei Mi <wmi@google.com> 2012-11-12 Jakub Jelinek <jakub@redhat.com>
* asan.c: Formatting cleanups.
2012-11-12 Wei Mi <wmi@google.com>
* gcc.c (LINK_COMMAND_SPEC): Add -lasan to link command if * gcc.c (LINK_COMMAND_SPEC): Add -lasan to link command if
-faddress-sanitizer is on. -faddress-sanitizer is on.
@ -28,7 +32,6 @@
* asan.c (create_cond_insert_point_before_iter): Factorize out of ... * asan.c (create_cond_insert_point_before_iter): Factorize out of ...
(build_check_stmt): ... here. (build_check_stmt): ... here.
2012-11-12 Dodji Seketeli <dodji@redhat.com> 2012-11-12 Dodji Seketeli <dodji@redhat.com>
* asan.c (create_cond_insert_point_before_iter): Factorize out of ... * asan.c (create_cond_insert_point_before_iter): Factorize out of ...
@ -40,7 +43,7 @@
represented by an SSA_NAME. represented by an SSA_NAME.
2012-11-12 Jakub Jelinek <jakub@redhat.com> 2012-11-12 Jakub Jelinek <jakub@redhat.com>
Wei Mi <wmi@google.com> Wei Mi <wmi@google.com>
* varasm.c: Include asan.h. * varasm.c: Include asan.h.
(assemble_noswitch_variable): Grow size by asan_red_zone_size (assemble_noswitch_variable): Grow size by asan_red_zone_size
@ -111,7 +114,7 @@
2012-11-12 Jakub Jelinek <jakub@redhat.com> 2012-11-12 Jakub Jelinek <jakub@redhat.com>
Xinliang David Li <davidxl@google.com> Xinliang David Li <davidxl@google.com>
Dodji Seketeli <dodji@redhat.com> Dodji Seketeli <dodji@redhat.com>
* Makefile.in (GTFILES): Add $(srcdir)/asan.c. * Makefile.in (GTFILES): Add $(srcdir)/asan.c.
(asan.o): Update the dependencies of asan.o. (asan.o): Update the dependencies of asan.o.
@ -155,9 +158,9 @@
* config/i386/i386.c (ix86_asan_shadow_offset): New function. * config/i386/i386.c (ix86_asan_shadow_offset): New function.
(TARGET_ASAN_SHADOW_OFFSET): Define. (TARGET_ASAN_SHADOW_OFFSET): Define.
2012-11-12 Wei Mi <wmi@google.com> 2012-11-12 Wei Mi <wmi@google.com>
Diego Novillo <dnovillo@google.com> Diego Novillo <dnovillo@google.com>
Dodji Seketeli <dodji@redhat.com> Dodji Seketeli <dodji@redhat.com>
* Makefile.in: Add asan.c and its dependencies. * Makefile.in: Add asan.c and its dependencies.
* common.opt: Add -faddress-sanitizer option. * common.opt: Add -faddress-sanitizer option.

View File

@ -33,42 +33,41 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h" #include "optabs.h"
#include "output.h" #include "output.h"
/* /* AddressSanitizer finds out-of-bounds and use-after-free bugs
AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average.
with <2x slowdown on average.
The tool consists of two parts: The tool consists of two parts:
instrumentation module (this file) and a run-time library. instrumentation module (this file) and a run-time library.
The instrumentation module adds a run-time check before every memory insn. The instrumentation module adds a run-time check before every memory insn.
For a 8- or 16- byte load accessing address X: For a 8- or 16- byte load accessing address X:
ShadowAddr = (X >> 3) + Offset ShadowAddr = (X >> 3) + Offset
ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access. ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access.
if (ShadowValue) if (ShadowValue)
__asan_report_load8(X); __asan_report_load8(X);
For a load of N bytes (N=1, 2 or 4) from address X: For a load of N bytes (N=1, 2 or 4) from address X:
ShadowAddr = (X >> 3) + Offset ShadowAddr = (X >> 3) + Offset
ShadowValue = *(char*)ShadowAddr; ShadowValue = *(char*)ShadowAddr;
if (ShadowValue) if (ShadowValue)
if ((X & 7) + N - 1 > ShadowValue) if ((X & 7) + N - 1 > ShadowValue)
__asan_report_loadN(X); __asan_report_loadN(X);
Stores are instrumented similarly, but using __asan_report_storeN functions. Stores are instrumented similarly, but using __asan_report_storeN functions.
A call too __asan_init() is inserted to the list of module CTORs. A call too __asan_init() is inserted to the list of module CTORs.
The run-time library redefines malloc (so that redzone are inserted around The run-time library redefines malloc (so that redzone are inserted around
the allocated memory) and free (so that reuse of free-ed memory is delayed), the allocated memory) and free (so that reuse of free-ed memory is delayed),
provides __asan_report* and __asan_init functions. provides __asan_report* and __asan_init functions.
Read more: Read more:
http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
The current implementation supports detection of out-of-bounds and The current implementation supports detection of out-of-bounds and
use-after-free in the heap, on the stack and for global variables. use-after-free in the heap, on the stack and for global variables.
[Protection of stack variables] [Protection of stack variables]
To understand how detection of out-of-bounds and use-after-free works To understand how detection of out-of-bounds and use-after-free works
for stack variables, lets look at this example on x86_64 where the for stack variables, lets look at this example on x86_64 where the
stack grows downward: stack grows downward:
int int
foo () foo ()
@ -82,28 +81,28 @@ along with GCC; see the file COPYING3. If not see
return a[5] + b[1]; return a[5] + b[1];
} }
For this function, the stack protected by asan will be organized as For this function, the stack protected by asan will be organized as
follows, from the top of the stack to the bottom: follows, from the top of the stack to the bottom:
Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone'] Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone']
Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make
the next slot be 32 bytes aligned; this one is called Partial the next slot be 32 bytes aligned; this one is called Partial
Redzone; this 32 bytes alignment is an asan constraint] Redzone; this 32 bytes alignment is an asan constraint]
Slot 3/ [24 bytes for variable 'a'] Slot 3/ [24 bytes for variable 'a']
Slot 4/ [red zone of 32 bytes called 'Middle RedZone'] Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2] Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
Slot 6/ [8 bytes for variable 'b'] Slot 6/ [8 bytes for variable 'b']
Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called 'LEFT Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called
RedZone'] 'LEFT RedZone']
The 32 bytes of LEFT red zone at the bottom of the stack can be The 32 bytes of LEFT red zone at the bottom of the stack can be
decomposed as such: decomposed as such:
1/ The first 8 bytes contain a magical asan number that is always 1/ The first 8 bytes contain a magical asan number that is always
0x41B58AB3. 0x41B58AB3.
@ -122,7 +121,7 @@ along with GCC; see the file COPYING3. If not see
3/ The following 16 bytes of the red zone have no particular 3/ The following 16 bytes of the red zone have no particular
format. format.
The shadow memory for that stack layout is going to look like this: The shadow memory for that stack layout is going to look like this:
- content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1. - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1.
The F1 byte pattern is a magic number called The F1 byte pattern is a magic number called
@ -149,39 +148,39 @@ along with GCC; see the file COPYING3. If not see
seat between two 32 aligned slots of {variable,padding}. seat between two 32 aligned slots of {variable,padding}.
- content of shadow memory 8 bytes for slot 3 and 2: - content of shadow memory 8 bytes for slot 3 and 2:
0xFFFFFFFFF4000000. This represents is the concatenation of 0xF4000000. This represents is the concatenation of
variable 'a' and the partial red zone following it, like what we variable 'a' and the partial red zone following it, like what we
had for variable 'b'. The least significant 3 bytes being 00 had for variable 'b'. The least significant 3 bytes being 00
means that the 3 bytes of variable 'a' are addressable. means that the 3 bytes of variable 'a' are addressable.
- content of shadow memory 8 bytes for slot 1: 0xFFFFFFFFF3F3F3F3. - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3.
The F3 byte pattern is a magic number called The F3 byte pattern is a magic number called
ASAN_STACK_MAGIC_RIGHT. It flags the fact that the memory ASAN_STACK_MAGIC_RIGHT. It flags the fact that the memory
region for this shadow byte is a RIGHT red zone intended to seat region for this shadow byte is a RIGHT red zone intended to seat
at the top of the variables of the stack. at the top of the variables of the stack.
Note that the real variable layout is done in expand_used_vars in Note that the real variable layout is done in expand_used_vars in
cfgexpand.c. As far as Address Sanitizer is concerned, it lays out cfgexpand.c. As far as Address Sanitizer is concerned, it lays out
stack variables as well as the different red zones, emits some stack variables as well as the different red zones, emits some
prologue code to populate the shadow memory as to poison (mark as prologue code to populate the shadow memory as to poison (mark as
non-accessible) the regions of the red zones and mark the regions of non-accessible) the regions of the red zones and mark the regions of
stack variables as accessible, and emit some epilogue code to stack variables as accessible, and emit some epilogue code to
un-poison (mark as accessible) the regions of red zones right before un-poison (mark as accessible) the regions of red zones right before
the function exits. the function exits.
[Protection of global variables] [Protection of global variables]
The basic idea is to insert a red zone between two global variables The basic idea is to insert a red zone between two global variables
and install a constructor function that calls the asan runtime to do and install a constructor function that calls the asan runtime to do
the populating of the relevant shadow memory regions at load time. the populating of the relevant shadow memory regions at load time.
So the global variables are laid out as to insert a red zone between So the global variables are laid out as to insert a red zone between
them. The size of the red zones is so that each variable starts on a them. The size of the red zones is so that each variable starts on a
32 bytes boundary. 32 bytes boundary.
Then a constructor function is installed so that, for each global Then a constructor function is installed so that, for each global
variable, it calls the runtime asan library function variable, it calls the runtime asan library function
__asan_register_globals_with an instance of this type: __asan_register_globals_with an instance of this type:
struct __asan_global struct __asan_global
{ {
@ -202,8 +201,8 @@ along with GCC; see the file COPYING3. If not see
uptr __has_dynamic_init; uptr __has_dynamic_init;
} }
A destructor function that calls the runtime asan library function A destructor function that calls the runtime asan library function
_asan_unregister_globals is also installed. */ _asan_unregister_globals is also installed. */
alias_set_type asan_shadow_set = -1; alias_set_type asan_shadow_set = -1;
@ -475,7 +474,7 @@ asan_protect_global (tree decl)
return false; return false;
#endif #endif
return true; return true;
} }
/* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}.
@ -490,13 +489,13 @@ report_error_func (bool is_store, int size_in_bytes)
char name[100]; char name[100];
sprintf (name, "__asan_report_%s%d", sprintf (name, "__asan_report_%s%d",
is_store ? "store" : "load", size_in_bytes); is_store ? "store" : "load", size_in_bytes);
fn_type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); fn_type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
def = build_fn_decl (name, fn_type); def = build_fn_decl (name, fn_type);
TREE_NOTHROW (def) = 1; TREE_NOTHROW (def) = 1;
TREE_THIS_VOLATILE (def) = 1; /* Attribute noreturn. Surprise! */ TREE_THIS_VOLATILE (def) = 1; /* Attribute noreturn. Surprise! */
DECL_ATTRIBUTES (def) = tree_cons (get_identifier ("leaf"), DECL_ATTRIBUTES (def) = tree_cons (get_identifier ("leaf"),
NULL, DECL_ATTRIBUTES (def)); NULL, DECL_ATTRIBUTES (def));
DECL_ASSEMBLER_NAME (def); DECL_ASSEMBLER_NAME (def);
return def; return def;
} }
@ -598,7 +597,7 @@ create_cond_insert_point (gimple_stmt_iterator *iter,
outcoming edge of the 'then block' -- starts with the statement outcoming edge of the 'then block' -- starts with the statement
pointed to by ITER. pointed to by ITER.
COND is the condition of the if. COND is the condition of the if.
If THEN_MORE_LIKELY_P is true, the probability of the edge to the If THEN_MORE_LIKELY_P is true, the probability of the edge to the
'then block' is higher than the probability of the edge to the 'then block' is higher than the probability of the edge to the
@ -796,7 +795,7 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
static void static void
instrument_derefs (gimple_stmt_iterator *iter, tree t, instrument_derefs (gimple_stmt_iterator *iter, tree t,
location_t location, bool is_store) location_t location, bool is_store)
{ {
tree type, base; tree type, base;
HOST_WIDE_INT size_in_bytes; HOST_WIDE_INT size_in_bytes;
@ -864,7 +863,7 @@ instrument_mem_region_access (tree base, tree len,
if (len != 0) if (len != 0)
{ {
//asan instrumentation code goes here. //asan instrumentation code goes here.
} }
// falltrough instructions, starting with *ITER. */ // falltrough instructions, starting with *ITER. */
gimple g = gimple_build_cond (NE_EXPR, gimple g = gimple_build_cond (NE_EXPR,
@ -930,7 +929,7 @@ instrument_mem_region_access (tree base, tree len,
region_end = region_end =
gimple_build_assign_with_ops (POINTER_PLUS_EXPR, gimple_build_assign_with_ops (POINTER_PLUS_EXPR,
make_ssa_name (TREE_TYPE (base), NULL), make_ssa_name (TREE_TYPE (base), NULL),
gimple_assign_lhs (region_end), gimple_assign_lhs (region_end),
gimple_assign_lhs (offset)); gimple_assign_lhs (offset));
gimple_set_location (region_end, location); gimple_set_location (region_end, location);
gsi_insert_after (&gsi, region_end, GSI_NEW_STMT); gsi_insert_after (&gsi, region_end, GSI_NEW_STMT);
@ -1378,7 +1377,7 @@ transform_statements (void)
{ {
if (bb->index >= saved_last_basic_block) continue; if (bb->index >= saved_last_basic_block) continue;
for (i = gsi_start_bb (bb); !gsi_end_p (i);) for (i = gsi_start_bb (bb); !gsi_end_p (i);)
{ {
gimple s = gsi_stmt (i); gimple s = gsi_stmt (i);
if (gimple_assign_single_p (s)) if (gimple_assign_single_p (s))
@ -1391,7 +1390,7 @@ transform_statements (void)
continue; continue;
} }
gsi_next (&i); gsi_next (&i);
} }
} }
} }
@ -1594,18 +1593,18 @@ struct gimple_opt_pass pass_asan =
{ {
{ {
GIMPLE_PASS, GIMPLE_PASS,
"asan", /* name */ "asan", /* name */
OPTGROUP_NONE, /* optinfo_flags */ OPTGROUP_NONE, /* optinfo_flags */
gate_asan, /* gate */ gate_asan, /* gate */
asan_instrument, /* execute */ asan_instrument, /* execute */
NULL, /* sub */ NULL, /* sub */
NULL, /* next */ NULL, /* next */
0, /* static_pass_number */ 0, /* static_pass_number */
TV_NONE, /* tv_id */ TV_NONE, /* tv_id */
PROP_ssa | PROP_cfg | PROP_gimple_leh,/* properties_required */ PROP_ssa | PROP_cfg | PROP_gimple_leh,/* properties_required */
0, /* properties_provided */ 0, /* properties_provided */
0, /* properties_destroyed */ 0, /* properties_destroyed */
0, /* todo_flags_start */ 0, /* todo_flags_start */
TODO_verify_flow | TODO_verify_stmts TODO_verify_flow | TODO_verify_stmts
| TODO_update_ssa /* todo_flags_finish */ | TODO_update_ssa /* todo_flags_finish */
} }
@ -1622,7 +1621,7 @@ struct gimple_opt_pass pass_asan_O0 =
{ {
GIMPLE_PASS, GIMPLE_PASS,
"asan0", /* name */ "asan0", /* name */
OPTGROUP_NONE, /* optinfo_flags */ OPTGROUP_NONE, /* optinfo_flags */
gate_asan_O0, /* gate */ gate_asan_O0, /* gate */
asan_instrument, /* execute */ asan_instrument, /* execute */
NULL, /* sub */ NULL, /* sub */