GCC Middle and Back End API Reference
|
Go to the source code of this file.
Macros | |
#define | ASAN_SHADOW_SHIFT 3 |
#define | ASAN_RED_ZONE_SIZE 32 |
#define | ASAN_STACK_MAGIC_LEFT 0xf1 |
#define | ASAN_STACK_MAGIC_MIDDLE 0xf2 |
#define | ASAN_STACK_MAGIC_RIGHT 0xf3 |
#define | ASAN_STACK_MAGIC_PARTIAL 0xf4 |
#define | ASAN_STACK_FRAME_MAGIC 0x41b58ab3 |
Functions | |
void | asan_finish_file (void) |
rtx | asan_emit_stack_protection (rtx, HOST_WIDE_INT *, tree *, int) |
bool | asan_protect_global (tree) |
void | initialize_sanitizer_builtins (void) |
static bool | asan_protect_stack_decl () |
static unsigned int | asan_red_zone_size () |
Variables | |
alias_set_type | asan_shadow_set |
#define ASAN_RED_ZONE_SIZE 32 |
Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE up to 2 * ASAN_RED_ZONE_SIZE - 1 bytes.
Referenced by asan_protect_stack_decl(), and expand_stack_vars().
#define ASAN_SHADOW_SHIFT 3 |
Shadow memory is found at (address >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset ().
#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3 |
#define ASAN_STACK_MAGIC_LEFT 0xf1 |
Shadow memory values for stack protection. Left is below protected vars, the first pointer in stack corresponding to that offset contains ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing the frame. Middle is for padding in between variables, right is above the last protected variable and partial immediately after variables up to ASAN_RED_ZONE_SIZE alignment.
Referenced by asan_clear_shadow().
#define ASAN_STACK_MAGIC_MIDDLE 0xf2 |
#define ASAN_STACK_MAGIC_PARTIAL 0xf4 |
#define ASAN_STACK_MAGIC_RIGHT 0xf3 |
rtx asan_emit_stack_protection | ( | rtx | base, |
HOST_WIDE_INT * | offsets, | ||
tree * | decls, | ||
int | length | ||
) |
Insert code to protect stack vars. The prologue sequence should be emitted directly, epilogue sequence returned. BASE is the register holding the stack base, against which OFFSETS array offsets are relative to, OFFSETS array contains pairs of offsets in reverse order, always the end offset of some gap that needs protection followed by starting offset, and DECLS is an array of representative decls for each var partition. LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1 elements long (OFFSETS include gap before the first variable as well as gaps after each stack variable).
First of all, prepare the description string.
Emit the prologue sequence.
Construct epilogue sequence.
void asan_finish_file | ( | void | ) |
AddressSanitizer, a fast memory error detector. Copyright (C) 2011-2013 Free Software Foundation, Inc. Contributed by Kostya Serebryany kcc@g oogl e.com
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.
Needs to be tree asan_ctor_statements;
/** Module-level instrumentation.
Avoid instrumenting code in the asan ctors/dtors. We don't need to insert padding after the description strings, nor after .LASAN* array.
Referenced by emit_debug_global_declarations().
|
inlinestatic |
Return true if DECL should be guarded on the stack.
References ASAN_RED_ZONE_SIZE.
Referenced by expand_stack_vars().
|
inlinestatic |
Return the size of padding needed to insert after a protected decl of SIZE.
void initialize_sanitizer_builtins | ( | void | ) |
Initialize sanitizer.def builtins if the FE hasn't initialized them.
This file contains the definitions and documentation for the Address Sanitizer and Thread Sanitizer builtins used in the GNU compiler. Copyright (C) 2012-2013 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.
Before including this file, you should define a macro:
DEF_SANITIZER_BUILTIN (ENUM, NAME, TYPE, ATTRS)
See builtins.def for details. The builtins are created by the C-family of FEs in c-family/c-common.c, for other FEs by asan.c.
Address Sanitizer
Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c relies on this order.
Thread Sanitizer
Undefined Behavior Sanitizer
References asan_protect_global(), TREE_ASM_WRITTEN, TREE_CODE, and constant_descriptor_tree::value.
Referenced by tsan_pass().
alias_set_type asan_shadow_set |
Alias set for accessing the shadow memory.
AddressSanitizer, a fast memory error detector. Copyright (C) 2012-2013 Free Software Foundation, Inc. Contributed by Kostya Serebryany kcc@g oogl e.com
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/. AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average.
The tool consists of two parts: instrumentation module (this file) and a run-time library. The instrumentation module adds a run-time check before every memory insn. For a 8- or 16- byte load accessing address X: ShadowAddr = (X >> 3) + Offset ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access. if (ShadowValue) __asan_report_load8(X); For a load of N bytes (N=1, 2 or 4) from address X: ShadowAddr = (X >> 3) + Offset ShadowValue = *(char*)ShadowAddr; if (ShadowValue) if ((X & 7) + N - 1 > ShadowValue) __asan_report_loadN(X); Stores are instrumented similarly, but using __asan_report_storeN functions. 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 allocated memory) and free (so that reuse of free-ed memory is delayed), provides __asan_report* and __asan_init functions.
Read more: http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
The current implementation supports detection of out-of-bounds and use-after-free in the heap, on the stack and for global variables.
[Protection of stack variables]
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 stack grows downward:
int foo () { char a[23] = {0}; int b[2] = {0};
a[5] = 1; b[1] = 2;
return a[5] + b[1]; }
For this function, the stack protected by asan will be organized as follows, from the top of the stack to the bottom:
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 the next slot be 32 bytes aligned; this one is called Partial Redzone; this 32 bytes alignment is an asan constraint]
Slot 3/ [24 bytes for variable 'a']
Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
Slot 6/ [8 bytes for variable 'b']
Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called 'LEFT RedZone']
The 32 bytes of LEFT red zone at the bottom of the stack can be decomposed as such:
1/ The first 8 bytes contain a magical asan number that is always 0x41B58AB3.
2/ The following 8 bytes contains a pointer to a string (to be parsed at runtime by the runtime asan library), which format is the following:
"<function-name> <space> <num-of-variables-on-the-stack> (<32-bytes-aligned-offset-in-bytes-of-variable> <space> <length-of-var-in-bytes> ){n} "
where '(...){n}' means the content inside the parenthesis occurs 'n' times, with 'n' being the number of variables on the stack.
3/ The following 16 bytes of the red zone have no particular format.
The shadow memory for that stack layout is going to look like this:
content of shadow memory 8 bytes for slots 6 and 5: 0xF4F4F400. The F4 byte pattern is a magic number called ASAN_STACK_MAGIC_PARTIAL. It flags the fact that the memory region for this shadow byte is a PARTIAL red zone intended to pad a variable A, so that the slot following {A,padding} is 32 bytes aligned.
Note that the fact that the least significant byte of this shadow memory content is 00 means that 8 bytes of its corresponding memory (which corresponds to the memory of variable 'b') is addressable.
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 stack variables as well as the different red zones, emits some 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 stack variables as accessible, and emit some epilogue code to un-poison (mark as accessible) the regions of red zones right before the function exits.
[Protection of 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 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 them. The size of the red zones is so that each variable starts on a 32 bytes boundary.
Then a constructor function is installed so that, for each global variable, it calls the runtime asan library function __asan_register_globals_with an instance of this type:
struct asan_global { Address of the beginning of the global variable. const void *beg;
Initial size of the global variable. uptr __size;
Size of the global variable + size of the red zone. This size is 32 bytes aligned. uptr __size_with_redzone;
Name of the global variable. const void *__name;
This is always set to NULL for now. uptr __has_dynamic_init; }
A destructor function that calls the runtime asan library function _asan_unregister_globals is also installed.