Re: [PATCH][PR sanitizer/84250] Avoid global symbols collision when using both ASan and UBSan
Hi Jeff, On 07/04/2018 05:45 AM, Jeff Law wrote: > On 05/23/2018 11:15 AM, Maxim Ostapenko wrote: >> Hi, >> >> >> as described in PR, when using both ASan and UBSan >> (-fsanitize=address,undefined ), we have symbols collision for global >> functions, like __sanitizer_set_report_path. This leads to fuzzy results >> when printing reports into files e.g. for this test case: >> >> #include >> int main(int argc, char **argv) { >> __sanitizer_set_report_path("/tmp/sanitizer.txt"); >> int i = 23; >> i <<= 32; >> int *array = new int[100]; >> delete [] array; >> return array[argc]; >> } >> >> only ASan's report gets written to file; UBSan output goes to stderr. >> >> To resolve this issue we could use two approaches: >> >> 1) Use the same approach to that is implemented in Clang (UBSan embedded >> to ASan). The only caveat here is that we need to link (unused) C++ part >> of UBSan even in C programs when linking static ASan runtime. This >> happens because GCC, as opposed to Clang, doesn't split C and C++ >> runtimes for sanitizers. >> >> 2) Just add SANITIZER_INTERFACE_ATTRIBUTE to report_file global >> variable. In this case all __sanitizer_set_report_path calls will set >> the same report_file variable. IMHO this is a hacky way to fix the >> issue, it's better to use the first option if possible. >> >> >> The attached patch fixes the symbols collision by embedding UBSan into >> ASan (variant 1), just like we do for LSan. >> >> >> Regtested/bootstrapped on x86_64-unknown-linux-gnu, looks reasonable >> enough for trunk? >> >> >> -Maxim >> >> >> pr84250-2.diff >> >> >> gcc/ChangeLog: >> >> 2018-05-23 Maxim Ostapenko >> >> * config/gnu-user.h (LIBASAN_EARLY_SPEC): Pass -lstdc++ for static >> libasan. >> * gcc.c: Do not pass LIBUBSAN_SPEC if ASan is enabled with UBSan. >> >> libsanitizer/ChangeLog: >> >> 2018-05-23 Maxim Ostapenko >> >> * Makefile.am: Reorder libs. >> * Makefile.in: Regenerate. >> * asan/Makefile.am: Define DCAN_SANITIZE_UB=1, add dependancy from >> libsanitizer_ubsan.la. >> * asan/Makefile.in: Regenerate. >> * ubsan/Makefile.am: Define new libsanitizer_ubsan.la library. >> * ubsan/Makefile.in: Regenerate. > You know this code better than anyone else working on GCC. My only > concern would be the kernel builds with asan, but I suspect they're > providing their own runtime anyway, so the libstdc++ caveat shouldn't apply. Yes, you are right, kernel provides its own runtime. > > OK for the trunk. Ok, thanks, I'll apply the patch today (with fixed ChangeLog entry). -Maxim > jeff > > >
Re: [PATCH][PR sanitizer/84250] Avoid global symbols collision when using both ASan and UBSan
On 07/05/2018 12:01 PM, Jakub Jelinek wrote: > On Wed, Jul 04, 2018 at 08:20:47PM +0300, Maxim Ostapenko wrote: >> On 07/04/2018 05:45 AM, Jeff Law wrote: >>> On 05/23/2018 11:15 AM, Maxim Ostapenko wrote: >>>> as described in PR, when using both ASan and UBSan >>>> (-fsanitize=address,undefined ), we have symbols collision for global >>>> functions, like __sanitizer_set_report_path. This leads to fuzzy results >>>> when printing reports into files e.g. for this test case: >>>> >>>> #include >>>> int main(int argc, char **argv) { >>>> __sanitizer_set_report_path("/tmp/sanitizer.txt"); >>>> int i = 23; >>>> i <<= 32; >>>> int *array = new int[100]; >>>> delete [] array; >>>> return array[argc]; >>>> } >>>> >>>> only ASan's report gets written to file; UBSan output goes to stderr. >>>> >>>> To resolve this issue we could use two approaches: >>>> >>>> 1) Use the same approach to that is implemented in Clang (UBSan embedded >>>> to ASan). The only caveat here is that we need to link (unused) C++ part >>>> of UBSan even in C programs when linking static ASan runtime. This >>>> happens because GCC, as opposed to Clang, doesn't split C and C++ >>>> runtimes for sanitizers. >>>> >>>> 2) Just add SANITIZER_INTERFACE_ATTRIBUTE to report_file global >>>> variable. In this case all __sanitizer_set_report_path calls will set >>>> the same report_file variable. IMHO this is a hacky way to fix the >>>> issue, it's better to use the first option if possible. >>>> >>>> >>>> The attached patch fixes the symbols collision by embedding UBSan into >>>> ASan (variant 1), just like we do for LSan. >>>> >>>> >>>> Regtested/bootstrapped on x86_64-unknown-linux-gnu, looks reasonable >>>> enough for trunk? >>>> >>>> >>>> -Maxim >>>> >>>> >>>> pr84250-2.diff >>>> >>>> >>>> gcc/ChangeLog: >>>> >>>> 2018-05-23 Maxim Ostapenko >>>> >>>>* config/gnu-user.h (LIBASAN_EARLY_SPEC): Pass -lstdc++ for static >>>>libasan. >>>>* gcc.c: Do not pass LIBUBSAN_SPEC if ASan is enabled with UBSan. >>>> >>>> libsanitizer/ChangeLog: >>>> >>>> 2018-05-23 Maxim Ostapenko >>>> >>>>* Makefile.am: Reorder libs. >>>>* Makefile.in: Regenerate. >>>>* asan/Makefile.am: Define DCAN_SANITIZE_UB=1, add dependancy from >>>>libsanitizer_ubsan.la. >>>>* asan/Makefile.in: Regenerate. >>>>* ubsan/Makefile.am: Define new libsanitizer_ubsan.la library. >>>>* ubsan/Makefile.in: Regenerate. >>> You know this code better than anyone else working on GCC. My only >>> concern would be the kernel builds with asan, but I suspect they're >>> providing their own runtime anyway, so the libstdc++ caveat shouldn't apply. >> Yes, you are right, kernel provides its own runtime. >> >>> OK for the trunk. >> Ok, thanks, I'll apply the patch today (with fixed ChangeLog entry). > This broke the c-c++-common/asan/pr59063-2.c test: > > FAIL: c-c++-common/asan/pr59063-2.c -O1 (test for excess errors) > Excess errors: > /usr/bin/ld: cannot find -lstdc++ I must mis-looked this, sorry :(. > While it could be fixed by tweaking asan-dg.exp, thinking about this, the > 1) variant is actually not a good idea, it will not work properly anyway > if you link one library with -fsanitize=undefined and another library > with -fsanitize=address, the right solution is to make the two libraries > coexist sanely Yes, you're right. Btw, we have pretty the same situation with ASan + LSan, right? > , so I'd prefer 2) or if not exporting a variable, export > an accessor function to get the address of the variable (or whole block of > shared state in one object between the libraries). > > Yes, it means trying to get something accepted upstream, but anything else > is an ugly hack. Ok. Could you please revert this patch for me (I don't have a write access to repo right now) so we can cook a proper fix? -Maxim > > Jakub > > >
[PATCH, Libbacktrace] Fix possible SEGV when handling stripped PIE binaries.
Hi! When testing ASan on large system, I've noticed that sometimes it crashes with SEGV in Libbacktrace when trying to symbolize stripped PIE (compiled with -pie -fPIC) binaries in fully stripped environment (this means that all dependent libraries are also stripped). Here a scenario I've observed: 1) _asan_backtrace_initialize calls elf_add passing &elf_fileline_fn as output parameter to properly initialize it. 2) elf_add doesn't elf_fileline_fn initialize and returns -1 for stripped PIE binary. 3) _asan_backtrace_initialize calls phdr_callback on each dependent library via dl_iterate_phdr. 4) phdr_callback initializes elf_fileline_fn iff it found debug info in some library (found_dwarf == 1), but this is false since all libs are stripped. So, we still have uninitialized elf_fileline_fn value. 5) _asan_backtrace_initialize uses elf_fileline_fn to initialize proper fileline_fn callback. 6) Libbacktrace uses fileline_fn callback later and crashes because it contains garbage. This patch fixes the issue by simply initializing elf_fileline_fn via elf_nodebug in _asan_backtrace_initialize prologue. Tested on x86_64-linux-gnu and arm-linux-gnueabi, OK for trunk? -Maxim libbacktrace/ChangeLog: 2016-03-02 Maxim Ostapenko * elf.c (backtrace_initialize): Properly initialize elf_fileline_fn to avoid possible crash. diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index 05cc5c0..c7168c6 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -925,7 +925,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor, int ret; int found_sym; int found_dwarf; - fileline elf_fileline_fn; + fileline elf_fileline_fn = elf_nodebug; struct phdr_data pd; ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
Re: [PATCH, Libbacktrace] Fix possible SEGV when handling stripped PIE binaries.
On 02/03/16 16:59, Ian Lance Taylor wrote: On Wed, Mar 2, 2016 at 12:51 AM, Maxim Ostapenko wrote: When testing ASan on large system, I've noticed that sometimes it crashes with SEGV in Libbacktrace when trying to symbolize stripped PIE (compiled with -pie -fPIC) binaries in fully stripped environment (this means that all dependent libraries are also stripped). Here a scenario I've observed: 1) _asan_backtrace_initialize calls elf_add passing &elf_fileline_fn as output parameter to properly initialize it. 2) elf_add doesn't elf_fileline_fn initialize and returns -1 for stripped PIE binary. 3) _asan_backtrace_initialize calls phdr_callback on each dependent library via dl_iterate_phdr. 4) phdr_callback initializes elf_fileline_fn iff it found debug info in some library (found_dwarf == 1), but this is false since all libs are stripped. So, we still have uninitialized elf_fileline_fn value. 5) _asan_backtrace_initialize uses elf_fileline_fn to initialize proper fileline_fn callback. 6) Libbacktrace uses fileline_fn callback later and crashes because it contains garbage. This patch fixes the issue by simply initializing elf_fileline_fn via elf_nodebug in _asan_backtrace_initialize prologue. Tested on x86_64-linux-gnu and arm-linux-gnueabi, OK for trunk? Thanks for the analysis. I would rather set *fileline_fn in the case where elf_add returns -1. Or, remove the setting of *fileline_fn = elf_nodebug in elf_add, since that would become the default. Ian Thanks, does this look better (I used the second option)? -Maxim libbacktrace/ChangeLog: 2016-03-02 Maxim Ostapenko * elf.c (backtrace_initialize): Properly initialize elf_fileline_fn to avoid possible crash. (elf_add): Don't set *fileline_fn to elf_nodebug value in case of missing debug info anymore. diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c index 05cc5c0..f85ac65 100644 --- a/libbacktrace/elf.c +++ b/libbacktrace/elf.c @@ -791,7 +791,6 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address, { if (!backtrace_close (descriptor, error_callback, data)) goto fail; - *fileline_fn = elf_nodebug; return 1; } @@ -925,7 +924,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor, int ret; int found_sym; int found_dwarf; - fileline elf_fileline_fn; + fileline elf_fileline_fn = elf_nodebug; struct phdr_data pd; ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
Re: RFC ThreadSanitizer tests
> Instead of mentioning the directory in the ChangeLog, > mention the individual test files. > ... >* g++.dg/dg.exp: Prune tsan subdirectory. Thanks, I fixed the ChangeLog file. > how long does it take to run make check-gcc check-g++ RUNTESTFLAGS=tsan.exp ? > How much memory does it need? I've run `make check-gcc RUNTESTFLAGS=tsan.exp' (this also includes c++ tests) under `/usr/bin/time -v' and got: -Elapsed (wall clock) time (h:mm:ss or m:ss): 3:17.04 -Maximum resident set size (kbytes): 199872 kbytes The same numbers for asan are (/usr/bin/time -v make check-gcc RUNTESTFLAGS=asan.exp): -Elapsed (wall clock) time (h:mm:ss or m:ss): 3:56.38 -Maximum resident set size (kbytes): 3155264 kbytes -Maxim 2013-12-05 Max Ostapenko < m.ostape...@partner.samsung.com > * c-c++-common/tsan/atomic_stack.c: New test. * c-c++-common/tsan/fd_pipe_race.c: New test. * c-c++-common/tsan/free_race.c: New test. * c-c++-common/tsan/mutexset1.c: New test. * c-c++-common/tsan/race_on_barrier.c: New test. * c-c++-common/tsan/sleep_sync.c: New test. * c-c++-common/tsan/thread_leak.c: New test. * c-c++-common/tsan/thread_leak1.c: New test. * c-c++-common/tsan/thread_leak2.c: New test. * c-c++-common/tsan/tiny_race.c: New test. * c-c++-common/tsan/tls_race.c: New test. * c-c++-common/tsan/write_in_reader_lock.c: New test. * lib/tsan-dg.exp: New file. * gcc.dg/tsan/tsan.exp: New file. * g++.dg/tsan/tsan.exp: New file. * g++.dg/dg.exp: Prune tsan subdirectory. diff --git a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c new file mode 100644 index 000..eac71b8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include + +int Global; + +void *Thread1(void *x) { + sleep(1); + __atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED); + return NULL; +} + +void *Thread2(void *x) { + Global++; + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ +/* { dg-output " Atomic write of size 4.*" } */ +/* { dg-output "#0 __tsan_atomic32_fetch_add.*" } */ +/* { dg-output "#1 Thread1.*" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c b/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c new file mode 100644 index 000..fc76cbf --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include + +int fds[2]; + +void *Thread1(void *x) { + write(fds[1], "a", 1); + return NULL; +} + +void *Thread2(void *x) { + sleep(1); + close(fds[0]); + close(fds[1]); + return NULL; +} + +int main() { + pipe(fds); + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*\n" } */ +/* { dg-output " Write of size 8.*\n" } */ +/* { dg-output "#0 close.*\n" } */ +/* { dg-output "#1 Thread2.*\n" } */ +/* { dg-output " Previous read of size 8.*\n" } */ +/* { dg-output "#0 write.*\n" } */ +/* { dg-output "#1 Thread1.*\n" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/free_race.c b/gcc/testsuite/c-c++-common/tsan/free_race.c new file mode 100644 index 000..362c92b --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/free_race.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include + +void __attribute__((noinline)) foo(int *mem) { + free(mem); +} + +void __attribute__((noinline)) bar(int *mem) { + mem[0] = 42; +} + +int main() { + int *mem =(int*)malloc (100); + foo(mem); + bar(mem); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " Write of size 4 at.* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 bar.*(\n|\r\n|\r)" } */ +/* { dg-output "#1 main.*(\n|\r\n|\r)" } */ +/* { dg-output " Previous write of size 8 at.* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 free.*(\n|\r\n|\r)" } */ +/* { dg-output "#\(1|2\) foo.*(\n|\r\n|\r)" } */ +/* { dg-output "#\(2|3\) main.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/mutexset1.c b/gcc/testsuite/c-c++-common/tsan/mutexset1.c new file mode 100644 index 000..783f262 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/mutexset1.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include + +int Global; +pthread_mutex_t mtx; + +void *Thread1(void *x) { + sleep(1); + pthread_mut
Re: RFC ThreadSanitizer tests
> 2013-12-05 Max Ostapenko < m.ostape...@partner.samsung.com > > 2013-12-05 Max Ostapenko actually. Ok, I'm sorry, I'll fix it. Ok to commit? -Maxim 2013-12-05 Max Ostapenko * c-c++-common/tsan/atomic_stack.c: New test. * c-c++-common/tsan/fd_pipe_race.c: New test. * c-c++-common/tsan/free_race.c: New test. * c-c++-common/tsan/mutexset1.c: New test. * c-c++-common/tsan/race_on_barrier.c: New test. * c-c++-common/tsan/sleep_sync.c: New test. * c-c++-common/tsan/thread_leak.c: New test. * c-c++-common/tsan/thread_leak1.c: New test. * c-c++-common/tsan/thread_leak2.c: New test. * c-c++-common/tsan/tiny_race.c: New test. * c-c++-common/tsan/tls_race.c: New test. * c-c++-common/tsan/write_in_reader_lock.c: New test. * lib/tsan-dg.exp: New file. * gcc.dg/tsan/tsan.exp: New file. * g++.dg/tsan/tsan.exp: New file. * g++.dg/dg.exp: Prune tsan subdirectory. diff --git a/gcc/testsuite/c-c++-common/tsan/atomic_stack.c b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c new file mode 100644 index 000..eac71b8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/atomic_stack.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include + +int Global; + +void *Thread1(void *x) { + sleep(1); + __atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED); + return NULL; +} + +void *Thread2(void *x) { + Global++; + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ +/* { dg-output " Atomic write of size 4.*" } */ +/* { dg-output "#0 __tsan_atomic32_fetch_add.*" } */ +/* { dg-output "#1 Thread1.*" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c b/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c new file mode 100644 index 000..fc76cbf --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include + +int fds[2]; + +void *Thread1(void *x) { + write(fds[1], "a", 1); + return NULL; +} + +void *Thread2(void *x) { + sleep(1); + close(fds[0]); + close(fds[1]); + return NULL; +} + +int main() { + pipe(fds); + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*\n" } */ +/* { dg-output " Write of size 8.*\n" } */ +/* { dg-output "#0 close.*\n" } */ +/* { dg-output "#1 Thread2.*\n" } */ +/* { dg-output " Previous read of size 8.*\n" } */ +/* { dg-output "#0 write.*\n" } */ +/* { dg-output "#1 Thread1.*\n" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/free_race.c b/gcc/testsuite/c-c++-common/tsan/free_race.c new file mode 100644 index 000..362c92b --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/free_race.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include + +void __attribute__((noinline)) foo(int *mem) { + free(mem); +} + +void __attribute__((noinline)) bar(int *mem) { + mem[0] = 42; +} + +int main() { + int *mem =(int*)malloc (100); + foo(mem); + bar(mem); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " Write of size 4 at.* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 bar.*(\n|\r\n|\r)" } */ +/* { dg-output "#1 main.*(\n|\r\n|\r)" } */ +/* { dg-output " Previous write of size 8 at.* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 free.*(\n|\r\n|\r)" } */ +/* { dg-output "#\(1|2\) foo.*(\n|\r\n|\r)" } */ +/* { dg-output "#\(2|3\) main.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/mutexset1.c b/gcc/testsuite/c-c++-common/tsan/mutexset1.c new file mode 100644 index 000..783f262 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/mutexset1.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include + +int Global; +pthread_mutex_t mtx; + +void *Thread1(void *x) { + sleep(1); + pthread_mutex_lock(&mtx); + Global++; + pthread_mutex_unlock(&mtx); + return NULL; +} + +void *Thread2(void *x) { + Global--; + return NULL;/* { dg-output ".*" } */ + +} + +int main() { + pthread_mutex_init(&mtx, 0); + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + pthread_mutex_destroy(&mtx); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ +/* { dg-output " Read of size 4 at 0x\[0-9a-f\]+ by thread T1 \\(mutexes: write M\[0-9\]\\):.*"
Fix tsan tests.
Hello, From http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59410#c1 issue: > BTW, the tsan.exp tests don't seem to be as cheap as was claimed during the patch > submission, I'd prefer to at least throttle the > torture options down to say -O0 > and -O2 rather than so many different variants when the tests are really small and > optimizations don't really affect them that much if at all. I've fixed tsan tests to be executed only with '-O0' and '-O2' options. The number of tests executed is decreased from 272 to 68. Ok to commit? -Maxim diff --git a/gcc/testsuite/c-c++-common/tsan/thread_leak2.c b/gcc/testsuite/c-c++-common/tsan/thread_leak2.c index 12ac734..d6f4e22 100644 --- a/gcc/testsuite/c-c++-common/tsan/thread_leak2.c +++ b/gcc/testsuite/c-c++-common/tsan/thread_leak2.c @@ -1,6 +1,5 @@ /* { dg-do run } */ /* { dg-shouldfail "tsan" } */ -/* { dg-skip-if "" { *-*-* } { "-O3 -funroll-loops" "-O3 -funroll-all-loops" } { "" } } */ #include #include diff --git a/gcc/testsuite/g++.dg/tsan/tsan.exp b/gcc/testsuite/g++.dg/tsan/tsan.exp index 164a92e..68b1d83 100644 --- a/gcc/testsuite/g++.dg/tsan/tsan.exp +++ b/gcc/testsuite/g++.dg/tsan/tsan.exp @@ -21,6 +21,7 @@ # Load support procs. load_lib g++-dg.exp load_lib tsan-dg.exp +load_lib torture-options.exp if ![check_effective_target_fthread_sanitizer] { return @@ -28,6 +29,11 @@ if ![check_effective_target_fthread_sanitizer] { # Initialize `dg'. dg-init +torture-init +set-torture-options [list \ + { -O0 } \ + { -O2 } ] + if [tsan_init] { # Main loop. diff --git a/gcc/testsuite/gcc.dg/tsan/tsan.exp b/gcc/testsuite/gcc.dg/tsan/tsan.exp index 248cfb1..a4a5b72 100644 --- a/gcc/testsuite/gcc.dg/tsan/tsan.exp +++ b/gcc/testsuite/gcc.dg/tsan/tsan.exp @@ -21,6 +21,7 @@ # Load support procs. load_lib gcc-dg.exp load_lib tsan-dg.exp +load_lib torture-options.exp if ![check_effective_target_fthread_sanitizer] { return @@ -28,6 +29,11 @@ if ![check_effective_target_fthread_sanitizer] { # Initialize `dg'. dg-init +torture-init +set-torture-options [list \ + { -O0 } \ + { -O2 } ] + if [tsan_init] { # Main loop. 2013-12-10 Max Ostapenko * c-c++-common/tsan/thread_leak2.c: `dg-skip-if' removed. * gcc-dg/tsan/tsan.exp: Run only with '-O0' and '-O2' options. * g++-dg/tsan/tsan.exp: Run only with '-O0' and '-O2' options.
New tsan tests.
Hi all, I've added new tests for tsan from LLVM. Tested on x86_64. Ok to commit? -Maxim diff --git a/gcc/testsuite/c-c++-common/tsan/free_race2.c b/gcc/testsuite/c-c++-common/tsan/free_race2.c new file mode 100644 index 000..3c15d2d --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/free_race2.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include + +void __attribute__((noinline)) foo(int *mem) { + free(mem); +} + +void __attribute__((noinline)) bar(int *mem) { + mem[0] = 42; +} + +int main() { + int *mem = (int*)malloc(100); + foo(mem); + bar(mem); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } */ +/* { dg-output " Write of size 4.* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 bar.*" } */ +/* { dg-output "#1 main .*" } */ +/* { dg-output " Previous write of size 8 at .* by main thread:(\n|\r\n|\r)" } */ +/* { dg-output "#0 free .*" } */ +/* { dg-output "#\(1|2\) foo.*(\n|\r\n|\r)" } */ +/* { dg-output "#\(2|3\) main .*" } */ + diff --git a/gcc/testsuite/c-c++-common/tsan/race_on_barrier2.c b/gcc/testsuite/c-c++-common/tsan/race_on_barrier2.c new file mode 100644 index 000..9576c67 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/race_on_barrier2.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include +#include + +pthread_barrier_t B; +int Global; + +void *Thread1(void *x) { + if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD) +pthread_barrier_destroy(&B); + return NULL; +} + +void *Thread2(void *x) { + if (pthread_barrier_wait(&B) == PTHREAD_BARRIER_SERIAL_THREAD) +pthread_barrier_destroy(&B); + return NULL; +} + +int main() { + pthread_barrier_init(&B, 0, 2); + pthread_t t; + pthread_create(&t, NULL, Thread1, NULL); + Thread2(0); + pthread_join(t, NULL); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c b/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c new file mode 100644 index 000..f112d09 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include +#include + +pthread_mutex_t Mtx; +int Global; + +void *Thread1(void *x) { + pthread_mutex_init(&Mtx, 0); + pthread_mutex_lock(&Mtx); + Global = 42; + pthread_mutex_unlock(&Mtx); + return NULL; +} + +void *Thread2(void *x) { + sleep(1); + pthread_mutex_lock(&Mtx); + Global = 43; + pthread_mutex_unlock(&Mtx); + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + pthread_mutex_destroy(&Mtx); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ +/* { dg-output " Atomic read of size 1 at .* by thread T2:(\n|\r\n|\r)" } */ +/* { dg-output "#0 pthread_mutex_lock.*" } */ +/* { dg-output "#1 Thread2.* .*(race_on_mutex.c:22|\\?{2}:0) (.*)" } */ +/* { dg-output " Previous write of size 1 at .* by thread T1:(\n|\r\n|\r)" } */ +/* { dg-output "#0 pthread_mutex_init .* (.)*" } */ +/* { dg-output "#1 Thread1.* .*(race_on_mutex.c:13|\\?{2}:0) .*" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c b/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c new file mode 100644 index 000..d8a6980 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include +#include +#include + +void *Thread(void *x) { + pthread_mutex_lock((pthread_mutex_t*)x); + pthread_mutex_unlock((pthread_mutex_t*)x); + return 0; +} + +int main() { + pthread_mutex_t Mtx; + pthread_mutex_init(&Mtx, 0); + pthread_t t; + pthread_create(&t, 0, Thread, &Mtx); + sleep(1); + pthread_mutex_destroy(&Mtx); + pthread_join(t, 0); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/simple_race.c b/gcc/testsuite/c-c++-common/tsan/simple_race.c new file mode 100644 index 000..24b88e8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tsan/simple_race.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-shouldfail "tsan" } */ + +#include +#include + +int Global; + +void *Thread1(void *x) { + Global = 42; + return NULL; +} + +void *Thread2(void *x) { + Global = 43; + return NULL; +} + +int main() { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, NULL); + pthread_create(&t[1], NULL, Thread2, NULL); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); + return 0; +} + +/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/tsan/simple_stack.c b/gcc/testsuite/c-c++-common/tsan/simple_stack.c new file
Re: New tsan tests.
> Anyway, let's keep the current tests as is, the patch is ok for trunk. Commited in 205925.
Re: RFC Asan instrumentation control
Hi all, On 12/06/2013 05:32 PM, Yury Gribov wrote: So it looks like people are generally ok with * --param asan-instrument-reads=0/1 * --param asan-instrument-writes=0/1 * --param asan-stack=0/1 * --param asan-globals=0/1 I've implemented these options. Tested on x86_64. * --param asan-memintrin=0/1 but not with blacklists (which is sad but understandable). -Y This one will be implemented in future. I've also added 4 new testfiles to test new options. Can you review this patch, please? -Maxim 2013-12-18 Max Ostapenko * gcc/asan.c (asan_emit_stack_protection): Optionally disable stack protection. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_mem_region_access): Likewise. (instrument_strlen_call): Likewise. (asan_finish_file): Optionally disable global variables protection. * gcc/doc/invoke.texi: Added doc for new options. * gcc/params.def: Added new options. * gcc/params.h: Likewise. 2013-12-18 Max Ostapenko * c-c++-common/asan/global-overflow-2.c: New test. * c-c++-common/asan/memcmp-3.c: Likewise. * c-c++-common/asan/no-instrument-reads.c: Likewise. * c-c++-common/asan/no-instrument-writes.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index 1394e13..1b8d0c2 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h" #include "predict.h" +#include "params.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -963,6 +964,9 @@ rtx asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, HOST_WIDE_INT *offsets, tree *decls, int length) { + if (!ASAN_STACK) +return NULL_RTX; + rtx shadow_base, shadow_mem, ret, mem, orig_base, lab; char buf[30]; unsigned char shadow_bytes[4]; @@ -1568,6 +1572,11 @@ static void instrument_derefs (gimple_stmt_iterator *iter, tree t, location_t location, bool is_store) { + if (is_store && !ASAN_INSTRUMENT_WRITES) +return; + if (!is_store && !ASAN_INSTRUMENT_READS) +return; + tree type, base; HOST_WIDE_INT size_in_bytes; @@ -1662,6 +1671,11 @@ instrument_mem_region_access (tree base, tree len, gimple_stmt_iterator *iter, location_t location, bool is_store) { + if (is_store && !ASAN_INSTRUMENT_WRITES) +return; + if (!is_store && !ASAN_INSTRUMENT_READS) +return; + if (!POINTER_TYPE_P (TREE_TYPE (base)) || !INTEGRAL_TYPE_P (TREE_TYPE (len)) || integer_zerop (len)) @@ -1825,6 +1839,9 @@ instrument_mem_region_access (tree base, tree len, static bool instrument_strlen_call (gimple_stmt_iterator *iter) { + if (!ASAN_INSTRUMENT_READS) +return false; + gimple call = gsi_stmt (*iter); gcc_assert (is_gimple_call (call)); @@ -2396,7 +2413,7 @@ asan_finish_file (void) ++gcount; htab_t const_desc_htab = constant_pool_htab (); htab_traverse (const_desc_htab, count_string_csts, &gcount); - if (gcount) + if (gcount && ASAN_GLOBALS) { tree type = asan_global_struct (), var, ctor; tree dtor_statements = NULL_TREE; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 99ec1d2..d1f20a9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10037,6 +10037,26 @@ The default choice depends on the target. Set the maximum number of existing candidates that will be considered when seeking a basis for a new straight-line strength reduction candidate. +@item asan-globals +Enable overflow/underflow detection for global objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable global objects protection use @option{--param asan-globals=0} option. + +@item asan-stack +Enable overflow/underflow detection for stack objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable stack protection use @option{--param asan-stack=0} option. + +@item asan-instrument-reads +Enable overflow/underflow detection for memory reads instructions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable memory reads instructions protection use @option{--param asan-instrument-reads=0} option. + +@item asan-instrument-writes +Enable overflow/underflow detection for memory writes instructions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable memory writes instructions protection use @option{--param asan-instrument-writes=0} option. + @end table @end table diff --git a/gcc/params.def b/gcc/params.def index c0f9622..aea5f41 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1049,6 +1049,26 @@ DEFPARAM (PARAM_MAX_SLSR_CANDIDATE_SCAN, "strength reduction", 50, 1, 99) +DEFPARAM(PARAM_ASAN_STACK, + "asan-stack", + "Enable asan stack protection", + 1, 0, 1) + +DEFP
Re: RFC Asan instrumentation control
2013-12-18 Max Ostapenko * gcc/asan.c (asan_emit_stack_protection): Optionally disable stack protection. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_mem_region_access): Likewise. (instrument_strlen_call): Likewise. (asan_finish_file): Optionally disable global variables protection. * gcc/doc/invoke.texi: Added doc for new options. * gcc/params.def: Added new options. * gcc/params.h: Likewise. > No gcc/ prefixes in ChangeLog entries. Thanks, fixed. --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h" #include "predict.h" +#include "params.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -963,6 +964,9 @@ rtx asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, HOST_WIDE_INT *offsets, tree *decls, int length) { + if (!ASAN_STACK) +return NULL_RTX; > This is a wrong spot to do this. Instead put it into the > if ((flag_sanitize & SANITIZE_ADDRESS) && pred) > condition in cfgexpand.c (and maybe also > if ((flag_sanitize & SANITIZE_ADDRESS) && isize != jsize ...) > too, maybe all four flag_sanitize & SANITIZE_ADDRESS occurrences in > cfgexpand.c. Moved this check to cfgexpand.c. @@ -2396,7 +2413,7 @@ asan_finish_file (void) ++gcount; htab_t const_desc_htab = constant_pool_htab (); htab_traverse (const_desc_htab, count_string_csts, &gcount); - if (gcount) + if (gcount && ASAN_GLOBALS) { tree type = asan_global_struct (), var, ctor; tree dtor_statements = NULL_TREE; > I'd say this isn't sufficient, for !ASAN_GLOBALS you should also make sure > asan_protect_global always returns false, so that no extra padding is emitted > around the global vars. Moved globals protection check to asan_protect_global. > Talking about this, perhaps there should be also > --param asan-use-after-return=0 > knob to disallow the support for use-after-return checking (in 4.8 this > didn't exist, in 4.9 there is some extra runtime code emitted, but still one > needs to enable it manually through environment variable). With that param > we would emit pretty much what 4.8 did, i.e. assume that use-after-return > will not be enabled in the runtime. Added this option and also implemented asan-memintrin option. Is it OK? -Maxim
Re: RFC Asan instrumentation control
Sorry, ChangeLog and patch, of course. -Maxim. 2013-12-19 Max Ostapenko * cfgexpand.c (expand_stack_vars): Optionally disable asan stack protection. (expand_used_vars): Likewise. (partition_stack_vars): Likewise. * asan.c (asan_emit_stack_protection): Optionally disable after return stack usage. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_builtin_call): Likewise. (instrument_strlen_call): Likewise. (asan_protect_global): Optionally disable global variables protection. * doc/invoke.texi: Added doc for new options. * params.def: Added new options. * params.h: Likewise. 2013-12-19 Max Ostapenko * c-c++-common/asan/global-overflow-2.c: New test. * c-c++-common/asan/memcmp-3.c: Likewise. * c-c++-common/asan/no-instrument-reads.c: Likewise. * c-c++-common/asan/no-instrument-writes.c: Likewise. * c-c++-common/asan/stack-use-after-return.c: Likewise * c-c++-common/asan/no-stack-use-after-return.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index 1394e13..005db18 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h" #include "predict.h" +#include "params.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -1003,7 +1004,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ - if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase) + if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase && ASAN_USE_AFTER_RETURN) { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment @@ -1239,6 +1240,9 @@ asan_needs_local_alias (tree decl) bool asan_protect_global (tree decl) { + if (!ASAN_GLOBALS) +return false; + rtx rtl, symbol; if (TREE_CODE (decl) == STRING_CST) @@ -1568,6 +1572,11 @@ static void instrument_derefs (gimple_stmt_iterator *iter, tree t, location_t location, bool is_store) { + if (is_store && !ASAN_INSTRUMENT_WRITES) +return; + if (!is_store && !ASAN_INSTRUMENT_READS) +return; + tree type, base; HOST_WIDE_INT size_in_bytes; @@ -1897,6 +1906,9 @@ instrument_strlen_call (gimple_stmt_iterator *iter) static bool instrument_builtin_call (gimple_stmt_iterator *iter) { + if (!ASAN_MEMINTRIN) +return false; + bool iter_advanced_p = false; gimple call = gsi_stmt (*iter); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 7a93975..55708eb 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -798,7 +798,7 @@ partition_stack_vars (void) sizes, as the shorter vars wouldn't be adequately protected. Don't do that for "large" (unsupported) alignment objects, those aren't protected anyway. */ - if ((flag_sanitize & SANITIZE_ADDRESS) && isize != jsize + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && isize != jsize && ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) break; @@ -981,7 +981,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { base = virtual_stack_vars_rtx; - if ((flag_sanitize & SANITIZE_ADDRESS) && pred) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred) { HOST_WIDE_INT prev_offset = frame_offset; tree repr_decl = NULL_TREE; @@ -1160,7 +1160,7 @@ defer_stack_allocation (tree var, bool toplevel) /* If stack protection is enabled, *all* stack variables must be deferred, so that we can re-order the strings to the top of the frame. Similarly for Address Sanitizer. */ - if (flag_stack_protect || (flag_sanitize & SANITIZE_ADDRESS)) + if (flag_stack_protect || ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK)) return true; /* We handle "large" alignment via dynamic allocation. We want to handle @@ -1820,7 +1820,7 @@ expand_used_vars (void) expand_stack_vars (stack_protect_decl_phase_2, &data); } - if (flag_sanitize & SANITIZE_ADDRESS) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK) /* Phase 3, any partitions that need asan protection in addition to phase 1 and 2. */ expand_stack_vars (asan_decl_phase_3, &data); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1a6d815..f25958b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10037,6 +10037,36 @@ The default choice depends on the target. Set the maximum number of existing candidates that will be considered when seeking a basis for a new straight-line strength reduction candidate. +@item asan-globals +Enable buffer overflow detection for global objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable global objects protection use @option{--param asan-
Re: RFC Asan instrumentation control
On 12/19/2013 04:27 PM, Jakub Jelinek wrote: On Thu, Dec 19, 2013 at 04:02:47PM +0400, Maxim Ostapenko wrote: Sorry, ChangeLog and patch, of course. 2013-12-19 Max Ostapenko * cfgexpand.c (expand_stack_vars): Optionally disable asan stack protection. Too long lines in ChangeLog, wrap to 80 columns. Thanks, fixed. (expand_used_vars): Likewise. (partition_stack_vars): Likewise. * asan.c (asan_emit_stack_protection): Optionally disable after return stack usage. Ditto. Likewise. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_builtin_call): Likewise. (instrument_strlen_call): Likewise. (asan_protect_global): Optionally disable global variables protection. * doc/invoke.texi: Added doc for new options. * params.def: Added new options. * params.h: Likewise. 2013-12-19 Max Ostapenko * c-c++-common/asan/global-overflow-2.c: New test. Missing vertical space between date/name/mail and first entry. Done. @@ -1003,7 +1004,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ - if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase) + if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase && ASAN_USE_AFTER_RETURN) { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment Please wrap this. Done. --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -798,7 +798,7 @@ partition_stack_vars (void) sizes, as the shorter vars wouldn't be adequately protected. Don't do that for "large" (unsupported) alignment objects, those aren't protected anyway. */ - if ((flag_sanitize & SANITIZE_ADDRESS) && isize != jsize + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && isize != jsize Replace the two spaces with just one. Done. --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10037,6 +10037,36 @@ The default choice depends on the target. Set the maximum number of existing candidates that will be considered when seeking a basis for a new straight-line strength reduction candidate. +@item asan-globals +Enable buffer overflow detection for global objects. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable global objects protection use @option{--param asan-globals=0} option. Too long lines (several times). Done. +To disable memory reads instructions protection use @option{--param asan-instrument-reads=0} option. + +@item asan-instrument-writes +Enable buffer overflow detection for memory writes instructions. This kind of protection +is enabled by default if you are using @option{-fsanitize=address} option. +To disable memory writes instructions protection use @option{--param asan-instrument-writes=0} option. + +@item asan-memintrin +Enable detection for builtin functions. This kind of protection I think for docs it should be "built-in functions". Done. As for the tests, I'm afraid I don't like them at all. If anything, it ought to be dg-do compile tests where you say scan assembly or some dump, but having runtime testcases that trigger undefined behavior that isn't detected by the instrumentation library at all and expect them to "pass" is simply wrong. Jakub Got it, converted all tests except no-asan-stack.c, because i failed to discover how to grep for stack instrumentation. Perhaps memcmp of random data is fine? 2013-12-24 Max Ostapenko * cfgexpand.c (expand_stack_vars): Optionally disable asan stack protection. (expand_used_vars): Likewise. (partition_stack_vars): Likewise. * asan.c (asan_emit_stack_protection): Optionally disable after return stack usage. (instrument_derefs): Optionally disable memory access instrumentation. (instrument_builtin_call): Likewise. (instrument_strlen_call): Likewise. (asan_protect_global): Optionally disable global variables protection. * doc/invoke.texi: Added doc for new options. * params.def: Added new options. * params.h: Likewise. 2013-12-24 Max Ostapenko * c-c++-common/asan/no-asan-globals.c: New test. * c-c++-common/asan/no-asan-stack.c: Likewise. * c-c++-common/asan/no-instrument-reads.c: Likewise. * c-c++-common/asan/no-instrument-writes.c: Likewise. * c-c++-common/asan/use-after-return-1.c: Likewise. * c-c++-common/asan/no-use-after-return.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index d4059d6..1d9d8ae 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h&
Re: RFC Asan instrumentation control
Hi! >> * c-c++-common/asan/no-asan-stack.c (this triggers read overflow >> because we haven't found a cross-platform way to grep for stack >> redzones instrumentation) > I'd prefer no test in that case, or just some semi-platform specific test > (scan that the 0x41b58ab3 constant doesn't appear in say some late RTL dump, > or perhaps just assembly (just scan it with lower and upper case and decimal > too)). Thanks, commited in 206458 without c-c++-common/asan/no-asan-stack.c testfile. I'll fix this test according to your recommendations a bit later. -Maxim.
Re: RFC Asan instrumentation control
Hi! >>> * c-c++-common/asan/no-asan-stack.c (this triggers read overflow >>> because we haven't found a cross-platform way to grep for stack >>> redzones instrumentation) >> >> I'd prefer no test in that case, or just some semi-platform specific test >> (scan that the 0x41b58ab3 constant doesn't appear in say some late RTL dump, >> or perhaps just assembly (just scan it with lower and upper case and decimal >> too)). > > Thanks, commited in 206458 without c-c++-common/asan/no-asan-stack.c testfile. > I'll fix this test according to your recommendations a bit later. I've fixed the c-c++-common/asan/no-asan-stack.c testfile. Tested on x86_64-unknown-linux-gnu. Ok to commit? -Maxim. 2014-01-10 Max Ostapenko * c-c++-common/asan/no-asan-stack.c: New test. diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-stack.c b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c new file mode 100644 index 000..d81b834 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c @@ -0,0 +1,17 @@ +/* { dg-do assemble { target { x86_64-unknown-linux-gnu } } } */ +/* { dg-options "-save-temps --param asan-stack=0" } */ +#include + +volatile int one = 1; + +int +main () +{ + volatile char a1[] = {one, 2, 3, 4}; + volatile char a2[] = {1, 2*one, 3, 4}; + volatile int res = memcmp ((void *)a1,(void *)a2, 5 + one); + return 0; +} + +/* { dg-final { scan-assembler-not "0x41b58ab3|0x41B58AB3|1102416563" } } */ +/* { dg-final { cleanup-saved-temps } } */
Re: RFC Asan instrumentation control
If you want to limit to x86_64-linux only, please do: target { { i?86-*-linux* x86_64-*-linux* } && lp64 } instead. Also, what advantages do you see for trying to assemble the result? If you instead just do dg-do compile, you can drop -save-temps from dg-options and /* { dg-final { cleanup-saved-temps } } */. Thanks, got it. Is it OK now? -Maxim. 2014-01-10 Max Ostapenko * c-c++-common/asan/no-asan-stack.c: New test. diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-stack.c b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c new file mode 100644 index 000..0f65ab3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */ +/* { dg-options "--param asan-stack=0" } */ +#include + +volatile int one = 1; + +int +main () +{ + volatile char a1[] = {one, 2, 3, 4}; + volatile char a2[] = {1, 2*one, 3, 4}; + volatile int res = memcmp ((void *)a1,(void *)a2, 5 + one); + return 0; +} + +/* { dg-final { scan-assembler-not "0x41b58ab3|0x41B58AB3|1102416563" } } */
Re: RFC Asan instrumentation control
On 01/10/2014 12:36 PM, Jakub Jelinek wrote: On Fri, Jan 10, 2014 at 12:34:49PM +0400, Maxim Ostapenko wrote: Thanks, got it. Is it OK now? Yes, thanks. 2014-01-10 Max Ostapenko * c-c++-common/asan/no-asan-stack.c: New test. Jakub Commited in 206515. -Maxim.
Re: libsanitizer merge from upstream r196090
Hi all, On Fri, Jan 10, 2014 at 10:39 AM, Jakub Jelinek wrote: > Some of the tsan tests seems to FAIL randomly for quite a while > (since they were added), didn't have time to look if it is just bugs in the test or > some compiler issue or library issue. When I've commited these tsan tests, all of them were passed on my x86_64-unknown-linux-gnu 64bit system. Should I review them more carefully? -Maxim.
[RFC, PATCH] Disable -fprofile-use related optimizations if corresponding .gcda file not found.
Hi, when testing OpenSSL performance, I found out that sometimes PGO-built binaries can actually introduce performance regressions. We could identify affected object files and disable PGO for them by simply removing corresponding .gcda file. However, even if profile data is not presented, GCC doesn't switch back -fprofile-use dependent optimizations (e.g. -fbranch-probabilities, -fvpt, etc). This may also lead to performance degradations. The issue had already raised quite time ago (https://gcc.gnu.org/ml/gcc-patches/2009-09/msg02119.html), but for some reasons wasn't discussed. Here a draft patch that disables -fprofile-use related optimizations if profile data wasn't found (perhaps it makes sense to introduce a special switch for this?). Does this look reasonable? Thanks, -Maxim gcc/ChangeLog: 2015-10-07 Maxim Ostapenko * coverage.c (disable_profile_use_flags): New function. (read_counts_file): Call it if corresponding .gcda file wasn't found. diff --git a/gcc/coverage.c b/gcc/coverage.c index 4c06fa4..37e16b7 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -134,6 +134,7 @@ static bool coverage_obj_init (void); static vec *coverage_obj_fn (vec *, tree, struct coverage_data const *); static void coverage_obj_finish (vec *); +static void disable_profile_use_flags (void); /* Return the type node for gcov_type. */ @@ -190,7 +191,10 @@ read_counts_file (void) unsigned cfg_checksum = 0; if (!gcov_open (da_file_name, 1)) -return; +{ + disable_profile_use_flags (); + return; +} if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC)) { @@ -1219,4 +1223,14 @@ coverage_finish (void) da_file_name = NULL; } +/* Reset flags if a .gcda file is not found. */ +static void +disable_profile_use_flags (void) +{ + flag_branch_probabilities = flag_profile_values = flag_unroll_loops = false; + flag_value_profile_transformations + = flag_tree_loop_distribute_patterns = false; + flag_rename_registers = flag_peel_loops = false; + flag_profile_reorder_functions = flag_tracer = false; +} + #include "gt-coverage.h"
Re: [RFC, PATCH] Disable -fprofile-use related optimizations if corresponding .gcda file not found.
On 07/10/15 19:18, Andrew Pinski wrote: On Wed, Oct 7, 2015 at 9:11 AM, Maxim Ostapenko wrote: Hi, when testing OpenSSL performance, I found out that sometimes PGO-built binaries can actually introduce performance regressions. We could identify affected object files and disable PGO for them by simply removing corresponding .gcda file. However, even if profile data is not presented, GCC doesn't switch back -fprofile-use dependent optimizations (e.g. -fbranch-probabilities, -fvpt, etc). This may also lead to performance degradations. The issue had already raised quite time ago (https://gcc.gnu.org/ml/gcc-patches/2009-09/msg02119.html), but for some reasons wasn't discussed. Here a draft patch that disables -fprofile-use related optimizations if profile data wasn't found (perhaps it makes sense to introduce a special switch for this?). Does this look reasonable? I thought if profile is not present, then branch probabilities goes back to the original heuristics? Which option is really causing the performance degradation here? -fprofile-use enabled -fpeel-loops that in turn enabled -frename-registers. This caused the scheduler to transform the code in sched2 pass. Also I think your patch is very incomplete as someone could use -frename-registers with -fprofile-use and then you just turned it off. Thanks, Andrew Pinski Doesn't -fprofile-use enable -frename-registers transitively through -fpeel-loops? Thanks, -Maxim
[PATCH] Fix another bootstrap-ubsan failure due to -Werror=maybe-uninitialized.
Hi, running UBSan bootstrap on trunk, I've run to the such issue: /home/max/workspace/downloads/svn/trunk/gcc/fortran/parse.c: In function ‘gfc_statement decode_statement()’: /home/max/workspace/downloads/svn/trunk/gcc/fortran/parse.c:368:51: error: ‘m’ may be used uninitialized in this function [-Werror=maybe-uninitialized] if (!(in_specification_block && m == MATCH_ERROR)) Actually, the situation is pretty much similar to PR sanitizer/67867 fixed by Marek in r228569. This tiny patch just initializes m with MATCH_NO value. By fixing this, UBSan bootstrap can proceed, although I see some errors detected (will report them later). Is this OK for trunk? -Maxim gcc/fortran/ChangeLog: 2015-10-08 Maxim Ostapenko * parse.c (decode_statement): Initialize M to MATCH_NO. diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 6f3d24b..4925c7e 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -296,7 +296,7 @@ decode_statement (void) gfc_namespace *ns; gfc_statement st; locus old_locus; - match m; + match m = MATCH_NO; char c; gfc_enforce_clean_symbol_state ();
[PATCH 0/7] Libsanitizer merge from upstream r249633.
Hi, it's been a while since the last libsanitizer merge from upstream into GCC happened and the library has significantly changed since that time. The main features to be ported are: -New common strings interceptors were added. -Various allocator improvements were performed. -Improvements for ASan deactivated start were performed. -TSan and LSan were enabled for Aarch64. -Fast unwinding was enabled for Aarch64. -New tsan_unaligned_{load, store}_[n] functions were intoduced. -asan_stack_malloc_[n] doesn't take a local stack as a second parameter anymore. -sanitization for std containers is supported now. -New interface functions for dynamic allocas and VLA's poisoning/unpoisoning were introduced. Some features are not ported for now, by might be enabled in future: -Embedded UBSan runtime into ASan and TSan ones. I don't enable this now, because of errors during ASan static linkage: GCC uses -whole-archive option that would lead to undefined references to C++ stuff. -UBSan data descriptors for float-cast conversion support location propagation now. But sometimes we have loc == UNKNOWN_LOCATION in ubsan_instrument_float_cast, so use old ABI for now. See below for details. The first patch of the series is the merge itself. The second one introduces corresponding compiler changes. Other patches are applied to library and they are GCC-specific: Patches 3 and 4 are just reapplied David's and Jakub's patches for SPARC and disabling ODR violation detection respectively. Patch 5 removes UBSan stubs from ASan and TSan code since we don't support embedded UBSan runtime into ASan and TSan. Patch 6 changes heuristic for extracting last PC from stack frame for ARM in fast unwind routine. More details can be found here (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771). Patch 7 forces libsanitizer to use an old ABI for ubsan float cast data descriptors, because sometimes we can have loc == UNKNOWN_LOCATION in ubsan_instrument_float_cast e.g. in a such case: .. volatile double foo; // ubsan_instrument_float_cast is called by convert function. .. Since foo is a tcc_declaration, loc is UNKNOWN_LOCATION. I'm actually not sure about this, perhaps we can fix this in GCC somehow. I've regtested and {A, UB}San bootstrapped these patches on x86-64-unknown-linux-gnu and aarch64-linux-gnueabi (Juno board, 39 bit VA space) and tested for ARM under QEMU-ARM. Testing ASan under QEMU-AARCH64 revealed many test failures due to LSan was enabled. In particular, it tries to call internal_clone function in LSan internals, that in turn calls _NR_clone syscall and than QEMU exits with EINTR error code (that might be expected, AFAIK QEMU is not very good with threads). So, I wonder, if I should disable LSan for AArch64 now? I'm also asking community to help me with testing these patches on various targets (ARM, PPC, etc) I'm lack of, so could you help me on this please? -Maxim
[PATCH 2/7] Libsanitizer merge from upstream r249633.
This patch introduces required compiler changes. Now, we don't version asan_init, we have a special __asan_version_mismatch_check_v[n] symbol for this. Also, asan_stack_malloc_[n] doesn't take a local stack as a second parameter anymore, so don't pass it. 2015-10-12 Maxim Ostapenko config/ * bootstrap-asan.mk: Replace ASAN_OPTIONS=detect_leaks with LSAN_OPTIONS=detect_leaks gcc/ * asan.c (asan_emit_stack_protection): Don't pass local stack to asan_stack_malloc_[n] anymore. (asan_finish_file): Instert __asan_version_mismatch_check_v[n] call. * sanitizer.def (BUILT_IN_ASAN_INIT): Rename to __asan_init. (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK): Add new builtin call. gcc/testsuite/ g++.dg/asan/default-options-1.C: Adjust testcase. Index: gcc/asan.c === --- gcc/asan.c (revision 228704) +++ gcc/asan.c (working copy) @@ -1132,12 +1132,10 @@ snprintf (buf, sizeof buf, "__asan_stack_malloc_%d", use_after_return_class); ret = init_one_libfunc (buf); - rtx addr = convert_memory_address (ptr_mode, base); - ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, + ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 1, GEN_INT (asan_frame_size + base_align_bias), - TYPE_MODE (pointer_sized_int_node), - addr, ptr_mode); + TYPE_MODE (pointer_sized_int_node)); ret = convert_memory_address (Pmode, ret); emit_move_insn (base, ret); emit_label (lab); @@ -2470,6 +2468,8 @@ { tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); + fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK); + append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); } FOR_EACH_DEFINED_VARIABLE (vnode) if (TREE_ASM_WRITTEN (vnode->decl) Index: gcc/sanitizer.def === --- gcc/sanitizer.def (revision 228704) +++ gcc/sanitizer.def (working copy) @@ -27,8 +27,11 @@ for other FEs by asan.c. */ /* Address Sanitizer */ -DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v4", +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_VERSION_MISMATCH_CHECK, + "__asan_version_mismatch_check_v6", + BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) /* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.c relies on this order. */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", Index: gcc/testsuite/g++.dg/asan/default-options-1.C === --- gcc/testsuite/g++.dg/asan/default-options-1.C (revision 228704) +++ gcc/testsuite/g++.dg/asan/default-options-1.C (working copy) @@ -12,4 +12,4 @@ return 0; } -// { dg-output "Using the defaults from __asan_default_options:.* foo=bar.*(\n|\r\n|\r)" } +// { dg-output "WARNING: found 1 unrecognized flag\\(s\\):(\n|\r\n|\r).*foo(\n|\r\n|\r)" }
[PATCH 3/7] Libsanitizer merge from upstream r249633.
This is just reapplied patch for SPARC by David S. Miller. I was unable to test this, so could anyone help me here? 2015-10-12 Maxim Ostapenko PR sanitizer/63958 Reapply: 2015-03-09 Jakub Jelinek PR sanitizer/63958 Reapply: 2014-10-14 David S. Miller * sanitizer_common/sanitizer_platform_limits_linux.cc (time_t): Define at __kernel_time_t, as needed for sparc. (struct __old_kernel_stat): Don't check if __sparc__ is defined. * libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (__sanitizer): Define struct___old_kernel_stat_sz, struct_kernel_stat_sz, and struct_kernel_stat64_sz for sparc. (__sanitizer_ipc_perm): Adjust for sparc targets. (__sanitizer_shmid_ds): Likewsie. (__sanitizer_sigaction): Likewise. (IOC_SIZE): Likewsie. Index: libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc === --- libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc (working copy) @@ -38,6 +38,7 @@ #define uid_t __kernel_uid_t #define gid_t __kernel_gid_t #define off_t __kernel_off_t +#define time_t __kernel_time_t // This header seems to contain the definitions of _kernel_ stat* structs. #include #undef ino_t @@ -62,7 +63,7 @@ } // namespace __sanitizer #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\ -&& !defined(__mips__) +&& !defined(__mips__) && !defined(__sparc__) COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); #endif Index: libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h === --- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (working copy) @@ -83,6 +83,14 @@ const unsigned struct_kernel_stat_sz = 144; #endif const unsigned struct_kernel_stat64_sz = 104; +#elif defined(__sparc__) && defined(__arch64__) + const unsigned struct___old_kernel_stat_sz = 0; + const unsigned struct_kernel_stat_sz = 104; + const unsigned struct_kernel_stat64_sz = 144; +#elif defined(__sparc__) && !defined(__arch64__) + const unsigned struct___old_kernel_stat_sz = 0; + const unsigned struct_kernel_stat_sz = 64; + const unsigned struct_kernel_stat64_sz = 104; #endif struct __sanitizer_perf_event_attr { unsigned type; @@ -105,7 +113,7 @@ #if defined(__powerpc64__) const unsigned struct___old_kernel_stat_sz = 0; -#else +#elif !defined(__sparc__) const unsigned struct___old_kernel_stat_sz = 32; #endif @@ -184,6 +192,18 @@ unsigned short __pad1; unsigned long __unused1; unsigned long __unused2; +#elif defined(__sparc__) +# if defined(__arch64__) +unsigned mode; +unsigned short __pad1; +# else +unsigned short __pad1; +unsigned short mode; +unsigned short __pad2; +# endif +unsigned short __seq; +unsigned long long __unused1; +unsigned long long __unused2; #else unsigned short mode; unsigned short __pad1; @@ -201,6 +221,26 @@ struct __sanitizer_shmid_ds { __sanitizer_ipc_perm shm_perm; + #if defined(__sparc__) + # if !defined(__arch64__) +u32 __pad1; + # endif +long shm_atime; + # if !defined(__arch64__) +u32 __pad2; + # endif +long shm_dtime; + # if !defined(__arch64__) +u32 __pad3; + # endif +long shm_ctime; +uptr shm_segsz; +int shm_cpid; +int shm_lpid; +unsigned long shm_nattch; +unsigned long __glibc_reserved1; +unsigned long __glibc_reserved2; + #else #ifndef __powerpc__ uptr shm_segsz; #elif !defined(__powerpc64__) @@ -238,6 +278,7 @@ uptr __unused4; uptr __unused5; #endif +#endif }; #elif SANITIZER_FREEBSD struct __sanitizer_ipc_perm { @@ -555,9 +596,13 @@ #else __sanitizer_sigset_t sa_mask; #ifndef __mips__ +#if defined(__sparc__) +unsigned long sa_flags; +#else int sa_flags; #endif #endif +#endif #if SANITIZER_LINUX void (*sa_restorer)(); #endif @@ -799,7 +844,7 @@ #define IOC_NRBITS 8 #define IOC_TYPEBITS 8 -#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) +#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || defined(__sparc__) #define IOC_SIZEBITS 13 #define IOC_DIRBITS 3 #define IOC_NONE 1U @@ -829,7 +874,17 @@ #define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK) #define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK) #define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK) + +#if defined(__sparc__) +// In sparc the 14 bits SIZE field overlaps with the +// least significant bit of DIR, so either IOC_READ or +// IOC_WRITE shall be 1 in order to ge
[PATCH 4/7] Libsanitizer merge from upstream r249633.
This is a reapplied Jakub's patch for disabling ODR violation detection. More details can be found here (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63888). 2015-10-12 Maxim Ostapenko PR bootstrap/63888 Reapply: 2015-02-20 Jakub Jelinek * asan/asan_globals.cc (RegisterGlobal): Disable detect_odr_violation support until it is rewritten upstream. * c-c++-common/asan/pr63888.c: New test. Index: libsanitizer/asan/asan_globals.cc === --- libsanitizer/asan/asan_globals.cc (revision 250059) +++ libsanitizer/asan/asan_globals.cc (working copy) @@ -146,7 +146,9 @@ CHECK(AddrIsInMem(g->beg)); CHECK(AddrIsAlignedByGranularity(g->beg)); CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); - if (flags()->detect_odr_violation) { + // This "ODR violation" detection is fundamentally incompatible with + // how GCC registers globals. Disable as useless until rewritten upstream. + if (0 && flags()->detect_odr_violation) { // Try detecting ODR (One Definition Rule) violation, i.e. the situation // where two globals with the same name are defined in different modules. if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
[PATCH 5/7] Libsanitizer merge from upstream r249633.
This patch removes UBSan stubs from ASan and TSan code. We don't embed UBSan to ASan and UBSan because that would lead to undefined references to C++ stuff when linking with -static-libasan. AFAIK, sanitizer developers use different libraries for C and CXX runtimes, but I think this is out of scope of this merge. 2015-10-13 Maxim Ostapenko * tsan/tsan_defs.h: Define TSAN_CONTAINS_UBSAN to 0. * asan/asan_flags.cc (InitializeFlags): Do not initialize UBSan flags. * asan/asan_rtl.cc (AsanInitInternal): Do not init UBSan. Index: libsanitizer/asan/asan_flags.cc === --- libsanitizer/asan/asan_flags.cc (revision 250059) +++ libsanitizer/asan/asan_flags.cc (working copy) @@ -86,15 +86,6 @@ RegisterCommonFlags(&lsan_parser); #endif -#if CAN_SANITIZE_UB - __ubsan::Flags *uf = __ubsan::flags(); - uf->SetDefaults(); - - FlagParser ubsan_parser; - __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); - RegisterCommonFlags(&ubsan_parser); -#endif - // Override from ASan compile definition. const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); asan_parser.ParseString(asan_compile_def); @@ -102,20 +93,11 @@ // Override from user-specified string. const char *asan_default_options = MaybeCallAsanDefaultOptions(); asan_parser.ParseString(asan_default_options); -#if CAN_SANITIZE_UB - const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions(); - ubsan_parser.ParseString(ubsan_default_options); -#endif - // Override from command line. asan_parser.ParseString(GetEnv("ASAN_OPTIONS")); #if CAN_SANITIZE_LEAKS lsan_parser.ParseString(GetEnv("LSAN_OPTIONS")); #endif -#if CAN_SANITIZE_UB - ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS")); -#endif - // Let activation flags override current settings. On Android they come // from a system property. On other platforms this is no-op. if (!flags()->start_deactivated) { Index: libsanitizer/asan/asan_rtl.cc === --- libsanitizer/asan/asan_rtl.cc (revision 250059) +++ libsanitizer/asan/asan_rtl.cc (working copy) @@ -513,10 +513,6 @@ } #endif // CAN_SANITIZE_LEAKS -#if CAN_SANITIZE_UB - __ubsan::InitAsPlugin(); -#endif - InitializeSuppressions(); VReport(1, "AddressSanitizer Init done\n"); Index: libsanitizer/tsan/rtl/tsan_defs.h === --- libsanitizer/tsan/tsan_defs.h (revision 250059) +++ libsanitizer/tsan/tsan_defs.h (working copy) @@ -29,7 +29,7 @@ #endif #ifndef TSAN_CONTAINS_UBSAN -# define TSAN_CONTAINS_UBSAN (CAN_SANITIZE_UB && !defined(SANITIZER_GO)) +# define TSAN_CONTAINS_UBSAN 0 #endif namespace __tsan {
[PATCH 6/7] Libsanitizer merge from upstream r249633.
This patch adjusts the fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771 to extract the last PC from the stack frame if no valid FP is available for ARM. 2015-10-13 Maxim Ostapenko * sanitizer_common/sanitizer_stacktrace.cc (GetCanonicFrame): Assume we compiled code with GCC when extracting the caller PC for ARM if no valid frame pointer is available. Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.cc === --- libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (working copy) @@ -62,8 +62,8 @@ // Nope, this does not look right either. This means the frame after next does // not have a valid frame pointer, but we can still extract the caller PC. // Unfortunately, there is no way to decide between GCC and LLVM frame - // layouts. Assume LLVM. - return bp_prev; + // layouts. Assume GCC. + return bp_prev - 1; #else return (uhwptr*)bp; #endif
[PATCH 7/7] Libsanitizer merge from upstream r249633.
This is the final patch. Force libsanitizer to use an old ABI for ubsan float cast data descriptors, because for some exprs (e.g. that type of tcc_declaration) we can't get the right location for now. I'm not sure about this, perhaps it should be fixed in GCC somehow. 2015-10-13 Maxim Ostapenko * ubsan/ubsan_handlers.cc (looksLikeFloatCastOverflowDataV1): Always return true for now. Index: libsanitizer/ubsan/ubsan_handlers.cc === --- libsanitizer/ubsan/ubsan_handlers.cc (revision 250059) +++ libsanitizer/ubsan/ubsan_handlers.cc (working copy) @@ -307,6 +307,9 @@ } static bool looksLikeFloatCastOverflowDataV1(void *Data) { + // (TODO): propagate SourceLocation into DataDescriptor and use this + // heuristic than. + return true; // First field is either a pointer to filename or a pointer to a // TypeDescriptor. u8 *FilenameOrTypeDescriptor;
Re: [PATCH 1/7] Libsanitizer merge from upstream r249633.
On 14/10/15 10:54, Jakub Jelinek wrote: On Tue, Oct 13, 2015 at 07:54:33PM +0300, Maxim Ostapenko wrote: On 13/10/15 14:15, Maxim Ostapenko wrote: This is the raw merge itself. I'm bumping SONAME to libasan.so.3. -Maxim I have just noticed that I've misused autoconf stuff (used wrong version). Here a fixed version of the same patch. Sorry for inconvenience. Is libubsan, libtsan backwards compatible, or do we want to change SONAME there too? No, they are not (for UBSan heuristic doesn't work well for GCC, TSan has some type changes into interceptors and data structures, e.g. in struct ReportStack). I can share more details, if desired. The aarch64 changes are terrible, not just because it doesn't yet have runtime decision on what VA to use or that it doesn't support 48-bit VA, but also that for the 42-bit VA it uses a different shadow offset from 39-bit VA. But on the compiler side we have just one... Though, only the 39-bit VA is enabled right now by default, so out of the box the state is as bad as we had in 5.x - users wanting 42-bit VA or 48-bit VA have to patch libsanitizer. Have you verified libbacktrace sanitization still works properly (that is something upstream does not test)? I'm sorry, didn't catch well your words about libbacktrace sanitization. Did you mean symbolization? If so, I didn't perform any special validation here (thought output patterns tests use libbacktrace output, no?). But I wonder how can I verify this more or less automatically. Do you plan to update the asan tests we have to reflect the changes in upstream? Hm, there aren't changes into instrumentation, so the only thing is new interceptors. If it is desirable, I can migrate some tests for new interceptors from upstream. Jakub
Re: [PATCH 7/7] Libsanitizer merge from upstream r249633.
On 14/10/15 10:48, Jakub Jelinek wrote: On Tue, Oct 13, 2015 at 02:22:36PM +0300, Maxim Ostapenko wrote: This is the final patch. Force libsanitizer to use an old ABI for ubsan float cast data descriptors, because for some exprs (e.g. that type of tcc_declaration) we can't get the right location for now. I'm not sure about this, perhaps it should be fixed in GCC somehow. I don't like this (neither the heuristics on the libubsan, it wouldn't be a big deal to add a new library entrypoint). If because of the heuristics you need to ensure that the SourceLocation is always known, then either you check in ubsan.c whether expand_location gives you NULL xloc.file and in that case use old style float cast overflow (without location) - i.e. pass 0, NULL, otherwise you use new style, i.e. pass 1, &loc. Or arrange through some special option to emit something like { "", 0, 0 } instead of { NULL, 0, 0 } for the float cast case. And, regardless of this, any progress in making sure we have fewer cases with UNKNOWN_LOCATION on this will not hurt. I think at this point I'd prefer the first choice, i.e. using old style for locations without filename, and new style otherwise. 2015-10-13 Maxim Ostapenko * ubsan/ubsan_handlers.cc (looksLikeFloatCastOverflowDataV1): Always return true for now. Index: libsanitizer/ubsan/ubsan_handlers.cc === --- libsanitizer/ubsan/ubsan_handlers.cc(revision 250059) +++ libsanitizer/ubsan/ubsan_handlers.cc(working copy) @@ -307,6 +307,9 @@ } static bool looksLikeFloatCastOverflowDataV1(void *Data) { + // (TODO): propagate SourceLocation into DataDescriptor and use this + // heuristic than. + return true; // First field is either a pointer to filename or a pointer to a // TypeDescriptor. u8 *FilenameOrTypeDescriptor; Jakub Ok, got it. The first solution would require changes in libsanitizer because heuristic doesn't work for GCC, so perhaps new UBSan entry point should go upstream, right? Or this may be implemented as local patch for GCC? BTW, I actually saw UNKNOWN_LOCATION for this expr: volatile double var; // this is tcc_decaration, so we have UNKNOWN_LOCATION for it. I wonder if we need emit __ubsan_handle_float_cast_overflow here at all.
Re: [PATCH 7/7] Libsanitizer merge from upstream r249633.
On 14/10/15 14:06, Jakub Jelinek wrote: On Wed, Oct 14, 2015 at 01:51:44PM +0300, Maxim Ostapenko wrote: Ok, got it. The first solution would require changes in libsanitizer because heuristic doesn't work for GCC, so perhaps new UBSan entry point should go upstream, right? Or this may be implemented as local patch for GCC? No. The heuristics relies on: 1) either it is old style float cast overflow without location 2) or it is new style float cast with location, but the location must: a) not have NULL filename b) the filename must not be "" c) the filename must not be "\1" So, my proposal was to emit in GCC the old style float cast overflow if a), b) or c) is true, otherwise the new style. I have no idea what you mean by heuristic doesn't work for GCC after that. I mean that there are some cases where (FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1] < 2) is not sufficient to determine if we should use old style. I actually caught this on float-cast-overflow-10.c testcase. Here: $ /home/max/build/master-ref/gcc/xgcc -B/home/max/build/master-ref/gcc/ /home/max/workspace/downloads/svn/trunk/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c -B/home/max/build/master-ref/x86_64-unknown-linux-gnu/./libsanitizer/ -B/home/max/build/master-ref/x86_64-unknown-linux-gnu/./libsanitizer/ubsan/ -L/home/max/build/master-ref/x86_64-unknown-linux-gnu/./libsanitizer/ubsan/.libs -fno-diagnostics-show-caret -fdiagnostics-color=never -O2 -fsanitize=float-cast-overflow -fsanitize-recover=float-cast-overflow -DUSE_INT128 -DUSE_DFP -DBROKEN_DECIMAL_INT128 -lm -o ./float-cast-overflow-10.s -S $ cat float-cast-overflow-10.s cvt_sc_d32: .LFB0: .cfi_startproc pushq %rbx .. .L6: movl%ebx, %esi movl$.Lubsan_data0, %edi call__ubsan_handle_float_cast_overflow ... .Lubsan_data0: .quad .Lubsan_type1 .quad .Lubsan_type0 .align 2 .type .Lubsan_type1, @object .size .Lubsan_type1, 17 .Lubsan_type1: .value -1 // <- TypeKind .value 32 .string "'_Decimal32'" .align 2 .type .Lubsan_type0, @object .size .Lubsan_type0, 18 .Lubsan_type0: .value 0 // <- TypeKind .value 7 .string "'signed char'" .section.rodata.cst4,"aM",@progbits,4 .align 4 Here, one can see, we have FilenameOrTypeDescriptor[0] == -1 and FilenameOrTypeDescriptor[1] == 0. So, we end up with wrong decision and have SEGV later. BTW, I actually saw UNKNOWN_LOCATION for this expr: volatile double var; // this is tcc_decaration, so we have UNKNOWN_LOCATION for it. This is not a complete testcase, so I wonder what exactly you are talking about. The above doesn't not generate any __ubsan_handle_float_cast_overflow calls with -fsanitize=float-cast-overflow, and volatile double d; int bar (void) { return d; } has location. Jakub
Re: [PATCH 5/7] Libsanitizer merge from upstream r249633.
On 14/10/15 10:37, Jakub Jelinek wrote: On Tue, Oct 13, 2015 at 02:20:06PM +0300, Maxim Ostapenko wrote: This patch removes UBSan stubs from ASan and TSan code. We don't embed UBSan to ASan and UBSan because that would lead to undefined references to C++ stuff when linking with -static-libasan. AFAIK, sanitizer developers use different libraries for C and CXX runtimes, but I think this is out of scope of this merge. Where is CAN_SANITIZE_UB defined? I don't see it anywhere in the current libsanitizer and in the patch only: grep CAN_SANITIZE_UB libsanitizer-249633-2.diff +#if CAN_SANITIZE_UB +# define TSAN_CONTAINS_UBSAN (CAN_SANITIZE_UB && !defined(SANITIZER_GO)) +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB +#if CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB Hm, this is strange, perhaps the patch was malformed. So, unless I'm missing something, it would be best to arrange for -DCAN_SANITIZE_UB=1 to be in CXXFLAGS for ubsan/ source files and -DCAN_SANITIZE_UB=0 to be in CXXFLAGS for {a,t}san/ source files? CAN_SANITIZE_UB definition is hardcoded into new ubsan/ubsan_platform.h file. To use DCAN_SANITIZE_UB from CXXFLAGS, we still need some changes in libsanitizer against upstream: Index: libsanitizer/ubsan/ubsan_platform.h === --- libsanitizer/ubsan/ubsan_platform.h(revision 250295) +++ libsanitizer/ubsan/ubsan_platform.h(working copy) @@ -13,6 +13,7 @@ #ifndef UBSAN_PLATFORM_H #define UBSAN_PLATFORM_H +#ifndef CAN_SANITIZE_UB // Other platforms should be easy to add, and probably work as-is. #if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \ (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \ @@ -23,5 +24,6 @@ #else # define CAN_SANITIZE_UB 0 #endif +#endif // CAN_SANITIZE_UB #endif Are there any other defines that are supposedly set from cmake or wherever upstream and are left undefined? There is ASAN_DYNAMIC macro, but I see it into current libsanitizer too and it's not touched in any Makefile. Same for ASAN_DYNAMIC_RUNTIME_THUNK, that is used for Windows build and ASAN_LOW_MEMORY, that set explicitly only for Android. Do we need to touch them? Also, ASAN_FLEXIBLE_MAPPING_AND_OFFSET was bumped upstream, so we don't need it anymore. I'm applying the patch mentioned above, redefining CAN_SANITIZE_UB in corresponding Makefiles, dropping ASAN_FLEXIBLE_MAPPING_AND_OFFSET and resending libsanitizer-249633-2.diff in corresponding thread. 2015-10-13 Maxim Ostapenko * tsan/tsan_defs.h: Define TSAN_CONTAINS_UBSAN to 0. * asan/asan_flags.cc (InitializeFlags): Do not initialize UBSan flags. * asan/asan_rtl.cc (AsanInitInternal): Do not init UBSan. Jakub
Re: [PATCH 2/7] Libsanitizer merge from upstream r249633.
On 14/10/15 10:30, Jakub Jelinek wrote: On Tue, Oct 13, 2015 at 02:16:23PM +0300, Maxim Ostapenko wrote: This patch introduces required compiler changes. Now, we don't version asan_init, we have a special __asan_version_mismatch_check_v[n] symbol for this. For this, I just have to wonder what is the actual improvement over what we had. To me it looks like a step in the wrong direction, it will only bloat the size of the ctors. I can live with it, but just want to put on record I think it is a mistake. Also, asan_stack_malloc_[n] doesn't take a local stack as a second parameter anymore, so don't pass it. I think this is another mistake, but this time with actually bad fix on the compiler side for it. If I read the code well, previously __asan_stack_malloc_n would return you the local stack if it failed for whatever reason, which is actually what you want as fallback. But, the new code returns NULL instead, so I think you would need to compare the return value of __asan_stack_malloc_n with NULL and if it is NULL, use the addr instead of what it returned; which is not what your asan.c change does. Now, what is the improvement here? Bloat the compiler generated code... :( Ah, right, fixing this now. Does this looks better now? 2015-10-12 Maxim Ostapenko config/ * bootstrap-asan.mk: Replace ASAN_OPTIONS=detect_leaks with LSAN_OPTIONS=detect_leaks Missing . at the end, and the config/ hunk missing from the patch. gcc/ * asan.c (asan_emit_stack_protection): Don't pass local stack to asan_stack_malloc_[n] anymore. (asan_finish_file): Instert __asan_version_mismatch_check_v[n] call. s/Instert/Instead/ Fixed now. Jakub 2015-10-12 Maxim Ostapenko config/ * bootstrap-asan.mk: Replace ASAN_OPTIONS=detect_leaks with LSAN_OPTIONS=detect_leaks. gcc/ * asan.c (asan_emit_stack_protection): Don't pass local stack to asan_stack_malloc_[n] anymore. Check if asan_stack_malloc_[n] returned NULL and use local stack than. (asan_finish_file): Insert __asan_version_mismatch_check_v[n] call in addition to __asan_init. * sanitizer.def (BUILT_IN_ASAN_INIT): Rename to __asan_init. (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK): Add new builtin call. gcc/testsuite/ g++.dg/asan/default-options-1.C: Adjust testcase. Index: gcc/asan.c === --- gcc/asan.c (revision 228817) +++ gcc/asan.c (working copy) @@ -1132,12 +1132,16 @@ snprintf (buf, sizeof buf, "__asan_stack_malloc_%d", use_after_return_class); ret = init_one_libfunc (buf); - rtx addr = convert_memory_address (ptr_mode, base); - ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, + ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 1, GEN_INT (asan_frame_size + base_align_bias), - TYPE_MODE (pointer_sized_int_node), - addr, ptr_mode); + TYPE_MODE (pointer_sized_int_node)); + /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded + and NULL otherwise. Check if RET value is NULL and jump over the + BASE reassignment in this case. Otherwise, reassign BASE to RET. */ + int very_unlikely = REG_BR_PROB_BASE / 2000 - 1; + emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX, + VOIDmode, 0, lab, very_unlikely); ret = convert_memory_address (Pmode, ret); emit_move_insn (base, ret); emit_label (lab); @@ -2470,6 +2474,8 @@ { tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); + fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK); + append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); } FOR_EACH_DEFINED_VARIABLE (vnode) if (TREE_ASM_WRITTEN (vnode->decl) Index: gcc/sanitizer.def === --- gcc/sanitizer.def (revision 228817) +++ gcc/sanitizer.def (working copy) @@ -27,8 +27,11 @@ for other FEs by asan.c. */ /* Address Sanitizer */ -DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v4", +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_VERSION_MISMATCH_CHECK, + "__asan_version_mismatch_check_v6", + BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) /* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.c relies on this order. */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", Index: gcc/testsuite/g++.dg/asan/default-options-1.C === --- gcc/testsuite/g++.dg/asan/default-options-1.C (revision 228817) +++ gcc/testsuite/g++.dg/asan/default-options-1.C
Re: [PATCH 7/7] Libsanitizer merge from upstream r249633.
On 14/10/15 15:12, Jakub Jelinek wrote: On Wed, Oct 14, 2015 at 03:02:22PM +0300, Maxim Ostapenko wrote: On 14/10/15 14:06, Jakub Jelinek wrote: On Wed, Oct 14, 2015 at 01:51:44PM +0300, Maxim Ostapenko wrote: Ok, got it. The first solution would require changes in libsanitizer because heuristic doesn't work for GCC, so perhaps new UBSan entry point should go upstream, right? Or this may be implemented as local patch for GCC? No. The heuristics relies on: 1) either it is old style float cast overflow without location 2) or it is new style float cast with location, but the location must: a) not have NULL filename b) the filename must not be "" c) the filename must not be "\1" So, my proposal was to emit in GCC the old style float cast overflow if a), b) or c) is true, otherwise the new style. I have no idea what you mean by heuristic doesn't work for GCC after that. I mean that there are some cases where (FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1] < 2) is not sufficient to determine if we should use old style. I actually caught this on float-cast-overflow-10.c testcase. Ah, ok, in that case the heuristics is flawed. If they want to keep it, they should check if MaybeFromTypeKind is either < 2 or equal to 0x1fe. Can you report it upstream? If that is changed, we'd need to change the above and also add d) the filename must not start with "\xff\xff" to the rules. I think it would be better to just add a whole new entrypoint, but if they think the heuristics is good enough, they should at least fix it up. Jakub Done. I've realized that we could just set loc to input_location if loc == UNKNOWN_LOCATION. In this case, we always would have new style. This would require some changes in tests, because upstream UBSan suppress different reports for one location. How about this? -Maxim gcc/ChangeLog: 2015-10-16 Maxim Ostapenko * ubsan.c (ubsan_instrument_float_cast): If location is unknown, assign input_location to loc. Propagate loc to ubsan_create_data. gcc/testsuite/ChangeLog: 2015-10-16 Maxim Ostapenko * c-c++-common/ubsan/float-cast-overflow-10.c: Adjust test. * c-c++-common/ubsan/float-cast-overflow-8.c: Likewise. * c-c++-common/ubsan/float-cast-overflow-9.c: Likewise. Index: gcc/ubsan.c === --- gcc/ubsan.c (revision 228817) +++ gcc/ubsan.c (working copy) @@ -1484,6 +1484,7 @@ machine_mode mode = TYPE_MODE (expr_type); int prec = TYPE_PRECISION (type); bool uns_p = TYPE_UNSIGNED (type); + if (loc == UNKNOWN_LOCATION) loc = input_location; /* Float to integer conversion first truncates toward zero, so even signed char c = 127.875f; is not problematic. @@ -1581,8 +1582,8 @@ else { /* Create the __ubsan_handle_float_cast_overflow fn call. */ - tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0, - NULL, ubsan_type_descriptor (expr_type), + tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 1, + &loc, ubsan_type_descriptor (expr_type), ubsan_type_descriptor (type), NULL_TREE, NULL_TREE); enum built_in_function bcode Index: gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c === --- gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c (revision 228817) +++ gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c (working copy) @@ -10,70 +10,37 @@ /* _Decimal32 */ /* { dg-output "value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside
Re: [PATCH 1/7] Libsanitizer merge from upstream r249633.
On 16/10/15 16:48, Renato Golin wrote: On 14 October 2015 at 19:38, Renato Golin wrote: On 14 October 2015 at 19:21, Evgenii Stepanov wrote: Wait. As Jakub correctly pointed out in the other thread, there is no obvious reason why there could not be a single shadow offset value that would work for all 3 possible VMA settings. I suggest figuring this out first. We are. For anyone interested, here are the first few reviews: http://reviews.llvm.org/D13781 http://reviews.llvm.org/D13782 There's more coming... :) I don't want to spam this list for all the future patches, so if you're interested, you might monitor the LLVM list, or register in our Phabricator and create a filter for reviews with "VMA" to always CC you. cheers, --renato Yeah, thanks. Just wondering if I should step back until they are resolved upstream or we can have another merge in the future (stage3 is coming ...)? -Maxim
[PATCH v2 0/6] Libsanitizer merge from upstream r250806 (was r249633).
Hi, this is the second attempt to perform libsanitizer merge from upstream. In previous patch set ( https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01212.html) we have revealed an issue with heuristic for old/new style ubsan_data that was needed to be fixed upstream + some errors in compiler changes were found. I thought that it would me too messy to proceed review in the previous thread, so creating the new one. The first patch is the merge itself. Since the heuristic fix for old/new style ubsan_data selection was applied upstream, I'm bumping revision to r250806. Since there aren't significant changes from r249633, I think this should be fine. The second one combines all compiler-related changes and addresses Jakub's nits from previous review. Patches 3, 4 and 5 are applied to library and were preapproved in previous review, but I'm attaching them here to form the full patch set. In patch 6, I'm trying to add a brief instruction how to perform the merge. This is just a documentation patch. Tested and {A, UB}San bootstrapped on x86-linux-gnu, x86_64-linux-gnu and aarch64-linux-gnu targets. Thanks, -Maxim
[PATCH v2 2/6] Libsanitizer merge from upstream r250806 (was r249633).
This patch introduces required compiler changes. Now, we don't version asan_init, we have a special __asan_version_mismatch_check_v[n] symbol for this. asan_stack_malloc_[n] doesn't take a local stack as a second parameter anymore, so don't pass it. Also, ubsan_instrument_float_cast was adjusted to pass source location for libubsan if it is possible. gcc/ChangeLog: 2015-10-20 Maxim Ostapenko gcc/ * asan.c (asan_emit_stack_protection): Don't pass local stack to asan_stack_malloc_[n] anymore. Check if asan_stack_malloc_[n] returned NULL and use local stack than. (asan_finish_file): Insert __asan_version_mismatch_check_v[n] call in addition to __asan_init. * sanitizer.def (BUILT_IN_ASAN_INIT): Rename to __asan_init. (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK): Add new builtin call. * asan.h (asan_intercepted_p): Handle new string builtins. * ubsan.c (ubsan_use_new_style_p): New function. (ubsan_instrument_float_cast): If location is unknown, assign input_location to loc. Propagate loc to ubsan_create_data if ubsan_use_new_style_p returned true. config/ * bootstrap-asan.mk: Replace ASAN_OPTIONS=detect_leaks with LSAN_OPTIONS=detect_leaks. gcc/testsuite/ChangeLog: 2015-10-20 Maxim Ostapenko * c-c++-common/ubsan/float-cast-overflow-10.c: Adjust test. * c-c++-common/ubsan/float-cast-overflow-8.c: Likewise. * c-c++-common/ubsan/float-cast-overflow-9.c: Likewise. * g++.dg/asan/default-options-1.C: Likewise. Index: gcc/asan.c === --- gcc/asan.c (revision 228817) +++ gcc/asan.c (working copy) @@ -1132,12 +1132,16 @@ snprintf (buf, sizeof buf, "__asan_stack_malloc_%d", use_after_return_class); ret = init_one_libfunc (buf); - rtx addr = convert_memory_address (ptr_mode, base); - ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, + ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 1, GEN_INT (asan_frame_size + base_align_bias), - TYPE_MODE (pointer_sized_int_node), - addr, ptr_mode); + TYPE_MODE (pointer_sized_int_node)); + /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded + and NULL otherwise. Check RET value is NULL here and jump over the + BASE reassignment in this case. Otherwise, reassign BASE to RET. */ + int very_unlikely = REG_BR_PROB_BASE / 2000 - 1; + emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX, + VOIDmode, 0, lab, very_unlikely); ret = convert_memory_address (Pmode, ret); emit_move_insn (base, ret); emit_label (lab); @@ -2470,6 +2474,8 @@ { tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); + fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK); + append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); } FOR_EACH_DEFINED_VARIABLE (vnode) if (TREE_ASM_WRITTEN (vnode->decl) Index: gcc/sanitizer.def === --- gcc/sanitizer.def (revision 228817) +++ gcc/sanitizer.def (working copy) @@ -27,8 +27,11 @@ for other FEs by asan.c. */ /* Address Sanitizer */ -DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v4", +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_VERSION_MISMATCH_CHECK, + "__asan_version_mismatch_check_v6", + BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) /* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.c relies on this order. */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", Index: gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c === --- gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c (revision 228817) +++ gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c (working copy) @@ -10,70 +10,37 @@ /* _Decimal32 */ /* { dg-output "value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*value is outside the range o
Re: [PATCH v2 0/6] Libsanitizer merge from upstream r250806 (was r249633).
This is just reapplied patch for SPARC by David S. Miller. The patch was preapproved here: (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01214.html). 2015-10-20 Maxim Ostapenko PR sanitizer/63958 Reapply: 2014-10-14 David S. Miller * sanitizer_common/sanitizer_platform_limits_linux.cc (time_t): Define at __kernel_time_t, as needed for sparc. (struct __old_kernel_stat): Don't check if __sparc__ is defined. * libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (__sanitizer): Define struct___old_kernel_stat_sz, struct_kernel_stat_sz, and struct_kernel_stat64_sz for sparc. (__sanitizer_ipc_perm): Adjust for sparc targets. (__sanitizer_shmid_ds): Likewsie. (__sanitizer_sigaction): Likewise. (IOC_SIZE): Likewsie. Index: libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc === --- libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc (working copy) @@ -38,6 +38,7 @@ #define uid_t __kernel_uid_t #define gid_t __kernel_gid_t #define off_t __kernel_off_t +#define time_t __kernel_time_t // This header seems to contain the definitions of _kernel_ stat* structs. #include #undef ino_t @@ -62,7 +63,7 @@ } // namespace __sanitizer #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\ -&& !defined(__mips__) +&& !defined(__mips__) && !defined(__sparc__) COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); #endif Index: libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h === --- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h (working copy) @@ -83,6 +83,14 @@ const unsigned struct_kernel_stat_sz = 144; #endif const unsigned struct_kernel_stat64_sz = 104; +#elif defined(__sparc__) && defined(__arch64__) + const unsigned struct___old_kernel_stat_sz = 0; + const unsigned struct_kernel_stat_sz = 104; + const unsigned struct_kernel_stat64_sz = 144; +#elif defined(__sparc__) && !defined(__arch64__) + const unsigned struct___old_kernel_stat_sz = 0; + const unsigned struct_kernel_stat_sz = 64; + const unsigned struct_kernel_stat64_sz = 104; #endif struct __sanitizer_perf_event_attr { unsigned type; @@ -105,7 +113,7 @@ #if defined(__powerpc64__) const unsigned struct___old_kernel_stat_sz = 0; -#else +#elif !defined(__sparc__) const unsigned struct___old_kernel_stat_sz = 32; #endif @@ -184,6 +192,18 @@ unsigned short __pad1; unsigned long __unused1; unsigned long __unused2; +#elif defined(__sparc__) +# if defined(__arch64__) +unsigned mode; +unsigned short __pad1; +# else +unsigned short __pad1; +unsigned short mode; +unsigned short __pad2; +# endif +unsigned short __seq; +unsigned long long __unused1; +unsigned long long __unused2; #else unsigned short mode; unsigned short __pad1; @@ -201,6 +221,26 @@ struct __sanitizer_shmid_ds { __sanitizer_ipc_perm shm_perm; + #if defined(__sparc__) + # if !defined(__arch64__) +u32 __pad1; + # endif +long shm_atime; + # if !defined(__arch64__) +u32 __pad2; + # endif +long shm_dtime; + # if !defined(__arch64__) +u32 __pad3; + # endif +long shm_ctime; +uptr shm_segsz; +int shm_cpid; +int shm_lpid; +unsigned long shm_nattch; +unsigned long __glibc_reserved1; +unsigned long __glibc_reserved2; + #else #ifndef __powerpc__ uptr shm_segsz; #elif !defined(__powerpc64__) @@ -238,6 +278,7 @@ uptr __unused4; uptr __unused5; #endif +#endif }; #elif SANITIZER_FREEBSD struct __sanitizer_ipc_perm { @@ -555,9 +596,13 @@ #else __sanitizer_sigset_t sa_mask; #ifndef __mips__ +#if defined(__sparc__) +unsigned long sa_flags; +#else int sa_flags; #endif #endif +#endif #if SANITIZER_LINUX void (*sa_restorer)(); #endif @@ -799,7 +844,7 @@ #define IOC_NRBITS 8 #define IOC_TYPEBITS 8 -#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) +#if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || defined(__sparc__) #define IOC_SIZEBITS 13 #define IOC_DIRBITS 3 #define IOC_NONE 1U @@ -829,7 +874,17 @@ #define IOC_DIR(nr) (((nr) >> IOC_DIRSHIFT) & IOC_DIRMASK) #define IOC_TYPE(nr) (((nr) >> IOC_TYPESHIFT) & IOC_TYPEMASK) #define IOC_NR(nr) (((nr) >> IOC_NRSHIFT) & IOC_NRMASK) + +#if defined(__sparc__) +// In sparc the 14 bits SIZE field overlaps with the +// least significant bit of DIR, so either IOC_READ or +// IOC_WRITE shall be 1 in order to get a non-zero SIZE
[PATCH v2 4/6] Libsanitizer merge from upstream r250806 (was r249633).
This is a reapplied Jakub's patch for disabling ODR violation detection. The patch was preapproved here: (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01215.html). 2015-10-20 Maxim Ostapenko PR bootstrap/63888 Reapply: 2015-02-20 Jakub Jelinek * asan/asan_globals.cc (RegisterGlobal): Disable detect_odr_violation support until it is rewritten upstream. * c-c++-common/asan/pr63888.c: New test. Index: libsanitizer/asan/asan_globals.cc === --- libsanitizer/asan/asan_globals.cc (revision 250059) +++ libsanitizer/asan/asan_globals.cc (working copy) @@ -146,7 +146,9 @@ CHECK(AddrIsInMem(g->beg)); CHECK(AddrIsAlignedByGranularity(g->beg)); CHECK(AddrIsAlignedByGranularity(g->size_with_redzone)); - if (flags()->detect_odr_violation) { + // This "ODR violation" detection is fundamentally incompatible with + // how GCC registers globals. Disable as useless until rewritten upstream. + if (0 && flags()->detect_odr_violation) { // Try detecting ODR (One Definition Rule) violation, i.e. the situation // where two globals with the same name are defined in different modules. if (__asan_region_is_poisoned(g->beg, g->size_with_redzone)) {
[PATCH v2 5/6] Libsanitizer merge from upstream r250806 (was r249633).
This patch adjusts the fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771 to extract the last PC from the stack frame if no valid FP is available for ARM. The patch was preapproved here: (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01217.html). 2015-10-20 Maxim Ostapenko * sanitizer_common/sanitizer_stacktrace.cc (GetCanonicFrame): Assume we compiled code with GCC when extracting the caller PC for ARM if no valid frame pointer is available. Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.cc === --- libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (revision 250059) +++ libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (working copy) @@ -62,8 +62,8 @@ // Nope, this does not look right either. This means the frame after next does // not have a valid frame pointer, but we can still extract the caller PC. // Unfortunately, there is no way to decide between GCC and LLVM frame - // layouts. Assume LLVM. - return bp_prev; + // layouts. Assume GCC. + return bp_prev - 1; #else return (uhwptr*)bp; #endif
[PATCH v2 6/6] Libsanitizer merge from upstream r250806 (was r249633).
In this patch, I'm trying to add a general instruction how to perform the merge. This is just a documentation patch, any suggestions and opinions are welcome. Index: libsanitizer/HOWTO_MERGE === --- libsanitizer/HOWTO_MERGE (revision 0) +++ libsanitizer/HOWTO_MERGE (working copy) @@ -0,0 +1,26 @@ +In general, merging process should not be very difficult, but we need to +track various ABI changes and GCC-specific patches carefully. Here is a +general list of actions required to perform the merge: + +- Checkout recent GCC tree. +- Run merge.sh script from libsanitizer directory. +- Modify Makefile.am files into asan/tsan/lsan/ubsan/sanitizer_common/interception + directories if needed. In particular, you may need to add new source files + and remove old ones in source files list, add new flags to {C, CXX}FLAGS if + needed and update DEFS with new defined variables. +- Apply all needed GCC-specific patches to libsanitizer (note that some of + them might be already included to upstream). +- Apply all necessary compiler changes. Be especially careful here, you must + not break ABI between compiler and library. +- Modify configure.ac file if needed (e.g. if you need to add link against new + library for sanitizer lilbs). +- Remove unused (deleted by merge) files from all source and include + directories. Be especially careful with headers, because they aren't listed + in Makefiles explicitly. +- Regenerate configure script and all Makefiles by autoreconf. You should use + exactly the same autotools version as for other GCC directories (current + version is 2.64, https://www.gnu.org/software/automake/faq/autotools-faq.html + for details how to install/use it). +- Run regression testing on at least three platforms (e.g. x86-linux-gnu, + x86_64-linux-gnu, aarch64-linux-gnu). +- Run {A, UB}San bootstrap on at least three platforms.
Re: [PATCH v2 1/6] Libsanitizer merge from upstream r250806 (was r249633).
Great, thanks! I'm going to commit the whole patch set tomorrow morning if no objections. On 20/10/15 14:52, Jakub Jelinek wrote: On Tue, Oct 20, 2015 at 02:18:25PM +0300, Maxim Ostapenko wrote: This is the merge itself. Added DCAN_SANITIZE_UB={0, 1} and nuked DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 (not used now) in corresponding Makefiles. Ok. Jakub
[PATCH] Fix bootsrap/68041
Hi, recent libsanitizer merge ( https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01851.html) broke bootstrap on x86_64-apple-darwin14 because for Darwin sanitizer libs shouldn't be linked with -lrt flag. Also, right now, libubsan links with -lc++abi for Darwin, that is wrong, because we don't want to link against system clang++'s C++ library (Dominique, am I right here?). This patch fixes bootstrap by adding additional check to determine if we really need librt for sanitizer_common into configure script and removes -lc++abi flag for UBSan on Darwin. Tested on x86_64-linux-gnu, how does it look? -Maxim libsanitizer/ChangeLog: 2015-10-21 Maxim Ostapenko PR bootstrap/68041 * configure.ac (link_sanitizer_common): Link against librt only if it contains shm_open, required by sanitizers. (CXX_ABI_NEEDED): Remove variable. * configure: Regenerate. * ubsan/Makefile.am (libubsan_la_LIBADD): Do not add -lc++abi anymore. * ubsan/Makefile.in: Regenerate. Index: libsanitizer/configure === --- libsanitizer/configure (revision 229119) +++ libsanitizer/configure (working copy) @@ -616,8 +616,6 @@ FORMAT_FILE SANITIZER_SUPPORTED_FALSE SANITIZER_SUPPORTED_TRUE -USE_CXX_ABI_FLAG_FALSE -USE_CXX_ABI_FLAG_TRUE USING_MAC_INTERPOSE_FALSE USING_MAC_INTERPOSE_TRUE link_liblsan @@ -12029,7 +12027,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12032 "configure" +#line 12030 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12135,7 +12133,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12138 "configure" +#line 12136 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15516,8 +15514,52 @@ # Common libraries that we need to link against for all sanitizer libs. -link_sanitizer_common='-lrt -lpthread -ldl -lm' +link_sanitizer_common='-lpthread -ldl -lm' +# At least for glibc, shm_open is in librt. But don't pull that +# in if it still doesn't give us the function we want. This +# test is copied from libgomp. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for shm_open in -lrt" >&5 +$as_echo_n "checking for shm_open in -lrt... " >&6; } +if test "${ac_cv_lib_rt_shm_open+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shm_open (); +int +main () +{ +return shm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_shm_open=yes +else + ac_cv_lib_rt_shm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ +conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_shm_open" >&5 +$as_echo "$ac_cv_lib_rt_shm_open" >&6; } +if test "x$ac_cv_lib_rt_shm_open" = x""yes; then : + link_sanitizer_common="-lrt $link_sanitizer_common" +fi + + # Set up the set of additional libraries that we need to link against for libasan. link_libasan=$link_sanitizer_common @@ -15534,9 +15576,57 @@ link_liblsan=$link_sanitizer_common + +# At least for glibc, clock_gettime is in librt. But don't pull that +# in if it still doesn't give us the function we want. This +# test is copied from libgomp. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ +conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_
[PATCH] Fix sanitizer/68042
Hi, currently we have memcmp-1.c and sanity-check-pure-c-1.c (ASan testsuite) output pattern test failures on x86_64-apple-darwin14. This patch adjusts their expecting patterns to match real ones. Tested by me on x86_64-unknown-linux-gnu and by Dominique on x86_64-apple-darwin14. Ok to apply? -Maxim gcc/testsuite/ChangeLog: 2015-10-22 Maxim Ostapenko PR sanitizer/68042 * c-c++-common/asan/memcmp-1.c: Adjust test to pass on Darwin. * c-c++-common/asan/sanity-check-pure-c-1.c: Likewise. Index: gcc/testsuite/c-c++-common/asan/memcmp-1.c === --- gcc/testsuite/c-c++-common/asan/memcmp-1.c (revision 229169) +++ gcc/testsuite/c-c++-common/asan/memcmp-1.c (working copy) @@ -16,5 +16,5 @@ } /* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */ -/* { dg-output "#0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)memcmp |\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "#0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)memcmp|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "#1 0x\[0-9a-f\]+ +(in _*main|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ Index: gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c === --- gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c (revision 229169) +++ gcc/testsuite/c-c++-common/asan/sanity-check-pure-c-1.c (working copy) @@ -10,7 +10,7 @@ } /* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */ -/* { dg-output "#0 \[^\n\r]*(in _*(interceptor_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "#0 \[^\n\r]*(in _*(interceptor_|wrap_)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "#1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ -/* { dg-output "#0 \[^\n\r]*(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "#0 \[^\n\r]*(in _*(interceptor_|wrap_)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "#1 \[^\n\r]*(in _*main (\[^\n\r]*sanity-check-pure-c-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
[Committed, PATCH] Update HOWTO_MERGE file for libsanitizer.
This patch updates libsanitizer/HOWTO_MERGE file according to Yura's nits here: https://gcc.gnu.org/ml/gcc-patches/2015-10/msg02039.html. Just a documentation patch, no changes in functionality. -Maxim Index: libsanitizer/HOWTO_MERGE === --- libsanitizer/HOWTO_MERGE (revision 229212) +++ libsanitizer/HOWTO_MERGE (working copy) @@ -2,25 +2,38 @@ track various ABI changes and GCC-specific patches carefully. Here is a general list of actions required to perform the merge: -- Checkout recent GCC tree. -- Run merge.sh script from libsanitizer directory. -- Modify Makefile.am files into asan/tsan/lsan/ubsan/sanitizer_common/interception +* Checkout recent GCC tree. +* Run merge.sh script from libsanitizer directory. +* Modify Makefile.am files into asan/tsan/lsan/ubsan/sanitizer_common/interception directories if needed. In particular, you may need to add new source files and remove old ones in source files list, add new flags to {C, CXX}FLAGS if - needed and update DEFS with new defined variables. -- Apply all needed GCC-specific patches to libsanitizer (note that some of + needed and update DEFS with new defined variables. You can find these changes + in corresponding CMakeLists.txt and config-ix.cmake files from compiler-rt source + directory. +* Apply all needed GCC-specific patches to libsanitizer (note that some of them might be already included to upstream). -- Apply all necessary compiler changes. Be especially careful here, you must - not break ABI between compiler and library. -- Modify configure.ac file if needed (e.g. if you need to add link against new +* Apply all necessary compiler changes. Be especially careful here, you must + not break ABI between compiler and library. You can reveal these changes by + inspecting the history of AddressSanitizer.cpp and ThreadSanitizer.cpp files + from LLVM source tree. +* Update ASan testsuite with corresponding tests from lib/asan/tests directory. + Not all tests can be migrated easily, so you don't need them all to be adapted. +* Modify configure.ac file if needed (e.g. if you need to add link against new library for sanitizer lilbs). -- Remove unused (deleted by merge) files from all source and include - directories. Be especially careful with headers, because they aren't listed - in Makefiles explicitly. -- Regenerate configure script and all Makefiles by autoreconf. You should use - exactly the same autotools version as for other GCC directories (current - version is 2.64, https://www.gnu.org/software/automake/faq/autotools-faq.html - for details how to install/use it). -- Run regression testing on at least three platforms (e.g. x86-linux-gnu, - x86_64-linux-gnu, aarch64-linux-gnu). -- Run {A, UB}San bootstrap on at least three platforms. +* Add new target platforms in configure.tgt script if needed. +* Bump SONAME for sanitizer libraries in asan/tsan/ubsan libtool-version files + if ABI has changed. +* Regenerate configure script and all Makefiles by autoreconf. You should use + exactly the same autoconf and automake versions as for other GCC directories (current + versions are written in Makefile.in and configure files). +* Run regression testing on at least three platforms (e.g. x86-linux-gnu, x86_64-linux-gnu, + aarch64-linux-gnu, arm-linux-gnueabi). +* Run {A, UB}San bootstrap on at least three platforms. +* Compare ABI of corresponding libclang_rt-asan and newly build libasan libraries. + You can use a pretty good libabigail tool (https://sourceware.org/libabigail/index.html) + to perform such a comparision. Note, that the list of exported symbols may differ, + e.g. because libasan currently does not include UBSan runtime. +* Split your changes into logical parts (e.g. raw merge, compiler changes, GCC-specific changes + in libasan, configure/Makefile changes). The review process has O(N^2) complexity, so you + would simplify and probably speed up the review process by doing this. +* Send your patches for review to GCC Patches Mailing List (gcc-patches@gcc.gnu.org).
[RFC, PATCH v2] Disable -fprofile-use related optimizations if corresponding .gcda file not found.
Hi! As was pointed out in previous thread (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg00723.html), sometimes PGO-built binaries can actually introduce performance regressions. We could identify affected object files and disable PGO for them by simply removing corresponding .gcda file. My previous patch was incomplete and had two major drawbacks: * It disabled unrelated options (e.g. -frename-registers) and PGO-related options, set up by user explicitly, if corresponding .gcda file is not found. * As Markus pointed out, in many cases we actually don't want to disable PGO-related options even if .gcda file is missing. This patch tries to solve these issues in the following way: * Introduce new -fprofile-use-partial switch. * If -fprofile-use-partial is ON, try to find corresponding .gcda file in the very early stage during compiler invoking (actually, when common command line options are parsed). If .gcda file exists, enable PGO-related optimizations and emit warning otherwise. I believe this should not break existing code. Regtested and bootstrapped on x86_64-unknown-linux-gnu. Does the patch look sensible? Thanks, -Maxim gcc/ChangeLog: 2015-10-27 Maxim Ostapenko * common.opt (profile_file_name): New variable. (fprofile-use-partial): Likewise. (fprofile-use-partial=): Likewise. * opts.c: Include gcov-io.h. (common_handle_option): Defer enabling PGO-related optimizations until we know if corresponding .gcda file exists. (maybe_setup_aux_base_name): New function. (setup_coverage_filename): Likewise. (enable_fdo_optimizations): Move up in source file. (finish_options): Call maybe_setup_aux_base_name and setup coverage filename. Enable PGO-related optimizations if corresponding .gcda file exists if -fprofile-use-partial is used. If -fprofile-use is used, enable PGO-related optimizations without any other conditions. * coverage.c (coverage_init): Adjust to use profile_file_name. diff --git a/gcc/common.opt b/gcc/common.opt index 12ca0d6..fb04201 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -198,6 +198,9 @@ const char *main_input_basename Variable int main_input_baselength +Variable +char *profile_file_name + ; Which options have been printed by --help. Variable char *help_printed @@ -1861,6 +1864,14 @@ fprofile-use= Common Joined RejectNegative Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=. +fprofile-use-partial +Common Var(flag_profile_use_partial) +Enable common options for performing profile feedback directed optimizations. + +fprofile-use-partial= +Common Joined RejectNegative +Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=. + fprofile-values Common Report Var(flag_profile_values) Insert code to profile values of expressions. diff --git a/gcc/coverage.c b/gcc/coverage.c index 4e08e5f..461dd48 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -1184,7 +1184,7 @@ void coverage_init (const char *filename) { int len = strlen (filename); - int prefix_len = 0; + da_file_name = profile_file_name; /* Since coverage_init is invoked very early, before the pass manager, we need to set up the dumping explicitly. This is @@ -1193,24 +1193,6 @@ coverage_init (const char *filename) g->get_passes ()->get_pass_profile ()->static_pass_number; g->get_dumps ()->dump_start (profile_pass_num, NULL); - if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename)) -profile_data_prefix = getpwd (); - - if (profile_data_prefix) -prefix_len = strlen (profile_data_prefix); - - /* Name of da file. */ - da_file_name = XNEWVEC (char, len + strlen (GCOV_DATA_SUFFIX) - + prefix_len + 2); - - if (profile_data_prefix) -{ - memcpy (da_file_name, profile_data_prefix, prefix_len); - da_file_name[prefix_len++] = '/'; -} - memcpy (da_file_name + prefix_len, filename, len); - strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX); - bbg_file_stamp = local_tick; if (flag_auto_profile) diff --git a/gcc/opts.c b/gcc/opts.c index 9a3fbb3..2e0cfa4 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "opts-diagnostic.h" #include "insn-attr-common.h" #include "common/common-target.h" +#include "gcov-io.h" static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); @@ -660,6 +661,97 @@ default_options_optimization (struct gcc_options *opts, lang_mask, handlers, loc, dc); } +/* Enable FDO-related flags. */ + +static void +enable_fdo_optimizations (struct gcc_options *opts, + struct gcc_options *opts_set, + int value) +{ + if (!opts_set->x_flag_branch_probabilities) +opts->x_flag_branch_probabilities = value; + if (!opts_set->x_flag_profile_values) +opts->x_flag_profile_values = value; + if (!opts_set->x_f
Re: [PATCH]Add -fprofile-use option for check_effective_target_freorder.
On 27/10/15 14:06, Bernd Schmidt wrote: On 10/27/2015 11:54 AM, Renlin Li wrote: Yes. In all of the related testcases, only -freorder-and-partition flag is provided explicitly. How about creating a new dg-add-options for freorder? proc add_options_for_freorder { flags } { return "$flags -freorder-blocks-and-partition -fprofile-use" } proc check_effective_target_freorder {} { return [check_no_compiler_messages freorder object { void foo (void) { } } [add_options_for_freorder ""]] } I don't know that tcl syntax but apparently this is done already for a number of other cases. So, probably the right thing to do. You might want to coordinate with Maxim ostapenko who's currently working on another -fprofile-use patch. Hopefully not one that disables -freorder-blocks-and-partition if it can't find .gcda files. AFAU, adding -fprofile-use would lead to enabling a bunch of PGO-related optimizations wherever you have .gcda file or not. So, you can end up with a completely different optimization pipeline for your tests if you enable -fprofile-use for them. Is it desirable? Anyway, disabling any compile options provided by user explicitly sounds like a bad idea for me, so disabling -freorder-blocks-and-partition if it can't find .gcda file seems to be not acceptable. -Maxim Bernd
[PATCH, ASan] Add new tests for string interceptors.
Hi, since the last libsanitizer merge happened, we have new string interceptors in libasan: strstr, strcasestr, strspn, strcspn and strpbrk. This patch migrates corresponding tests for them from LLVM. Also, asan_intercepted_p predicate is updated to handle corresponding builtin codes. Regtested and bootstrapped on x86_64-unknown-linux-gnu, OK to apply? -Maxim gcc/ChangeLog: 2015-10-28 Maxim Ostapenko * asan.h (asan_intercepted_p): Handle BUILT_IN_STRCSPN, BUILT_IN_STRPBRK, BUILT_IN_STRSPN and BUILT_IN_STRSTR. gcc/testsuite/ChangeLog: 2015-10-28 Maxim Ostapenko * c-c++-common/asan/strcasestr-1.c: New test. * c-c++-common/asan/strcasestr-2.c: Likewise. * c-c++-common/asan/strcspn-1.c: Likewise. * c-c++-common/asan/strcspn-2.c: Likewise. * c-c++-common/asan/strpbrk-1.c: Likewise. * c-c++-common/asan/strpbrk-2.c: Likewise. * c-c++-common/asan/strspn-1.c: Likewise. * c-c++-common/asan/strspn-2.c: Likewise. * c-c++-common/asan/strstr-1.c: Likewise. * c-c++-common/asan/strstr-2.c: Likewise. Index: gcc/asan.h === --- gcc/asan.h (revision 229169) +++ gcc/asan.h (working copy) @@ -103,6 +103,10 @@ || fcode == BUILT_IN_STRNCASECMP || fcode == BUILT_IN_STRNCAT || fcode == BUILT_IN_STRNCMP + || fcode == BUILT_IN_STRCSPN + || fcode == BUILT_IN_STRPBRK + || fcode == BUILT_IN_STRSPN + || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRNCPY; } #endif /* TREE_ASAN */ Index: gcc/testsuite/c-c++-common/asan/strcasestr-1.c === --- gcc/testsuite/c-c++-common/asan/strcasestr-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/strcasestr-1.c (working copy) @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "strict_string_checks=true" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +#ifndef __cplusplus +#define _GNU_SOURCE +#else +extern "C" +#endif +char * +strcasestr(const char *haystack, const char *needle); + +int main(int argc, char **argv) { + char *r = 0; + char s2[] = "c"; + char s1[4] = "abC"; + __asan_poison_memory_region ((char *)&s1[2], 2); + r = strcasestr(s1, s2); + assert(r == s1 + 2); + return 0; +} + +/* { dg-output "READ of size 4 at .* thread T0.*" } */ +/* { dg-output ".*(main)?.*strcasestr-1.(c:21)?.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'s1\' <== Memory access at offset \[0-9\]+ partially overflows this variable" } */ Index: gcc/testsuite/c-c++-common/asan/strcasestr-2.c === --- gcc/testsuite/c-c++-common/asan/strcasestr-2.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/strcasestr-2.c (working copy) @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "strict_string_checks=true" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +#ifndef __cplusplus +#define _GNU_SOURCE +#else +extern "C" +#endif +char * +strcasestr(const char *haystack, const char *needle); + +int main(int argc, char **argv) { + char *r = 0; + char s1[] = "ab"; + char s2[4] = "cba"; + __asan_poison_memory_region ((char *)&s2[2], 2); + r = strcasestr(s1, s2); + assert(r == 0); + return 0; +} + +/* { dg-output "READ of size 4 at .* thread T0.*" } */ +/* { dg-output ".*(main)?.*strcasestr-2.(c:21)?.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'s2\' <== Memory access at offset \[0-9\]+ partially overflows this variable" } */ Index: gcc/testsuite/c-c++-common/asan/strcspn-1.c === --- gcc/testsuite/c-c++-common/asan/strcspn-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/strcspn-1.c (working copy) @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "strict_string_checks=true" } */ +/* { dg-shouldfail "asan" } */ + +#include +#include +#ifdef __cplusplus +extern "C" +#endif +__SIZE_TYPE__ +strcspn (const char *s, const char *reject); + +int main(int argc, char **argv) { + __SIZE_TYPE__ r; + char s2[] = "ab"; + char s1[4] = "caB"; + __asan_poison_memory_region ((char *)&s1[2], 2); + r = strcspn(s1, s2); + assert(r == 1); + return 0; +} + +/* { dg-output "READ of size 4 at .* thread T0.*" } */ +/* { dg-output ".*(main)?.*strcspn-1.(c:18)?.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'s1\' <== Memory access at offset \[0-9\]+ partially overflows this variable" } */ Index: gcc/testsuite/c-c++-common/asan/strcspn-2.c ==
[PATCH][4.9] Backport fix for PR sanitizer/64820.
Hi, this small patch fixes the logic in ASan vs SSP interaction to provide correct "size" parameter to asan_stack_malloc_[N] routines. With current logic, we would have assertion failure in libsanitizer in UAR mode on 32-bit targets due to wrong granularity of resulting addr + size address. Regtested via make check RUNTESTFLAGS="--target_board=unix'{-m32,-m64}' -j12 on x86_64-unknown-linux-gnu and bootstrapped on x86_64-unknown-linux-gnu. Ok for gcc-4_9-branch? -Maxim diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4df00bf..f1f2744 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2015-11-18 Max Ostapenko + + Backport from mainline. + 2015-03-16 Max Ostapenko + + PR sanitizer/64820 + * cfgexpand.c (align_base): New function. + (alloc_stack_frame_space): Call it. + (expand_stack_vars): Align prev_frame to be sure + data->asan_vec elements aligned properly. + 2015-11-12 Eric Botcazou PR target/67265 diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 14511e1..8bebd85 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -248,6 +248,15 @@ align_local_variable (tree decl) return align / BITS_PER_UNIT; } +/* Align given offset BASE with ALIGN. Truncate up if ALIGN_UP is true, + down otherwise. Return truncated BASE value. */ + +static inline unsigned HOST_WIDE_INT +align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up) +{ + return align_up ? (base + align - 1) & -align : base & -align; +} + /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame. Return the frame offset. */ @@ -256,20 +265,17 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align) { HOST_WIDE_INT offset, new_frame_offset; - new_frame_offset = frame_offset; if (FRAME_GROWS_DOWNWARD) { - new_frame_offset -= size + frame_phase; - new_frame_offset &= -align; - new_frame_offset += frame_phase; + new_frame_offset + = align_base (frame_offset - frame_phase - size, + align, false) + frame_phase; offset = new_frame_offset; } else { - new_frame_offset -= frame_phase; - new_frame_offset += align - 1; - new_frame_offset &= -align; - new_frame_offset += frame_phase; + new_frame_offset + = align_base (frame_offset - frame_phase, align, true) + frame_phase; offset = new_frame_offset; new_frame_offset += size; } @@ -983,13 +989,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) base = virtual_stack_vars_rtx; if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred) { - HOST_WIDE_INT prev_offset = frame_offset; + HOST_WIDE_INT prev_offset + = align_base (frame_offset, + MAX (alignb, ASAN_RED_ZONE_SIZE), + FRAME_GROWS_DOWNWARD); tree repr_decl = NULL_TREE; - offset = alloc_stack_frame_space (stack_vars[i].size + ASAN_RED_ZONE_SIZE, MAX (alignb, ASAN_RED_ZONE_SIZE)); + data->asan_vec.safe_push (prev_offset); data->asan_vec.safe_push (offset + stack_vars[i].size); /* Find best representative of the partition. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0072132..3d565ec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-11-18 Max Ostapenko + + Backport from mainline. + 2015-03-16 Max Ostapenko + + PR sanitizer/64820 + * c-c++-common/asan/pr64820.c: New test. + 2015-11-12 Eric Botcazou * gcc.target/i386/pr67265-2.c: New test. diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c new file mode 100644 index 000..885a662 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr64820.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-require-effective-target fstack_protector } */ +/* { dg-options "-fstack-protector-strong" } */ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ +/* { dg-shouldfail "asan" } */ + +__attribute__((noinline)) +char *Ident(char *x) { + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local[1 << 12]; + return Ident(local); +} + +__attribute__((noinline)) +void Func2(char *x) { + *x = 1; +} +int main(int argc, char **argv) { + Func2(Func1()); + return 0; +} + +/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "WRITE of size 1 at .* thread T0.*" } */ +/* { dg-output "#0.*(Func2)?.*pr64820.(c:21)?.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'local\' <== Memory access at offset 32 is inside this variable" } */
Backport important ASan features from upstream.
Hi! Since the last sanitizer library merge to GCC happened, some new useful features were applied upstream. In particular, the most significant are: * The shadow offset for ASan was unified on Aarch64 for 39 and 42 VMAs (http://reviews.llvm.org/D13782). AFAU, this change wouldn't require any additional support from compiler side, because the shadow offset is the same as for 39-bit VMA (36) . * Optional ASan recovery functionality was merged to sanitizer library (http://reviews.llvm.org/D12318). This feature seems to be very helpful in complex systems where we may want to proceed to work even in case of bug was detected. However, to access this functionality, we'll need to implement new asan_report_{store, load}{1, 2, 4, 8, 16, N}_noabort callbacks in compiler. This is probably unacceptable for stage 3. I think it would be nice to have unified shadow offset on Aarch64 for 39 and 42 VMAs even in GCC 6 (enabling ASan recovery would be nice too, but it's much harder). So, my question is: is it acceptable to backport these features from upstream without touching compiler side? If so, I see two options here: - Perform sanitizer library merge to GCC without changing compiler side. - Cherry-pick the patch for AArch64 on top of current trunk. Thanks, -Maxim
Re: Backport important ASan features from upstream.
On 19/11/15 13:18, Jakub Jelinek wrote: On Thu, Nov 19, 2015 at 11:19:23AM +0300, Maxim Ostapenko wrote: Hi! Since the last sanitizer library merge to GCC happened, some new useful features were applied upstream. In particular, the most significant are: * The shadow offset for ASan was unified on Aarch64 for 39 and 42 VMAs (http://reviews.llvm.org/D13782). AFAU, this change wouldn't require any additional support from compiler side, because the shadow offset is the same as for 39-bit VMA (36) . * Optional ASan recovery functionality was merged to sanitizer library (http://reviews.llvm.org/D12318). This feature seems to be very helpful in complex systems where we may want to proceed to work even in case of bug was detected. However, to access this functionality, we'll need to implement new asan_report_{store, load}{1, 2, 4, 8, 16, N}_noabort callbacks in compiler. This is probably unacceptable for stage 3. No, those are already there (for -fsanitize{,-recover}=kernel-address). IMHO all you need is remove: if (opts->x_flag_sanitize_recover & SANITIZE_USER_ADDRESS) error_at (loc, "-fsanitize-recover=address is not supported"); in opts.c (finish_options), and in asan.c (asan_expand_check_ifn) change bool recover_p = (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0; to say: bool recover_p; if (flag_sanitize & SANITIZE_USER_ADDRESS) recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0; else recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0; (plus add some testsuite coverage). This is small enough change that I'm ok with an exception for this. I think it would be nice to have unified shadow offset on Aarch64 for 39 and 42 VMAs even in GCC 6 (enabling ASan recovery would be nice too, but it's much harder). So, my question is: is it acceptable to backport these features from upstream without touching compiler side? If so, I see two options here: - Perform sanitizer library merge to GCC without changing compiler side. And at this point I also prefer the above, rather than cherry-picking, of course later on in the process cherry-picking will be desirable instead. Great, thanks! I'll try to perform another merge as soon as possible. - Cherry-pick the patch for AArch64 on top of current trunk. Jakub
[PATCH 0/2] Libsanitizer merge from upstream r253555.
Hi! Following recent discussion (https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02310.html), I would like to merge recent sanitizer library to GCC to make available new useful features from upstream in GCC 6: * The shadow offset for ASan was unified on Aarch64 for 39 and 42 VMAs (http://reviews.llvm.org/D13782). This change would not require any new code into compiler side. * Optional ASan recovery functionality was merged to sanitizer library (http://reviews.llvm.org/D12318). This feature requires some minimal compiler changes that I'll post below. * LSan was finally fixed and enabled for AArch64 (http://reviews.llvm.org/rL250898). The first patch is the library merge itself. I've also applied 3 GCC specific patches here (I don't post them separately to avoid polluting ChangeLog): * Patch for SPARC by David S. Miller (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01855.html). * Disable ODR violation detection (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01856.html). * Adjust the fix for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771 to extract the last PC from the stack frame if no valid FP is available for ARM (https://gcc.gnu.org/ml/gcc-patches/2015-10/msg01857.html). The second one reflects to corresponding compiler changes. In particular, it just enables -fsanitize-recover=address switch and migrates two small testcases from upstream. Regtested and bootstrapped on {x86_64, aarch64}-unknown-linux-gnu and arm-linux-gnueabi. Is it OK for mainline?
[PATCH 2/2] Libsanitizer merge from upstream r253555.
This patch reflects to corresponding compiler changes. In particular, it just enables -fsanitize-recover=address switch and migrates two small testcases from upstream. I don't backport other stress tests because they are heavy and have unstable output. -Maxim gcc/testsuite/ChangeLog: 2015-11-23 Maxim Ostapenko * c-c++-common/asan/halt_on_error-1.c: New test. * c-c++-common/asan/halt_on_error-2.c: Likewise. gcc/ChangeLog: 2015-11-23 Maxim Ostapenko * opts.c (finish_options): Allow -fsanitize-recover=address for userspace sanitization. * asan.c (asan_expand_check_ifn): Redefine recover_p. * doc/invoke.texi (fsanitize-recover): Update documentation. Index: gcc/asan.c === --- gcc/asan.c (revision 230597) +++ gcc/asan.c (working copy) @@ -2533,10 +2533,12 @@ { gimple *g = gsi_stmt (*iter); location_t loc = gimple_location (g); + bool recover_p; + if (flag_sanitize & SANITIZE_USER_ADDRESS) +recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0; + else +recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0; - bool recover_p -= (flag_sanitize & flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0; - HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0)); gcc_assert (flags < ASAN_CHECK_LAST); bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0; Index: gcc/doc/invoke.texi === --- gcc/doc/invoke.texi (revision 230597) +++ gcc/doc/invoke.texi (working copy) @@ -6111,8 +6111,10 @@ Currently this feature only works for @option{-fsanitize=undefined} (and its suboptions except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}), -@option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero} and -@option{-fsanitize=kernel-address}. For these sanitizers error recovery is turned on by default. +@option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero}, +@option{-fsanitize=kernel-address} and @option{-fsanitize=address}. +For these sanitizers error recovery is turned on by default, except @option{-fsanitize=address}, +for which this feature is experimental. @option{-fsanitize-recover=all} and @option{-fno-sanitize-recover=all} is also accepted, the former enables recovery for all sanitizers that support it, the latter disables recovery for all sanitizers that support it. Index: gcc/opts.c === --- gcc/opts.c (revision 230597) +++ gcc/opts.c (working copy) @@ -941,11 +941,8 @@ "-fsanitize=address and -fsanitize=kernel-address " "are incompatible with -fsanitize=thread"); - /* Error recovery is not allowed for ASan and TSan. */ + /* Error recovery is not allowed for LSan and TSan. */ - if (opts->x_flag_sanitize_recover & SANITIZE_USER_ADDRESS) -error_at (loc, "-fsanitize-recover=address is not supported"); - if (opts->x_flag_sanitize_recover & SANITIZE_THREAD) error_at (loc, "-fsanitize-recover=thread is not supported"); Index: gcc/testsuite/c-c++-common/asan/halt_on_error-1.c === --- gcc/testsuite/c-c++-common/asan/halt_on_error-1.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/halt_on_error-1.c (working copy) @@ -0,0 +1,23 @@ +/* Test recovery mode. */ +/* { dg-do run } */ +/* { dg-options "-fsanitize-recover=address" } */ +/* { dg-set-target-env-var ASAN_OPTIONS "halt_on_error=false" } */ + +#include + +volatile int ten = 10; + +int main() { + char x[10]; + memset(x, 0, 11); + asm volatile ("" : : : "memory"); + volatile int res = x[ten]; + x[ten] = res + 3; + res = x[ten]; + return 0; +} + +/* { dg-output "WRITE of size 11 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */ +/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */ +/* { dg-output "\[^\n\r]*WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */ +/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r).*" } */ Index: gcc/testsuite/c-c++-common/asan/halt_on_error-2.c === --- gcc/testsuite/c-c++-common/asan/halt_on_error-2.c (revision 0) +++ gcc/testsuite/c-c++-common/asan/halt_on_error-2.c (working copy) @@ -0,0 +1,24 @@ +/* Test recovery mode. */ +/* { dg-do run } */ +/* { dg-options "-fsanitize-recover=address" } */ +/* { dg-set-target-env-var ASAN_OPTIONS "halt_on_error=true" } */ +/* { dg-shouldfail "asan" } */ + +#include + +volatile int ten = 10; + +int main() { + char x[10]; + memset(x, 0, 11); + asm volatile ("" : : : "mem
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
+ Adhemerval Christophe, it looks like your kernel headers (asm/ptrace.h) don't contain ARM_VFPREGS_SIZE. Do you use old kernel version? -Maxim On 23/11/15 15:16, Christophe Lyon wrote: On 23 November 2015 at 09:07, Jakub Jelinek wrote: On Mon, Nov 23, 2015 at 10:46:33AM +0300, Maxim Ostapenko wrote: Index: libsanitizer/configure.ac === --- libsanitizer/configure.ac (revision 230597) +++ libsanitizer/configure.ac (working copy) @@ -136,6 +136,12 @@ esac AM_CONDITIONAL(USING_MAC_INTERPOSE, $MAC_INTERPOSE) +case "$target" in + aarch64-*-linux*) tsan_aarch64=true ;; + *) tsan_aarch64=false ;; +esac +AM_CONDITIONAL(TSAN_AARCH64, $tsan_aarch64) + I don't understand the purpose of the above. Index: libsanitizer/configure.tgt === --- libsanitizer/configure.tgt(revision 230597) +++ libsanitizer/configure.tgt(working copy) @@ -37,6 +37,8 @@ aarch64*-*-linux*) if test x$ac_cv_sizeof_void_p = x8; then TSAN_SUPPORTED=yes + LSAN_SUPPORTED=yes + TSAN_TARGET_DEPENDENT_OBJECTS=tsan_rtl_aarch64.lo fi ;; x86_64-*-darwin[1]* | i?86-*-darwin[1]*) You already have this. Index: libsanitizer/tsan/Makefile.am === --- libsanitizer/tsan/Makefile.am (revision 230597) +++ libsanitizer/tsan/Makefile.am (working copy) @@ -21,6 +21,8 @@ tsan_interface_atomic.cc \ tsan_interface.cc \ tsan_interface_java.cc \ + tsan_libdispatch_mac.cc \ + tsan_malloc_mac.cc \ tsan_md5.cc \ tsan_mman.cc \ tsan_mutex.cc \ @@ -28,6 +30,7 @@ tsan_new_delete.cc \ tsan_platform_linux.cc \ tsan_platform_mac.cc \ + tsan_platform_posix.cc \ tsan_platform_windows.cc \ tsan_report.cc \ tsan_rtl.cc \ @@ -41,7 +44,11 @@ tsan_sync.cc libtsan_la_SOURCES = $(tsan_files) +if TSAN_AARCH64 +EXTRA_libtsan_la_SOURCES = tsan_rtl_aarch64.S +else EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S +endif And if I understand automake manual, you can list in there both EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S unconditionally, and what object actually gets linked in is picked from the $(TSAN_TARGET_DEPENDENT_OBJECTS) (and similarly dependencies). Otherwise LGTM. Since this commit (r230739), I've noticed that the arm*linux* builds fail: libtool: compile: /tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/./gcc/xgcc -shared-libgcc -B/tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/g cc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/./gcc -nostdinc++ -L/tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/arm-none-linux-gnueabi/ libstdc++-v3/src -L/tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/arm-none-linux-gnueabi/libstdc++-v3/src/.libs -L/tmp/1800227_1.tmpdir/ aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-linux-gnueabi/gcc3/arm-none-linux-gnueabi/libstdc++-v3/libsupc++/.libs -B/tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/t ools/arm-none-linux-gnueabi/bin/ -B/tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/arm-none-linux-gnueabi/lib/ -isystem /tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gc c-fsf-gccsrc/tools/arm-none-linux-gnueabi/include -isystem /tmp/1800227_1.tmpdir/aci-gcc-fsf/builds/gcc-fsf-gccsrc/tools/arm-none-linux-gnueabi/sys-include -D_GNU_SOURCE -D_DEBU G -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DHAVE_RPC_XDR_H=1 -DHAVE_TIRPC_RPC_XDR_H=0 -I. -I/tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsr c/libsanitizer/sanitizer_common -I.. -I /tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libsanitizer/include -isystem /tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/ gccsrc/libsanitizer/include/system -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti -fomit-frame-pointer -fun wind-tables -fvisibility=hidden -Wno-variadic-macros -I../../libstdc++-v3/include -I../../libstdc++-v3/include/arm-none-linux-gnueabi -I/tmp/1800227_1.tmpdir/aci-gcc-fsf/sources /gcc-fsf/gccsrc/libsanitizer/../libstdc++-v3/libsupc++ -std=gnu++11 -DSANITIZER_LIBBACKTRACE -DSANITIZER_CP_DEMANGLE -I /tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/ libsanitizer/../libbacktrace -I ../libbacktrace -I /tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libsanitizer/../include -include /tmp/1800227_1.tmpdir/aci-gcc-fsf/so urces/gcc-fsf/gccsrc/libsanitizer/libbacktrace/backtrace-rename.h -g -O2 -D_GNU_SOURCE -MT sanitizer_platform_limits_posix.lo -MD -MP -MF .deps/sanitizer_platform_limits_posix.T po -c /tmp/1800227_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 23/11/15 16:00, Christophe Lyon wrote: On 23 November 2015 at 13:41, Jakub Jelinek wrote: On Mon, Nov 23, 2015 at 03:33:57PM +0300, Maxim Ostapenko wrote: + Adhemerval Christophe, it looks like your kernel headers (asm/ptrace.h) don't contain ARM_VFPREGS_SIZE. Do you use old kernel version? Yes, I do use old kernel headers. I could upgrade them, but I tend to avoid changing versions (binutils, glibc, newlib, kernel headers) unless really necessary. Unlike LLVM, we do care to support older kernel headers. So, if it is say a define, you could add libsanitizer/include/system/linux/ptrace.h or libsanitizer/include/system/asm/ptrace.h that would #include_next the original header and ifdef __arm__ and that define is not defined (or some other condition, kernel version etc.), define it. Jakub So, given Jakub's answer I'll not upgrade them yet on my side :-) Yeah, right. I've asked about kernel headers just to make sure I correctly understand the issue. Actually, I see such code in lib/sanitizer_common/sanitizer_platform_limits_posix.cc: #if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS) int ptrace_getvfpregs = PTRACE_GETVFPREGS; int ptrace_setvfpregs = PTRACE_SETVFPREGS; #else int ptrace_getvfpregs = -1; int ptrace_setvfpregs = -1; #endif and in ptrace interceptor: else if (request == ptrace_setvfpregs) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_getvfpregs) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz) So, perhaps we can do the same thing with ARM_VFPREGS_SIZE, something like this? diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc index 9866cc9..20ff224 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -323,10 +323,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); #endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__ #ifdef __arm__ +#if defined(ARM_VFPREGS_SIZE) unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; #else unsigned struct_user_vfpregs_struct_sz = 0; #endif +#else + unsigned struct_user_vfpregs_struct_sz = 0; +#endif
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 23/11/15 16:24, Jakub Jelinek wrote: On Mon, Nov 23, 2015 at 04:21:34PM +0300, Maxim Ostapenko wrote: Yeah, right. I've asked about kernel headers just to make sure I correctly understand the issue. Actually, I see such code in lib/sanitizer_common/sanitizer_platform_limits_posix.cc: #if defined(PTRACE_GETVFPREGS) && defined(PTRACE_SETVFPREGS) int ptrace_getvfpregs = PTRACE_GETVFPREGS; int ptrace_setvfpregs = PTRACE_SETVFPREGS; #else int ptrace_getvfpregs = -1; int ptrace_setvfpregs = -1; #endif and in ptrace interceptor: else if (request == ptrace_setvfpregs) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz); else if (request == ptrace_getvfpregs) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz) So, perhaps we can do the same thing with ARM_VFPREGS_SIZE, something like this? diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc index 9866cc9..20ff224 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -323,10 +323,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); #endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__ #ifdef __arm__ +#if defined(ARM_VFPREGS_SIZE) unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; #else unsigned struct_user_vfpregs_struct_sz = 0; #endif +#else + unsigned struct_user_vfpregs_struct_sz = 0; +#endif Maybe, but then it would need to be approved upstream. If you just define ARM_VFPREGS_SIZE to 0 or whatever else in the GCC owned wrapper headers, you can avoid that. I guess talk to upstream. Jakub Ok, I posted a fix to upstream (http://reviews.llvm.org/D14921) yesterday, but it's still not reviewed. So, I'm wondering if I should fix the issue locally? Attaching proposed fix following Jakub's suggestion. Christophe could you try the patch? diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index b97fc7d..c392c57 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,7 @@ +2015-11-24 Maxim Ostapenko + + * include/system/linux/asm/ptrace.h: New header. + 2015-11-23 Maxim Ostapenko * All source files: Merge from upstream r253555. diff --git a/libsanitizer/include/system/linux/asm/ptrace.h b/libsanitizer/include/system/linux/asm/ptrace.h new file mode 100644 index 000..dbdd58b --- /dev/null +++ b/libsanitizer/include/system/linux/asm/ptrace.h @@ -0,0 +1,8 @@ +#include_next +#if defined(__arm__) +#ifndef ARM_VFPREGS_SIZE +/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + and core dumps. */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) +#endif +#endif
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 24/11/15 11:25, Jakub Jelinek wrote: On Tue, Nov 24, 2015 at 10:51:05AM +0300, Maxim Ostapenko wrote: Ok, I posted a fix to upstream (http://reviews.llvm.org/D14921) yesterday, but it's still not reviewed. So, I'm wondering if I should fix the issue locally? Attaching proposed fix following Jakub's suggestion. Christophe could you try the patch? diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index b97fc7d..c392c57 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,7 @@ +2015-11-24 Maxim Ostapenko + + * include/system/linux/asm/ptrace.h: New header. + 2015-11-23 Maxim Ostapenko * All source files: Merge from upstream r253555. diff --git a/libsanitizer/include/system/linux/asm/ptrace.h b/libsanitizer/include/system/linux/asm/ptrace.h new file mode 100644 index 000..dbdd58b --- /dev/null +++ b/libsanitizer/include/system/linux/asm/ptrace.h @@ -0,0 +1,8 @@ +#include_next +#if defined(__arm__) +#ifndef ARM_VFPREGS_SIZE +/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + and core dumps. */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) +#endif +#endif You could have just used #if defined(__arm__) && !defined(ARM_VFPREGS_SIZE) or #ifdef __arm__ or #if !defined(ARM_VFPREGS_SIZE). Mixing if defined with ifndef on the next line is just weird. And, you should mention which kernel version introduced ARM_VFPREGS_SIZE macro (I believe it was 2011-ish, but have not checked exact kernel version). Jakub Ok, does it look better now? -Maxim diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index b97fc7d..c392c57 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,7 @@ +2015-11-24 Maxim Ostapenko + + * include/system/linux/asm/ptrace.h: New header. + 2015-11-23 Maxim Ostapenko * All source files: Merge from upstream r253555. diff --git a/libsanitizer/include/system/linux/asm/ptrace.h b/libsanitizer/include/system/linux/asm/ptrace.h new file mode 100644 index 000..d4249fe --- /dev/null +++ b/libsanitizer/include/system/linux/asm/ptrace.h @@ -0,0 +1,7 @@ +#include_next +/* ARM_VFPREGS_SIZE has been added in 3.0 */ +#if defined(__arm__) && !defined(ARM_VFPREGS_SIZE) +/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + and core dumps. */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) +#endif
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 24/11/15 11:38, Jakub Jelinek wrote: On Tue, Nov 24, 2015 at 11:36:20AM +0300, Maxim Ostapenko wrote: Ok, does it look better now? Sure, this is ok for trunk. diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index b97fc7d..c392c57 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,7 @@ +2015-11-24 Maxim Ostapenko + + * include/system/linux/asm/ptrace.h: New header. + 2015-11-23 Maxim Ostapenko * All source files: Merge from upstream r253555. diff --git a/libsanitizer/include/system/linux/asm/ptrace.h b/libsanitizer/include/system/linux/asm/ptrace.h new file mode 100644 index 000..d4249fe --- /dev/null +++ b/libsanitizer/include/system/linux/asm/ptrace.h @@ -0,0 +1,7 @@ +#include_next +/* ARM_VFPREGS_SIZE has been added in 3.0 */ +#if defined(__arm__) && !defined(ARM_VFPREGS_SIZE) +/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + and core dumps. */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) +#endif Jakub Thanks, applied as r230790. Christophe, please let me know if it cured your build. -Maxim
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 24/11/15 14:27, Jakub Jelinek wrote: On Tue, Nov 24, 2015 at 12:23:05PM +0100, Christophe Lyon wrote: On 24 November 2015 at 12:12, Jakub Jelinek wrote: On Tue, Nov 24, 2015 at 12:08:13PM +0100, Christophe Lyon wrote: Sure. I had a build in progress with your proposed patch, but it didn't complete before you committed :-) So... it still does not work for me. I re-tried several times, made sure I had everything cleanup before starting new builds from scratch, hence the delay. I'm still seeing: /tmp/2050111_1.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc:326:44: error: 'ARM_VFPREGS_SIZE' was not declared in this scope unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; So cut'n'paste the sanitizer_platform_limits_posix.cc compilation command line and replace -c with -E -dD, then look if the wrapper asm/ptrace.h is included or not and why? It pulls the one from the sysroot: sysroot-arm-none-linux-gnueabihf/usr/include/asm/ptrace.h (I configure GCC --with-sysroot=XXX) Then you should figure out where the sysroot include dirs are added in the sanitizer_common/Makefile and make sure -isystem $(top_srcdir)/include/system comes before that. Jakub It seems that I placed new header into wrong directory, it should be libsanitizer/include/system/asm/ptrace.h instead of libsanitizer/include/system/linux/asm/ptrace.h This should work: $ cat .libs/sanitizer_platform_limits_posix.i . # 1 "/home/max/workspace/downloads/gcc/libsanitizer/include/system/asm/ptrace.h" 1 3 4 # 1 "/home/max/install/armv7l-tizen/armv7l-tizen-linux-gnueabi/sys-root/usr/include/asm/ptrace.h" 1 3 4 # 11 "/home/max/install/armv7l-tizen/armv7l-tizen-linux-gnueabi/sys-root/usr/include/asm/ptrace.h" 3 4 #define __ASM_ARM_PTRACE_H~ # 1 "/home/max/install/armv7l-tizen/armv7l-tizen-linux-gnueabi/sys-root/usr/include/asm/hwcap.h" 1 3 4 #define __ASMARM_HWCAP_H~ . diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index c392c57..895d3bd 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,5 +1,10 @@ 2015-11-24 Maxim Ostapenko + * include/system/linux/asm/ptrace.h: Move to ... + * include/system/asm/ptrace.h: ... this. + +2015-11-24 Maxim Ostapenko + * include/system/linux/asm/ptrace.h: New header. 2015-11-23 Maxim Ostapenko diff --git a/libsanitizer/include/system/asm/ptrace.h b/libsanitizer/include/system/asm/ptrace.h new file mode 100644 index 000..5d2fe9b --- /dev/null +++ b/libsanitizer/include/system/asm/ptrace.h @@ -0,0 +1,7 @@ +#include_next +/* ARM_VFPREGS_SIZE has been added in 3.0 */ +#if defined(__arm__) && !defined(ARM_VFPREGS_SIZE) +/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS + and core dumps. */ +#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) +#endif diff --git a/libsanitizer/include/system/linux/asm/ptrace.h b/libsanitizer/include/system/linux/asm/ptrace.h deleted file mode 100644 index d4249fe..000 --- a/libsanitizer/include/system/linux/asm/ptrace.h +++ /dev/null @@ -1,7 +0,0 @@ -#include_next -/* ARM_VFPREGS_SIZE has been added in 3.0 */ -#if defined(__arm__) && !defined(ARM_VFPREGS_SIZE) -/* The size of the user-visible VFP state as seen by PTRACE_GET/SETVFPREGS - and core dumps. */ -#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ ) -#endif
Re: [PATCH 1/2] Libsanitizer merge from upstream r253555.
On 24/11/15 15:17, Christophe Lyon wrote: On 24 November 2015 at 12:57, Jakub Jelinek wrote: On Tue, Nov 24, 2015 at 02:55:26PM +0300, Maxim Ostapenko wrote: diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index c392c57..895d3bd 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,5 +1,10 @@ 2015-11-24 Maxim Ostapenko + * include/system/linux/asm/ptrace.h: Move to ... + * include/system/asm/ptrace.h: ... this. + +2015-11-24 Maxim Ostapenko + * include/system/linux/asm/ptrace.h: New header. Of course, sorry for not catching that. Indeed, this works. Thanks. Jakub Applied as r230804, sorry for inconvenience! -Maxim
[PING][PATCH][4.9] Backport fix for PR sanitizer/64820.
I would like to ping the patch: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02174.html.
[PING v2][PATCH][4.9] Backport fix for PR sanitizer/64820.
On 25/11/15 12:14, Maxim Ostapenko wrote: I would like to ping the patch: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02174.html. Ping. -Maxim
[PING v3][PATCH][4.9] Backport fix for PR sanitizer/64820.
On 01/12/15 20:23, Maxim Ostapenko wrote: On 25/11/15 12:14, Maxim Ostapenko wrote: I would like to ping the patch: https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02174.html. Ping. Ping. -Maxim
[PING^3][RFC, PATCH][ASAN] Implement dynamic allocas/VLAs sanitization.
Hi, I would like to ping the following patch: https://gcc.gnu.org/ml/gcc-patches/2017-05/msg01374.html Rebased version is attached. Thanks, -Maxim gcc/ChangeLog: 2017-06-13 Maxim Ostapenko * asan.c: Include gimple-fold.h. (get_last_alloca_addr): New function. (handle_builtin_stackrestore): Likewise. (handle_builtin_alloca): Likewise. (asan_emit_allocas_unpoison): Likewise. (get_mem_refs_of_builtin_call): Add new parameter, remove const quallifier from first paramerer. Handle BUILT_IN_ALLOCA, BUILT_IN_ALLOCA_WITH_ALIGN and BUILT_IN_STACK_RESTORE builtins. (instrument_builtin_call): Pass gimple iterator to get_mem_refs_of_builtin_call. (last_alloca_addr): New global. * asan.h (asan_emit_allocas_unpoison): Declare. * builtins.c (expand_asan_emit_allocas_unpoison): New function. (expand_builtin): Handle BUILT_IN_ASAN_ALLOCAS_UNPOISON. * cfgexpand.c (expand_used_vars): Call asan_emit_allocas_unpoison if function calls alloca. * gimple-fold.c (replace_call_with_value): Remove static keyword. * gimple-fold.h (replace_call_with_value): Declare. * internal-fn.c: Include asan.h. * sanitizer.def (BUILT_IN_ASAN_ALLOCA_POISON, BUILT_IN_ASAN_ALLOCAS_UNPOISON): New builtins. gcc/testsuite/ChangeLog: 2017-06-13 Maxim Ostapenko * c-c++-common/asan/alloca_big_alignment.c: New test. * c-c++-common/asan/alloca_detect_custom_size.c: Likewise. * c-c++-common/asan/alloca_instruments_all_paddings.c: Likewise. * c-c++-common/asan/alloca_loop_unpoisoning.c: Likewise. * c-c++-common/asan/alloca_overflow_partial.c: Likewise. * c-c++-common/asan/alloca_overflow_right.c: Likewise. * c-c++-common/asan/alloca_safe_access.c: Likewise. * c-c++-common/asan/alloca_underflow_left.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index bf564a4..4835db9 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "cfgloop.h" #include "gimple-builder.h" +#include "gimple-fold.h" #include "ubsan.h" #include "params.h" #include "builtins.h" @@ -245,6 +246,7 @@ along with GCC; see the file COPYING3. If not see static unsigned HOST_WIDE_INT asan_shadow_offset_value; static bool asan_shadow_offset_computed; static vec sanitized_sections; +static tree last_alloca_addr = NULL_TREE; /* Set of variable declarations that are going to be guarded by use-after-scope sanitizer. */ @@ -531,11 +533,166 @@ get_mem_ref_of_assignment (const gassign *assignment, return true; } +/* Return address of last allocated dynamic alloca. */ + +static tree +get_last_alloca_addr () +{ + if (last_alloca_addr) +return last_alloca_addr; + + gimple_seq seq = NULL; + gassign *g; + + last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr"); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, + build_int_cst (ptr_type_node, 0)); + gimple_seq_add_stmt_without_update (&seq, g); + + edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + gsi_insert_seq_on_edge_immediate (e, seq); + return last_alloca_addr; +} + +/* Insert __asan_allocas_unpoison(top, bottom) call after + __builtin_stackrestore(new_sp) call. + The pseudocode of this routine should look like this: + __builtin_stackrestore(new_sp); + top = last_alloca_addr; + bot = virtual_dynamic_stack_rtx; + __asan_allocas_unpoison(top, bottom); + last_alloca_addr = new_sp; + We don't use new_sp as bot parameter because on some architectures + SP has non zero offset from dynamic stack area. Moreover, on some + architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each + particular function only after all callees were expanded to rtl. + The most noticable example is PowerPC{,64}, see + http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK. +*/ + +static void +handle_builtin_stackrestore (gcall *call, gimple_stmt_iterator *iter) +{ + if (!iter) +return; + + gimple_stmt_iterator gsi = *iter; + gimple_seq seq = NULL; + tree last_alloca_addr = get_last_alloca_addr (); + tree restored_stack = gimple_call_arg (call, 0); + tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON); + gimple *g = gimple_build_call (fn, 2, last_alloca_addr, restored_stack); + gimple_seq_add_stmt_without_update (&seq, g); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, restored_stack); + gimple_seq_add_stmt_without_update (&seq, g); + gsi_insert_seq_after (&gsi, seq, GSI_SAME_STMT); +} + +/* Deploy and poison redzones around __builtin_alloca call. To do this, we + should replace this call with another one with changed parameters and + replace all its uses with new address, so + addr = __builtin_alloca (old_size, align); + is replaced by + new_size = old_size + additional_size; + tmp = __builtin_alloca (new_size, max(align, 32)) + addr = tmp + 32 (first 3
Re: [PING^3][RFC, PATCH][ASAN] Implement dynamic allocas/VLAs sanitization.
Hi Jakub, thank you for your points. I've updated the patch. -Maxim gcc/ChangeLog: 2017-06-14 Maxim Ostapenko * asan.c: Include gimple-fold.h. (get_last_alloca_addr): New function. (handle_builtin_stackrestore): Likewise. (handle_builtin_alloca): Likewise. (asan_emit_allocas_unpoison): Likewise. (get_mem_refs_of_builtin_call): Add new parameter, remove const quallifier from first paramerer. Handle BUILT_IN_ALLOCA, BUILT_IN_ALLOCA_WITH_ALIGN and BUILT_IN_STACK_RESTORE builtins. (instrument_builtin_call): Pass gimple iterator to get_mem_refs_of_builtin_call. (last_alloca_addr): New global. * asan.h (asan_emit_allocas_unpoison): Declare. * builtins.c (expand_asan_emit_allocas_unpoison): New function. (expand_builtin): Handle BUILT_IN_ASAN_ALLOCAS_UNPOISON. * cfgexpand.c (expand_used_vars): Call asan_emit_allocas_unpoison if function calls alloca. * gimple-fold.c (replace_call_with_value): Remove static keyword. * gimple-fold.h (replace_call_with_value): Declare. * internal-fn.c: Include asan.h. * sanitizer.def (BUILT_IN_ASAN_ALLOCA_POISON, BUILT_IN_ASAN_ALLOCAS_UNPOISON): New builtins. gcc/testsuite/ChangeLog: 2017-06-14 Maxim Ostapenko * c-c++-common/asan/alloca_big_alignment.c: New test. * c-c++-common/asan/alloca_detect_custom_size.c: Likewise. * c-c++-common/asan/alloca_instruments_all_paddings.c: Likewise. * c-c++-common/asan/alloca_loop_unpoisoning.c: Likewise. * c-c++-common/asan/alloca_overflow_partial.c: Likewise. * c-c++-common/asan/alloca_overflow_right.c: Likewise. * c-c++-common/asan/alloca_safe_access.c: Likewise. * c-c++-common/asan/alloca_underflow_left.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index bf564a4..28e773a 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "cfgloop.h" #include "gimple-builder.h" +#include "gimple-fold.h" #include "ubsan.h" #include "params.h" #include "builtins.h" @@ -245,6 +246,7 @@ along with GCC; see the file COPYING3. If not see static unsigned HOST_WIDE_INT asan_shadow_offset_value; static bool asan_shadow_offset_computed; static vec sanitized_sections; +static tree last_alloca_addr = NULL_TREE; /* Set of variable declarations that are going to be guarded by use-after-scope sanitizer. */ @@ -531,11 +533,166 @@ get_mem_ref_of_assignment (const gassign *assignment, return true; } +/* Return address of last allocated dynamic alloca. */ + +static tree +get_last_alloca_addr () +{ + if (last_alloca_addr) +return last_alloca_addr; + + gimple_seq seq = NULL; + gassign *g; + + last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr"); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, + build_int_cst (ptr_type_node, 0)); + gimple_seq_add_stmt_without_update (&seq, g); + + edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + gsi_insert_seq_on_edge_immediate (e, seq); + return last_alloca_addr; +} + +/* Insert __asan_allocas_unpoison (top, bottom) call after + __builtin_stack_restore (new_sp) call. + The pseudocode of this routine should look like this: + __builtin_stack_restore (new_sp); + top = last_alloca_addr; + bot = virtual_dynamic_stack_rtx; + __asan_allocas_unpoison (top, bottom); + last_alloca_addr = new_sp; + We don't use new_sp as bot parameter because on some architectures + SP has non zero offset from dynamic stack area. Moreover, on some + architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each + particular function only after all callees were expanded to rtl. + The most noticable example is PowerPC{,64}, see + http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK. +*/ + +static void +handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter) +{ + if (!iter) +return; + + gimple_stmt_iterator gsi = *iter; + gimple_seq seq = NULL; + tree last_alloca_addr = get_last_alloca_addr (); + tree restored_stack = gimple_call_arg (call, 0); + tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON); + gimple *g = gimple_build_call (fn, 2, last_alloca_addr, restored_stack); + gimple_seq_add_stmt_without_update (&seq, g); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, restored_stack); + gimple_seq_add_stmt_without_update (&seq, g); + gsi_insert_seq_after (&gsi, seq, GSI_SAME_STMT); +} + +/* Deploy and poison redzones around __builtin_alloca call. To do this, we + should replace this call with another one with changed parameters and + replace all its uses with new address, so + addr = __builtin_alloca (old_size, align); + is replaced by + new_size = old_size + additional_size; + tmp = __builtin_alloca (new_size, max (align, 32)) + addr = tmp + 32 (first 32 bytes are for the left redzone); + ADDITIONAL_SIZE is added to m
[PATCH, Committed] Add myself to MAINTAINERS file
Hi, when requesting cfarm account, Segher noticed that I didn't add myself in MAINTAINERS file when obtained write access to SVN repo. Fixing this now. -Maxim diff --git a/MAINTAINERS b/MAINTAINERS index c76c181..04fcb8a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -523,6 +523,7 @@ Braden Obrzut Carlos O'Donell Peter O'Gorman Andrea Ornstein +Maxim Ostapenko Patrick Palka Devang Patel Andris Pavenis
[PATCH v2][ASAN] Implement dynamic allocas/VLAs sanitization.
Hi, I'm sorry for a long delay. Here an updated patch. Following Jakub's suggestion from previous review, I've added a get_nonzero_bits stuff into handle_builtin_alloca in order to avoid redundant redzone size calculations in case we know that alloca has alignment >= ASAN_RED_ZONE_SIZE. Thus, for the following code: struct __attribute__((aligned (N))) S { char s[N]; }; void bar (struct S *, struct S *); void foo (int x) { struct S a; { struct S b[x]; bar (&a, &b[0]); } { struct S b[x + 4]; bar (&a, &b[0]); } } void baz (int x) { struct S a; struct S b[x]; bar (&a, &b[0]); } compiled with -O2 -fsanitize=address -DN=64, we have expected _2 = (sizetype) x_1(D); _8 = _2 * 64; _14 = _8 + 96; _15 = __builtin_alloca_with_align (_14, 512); _16 = _15 + 64; __builtin___asan_alloca_poison (_16, _8); instead of previous _1 = (sizetype) x_4(D); _2 = _1 * 64; _24 = _2 & 31; _19 = _2 + 128; _27 = _19 - _24; _28 = __builtin_alloca_with_align (_27, 512); _29 = _28 + 64; __builtin___asan_alloca_poison (_29, _2); Also, I've added a simple pattern for X & C -> 0 if we know that corresponding bits are zero, but I'm not sure this pattern has a practical value. Tested and bootstrapped on x86_64-unknown-linux-gnu. Could you take a look? -Maxim gcc/ChangeLog: 2017-06-26 Maxim Ostapenko * asan.c: Include gimple-fold.h. (get_last_alloca_addr): New function. (handle_builtin_stackrestore): Likewise. (handle_builtin_alloca): Likewise. (asan_emit_allocas_unpoison): Likewise. (get_mem_refs_of_builtin_call): Add new parameter, remove const quallifier from first paramerer. Handle BUILT_IN_ALLOCA, BUILT_IN_ALLOCA_WITH_ALIGN and BUILT_IN_STACK_RESTORE builtins. (instrument_builtin_call): Pass gimple iterator to get_mem_refs_of_builtin_call. (last_alloca_addr): New global. * asan.h (asan_emit_allocas_unpoison): Declare. * builtins.c (expand_asan_emit_allocas_unpoison): New function. (expand_builtin): Handle BUILT_IN_ASAN_ALLOCAS_UNPOISON. * cfgexpand.c (expand_used_vars): Call asan_emit_allocas_unpoison if function calls alloca. * gimple-fold.c (replace_call_with_value): Remove static keyword. * gimple-fold.h (replace_call_with_value): Declare. * internal-fn.c: Include asan.h. * sanitizer.def (BUILT_IN_ASAN_ALLOCA_POISON, BUILT_IN_ASAN_ALLOCAS_UNPOISON): New builtins. * match.pd: Add new pattern. gcc/testsuite/ChangeLog: 2017-06-26 Maxim Ostapenko * c-c++-common/asan/alloca_big_alignment.c: New test. * c-c++-common/asan/alloca_detect_custom_size.c: Likewise. * c-c++-common/asan/alloca_instruments_all_paddings.c: Likewise. * c-c++-common/asan/alloca_loop_unpoisoning.c: Likewise. * c-c++-common/asan/alloca_overflow_partial.c: Likewise. * c-c++-common/asan/alloca_overflow_right.c: Likewise. * c-c++-common/asan/alloca_safe_access.c: Likewise. * c-c++-common/asan/alloca_underflow_left.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index e730530..6d7a5ec 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "cfgloop.h" #include "gimple-builder.h" +#include "gimple-fold.h" #include "ubsan.h" #include "params.h" #include "builtins.h" @@ -245,6 +246,7 @@ along with GCC; see the file COPYING3. If not see static unsigned HOST_WIDE_INT asan_shadow_offset_value; static bool asan_shadow_offset_computed; static vec sanitized_sections; +static tree last_alloca_addr = NULL_TREE; /* Set of variable declarations that are going to be guarded by use-after-scope sanitizer. */ @@ -529,11 +531,183 @@ get_mem_ref_of_assignment (const gassign *assignment, return true; } +/* Return address of last allocated dynamic alloca. */ + +static tree +get_last_alloca_addr () +{ + if (last_alloca_addr) +return last_alloca_addr; + + gimple_seq seq = NULL; + gassign *g; + + last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr"); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, + build_int_cst (ptr_type_node, 0)); + gimple_seq_add_stmt_without_update (&seq, g); + + edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + gsi_insert_seq_on_edge_immediate (e, seq); + return last_alloca_addr; +} + +/* Insert __asan_allocas_unpoison (top, bottom) call after + __builtin_stack_restore (new_sp) call. + The pseudocode of this routine should look like this: + __builtin_stack_restore (new_sp); + top = last_alloca_addr; + bot = virtual_dynamic_stack_rtx; + __asan_allocas_unpoison (top, bottom); + last_alloca_addr = new_sp; + We don't use new_sp as bot parameter because on some architectures + SP has non zero offset from dynamic stack area. Moreover, on some + architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each + part
Re: [PATCH v2][ASAN] Implement dynamic allocas/VLAs sanitization.
Hi, On 29/06/17 15:35, Jakub Jelinek wrote: Hi! Sorry for the review delay. On Mon, Jun 26, 2017 at 03:49:23PM +0300, Maxim Ostapenko wrote: (handle_builtin_stackrestore): Likewise. The function is called with _ between stack and restore. * match.pd: Add new pattern. Unless the patch relies on this, I think it should be posted separately and reviewed by Richard. OK, good point, will remove from this patch. @@ -245,6 +246,7 @@ along with GCC; see the file COPYING3. If not see static unsigned HOST_WIDE_INT asan_shadow_offset_value; static bool asan_shadow_offset_computed; static vec sanitized_sections; +static tree last_alloca_addr = NULL_TREE; You are shadowing this variable in multiple places. Either rename it to something different, or rename the results of get_last_alloca_addr. And the " = NULL_TREE" part is not needed. Err, thanks, will fix it. /* Set of variable declarations that are going to be guarded by use-after-scope sanitizer. */ @@ -529,11 +531,183 @@ get_mem_ref_of_assignment (const gassign *assignment, return true; } +/* Return address of last allocated dynamic alloca. */ + +static tree +get_last_alloca_addr () +{ + if (last_alloca_addr) +return last_alloca_addr; + + gimple_seq seq = NULL; + gassign *g; + + last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr"); + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, + build_int_cst (ptr_type_node, 0)); Instead of build_int_cst (ptr_type_node, 0) you should use null_pointer_node. And the NOP_EXPR there is just wrong, either it should be gimple_build_assign (last_alloca_addr, null_pointer_node); or gimple_build_assign (last_alloca_addr, INTEGER_CST, null_pointer_node); + gimple_seq_add_stmt_without_update (&seq, g); Why the seq stuff at all? You have a single stmt you want to insert on edge. Right, will fix it. + + edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + gsi_insert_seq_on_edge_immediate (e, seq); So just use here gsi_insert_on_edge_immediate (e, g); instead. + return last_alloca_addr; +} + +/* Insert __asan_allocas_unpoison (top, bottom) call after + __builtin_stack_restore (new_sp) call. + The pseudocode of this routine should look like this: + __builtin_stack_restore (new_sp); + top = last_alloca_addr; + bot = virtual_dynamic_stack_rtx; + __asan_allocas_unpoison (top, bottom); + last_alloca_addr = new_sp; The comment doesn't seem to agree with what you actually implement. There is no virtual_dynamic_stack_rtx during the asan pass, it is there only during expansion until the virtual regs are instantiated in the next pass. Furthermore, you have bot variable, but then use bottom. Right, 'bottom' should be replaced by 'bot'. Regarding to virtual_dynamic_stactk_rtx - as you correctly noted below, second parameter of __asan_allocas_unpoison will be completely rewritten in expand_builtin_alloca function by virtual_dynamic_stactk_rtx. Here I've just passed new_sp as a dummy argument. This looks hacky, but the problem is that for several architectures (e.g. PPC) we cannot use new_sp as a 'bot' parameter because new_sp != last_alloca_addr on these targets. Originally, I tried to do something like this: top = last_alloca_addr; bot = new_sp + STACK_DYNAMIC_OFFSET; __asan_allocas_unpoison(top, bot); last_alloca_addr = bot; but I was confused by the fact that STACK_DYNAMIC_OFFSET becomes available only after expansion to RTL. Rewriting 'bot' with virtual_dynamic_stactk_rtx in RTL looks like the most feasible way how to overcome this issue for me. + tree last_alloca_addr = get_last_alloca_addr (); Here is the shadowing I talked about. + tree restored_stack = gimple_call_arg (call, 0); + tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON); + gimple *g = gimple_build_call (fn, 2, last_alloca_addr, restored_stack); Here you clearly use the first argument of __builtin_stack_restore, which is that new_sp. + gimple_seq_add_stmt_without_update (&seq, g); Why the messing up with sequences? Just insert the stmt immediately in, and the others as well. + g = gimple_build_assign (last_alloca_addr, NOP_EXPR, restored_stack); This is again wrong, here you really don't know what restored_stack is, it could be SSA_NAME, but also something different, so you should use gimple_build_assign (last_alloca_addr, restored_stack); and let it figure out the rhs code. Thanks, will fix. + /* Extract lower bits from old_size. */ + wide_int size_nonzero_bits = get_nonzero_bits (old_size); + wide_int rz_mask += wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits)); + wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask); + + /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial +
[Ping][PATCH v2] Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697)
Hi, I would like to ping the following patch: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg02288.html Thanks, -Maxim gcc/ChangeLog: 2017-11-13 Maxim Ostapenko PR sanitizer/81697 * asan.c (asan_protect_global): Add new ignore_decl_rtl_set_p parameter. Return true if ignore_decl_rtl_set_p is true and other conditions are satisfied. * asan.h (asan_protect_global): Add new parameter. * varasm.c (categorize_decl_for_section): Pass true as second parameter to asan_protect_global calls. gcc/testsuite/ChangeLog: 2017-11-13 Maxim Ostapenko PR sanitizer/81697 * g++.dg/asan/global-alignment.C: New test. diff --git a/gcc/asan.c b/gcc/asan.c index d5128aa..78c3b60 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1605,7 +1605,7 @@ is_odr_indicator (tree decl) ASAN_RED_ZONE_SIZE bytes. */ bool -asan_protect_global (tree decl) +asan_protect_global (tree decl, bool ignore_decl_rtl_set_p) { if (!ASAN_GLOBALS) return false; @@ -1627,7 +1627,13 @@ asan_protect_global (tree decl) || DECL_THREAD_LOCAL_P (decl) /* Externs will be protected elsewhere. */ || DECL_EXTERNAL (decl) - || !DECL_RTL_SET_P (decl) + /* PR sanitizer/81697: For architectures that use section anchors first + call to asan_protect_global may occur before DECL_RTL (decl) is set. + We should ignore DECL_RTL_SET_P then, because otherwise the first call + to asan_protect_global will return FALSE and the following calls on the + same decl after setting DECL_RTL (decl) will return TRUE and we'll end + up with inconsistency at runtime. */ + || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p) /* Comdat vars pose an ABI problem, we can't know if the var that is selected by the linker will have padding or not. */ @@ -1651,6 +1657,9 @@ asan_protect_global (tree decl) || is_odr_indicator (decl)) return false; + if (ignore_decl_rtl_set_p) +return true; + rtl = DECL_RTL (decl); if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) return false; diff --git a/gcc/asan.h b/gcc/asan.h index c82d4d9..885b47e 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -26,7 +26,7 @@ extern void asan_finish_file (void); extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int, HOST_WIDE_INT *, tree *, int); extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *); -extern bool asan_protect_global (tree); +extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false); extern void initialize_sanitizer_builtins (void); extern tree asan_dynamic_init_call (bool); extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool); diff --git a/gcc/testsuite/g++.dg/asan/global-alignment.C b/gcc/testsuite/g++.dg/asan/global-alignment.C new file mode 100644 index 000..84dac37 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/global-alignment.C @@ -0,0 +1,18 @@ +/* { dg-options "-fmerge-all-constants" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#include +#include + +const char kRecoveryInstallString[] = "NEW"; +const char kRecoveryUpdateString[] = "UPDATE"; +const char kRecoveryUninstallationString[] = "UNINSTALL"; + +const std::map kStringToRequestMap = { + {kRecoveryInstallString, 0}, + {kRecoveryUpdateString, 0}, + {kRecoveryUninstallationString, 0}, +}; + +/* { dg-final { scan-assembler-times {\.section\s+\.rodata\n(?:(?!\.section).)*\.\w+\s+"NEW} 1 } } */ diff --git a/gcc/varasm.c b/gcc/varasm.c index a139151..849eae0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6508,7 +6508,7 @@ categorize_decl_for_section (const_tree decl, int reloc) else if (TREE_CODE (decl) == STRING_CST) { if ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl))) + && asan_protect_global (CONST_CAST_TREE (decl), true)) /* or !flag_merge_constants */ return SECCAT_RODATA; else @@ -6536,7 +6536,7 @@ categorize_decl_for_section (const_tree decl, int reloc) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl + && asan_protect_global (CONST_CAST_TREE (decl), true))) /* C and C++ don't allow different variables to share the same location. -fmerge-all-constants allows even that (at the expense of not conforming). */
Re: [RFC PATCH] Merge libsanitizer from upstream
Hi, On 13/11/17 15:47, Christophe Lyon wrote: On 30 October 2017 at 16:21, Maxim Ostapenko wrote: On 30/10/17 17:08, Christophe Lyon wrote: On 30/10/2017 11:12, Maxim Ostapenko wrote: Hi, sorry for the late response. On 20/10/17 13:45, Christophe Lyon wrote: Hi, On 19 October 2017 at 13:17, Jakub Jelinek wrote: On Thu, Oct 19, 2017 at 02:07:24PM +0300, Maxim Ostapenko wrote: Is the patch (the merge + this incremental) ok for trunk? I think the patch is OK, just wondering about two things: Richi just approved the patch on IRC, so I'll commit, then we can deal with follow-ups. Does anyone else run these tests on arm? Since you applied this patch, I'm seeing lots of new errors and timeouts. I have been ignoring regression reports for *san because of yyrandomness in the results, but the timeouts are a major inconvenience in testing because it increases latency a lot in getting results, or worse I get no result at all because the validation job is killed before completion. Looking at some intermediate logs, I have noticed: ==24797==AddressSanitizer CHECK failed: /libsanitizer/asan/asan_poisoning.cc:34 "((AddrIsAlignedByGranularity(addr))) != (0)" (0x0, 0x0) #0 0x408d7d65 in AsanCheckFailed /libsanitizer/asan/asan_rtl.cc:67 #1 0x408ecd5d in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /libsanitizer/sanitizer_common/sanitizer_termination.cc:77 #2 0x408d22d5 in __asan::PoisonShadow(unsigned long, unsigned long, unsigned char) /libsanitizer/asan/asan_poisoning.cc:34 #3 0x4085409b in __asan_register_globals /libsanitizer/asan/asan_globals.cc:368 #4 0x109eb in _GLOBAL__sub_I_00099_1_ten (/aci-gcc-fsf/builds/gcc-fsf-gccsrc-thumb/obj-arm-none-linux-gnueabi/gcc3/gcc/testsuite/gcc/alloca_big_alignment.exe+0x109eb) in MANY (193 in gcc) tests. and many others (152 in gcc) just time out individually (eg c-c++-common/asan/alloca_instruments_all_paddings.c) with no error in the logs besides Dejagnu's WARNING: program timed out. Since I'm using an apparently unusual setup, maybe I have to update it to cope with the new version, so I'd like to know if others are seeing the same problems on arm? I'm using qemu -R 0 to execute the test programs, encapsulated by proot (similar to chroot, but does not require root privileges). Am I missing something obvious? I've caught the same error on my Arndale board. The issue seems to be quite obvious: after merge, ASan requires globals array to be aligned by shadow granularity. Thanks for confirming. I've spent a lot of time investigating the timeout issues, that led to zombie processes and servers needing reboot. I've finally identified that going back to qemu-2.7 avoid the timeout issues (I've reported a qemu bug). This trivial patch seems to fix the issue. Could you check it on your setup? I was just about to finally start looking at this sanity check problem, so thank you very much for sharing your patch. I manually tested it on the subset of my configs and it solves the assertion failure, thanks! However, I can notice many regressions compared to before the merge: c-c++-common/asan/alloca_instruments_all_paddings.c c-c++-common/asan/alloca_loop_unpoisoning.c c-c++-common/asan/alloca_safe_access.c c-c++-common/asan/asan-interface-1.c c-c++-common/asan/halt_on_error-1.c c-c++-common/asan/pr59063-1.c c-c++-common/asan/pr59063-2.c c-c++-common/asan/pr63316.c c-c++-common/asan/pr63888.c c-c++-common/asan/pr70712.c c-c++-common/asan/pr71480.c c-c++-common/asan/pr79944.c c-c++-common/asan/pr80308.c c-c++-common/asan/swapcontext-test-1.c gcc.dg/asan/nosanitize-and-inline.c gcc.dg/asan/pr79196.c gcc.dg/asan/pr80166.c gcc.dg/asan/pr81186.c gcc.dg/asan/use-after-scope-11.c gcc.dg/asan/use-after-scope-4.c gcc.dg/asan/use-after-scope-6.c gcc.dg/asan/use-after-scope-7.c gcc.dg/asan/use-after-scope-goto-1.c gcc.dg/asan/use-after-scope-goto-2.c gcc.dg/asan/use-after-scope-switch-1.c gcc.dg/asan/use-after-scope-switch-2.c gcc.dg/asan/use-after-scope-switch-3.c gcc.dg/asan/use-after-scope-switch-4.c out of which only c-c++-common/asan/swapcontext-test-1.c c-c++-common/asan/halt_on_error-1.c print something in gcc.log Do they pass for you? Ah, I see. The problem is that after this merge LSan was enabled for ARM. LSan sets atexit handler that calls internal_clone function that's not supported in QEMU. That's why these tests pass on board, but fail under QEMU. Could you try set ASAN_OPTIONS=detect_leaks=0 in your environment? Hi, I have a followup on this issue, after investigating a bit more. I filed a bug report against QEMU, and indeed it seems that it rejects clone() as called by the sanitizers on purpose, because it cannot support CLONE_UNTRACED. That being said, I was wondering why the same tests worked "better" with qemu-aarch64 (as opposed to qemu-arm). And I noticed that on aarch64, we have san
Re: [RFC PATCH] Merge libsanitizer from upstream
Hi Christophe, On 13/11/17 15:47, Christophe Lyon wrote: On 30 October 2017 at 16:21, Maxim Ostapenko wrote: On 30/10/17 17:08, Christophe Lyon wrote: On 30/10/2017 11:12, Maxim Ostapenko wrote: Hi, sorry for the late response. On 20/10/17 13:45, Christophe Lyon wrote: Hi, On 19 October 2017 at 13:17, Jakub Jelinek wrote: On Thu, Oct 19, 2017 at 02:07:24PM +0300, Maxim Ostapenko wrote: Is the patch (the merge + this incremental) ok for trunk? I think the patch is OK, just wondering about two things: Richi just approved the patch on IRC, so I'll commit, then we can deal with follow-ups. Does anyone else run these tests on arm? Since you applied this patch, I'm seeing lots of new errors and timeouts. I have been ignoring regression reports for *san because of yyrandomness in the results, but the timeouts are a major inconvenience in testing because it increases latency a lot in getting results, or worse I get no result at all because the validation job is killed before completion. Looking at some intermediate logs, I have noticed: ==24797==AddressSanitizer CHECK failed: /libsanitizer/asan/asan_poisoning.cc:34 "((AddrIsAlignedByGranularity(addr))) != (0)" (0x0, 0x0) #0 0x408d7d65 in AsanCheckFailed /libsanitizer/asan/asan_rtl.cc:67 #1 0x408ecd5d in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /libsanitizer/sanitizer_common/sanitizer_termination.cc:77 #2 0x408d22d5 in __asan::PoisonShadow(unsigned long, unsigned long, unsigned char) /libsanitizer/asan/asan_poisoning.cc:34 #3 0x4085409b in __asan_register_globals /libsanitizer/asan/asan_globals.cc:368 #4 0x109eb in _GLOBAL__sub_I_00099_1_ten (/aci-gcc-fsf/builds/gcc-fsf-gccsrc-thumb/obj-arm-none-linux-gnueabi/gcc3/gcc/testsuite/gcc/alloca_big_alignment.exe+0x109eb) in MANY (193 in gcc) tests. and many others (152 in gcc) just time out individually (eg c-c++-common/asan/alloca_instruments_all_paddings.c) with no error in the logs besides Dejagnu's WARNING: program timed out. Since I'm using an apparently unusual setup, maybe I have to update it to cope with the new version, so I'd like to know if others are seeing the same problems on arm? I'm using qemu -R 0 to execute the test programs, encapsulated by proot (similar to chroot, but does not require root privileges). Am I missing something obvious? I've caught the same error on my Arndale board. The issue seems to be quite obvious: after merge, ASan requires globals array to be aligned by shadow granularity. Thanks for confirming. I've spent a lot of time investigating the timeout issues, that led to zombie processes and servers needing reboot. I've finally identified that going back to qemu-2.7 avoid the timeout issues (I've reported a qemu bug). This trivial patch seems to fix the issue. Could you check it on your setup? I was just about to finally start looking at this sanity check problem, so thank you very much for sharing your patch. I manually tested it on the subset of my configs and it solves the assertion failure, thanks! However, I can notice many regressions compared to before the merge: c-c++-common/asan/alloca_instruments_all_paddings.c c-c++-common/asan/alloca_loop_unpoisoning.c c-c++-common/asan/alloca_safe_access.c c-c++-common/asan/asan-interface-1.c c-c++-common/asan/halt_on_error-1.c c-c++-common/asan/pr59063-1.c c-c++-common/asan/pr59063-2.c c-c++-common/asan/pr63316.c c-c++-common/asan/pr63888.c c-c++-common/asan/pr70712.c c-c++-common/asan/pr71480.c c-c++-common/asan/pr79944.c c-c++-common/asan/pr80308.c c-c++-common/asan/swapcontext-test-1.c gcc.dg/asan/nosanitize-and-inline.c gcc.dg/asan/pr79196.c gcc.dg/asan/pr80166.c gcc.dg/asan/pr81186.c gcc.dg/asan/use-after-scope-11.c gcc.dg/asan/use-after-scope-4.c gcc.dg/asan/use-after-scope-6.c gcc.dg/asan/use-after-scope-7.c gcc.dg/asan/use-after-scope-goto-1.c gcc.dg/asan/use-after-scope-goto-2.c gcc.dg/asan/use-after-scope-switch-1.c gcc.dg/asan/use-after-scope-switch-2.c gcc.dg/asan/use-after-scope-switch-3.c gcc.dg/asan/use-after-scope-switch-4.c out of which only c-c++-common/asan/swapcontext-test-1.c c-c++-common/asan/halt_on_error-1.c print something in gcc.log Do they pass for you? Ah, I see. The problem is that after this merge LSan was enabled for ARM. LSan sets atexit handler that calls internal_clone function that's not supported in QEMU. That's why these tests pass on board, but fail under QEMU. Could you try set ASAN_OPTIONS=detect_leaks=0 in your environment? Hi, I have a followup on this issue, after investigating a bit more. I filed a bug report against QEMU, and indeed it seems that it rejects clone() as called by the sanitizers on purpose, because it cannot support CLONE_UNTRACED. That being said, I was wondering why the same tests worked "better" with qemu-aarch64 (as opposed to qemu-arm). And I noticed tha
[Ping][PATCH v3] Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697)
Hi, I would like to ping the following patch: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg02288.html Thanks, -Maxim gcc/ChangeLog: 2017-11-21 Maxim Ostapenko PR sanitizer/81697 * asan.c (asan_protect_global): Add new ignore_decl_rtl_set_p parameter. Return true if ignore_decl_rtl_set_p is true and other conditions are satisfied. * asan.h (asan_protect_global): Add new parameter. * varasm.c (categorize_decl_for_section): Pass true as second parameter to asan_protect_global calls. gcc/testsuite/ChangeLog: 2017-11-21 Maxim Ostapenko PR sanitizer/81697 * g++.dg/asan/global-alignment.C: New test. diff --git a/gcc/asan.c b/gcc/asan.c index d5128aa..78c3b60 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1605,7 +1605,7 @@ is_odr_indicator (tree decl) ASAN_RED_ZONE_SIZE bytes. */ bool -asan_protect_global (tree decl) +asan_protect_global (tree decl, bool ignore_decl_rtl_set_p) { if (!ASAN_GLOBALS) return false; @@ -1627,7 +1627,13 @@ asan_protect_global (tree decl) || DECL_THREAD_LOCAL_P (decl) /* Externs will be protected elsewhere. */ || DECL_EXTERNAL (decl) - || !DECL_RTL_SET_P (decl) + /* PR sanitizer/81697: For architectures that use section anchors first + call to asan_protect_global may occur before DECL_RTL (decl) is set. + We should ignore DECL_RTL_SET_P then, because otherwise the first call + to asan_protect_global will return FALSE and the following calls on the + same decl after setting DECL_RTL (decl) will return TRUE and we'll end + up with inconsistency at runtime. */ + || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p) /* Comdat vars pose an ABI problem, we can't know if the var that is selected by the linker will have padding or not. */ @@ -1651,6 +1657,9 @@ asan_protect_global (tree decl) || is_odr_indicator (decl)) return false; + if (ignore_decl_rtl_set_p) +return true; + rtl = DECL_RTL (decl); if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) return false; diff --git a/gcc/asan.h b/gcc/asan.h index c82d4d9..885b47e 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -26,7 +26,7 @@ extern void asan_finish_file (void); extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int, HOST_WIDE_INT *, tree *, int); extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *); -extern bool asan_protect_global (tree); +extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false); extern void initialize_sanitizer_builtins (void); extern tree asan_dynamic_init_call (bool); extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool); diff --git a/gcc/testsuite/g++.dg/asan/global-alignment.C b/gcc/testsuite/g++.dg/asan/global-alignment.C new file mode 100644 index 000..84dac37 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/global-alignment.C @@ -0,0 +1,18 @@ +/* { dg-options "-fmerge-all-constants" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#include +#include + +const char kRecoveryInstallString[] = "NEW"; +const char kRecoveryUpdateString[] = "UPDATE"; +const char kRecoveryUninstallationString[] = "UNINSTALL"; + +const std::map kStringToRequestMap = { + {kRecoveryInstallString, 0}, + {kRecoveryUpdateString, 0}, + {kRecoveryUninstallationString, 0}, +}; + +/* { dg-final { scan-assembler-times {\.section\s+\.rodata\n(?:(?!\.section).)*\.\w+\s+"NEW} 1 } } */ diff --git a/gcc/varasm.c b/gcc/varasm.c index a139151..849eae0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6508,7 +6508,7 @@ categorize_decl_for_section (const_tree decl, int reloc) else if (TREE_CODE (decl) == STRING_CST) { if ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl))) + && asan_protect_global (CONST_CAST_TREE (decl), true)) /* or !flag_merge_constants */ return SECCAT_RODATA; else @@ -6536,7 +6536,7 @@ categorize_decl_for_section (const_tree decl, int reloc) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl + && asan_protect_global (CONST_CAST_TREE (decl), true))) /* C and C++ don't allow different variables to share the same location. -fmerge-all-constants allows even that (at the expense of not conforming). */
Re: [Ping][PATCH v3] Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697)
(CC'ing Jakub and Ramana) Hi, I would like to ping the following patch: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg02288.html Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697) -Maxim gcc/ChangeLog: 2017-11-28 Maxim Ostapenko PR sanitizer/81697 * asan.c (asan_protect_global): Add new ignore_decl_rtl_set_p parameter. Return true if ignore_decl_rtl_set_p is true and other conditions are satisfied. * asan.h (asan_protect_global): Add new parameter. * varasm.c (categorize_decl_for_section): Pass true as second parameter to asan_protect_global calls. gcc/testsuite/ChangeLog: 2017-11-28 Maxim Ostapenko PR sanitizer/81697 * g++.dg/asan/global-alignment.C: New test. diff --git a/gcc/asan.c b/gcc/asan.c index d5128aa..78c3b60 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1605,7 +1605,7 @@ is_odr_indicator (tree decl) ASAN_RED_ZONE_SIZE bytes. */ bool -asan_protect_global (tree decl) +asan_protect_global (tree decl, bool ignore_decl_rtl_set_p) { if (!ASAN_GLOBALS) return false; @@ -1627,7 +1627,13 @@ asan_protect_global (tree decl) || DECL_THREAD_LOCAL_P (decl) /* Externs will be protected elsewhere. */ || DECL_EXTERNAL (decl) - || !DECL_RTL_SET_P (decl) + /* PR sanitizer/81697: For architectures that use section anchors first + call to asan_protect_global may occur before DECL_RTL (decl) is set. + We should ignore DECL_RTL_SET_P then, because otherwise the first call + to asan_protect_global will return FALSE and the following calls on the + same decl after setting DECL_RTL (decl) will return TRUE and we'll end + up with inconsistency at runtime. */ + || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p) /* Comdat vars pose an ABI problem, we can't know if the var that is selected by the linker will have padding or not. */ @@ -1651,6 +1657,9 @@ asan_protect_global (tree decl) || is_odr_indicator (decl)) return false; + if (ignore_decl_rtl_set_p) +return true; + rtl = DECL_RTL (decl); if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) return false; diff --git a/gcc/asan.h b/gcc/asan.h index c82d4d9..885b47e 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -26,7 +26,7 @@ extern void asan_finish_file (void); extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int, HOST_WIDE_INT *, tree *, int); extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *); -extern bool asan_protect_global (tree); +extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false); extern void initialize_sanitizer_builtins (void); extern tree asan_dynamic_init_call (bool); extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool); diff --git a/gcc/testsuite/g++.dg/asan/global-alignment.C b/gcc/testsuite/g++.dg/asan/global-alignment.C new file mode 100644 index 000..84dac37 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/global-alignment.C @@ -0,0 +1,18 @@ +/* { dg-options "-fmerge-all-constants" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#include +#include + +const char kRecoveryInstallString[] = "NEW"; +const char kRecoveryUpdateString[] = "UPDATE"; +const char kRecoveryUninstallationString[] = "UNINSTALL"; + +const std::map kStringToRequestMap = { + {kRecoveryInstallString, 0}, + {kRecoveryUpdateString, 0}, + {kRecoveryUninstallationString, 0}, +}; + +/* { dg-final { scan-assembler-times {\.section\s+\.rodata\n(?:(?!\.section).)*\.\w+\s+"NEW} 1 } } */ diff --git a/gcc/varasm.c b/gcc/varasm.c index a139151..849eae0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6508,7 +6508,7 @@ categorize_decl_for_section (const_tree decl, int reloc) else if (TREE_CODE (decl) == STRING_CST) { if ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl))) + && asan_protect_global (CONST_CAST_TREE (decl), true)) /* or !flag_merge_constants */ return SECCAT_RODATA; else @@ -6536,7 +6536,7 @@ categorize_decl_for_section (const_tree decl, int reloc) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl + && asan_protect_global (CONST_CAST_TREE (decl), true))) /* C and C++ don't allow different variables to share the same location. -fmerge-all-constants allows even that (at the expense of not conforming). */
Re: [Ping][PATCH v3] Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697)
Hi Jakub, thanks for review. I've fixed the issues you've pointed in review. Regarding a testcase -- I've cooked a runtime test, but it shows FP on unpatched GCC version only when linking with Gold (because it strips redzones more aggressively). This patch passes tests on arm-linux and x86_64-linux, bootstrap is in progress. Thanks, -Maxim On 29/11/17 13:10, Jakub Jelinek wrote: On Tue, Nov 28, 2017 at 10:04:51AM +0300, Maxim Ostapenko wrote: (CC'ing Jakub and Ramana) I would like to ping the following patch: https://gcc.gnu.org/ml/gcc-patches/2017-10/msg02288.html Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697) -Maxim gcc/ChangeLog: 2017-11-28 Maxim Ostapenko PR sanitizer/81697 * asan.c (asan_protect_global): Add new ignore_decl_rtl_set_p parameter. Return true if ignore_decl_rtl_set_p is true and other conditions are satisfied. * asan.h (asan_protect_global): Add new parameter. * varasm.c (categorize_decl_for_section): Pass true as second parameter to asan_protect_global calls. gcc/testsuite/ChangeLog: 2017-11-28 Maxim Ostapenko PR sanitizer/81697 * g++.dg/asan/global-alignment.C: New test. diff --git a/gcc/asan.c b/gcc/asan.c index d5128aa..78c3b60 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1605,7 +1605,7 @@ is_odr_indicator (tree decl) ASAN_RED_ZONE_SIZE bytes. */ bool -asan_protect_global (tree decl) +asan_protect_global (tree decl, bool ignore_decl_rtl_set_p) { if (!ASAN_GLOBALS) return false; @@ -1627,7 +1627,13 @@ asan_protect_global (tree decl) || DECL_THREAD_LOCAL_P (decl) /* Externs will be protected elsewhere. */ || DECL_EXTERNAL (decl) - || !DECL_RTL_SET_P (decl) + /* PR sanitizer/81697: For architectures that use section anchors first +call to asan_protect_global may occur before DECL_RTL (decl) is set. +We should ignore DECL_RTL_SET_P then, because otherwise the first call +to asan_protect_global will return FALSE and the following calls on the +same decl after setting DECL_RTL (decl) will return TRUE and we'll end +up with inconsistency at runtime. */ + || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p) This part is fine. /* Comdat vars pose an ABI problem, we can't know if the var that is selected by the linker will have padding or not. */ @@ -1651,6 +1657,9 @@ asan_protect_global (tree decl) || is_odr_indicator (decl)) return false; + if (ignore_decl_rtl_set_p) +return true; This isn't, because then you bypass checks that really don't care about RTL, like: if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) return false; if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl)) return false; So, IMHO just wrap only the DECL_RTL/symbol related stuff in if (!ignore_decl_rtl_set_p). Perhaps even better in if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl)) so that if the rtl is already set, you do the check anyway. --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/global-alignment.C @@ -0,0 +1,18 @@ +/* { dg-options "-fmerge-all-constants" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +#include +#include + +const char kRecoveryInstallString[] = "NEW"; +const char kRecoveryUpdateString[] = "UPDATE"; +const char kRecoveryUninstallationString[] = "UNINSTALL"; + +const std::map kStringToRequestMap = { + {kRecoveryInstallString, 0}, + {kRecoveryUpdateString, 0}, + {kRecoveryUninstallationString, 0}, +}; + +/* { dg-final { scan-assembler-times {\.section\s+\.rodata\n(?:(?!\.section).)*\.\w+\s+"NEW} 1 } } */ I don't really like the testcase. The scaning for .rodata section is too fragile, e.g. darwin will need something completely different, doesn't e.g. powerpc use .sdata section instead, etc. And, isn't std::map and std::string completely unnecessary? I'd prefer a runtime test that shows the false positive without the patch, preferrably in C, just with those const char arrays used by some C code without any headers. diff --git a/gcc/varasm.c b/gcc/varasm.c index a139151..849eae0 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6508,7 +6508,7 @@ categorize_decl_for_section (const_tree decl, int reloc) else if (TREE_CODE (decl) == STRING_CST) { if ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl))) + && asan_protect_global (CONST_CAST_TREE (decl), true)) This doesn't make sense to me. asan_protect_global for STRING_CST doesn't care about any RTL, nor -fsection-anchors puts them into any kind of block. /* or !flag_mer
Re: [Ping][PATCH v3] Fix Incorrect ASan global variables alignment on arm (PR sanitizer/81697)
Ok, thanks, here is the patch I'm going to install after bootstrap completes. On 30/11/17 14:54, Jakub Jelinek wrote: On Thu, Nov 30, 2017 at 02:38:25PM +0300, Maxim Ostapenko wrote: Hi Jakub, thanks for review. I've fixed the issues you've pointed in review. Regarding a testcase -- I've cooked a runtime test, but it shows FP on unpatched GCC version only when linking with Gold (because it strips redzones more aggressively). I think we can live with that. --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6550,7 +6550,19 @@ categorize_decl_for_section (const_tree decl, int reloc) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl + /* PR 81697: for architectures that use section anchors we + need to ignore DECL_RTL_SET_P (decl) for string constants + inside this asan_protect_global call because otherwise + we'll wrongly put them into SECCAT_RODATA_MERGE_CONST + section, set DECL_RTL (decl) later on and add DECL to + protected globals via successive asan_protect_global + calls. In this scenario we'll end up with wrong + alignment of these strings at runtime and possible ASan + false positives. */ + && asan_protect_global (CONST_CAST_TREE (decl), + use_object_blocks_p () +&& use_blocks_for_decl_p ( + CONST_CAST_TREE (decl) Formatting is too bad here. && should go below use_object_block_p.. The opening ( should either go on the next line, like: use_object_blocks_p () && use_blocks_for_decl_p (CONST_CAST_TREE (decl) or perhaps better just introduce a temporary somewhere: else if (VAR_P (decl)) { + tree d = CONST_CAST_TREE (decl); if (bss_initializer_p (decl)) ret = SECCAT_BSS; and use d instead of CONST_CAST_TREE (decl) later? Ok with those changes. Jakub gcc/ChangeLog: 2017-11-30 Maxim Ostapenko PR sanitizer/81697 * asan.c (asan_protect_global): Add new ignore_decl_rtl_set_p parameter. Return true if ignore_decl_rtl_set_p is true and other conditions are satisfied. * asan.h (asan_protect_global): Add new parameter. * varasm.c (categorize_decl_for_section): Pass true as second parameter to asan_protect_global calls. gcc/testsuite/ChangeLog: 2017-11-30 Maxim Ostapenko PR sanitizer/81697 * c-c++-common/asan/pr81697.c: New test. diff --git a/gcc/asan.c b/gcc/asan.c index ca5fceed..873687f 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1605,7 +1605,7 @@ is_odr_indicator (tree decl) ASAN_RED_ZONE_SIZE bytes. */ bool -asan_protect_global (tree decl) +asan_protect_global (tree decl, bool ignore_decl_rtl_set_p) { if (!ASAN_GLOBALS) return false; @@ -1627,7 +1627,13 @@ asan_protect_global (tree decl) || DECL_THREAD_LOCAL_P (decl) /* Externs will be protected elsewhere. */ || DECL_EXTERNAL (decl) - || !DECL_RTL_SET_P (decl) + /* PR sanitizer/81697: For architectures that use section anchors first + call to asan_protect_global may occur before DECL_RTL (decl) is set. + We should ignore DECL_RTL_SET_P then, because otherwise the first call + to asan_protect_global will return FALSE and the following calls on the + same decl after setting DECL_RTL (decl) will return TRUE and we'll end + up with inconsistency at runtime. */ + || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p) /* Comdat vars pose an ABI problem, we can't know if the var that is selected by the linker will have padding or not. */ @@ -1651,14 +1657,18 @@ asan_protect_global (tree decl) || is_odr_indicator (decl)) return false; - rtl = DECL_RTL (decl); - if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) -return false; - symbol = XEXP (rtl, 0); + if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl)) +{ - if (CONSTANT_POOL_ADDRESS_P (symbol) - || TREE_CONSTANT_POOL_ADDRESS_P (symbol)) -return false; + rtl = DECL_RTL (decl); + if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF) + return false; + symbol = XEXP (rtl, 0); + + if (CONSTANT_POOL_ADDRESS_P (symbol) + || TREE_CONSTANT_POOL_ADDRESS_P (symbol)) + return false; +} if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) return false; diff --git a/gcc/asan.h b/gcc/asan.h index c82d4d9..885b47e 100644
Re: [PATCH][PR sanitizer/86090] Add checks for lstat and readlink to sanitizer configure.
Hi, On 06/10/2018 09:49 PM, Jakub Jelinek wrote: > On Fri, Jun 08, 2018 at 08:10:40PM +0300, Denis Khalikov wrote: >> From: Denis Khalikov >> Date: Fri, 8 Jun 2018 19:53:01 +0300 >> Subject: [PATCH] PR sanitizer/86090 >> >> * configure.ac: Check for lstat and readlink. >> * configure, config.h.in: Rebuild. > Ok for trunk. Will somebody commit it for you or should I? sorry for the delay, we had public holidays at the beginning of this week. I'll commit this today. -Maxim > > Jakub > > >
[PATCH][PR sanitizer/78651] Incorrect exception handling when catch clause uses local class and PIC and sanitizer are active
Hi, as noted in bugzilla, ASan inserts redzones for `.LDFCM*' variables and breaks internal ABI between GCC and libstdc++ because libstdc++ tries to obtain a pointer to `typeinfo for (anonymous namespace)::SomeRandomType' from a constant offset from `.LDFCM*' labels and hits these redzones. This can be trivially fixed by not sanitizing `.LDFCM*' variables (and other debug variables) at all. Attached patch is tested/bootstrapped on x86_64-unknown-linux-gnu and ppc64le-redhat-linux targets. Is it OK for trunk now, or should I wait for stage 1? -Maxim gcc/ PR sanitizer/78651 * dwarf2asm.c (dw2_output_indirect_constant_1): Call assemble_variable with new parameter. * output.h (assemble_variable): Add new parameter. * varasm.c (assemble_variable): Add new parameter. Do not protect variable with ASan if is_debug_var is true. gcc/testsuite/ChangeLog: PR sanitizer/78651 * g++.dg/asan/pr78651.C: New test. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5b5559..a26f05e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * dwarf2asm.c (dw2_output_indirect_constant_1): Call assemble_variable + with new parameter. + * output.h (assemble_variable): Add new parameter. + * varasm.c (assemble_variable): Add new parameter. Do not protect + variable with ASan if is_debug_var is true. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index e9b18b8..5c90994 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -967,7 +967,7 @@ dw2_output_indirect_constant_1 (const char *sym, tree id) } sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym); - assemble_variable (decl, 1, 1, 1); + assemble_variable (decl, 1, 1, 1, 1); assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1); return 0; diff --git a/gcc/output.h b/gcc/output.h index f708cc7..678c370 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -200,7 +200,7 @@ extern void assemble_end_function (tree, const char *); to define things that have had only tentative definitions. DONT_OUTPUT_DATA if nonzero means don't actually output the initial value (that will be done by the caller). */ -extern void assemble_variable (tree, int, int, int); +extern void assemble_variable (tree, int, int, int, int is_debug_var = 0); /* Put the vtable verification constructor initialization function into the preinit array. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 868d8e8..6ff9217 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * g++.dg/asan/pr78651.C: New test. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/testsuite/g++.dg/asan/pr78651.C b/gcc/testsuite/g++.dg/asan/pr78651.C new file mode 100644 index 000..3f14be7 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/pr78651.C @@ -0,0 +1,24 @@ +// { dg-do run { target fpic } } + +struct A { }; + +namespace { + +void thisThrows () { + throw A(); +} + +struct SomeRandomType {}; +} + +int main() { + try { +thisThrows(); + } + catch (SomeRandomType) { +throw; + } + catch (A) { + } + return 0; +} diff --git a/gcc/varasm.c b/gcc/varasm.c index 2b5c70c..b18d011 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2158,11 +2158,14 @@ assemble_undefined_decl (tree decl) AT_END is nonzero if this is the special handling, at end of compilation, to define things that have had only tentative definitions. DONT_OUTPUT_DATA if nonzero means don't actually output the - initial value (that will be done by the caller). */ + initial value (that will be done by the caller). + IS_DEBUG_VAR if nonzero that we are assembling debug variable. + This information is useful for ASan, see pr78651. */ void assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, - int at_end ATTRIBUTE_UNUSED, int dont_output_data) + int at_end ATTRIBUTE_UNUSED, int dont_output_data, + int is_debug_var) { const char *name; rtx decl_rtl, symbol; @@ -2258,6 +2261,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, align_variable (decl, dont_output_data); if ((flag_sanitize & SANITIZE_ADDRESS) + && !is_debug_var && asan_protect_global (decl)) { asan_protected = true;
Re: [PATCH][PR sanitizer/78651] Incorrect exception handling when catch clause uses local class and PIC and sanitizer are active
On 03/19/2018 06:55 PM, Jakub Jelinek wrote: On Mon, Mar 19, 2018 at 06:44:39PM +0300, Maxim Ostapenko wrote: as noted in bugzilla, ASan inserts redzones for `.LDFCM*' variables and breaks internal ABI between GCC and libstdc++ because libstdc++ tries to obtain a pointer to `typeinfo for (anonymous namespace)::SomeRandomType' from a constant offset from `.LDFCM*' labels and hits these redzones. This can be trivially fixed by not sanitizing `.LDFCM*' variables (and other debug variables) at all. I don't like very much adding an extra argument for such so frequently used function to handle a corner case. Wouldn't just: /* Don't instrument this decl with -fsanitize=*address. */ unsigned int save_flag_sanitize = flag_sanitize; flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS); assemble_variable (decl, 1, 1, 1); flag_sanitize = save_flag_sanitize; DTRT? Yes, it works, attaching the patch. -Maxim diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5b5559..356e68c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * dwarf2asm.c (dw2_output_indirect_constant_1): Disable ASan before + calling assemble_variable. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index e9b18b8..065406b 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -967,7 +967,11 @@ dw2_output_indirect_constant_1 (const char *sym, tree id) } sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym); + unsigned int save_flag_sanitize = flag_sanitize; + flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS + | SANITIZE_KERNEL_ADDRESS); assemble_variable (decl, 1, 1, 1); + flag_sanitize = save_flag_sanitize; assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1); return 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 868d8e8..6ff9217 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * g++.dg/asan/pr78651.C: New test. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/testsuite/g++.dg/asan/pr78651.C b/gcc/testsuite/g++.dg/asan/pr78651.C new file mode 100644 index 000..3f14be7 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/pr78651.C @@ -0,0 +1,24 @@ +// { dg-do run { target fpic } } + +struct A { }; + +namespace { + +void thisThrows () { + throw A(); +} + +struct SomeRandomType {}; +} + +int main() { + try { +thisThrows(); + } + catch (SomeRandomType) { +throw; + } + catch (A) { + } + return 0; +}
Re: [PATCH][PR sanitizer/78651] Incorrect exception handling when catch clause uses local class and PIC and sanitizer are active
On 03/19/2018 07:35 PM, Jakub Jelinek wrote: On Mon, Mar 19, 2018 at 07:28:11PM +0300, Maxim Ostapenko wrote: Yes, it works, attaching the patch. Can you please add a short comment why we do this? Also, the testcase needs work, see below. Ok for trunk with those changes and after a while for affected release branches as well. Ok, thanks, attaching the patch I'm going to apply. -Maxim diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5b5559..356e68c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * dwarf2asm.c (dw2_output_indirect_constant_1): Disable ASan before + calling assemble_variable. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index e9b18b8..2e108ac 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -967,7 +967,13 @@ dw2_output_indirect_constant_1 (const char *sym, tree id) } sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym); + /* Disable ASan for decl because redzones cause ABI breakage between GCC and + libstdc++ for `.LDFCM*' variables. See PR 78651 for details. */ + unsigned int save_flag_sanitize = flag_sanitize; + flag_sanitize &= ~(SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS + | SANITIZE_KERNEL_ADDRESS); assemble_variable (decl, 1, 1, 1); + flag_sanitize = save_flag_sanitize; assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1); return 0; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 868d8e8..6ff9217 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-03-19 Maxim Ostapenko + + PR sanitizer/78651 + * g++.dg/asan/pr78651.C: New test. + 2018-03-19 Richard Biener PR tree-optimization/84929 diff --git a/gcc/testsuite/g++.dg/asan/pr78651.C b/gcc/testsuite/g++.dg/asan/pr78651.C new file mode 100644 index 000..09f1be5 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/pr78651.C @@ -0,0 +1,26 @@ +// PR sanitizer/78651 +// { dg-do run } +// { dg-additional-options "-fpic" { target fpic } } + +struct A { }; + +namespace { + +void thisThrows () { + throw A(); +} + +struct SomeRandomType {}; +} + +int main() { + try { +thisThrows(); + } + catch (SomeRandomType) { +throw; + } + catch (A) { + } + return 0; +}
Re: [PATCH] Fix -fsanitize=address VLA instrumentation (PR sanitizer/85230)
On 04/13/2018 01:16 AM, Jakub Jelinek wrote: > Hi! > > As mentioned in the PR, we need to unpoison the red zones when leaving a > scope with VLA variable(s); this is done through __asan_allocas_unpoison > call, unfortunately it is called after the __builtin_stack_restore which > restores the stack pointer; now, if an interrupt comes in between the stack > restore and the __asan_allocas_unpoison call, the interrupt handler might > have some stack bytes marked as red zones in the shadow memory and might > diagnose sanitizing error even when there is none in the original program. > > The following patch ought to fix this by swapping the two calls, so we first > unpoison and only after it is unpoisoned in shadow memory release the stack. > The second argument to the __asan_allocas_unpoison call is meant to > be virtual_dynamic_stack_rtx after the __builtin_stack_restore, i.e. the new > stack_pointer_rtx value + STACK_DYNAMIC_OFFSET (current_function_decl). > As the STACK_DYNAMIC_OFFSET value isn't known until the vregs pass, the code > used a hack where it ignored the second argument and replaced it by > virtual_dynamic_stack_rtx. With the asan.c change below this doesn't work > anymore, because virtual_dynamic_stack_rtx aka stack_pointer_rtx + > STACK_DYNAMIC_OFFSET (current_function_decl) before the > __builtin_stack_restore is a different value. The patch instead uses the > argument passed to the __asan_allocas_unpoison at GIMPLE time, which is the > same as passed to __builtin_stack_restore; this is the new stack_pointer_rtx > value after __builtin_stack_restore. And, because we don't want that value, > but that + STACK_DYNAMIC_OFFSET (current_function_decl), we compute > arg1 + (virtual_dynamic_stack_rtx - stack_pointer_rtx) and let CSE/combiner > optimize it into arg1 (on targets like x86_64 where STACK_DYNAMIC_OFFSET can > be even 0 when not accumulating outgoing args or when that size is 0) or > arg1 + some_constant. > > Bootstrapped on > {x86_64,i686,powerpc64,powerpc64le,aarch64,s390x,armv7hl}-linux, regtested > on {x86_64,i686,powerpc64,powerpc64le}-linux so far, but on the power* ones > on virtual address space size that isn't really supported (likely > https://github.com/google/sanitizers/issues/933#issuecomment-380058705 > issue, so while nothing regresses there, pretty much all asan tests fail > there before and after the patch); also tested successfully with > asan.exp=alloca* on gcc110 and gcc112 on compile farm where it doesn't > suffer from the VA issue. Ok if testing passes also on aarch64, s390x > and armv7hl? OK with me, thanks. -Maxim > 2018-04-12 Jakub Jelinek > > PR sanitizer/85230 > * asan.c (handle_builtin_stack_restore): Adjust comment. Emit > __asan_allocas_unpoison call and last_alloca_addr = new_sp before > __builtin_stack_restore rather than after it. > * builtins.c (expand_asan_emit_allocas_unpoison): Pass > arg1 + (virtual_dynamic_stack_rtx - stack_pointer_rtx) as second > argument instead of virtual_dynamic_stack_rtx. > > --- gcc/asan.c.jj 2018-01-09 21:53:38.821577722 +0100 > +++ gcc/asan.c2018-04-12 13:22:59.166095523 +0200 > @@ -554,14 +554,14 @@ get_last_alloca_addr () > return last_alloca_addr; > } > > -/* Insert __asan_allocas_unpoison (top, bottom) call after > +/* Insert __asan_allocas_unpoison (top, bottom) call before > __builtin_stack_restore (new_sp) call. > The pseudocode of this routine should look like this: > - __builtin_stack_restore (new_sp); >top = last_alloca_addr; >bot = new_sp; >__asan_allocas_unpoison (top, bot); >last_alloca_addr = new_sp; > + __builtin_stack_restore (new_sp); > In general, we can't use new_sp as bot parameter because on some > architectures SP has non zero offset from dynamic stack area. Moreover, > on > some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for > each > @@ -570,9 +570,8 @@ get_last_alloca_addr () > > http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK. > To overcome the issue we use following trick: pass new_sp as a second > parameter to __asan_allocas_unpoison and rewrite it during expansion with > - virtual_dynamic_stack_rtx later in expand_asan_emit_allocas_unpoison > - function. > -*/ > + new_sp + (virtual_dynamic_stack_rtx - sp) later in > + expand_asan_emit_allocas_unpoison function. */ > > static void > handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter) > @@ -584,9 +583,9 @@ handle_builtin_stack_restore (gcall *cal > tree restored_stack = gimple_call_arg (call, 0); > tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON); > gimple *g = gimple_build_call (fn, 2, last_alloca, restored_stack); > - gsi_insert_after (iter, g, GSI_NEW_STMT); > + gsi_insert_before (iter, g, GSI_SAME_STMT); > g = gimple_build_assign (last_alloca, restored_stack); > - gsi_insert_a
[PATCH][PR sanitizer/84250] Avoid global symbols collision when using both ASan and UBSan
Hi, as described in PR, when using both ASan and UBSan (-fsanitize=address,undefined ), we have symbols collision for global functions, like __sanitizer_set_report_path. This leads to fuzzy results when printing reports into files e.g. for this test case: #include int main(int argc, char **argv) { __sanitizer_set_report_path("/tmp/sanitizer.txt"); int i = 23; i <<= 32; int *array = new int[100]; delete [] array; return array[argc]; } only ASan's report gets written to file; UBSan output goes to stderr. To resolve this issue we could use two approaches: 1) Use the same approach to that is implemented in Clang (UBSan embedded to ASan). The only caveat here is that we need to link (unused) C++ part of UBSan even in C programs when linking static ASan runtime. This happens because GCC, as opposed to Clang, doesn't split C and C++ runtimes for sanitizers. 2) Just add SANITIZER_INTERFACE_ATTRIBUTE to report_file global variable. In this case all __sanitizer_set_report_path calls will set the same report_file variable. IMHO this is a hacky way to fix the issue, it's better to use the first option if possible. The attached patch fixes the symbols collision by embedding UBSan into ASan (variant 1), just like we do for LSan. Regtested/bootstrapped on x86_64-unknown-linux-gnu, looks reasonable enough for trunk? -Maxim gcc/ChangeLog: 2018-05-23 Maxim Ostapenko * config/gnu-user.h (LIBASAN_EARLY_SPEC): Pass -lstdc++ for static libasan. * gcc.c: Do not pass LIBUBSAN_SPEC if ASan is enabled with UBSan. libsanitizer/ChangeLog: 2018-05-23 Maxim Ostapenko * Makefile.am: Reorder libs. * Makefile.in: Regenerate. * asan/Makefile.am: Define DCAN_SANITIZE_UB=1, add dependancy from libsanitizer_ubsan.la. * asan/Makefile.in: Regenerate. * ubsan/Makefile.am: Define new libsanitizer_ubsan.la library. * ubsan/Makefile.in: Regenerate. diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index cba3c0b..ccae957 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h @@ -161,7 +161,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \ "%{static-libasan:%{!shared:" \ LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \ - LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}" + LD_DYNAMIC_OPTION " -lstdc++ }}%{!static-libasan:-lasan}" #undef LIBTSAN_EARLY_SPEC #define LIBTSAN_EARLY_SPEC "%{!shared:libtsan_preinit%O%s} " \ "%{static-libtsan:%{!shared:" \ diff --git a/gcc/gcc.c b/gcc/gcc.c index a716f70..215e7a0 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -984,7 +984,7 @@ proper position among the other output files. */ %{static:%ecannot specify -static with -fsanitize=address}}\ %{%:sanitize(thread):" LIBTSAN_SPEC "\ %{static:%ecannot specify -static with -fsanitize=thread}}\ -%{%:sanitize(undefined):" LIBUBSAN_SPEC "}\ +%{!%:sanitize(address):%{%:sanitize(undefined):" LIBUBSAN_SPEC "}}\ %{%:sanitize(leak):" LIBLSAN_SPEC "}}}" #endif diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am index 018f0b0..08d952b 100644 --- a/libsanitizer/Makefile.am +++ b/libsanitizer/Makefile.am @@ -14,7 +14,7 @@ endif if LIBBACKTRACE_SUPPORTED SUBDIRS += libbacktrace endif -SUBDIRS += lsan asan ubsan +SUBDIRS += lsan ubsan asan nodist_saninclude_HEADERS += \ include/sanitizer/lsan_interface.h \ include/sanitizer/asan_interface.h \ diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in index a9fea21e..9074292 100644 --- a/libsanitizer/Makefile.in +++ b/libsanitizer/Makefile.in @@ -140,8 +140,8 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan asan \ - ubsan tsan +DIST_SUBDIRS = sanitizer_common interception libbacktrace lsan ubsan \ + asan tsan ACLOCAL = @ACLOCAL@ ALLOC_FILE = @ALLOC_FILE@ AMTAR = @AMTAR@ @@ -294,7 +294,7 @@ ACLOCAL_AMFLAGS = -I .. -I ../config sanincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include/sanitizer nodist_saninclude_HEADERS = $(am__append_1) @SANITIZER_SUPPORTED_TRUE@SUBDIRS = sanitizer_common $(am__append_2) \ -@SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan asan ubsan \ +@SANITIZER_SUPPORTED_TRUE@ $(am__append_3) lsan ubsan asan \ @SANITIZER_SUPPORTED_TRUE@ $(am__append_4) gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am index f105b03..3ac49ee 100644 --- a/libsanitizer/asan/Makefile.am +++ b/libsanitizer/asan/Makefile.am @@ -3,7 +3,7 @@ AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir) # May be used by toolexeclibdir. gcc_version := $(shell @get_g
[PING][PATCH] Add patch for debugging compiler ICEs.
Ping. -Maxim Original Message Subject:[PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko To: GCC Patches CC: Jeff Law , Jakub Jelinek , tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov On 08/04/2014 09:03 PM, Maxim Ostapenko wrote: Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim
Fwd: [PATCH] Add patch for debugging compiler ICEs.
Ping. -Maxim Original Message Subject:[PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko To: GCC Patches CC: Jeff Law , Jakub Jelinek , tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim 2014-08-04 Jakub Jelinek Max Ostapenko * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 0c4f86b..aa79250 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 0cc7593..67b8c5b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4f327df..dafb573 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..f7a56d1 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2902,6 +2912,17 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { +#ifdef RETRY_ICE_SUPPORTED + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ +
[PATCH] Fix environment variables restoring in GCC testsuite.
Hi, When testing, I've noticed, that Asan-bootstrapped GCC should be executed with ASAN_OPTIONS=detect_leaks=0 because of memory leaks in GCC, reported by Leak Sanitizer. When I ran Asan test on Asan-bootstrapped GCC, some of them fail with memory leaks into GCC, even if Lsan is disabled. This caused by slightly wrong logic in saving/restoring env variables functionality in gcc-dg.exp (some tests override ASAN_OPTIONS and this env variable isn't restored correcty). This tiny patch seems to fix the issue. Tested on x86_64-pc-linux-gnu. Ok to commit? -Maxim gcc/testsuite/ChangeLog: 2014-08-22 Max Ostapenko * lib/gcc-dg.exp: Change pattern. diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 3390caa..d438c05 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -295,8 +295,8 @@ proc set-target-env-var { } { foreach env_var $set_target_env_var { set var [lindex $env_var 0] set value [lindex $env_var 1] - if [info exists env($var)] { - lappend saved_target_env_var [list $var 1 $env($var)] + if [info exists ::env($var)] { + lappend saved_target_env_var [list $var 1 $::env($var)] } else { lappend saved_target_env_var [list $var 0] }
[PATCH] Fix libbacktrace and libiberty tests fail on sanitized GCC due to wrong link options.
Hi, When I ran Asan tests under Asan-bootstrapped GCC 5.0, I've noted, that tests for libiberty and libbacktrace fail to link with sanitized libbacktrace.a and libiberty.a because of missing -static-libasan -fsanitize=address linker flags. This patch adds necessary flags to provide a linkage of these tests in bootstrap-asan case. I've checked that regression tests pass with disabled bootstrap, normal bootstrap (stage1, stage3) and Asan-bootstrap (stage 1, stage3) on x86_64-pc-linux-gnu. Does the patch look sane? -Maxim libiberty/ChangeLog: 2014-08-25 Max Ostapenko * testsuite/Makefile.in(LIBCFLAGS): Add LDFLAGS. ChangeLog: 2014-08-25 Max Ostapenko * Makefile.in (EXTRA_HOST_EXPORTS): New variables. (EXTRA_BOOTSTRAP_FLAGS): Likewise. (check-libiberty): Add EXTRA_HOST_EXPORTS and EXTRA_BOOTSTRAP_FLAGS. (check-libbacktrace): Likewise. diff --git a/Makefile.in b/Makefile.in index add8cf6..93d48b8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20541,8 +20541,9 @@ check-libbacktrace: @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ $(HOST_EXPORTS) \ + $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/libbacktrace && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif libbacktrace @@ -23597,6 +23598,13 @@ clean-stagefeedback-libiberty: @endif libiberty-bootstrap +@if gcc-bootstrap +EXTRA_HOST_EXPORTS = if [ $(current_stage) != stage1 ]; then \ + $(POSTSTAGE1_HOST_EXPORTS) \ + fi ; + +EXTRA_BOOTSTRAP_FLAGS = CC="$$CC" CXX="$$CXX" LDFLAGS="$$LDFLAGS" +@endif gcc-bootstrap @@ -23610,8 +23618,9 @@ check-libiberty: @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ $(HOST_EXPORTS) \ + $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/libiberty && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif libiberty diff --git a/libiberty/testsuite/Makefile.in b/libiberty/testsuite/Makefile.in index d23c09c..ef693c2 100644 --- a/libiberty/testsuite/Makefile.in +++ b/libiberty/testsuite/Makefile.in @@ -33,7 +33,7 @@ SHELL = @SHELL@ CC = @CC@ CFLAGS = @CFLAGS@ -LIBCFLAGS = $(CFLAGS) +LIBCFLAGS = $(CFLAGS) $(LDFLAGS) # Multilib support variables. MULTISRCTOP =
[Ping v2][PATCH] Add patch for debugging compiler ICEs.
Ping. Add Joseph S. Myers as driver maintainer. -Maxim Original Message Subject:Fwd: [PATCH] Add patch for debugging compiler ICEs. Date: Tue, 19 Aug 2014 17:57:51 +0400 From: Maxim Ostapenko To: Jeff Law , GCC Patches CC: tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov , Maxim Ostapenko Ping. -Maxim Original Message Subject:[PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko To: GCC Patches CC: Jeff Law , Jakub Jelinek , tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim 2014-08-04 Jakub Jelinek Max Ostapenko * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 0c4f86b..aa79250 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 0cc7593..67b8c5b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4f327df..dafb573 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..f7a56d1 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + i
Re: [PATCH] Fix libbacktrace and libiberty tests fail on sanitized GCC due to wrong link options.
On 08/25/2014 07:21 PM, Bernhard Reutner-Fischer wrote: On 25 August 2014 16:23:54 CEST, Yury Gribov wrote: On 08/25/2014 11:04 AM, Maxim Ostapenko wrote: This patch adds necessary flags to provide a linkage of these tests in bootstrap-asan case. I think you'll want to modify Makefile.def and Makefile.tpl because Makefile is generated from them. Thanks, got it. Here the updated version of previous patch. Does the patch look sane now? Sounds like this would fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56781 Thanks, -Maxim libiberty/ChangeLog: 2014-09-01 Max Ostapenko * testsuite/Makefile.in(LIBCFLAGS): Add LDFLAGS. ChangeLog: 2014-09-01 Max Ostapenko * Makefile.tpl (EXTRA_HOST_EXPORTS): New variables. (EXTRA_BOOTSTRAP_FLAGS): Likewise. (check-[+module+]): Add EXTRA_HOST_EXPORTS and EXTRA_BOOTSTRAP_FLAGS. * Makefile.in: Regenerate. diff --git a/Makefile.in b/Makefile.in index add8cf6..b0917e3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -830,6 +830,14 @@ POSTSTAGE1_FLAGS_TO_PASS = \ HOST_LIBS="$${HOST_LIBS}" \ "`echo 'ADAFLAGS=$(BOOT_ADAFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" +@if gcc-bootstrap +EXTRA_HOST_EXPORTS = if [ $(current_stage) != stage1 ]; then \ + $(POSTSTAGE1_HOST_EXPORTS) \ + fi ; + +EXTRA_BOOTSTRAP_FLAGS = CC="$$CC" CXX="$$CXX" LDFLAGS="$$LDFLAGS" +@endif gcc-bootstrap + # Flags to pass down to makes which are built with the target environment. # The double $ decreases the length of the command line; those variables # are set in BASE_FLAGS_TO_PASS, and the sub-make will expand them. The @@ -3518,9 +3526,9 @@ check-bfd: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/bfd && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif bfd @@ -4392,9 +4400,9 @@ check-opcodes: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/opcodes && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif opcodes @@ -5266,9 +5274,9 @@ check-binutils: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/binutils && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif binutils @@ -5696,9 +5704,9 @@ check-bison: @if [ '$(host)' = '$(target)' ] ; then \ r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/bison && \ - $(MAKE) $(FLAGS_TO_PASS) check); \ + $(MAKE) $(FLAGS_TO_PASS) check) fi @endif bison @@ -6138,7 +6146,7 @@ check-cgen: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/cgen && \ $(MAKE) $(FLAGS_TO_PASS) check) @@ -6579,7 +6587,7 @@ check-dejagnu: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/dejagnu && \ $(MAKE) $(FLAGS_TO_PASS) check) @@ -7020,7 +7028,7 @@ check-etc: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/etc && \ $(MAKE) $(FLAGS_TO_PASS) check) @@ -7463,9 +7471,9 @@ check-fastjar: @if [ '$(host)' = '$(target)' ] ; then \ r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/fastjar && \ - $(MAKE) $(FLAGS_TO_PASS) check); \ + $(MAKE) $(FLAGS_TO_PASS) check) fi @endif fastjar @@ -8351,9 +8359,9 @@ check-fixincludes: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/fixincludes && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif fixincludes @@ -8766,9 +8774,9 @@ check-flex: @if [ '$(host)' = '$(target)' ] ; then \ r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/flex && \ - $(MAKE) $(FLAGS_TO_PASS) check); \ +
Re: [PATCH] Fix libbacktrace and libiberty tests fail on sanitized GCC due to wrong link options.
On 09/01/2014 11:29 AM, Jakub Jelinek wrote: On Mon, Sep 01, 2014 at 11:19:07AM +0400, Maxim Ostapenko wrote: libiberty/ChangeLog: 2014-09-01 Max Ostapenko * testsuite/Makefile.in(LIBCFLAGS): Add LDFLAGS. Space before (. Ugh, sorry. # Flags to pass down to makes which are built with the target environment. # The double $ decreases the length of the command line; those variables # are set in BASE_FLAGS_TO_PASS, and the sub-make will expand them. The @@ -3518,9 +3526,9 @@ check-bfd: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/bfd && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) I'd put the double space right before check instead of in between different flags, or use a single space everywhere. Here the first space appears because extra_make_flags (EXTRA_GCC_FLAGS) is empty and autogen replaces this with a space. Removing the second one will lead to concatinating of $(EXTRA_GCC_FLAGS) and $(EXTRA_BOOTSTRAP_FLAGS). I know, two spaces look ugly, but is there more convenient way to avoid this? @@ -4392,9 +4400,9 @@ check-opcodes: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/opcodes && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) Ditto etc. @@ -6138,7 +6146,7 @@ check-cgen: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ Why? This is pretty the same. For all libs, that wouldn't be bootstrapped, autogen inserts a space instead of $(EXTRA_HOST_EXPORTS). Perhaps I should always insert $(EXTRA_HOST_EXPORTS) and $(EXTRA_BOOTSTRAP_FLAGS) with empty/nonempty values instead of tracking libraries, that would/wouldn't be bootstrapped? -Maxim Jakub
[PING][PATCH] Fix environment variables restoring in GCC testsuite.
Ping. -Maxim Original Message Subject:[PATCH] Fix environment variables restoring in GCC testsuite. Date: Fri, 22 Aug 2014 14:39:16 +0400 From: Maxim Ostapenko To: GCC Patches CC: Yury Gribov , Slava Garbuzov Hi, When testing, I've noticed, that Asan-bootstrapped GCC should be executed with ASAN_OPTIONS=detect_leaks=0 because of memory leaks in GCC, reported by Leak Sanitizer. When I ran Asan test on Asan-bootstrapped GCC, some of them fail with memory leaks into GCC, even if Lsan is disabled. This caused by slightly wrong logic in saving/restoring env variables functionality in gcc-dg.exp (some tests override ASAN_OPTIONS and this env variable isn't restored correcty). This tiny patch seems to fix the issue. Tested on x86_64-pc-linux-gnu. Ok to commit? -Maxim gcc/testsuite/ChangeLog: 2014-09-01 Max Ostapenko * lib/gcc-dg.exp: Change pattern. diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 3390caa..d438c05 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -295,8 +295,8 @@ proc set-target-env-var { } { foreach env_var $set_target_env_var { set var [lindex $env_var 0] set value [lindex $env_var 1] - if [info exists env($var)] { - lappend saved_target_env_var [list $var 1 $env($var)] + if [info exists ::env($var)] { + lappend saved_target_env_var [list $var 1 $::env($var)] } else { lappend saved_target_env_var [list $var 0] }
[Ping v3][PATCH] Add patch for debugging compiler ICEs.
Ping. -Maxim On 08/28/2014 11:31 AM, Maxim Ostapenko wrote: Ping. Add Joseph S. Myers as driver maintainer. -Maxim Original Message Subject: Fwd: [PATCH] Add patch for debugging compiler ICEs. Date: Tue, 19 Aug 2014 17:57:51 +0400 From: Maxim Ostapenko To: Jeff Law , GCC Patches CC: tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov , Maxim Ostapenko Ping. -Maxim Original Message Subject: [PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko To: GCC Patches CC: Jeff Law , Jakub Jelinek , tsaund...@mozilla.com, Yury Gribov , Slava Garbuzov Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim 2014-08-04 Jakub Jelinek Max Ostapenko * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index f7021102..1133e61 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 73666d6..60ed607 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -494,7 +494,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d15d4a9..f41a1d8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6316,6 +6316,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..e0c403d 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (v
[Ping][PATCH] Fix libbacktrace and libiberty tests fail on sanitized GCC due to wrong link options.
Ping. Original Message Subject: Re: [PATCH] Fix libbacktrace and libiberty tests fail on sanitized GCC due to wrong link options. Date: Mon, 01 Sep 2014 12:33:09 +0400 From: Maxim Ostapenko To: Jakub Jelinek CC: Bernhard Reutner-Fischer , Yury Gribov , GCC Patches , Slava Garbuzov On 09/01/2014 11:29 AM, Jakub Jelinek wrote: On Mon, Sep 01, 2014 at 11:19:07AM +0400, Maxim Ostapenko wrote: libiberty/ChangeLog: 2014-09-01 Max Ostapenko * testsuite/Makefile.in(LIBCFLAGS): Add LDFLAGS. Space before (. Ugh, sorry. # Flags to pass down to makes which are built with the target environment. # The double $ decreases the length of the command line; those variables # are set in BASE_FLAGS_TO_PASS, and the sub-make will expand them. The @@ -3518,9 +3526,9 @@ check-bfd: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/bfd && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) I'd put the double space right before check instead of in between different flags, or use a single space everywhere. Here the first space appears because extra_make_flags (EXTRA_GCC_FLAGS) is empty and autogen replaces this with a space. Removing the second one will lead to concatinating of $(EXTRA_GCC_FLAGS) and $(EXTRA_BOOTSTRAP_FLAGS). I know, two spaces look ugly, but is there more convenient way to avoid this? @@ -4392,9 +4400,9 @@ check-opcodes: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/opcodes && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) Ditto etc. @@ -6138,7 +6146,7 @@ check-cgen: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) \ Why? This is pretty the same. For all libs, that wouldn't be bootstrapped, autogen inserts a space instead of $(EXTRA_HOST_EXPORTS). Perhaps I should always insert $(EXTRA_HOST_EXPORTS) and $(EXTRA_BOOTSTRAP_FLAGS) with empty/nonempty values instead of tracking libraries, that would/wouldn't be bootstrapped? -Maxim Jakub libiberty/ChangeLog: 2014-09-01 Max Ostapenko * testsuite/Makefile.in (LIBCFLAGS): Add LDFLAGS. ChangeLog: 2014-09-01 Max Ostapenko * Makefile.tpl (EXTRA_HOST_EXPORTS): New variables. (EXTRA_BOOTSTRAP_FLAGS): Likewise. (check-[+module+]): Add EXTRA_HOST_EXPORTS and EXTRA_BOOTSTRAP_FLAGS. * Makefile.in: Regenerate. diff --git a/Makefile.in b/Makefile.in index add8cf6..b0917e3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -830,6 +830,14 @@ POSTSTAGE1_FLAGS_TO_PASS = \ HOST_LIBS="$${HOST_LIBS}" \ "`echo 'ADAFLAGS=$(BOOT_ADAFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" +@if gcc-bootstrap +EXTRA_HOST_EXPORTS = if [ $(current_stage) != stage1 ]; then \ + $(POSTSTAGE1_HOST_EXPORTS) \ + fi ; + +EXTRA_BOOTSTRAP_FLAGS = CC="$$CC" CXX="$$CXX" LDFLAGS="$$LDFLAGS" +@endif gcc-bootstrap + # Flags to pass down to makes which are built with the target environment. # The double $ decreases the length of the command line; those variables # are set in BASE_FLAGS_TO_PASS, and the sub-make will expand them. The @@ -3518,9 +3526,9 @@ check-bfd: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/bfd && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif bfd @@ -4392,9 +4400,9 @@ check-opcodes: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/opcodes && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif opcodes @@ -5266,9 +5274,9 @@ check-binutils: @: $(MAKE); $(unstage) @r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $(HOST_EXPORTS) \ + $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \ (cd $(HOST_SUBDIR)/binutils && \ - $(MAKE) $(FLAGS_TO_PASS) check) + $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check) @endif binutils @@ -5696,9 +5704,9 @@ check-bison: @if [ '$(host)' = '$(target)' ] ; then \ r=`${PWD_COMMAND}`; export r; \ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ - $
Re: [PATCH] PR58867 ASan and UBSan tests not run for installed testing.
Does it work without restore_ld_library_path in {asan, ubsan, tsan}_finish? I see two opportunities to fix the issue: 1) Implement a stack of saved contexts. 2) Implement new functions, say {asan, ubsan, tsan}_restore_ld_library_path, to be able {asan, ubsan, tsan}_finish functions restore context correctly. What solution is preferable? -Maxim On 10/08/2014 01:02 PM, Marcus Shawcroft wrote: On 1 October 2014 08:09, Maxim Ostapenko wrote: Hi, some time ago, Andrew wrote a patch that fixes PR58867 (http://patchwork.ozlabs.org/patch/286866/), but for some reasons it wasn't committed to trunk. This is resurrected Andrew's patch, extended to support Tsan testsuite. Tested on x86_64-pc-linux-gnu, ok to commit? -Maxim Hi, This patch results in wide spread failures in our bare metal test runs. I have not dug into the issue in detail but it appears that the issue is related to the attempted use of set_ld_library_path_env_vars and restore_ld_library_path_env_vars to save and restore nested contexts. Consider ubsan/ubsan.exp: load_lib gcc-dg.exp ... dg-init ubsan_init ... ubsan_finish The gcc-dg.exp library load calls set_ld_library_path_env_vars the first time an initializes GCC_EXEC_PREFIX. The ubsan_init call makes a further call to set_ld_library_path_env_vars which has no effect. The ubsan_finish invokes restore_ld_library_path_env_vars, restoring the environments as it was prior to the call to dg-init. Any further test execution has now lost the original initialization of GCC_EXEC_PREFIX by gcc-dg.exp It seems to me that either this patch assumes that the set/restore_ld_library_path_env foo is capable of maintaining a stack of saved contexts... which it is not. Prior to this patch ubsan_finish did not attempt to call restore_ld_library_path_env_vars hence the gcc-dg.exp environment remained in place for subsequent test executions. Cheers /Marcus
Re: [PATCH] PR58867 ASan and UBSan tests not run for installed testing.
Hm, as I see, others testsuites such as gfortran.exp, go.exp etc. do not call restore_ld_library_path at all. Perhaps we could simply follow this way? Would failing tests still fail if remove restore_ld_library_path from {asan, tsan, ubsan}_finish? On 10/08/2014 03:40 PM, Marcus Shawcroft wrote: On 8 October 2014 11:10, Maxim Ostapenko wrote: Does it work without restore_ld_library_path in {asan, ubsan, tsan}_finish? I see two opportunities to fix the issue: 1) Implement a stack of saved contexts. 2) Implement new functions, say {asan, ubsan, tsan}_restore_ld_library_path, to be able {asan, ubsan, tsan}_finish functions restore context correctly. What solution is preferable? Option 1 has the advantage that it places all of the context save and restore in one place rather than spreading it around the infrastructure. Please can we revert this patch while a correct implementation is being worked? Cheers /Marcus diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index 9769138..c98fd3c 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -132,7 +132,6 @@ proc asan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars } # Symbolize lines like diff --git a/gcc/testsuite/lib/tsan-dg.exp b/gcc/testsuite/lib/tsan-dg.exp index 54ec404..6f7a4d9 100644 --- a/gcc/testsuite/lib/tsan-dg.exp +++ b/gcc/testsuite/lib/tsan-dg.exp @@ -143,5 +143,4 @@ proc tsan_finish { args } { } else { unset dg-do-what-default } -restore_ld_library_path_env_vars } diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp index 5a7a653..87c460f 100644 --- a/gcc/testsuite/lib/ubsan-dg.exp +++ b/gcc/testsuite/lib/ubsan-dg.exp @@ -114,5 +114,4 @@ proc ubsan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars }
Re: [PATCH] PR58867 ASan and UBSan tests not run for installed testing.
Hi Jiong, I couldn't reproduce tests failures on my box, perhaps I missed something. How can I test this? -Maxim On 10/08/2014 06:30 PM, Jiong Wang wrote: On 08/10/14 15:00, Maxim Ostapenko wrote: Hm, as I see, others testsuites such as gfortran.exp, go.exp etc. do not call restore_ld_library_path at all. Perhaps we could simply follow this way? Would failing tests still fail if remove restore_ld_library_path from {asan, tsan, ubsan}_finish? Hi Maxim, verified those fails gone away on check-gcc. but not sure whether this remove will cause problem on other test environments which they are aimed to solve. -- Jiong On 10/08/2014 03:40 PM, Marcus Shawcroft wrote: On 8 October 2014 11:10, Maxim Ostapenko wrote: Does it work without restore_ld_library_path in {asan, ubsan, tsan}_finish? I see two opportunities to fix the issue: 1) Implement a stack of saved contexts. 2) Implement new functions, say {asan, ubsan, tsan}_restore_ld_library_path, to be able {asan, ubsan, tsan}_finish functions restore context correctly. What solution is preferable? Option 1 has the advantage that it places all of the context save and restore in one place rather than spreading it around the infrastructure. Please can we revert this patch while a correct implementation is being worked? Cheers /Marcus
[PATCH] Fix GCC tests fail for installed toolchain due to ASan, UBSan and TSan testsuites drop GCC_EXEC_PREFIX.
Hi, After enabling ASan, TSan and UBSan testsuites for installed toolchain, many tests started to fail. This is caused by wrong logic in {asan, ubsan, tsan}_finish functions. Here, restore_ld_library_path is called, that is wrong, because it drops some env variables ( GCC_EXEC_PREFIX, LD_LIBRARY_PATH, etc) to state that was before gcc-dg.exp initialized testing environment, so installed GCC will be confused to find some needed stuff later. Removing restore_ld_library_path from {asan, ubsan, tsan}_finish seems to fix the issue. Tested on x86_64-pc-linux-gnu, ok to commit? -Maxim gcc/testsuite/ChangeLog: 2014-10-09 Max Ostapenko * lib/asan-dg.exp (asan_finish): Remove restore_ld_library_path_env_vars. * lib/tsan-dg.exp (tsan_finish): Likewise. * lib/ubsan-dg.exp (ubsan_finish): Likewise. diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index 9769138..c98fd3c 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -132,7 +132,6 @@ proc asan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars } # Symbolize lines like diff --git a/gcc/testsuite/lib/tsan-dg.exp b/gcc/testsuite/lib/tsan-dg.exp index 54ec404..6f7a4d9 100644 --- a/gcc/testsuite/lib/tsan-dg.exp +++ b/gcc/testsuite/lib/tsan-dg.exp @@ -143,5 +143,4 @@ proc tsan_finish { args } { } else { unset dg-do-what-default } -restore_ld_library_path_env_vars } diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp index 5a7a653..87c460f 100644 --- a/gcc/testsuite/lib/ubsan-dg.exp +++ b/gcc/testsuite/lib/ubsan-dg.exp @@ -114,5 +114,4 @@ proc ubsan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars }
Re: [PATCH] Fix GCC tests fail for installed toolchain due to ASan, UBSan and TSan testsuites drop GCC_EXEC_PREFIX.
Adding Jakub. -Maxim On 10/09/2014 04:34 PM, Maxim Ostapenko wrote: Hi, After enabling ASan, TSan and UBSan testsuites for installed toolchain, many tests started to fail. This is caused by wrong logic in {asan, ubsan, tsan}_finish functions. Here, restore_ld_library_path is called, that is wrong, because it drops some env variables ( GCC_EXEC_PREFIX, LD_LIBRARY_PATH, etc) to state that was before gcc-dg.exp initialized testing environment, so installed GCC will be confused to find some needed stuff later. Removing restore_ld_library_path from {asan, ubsan, tsan}_finish seems to fix the issue. Tested on x86_64-pc-linux-gnu, ok to commit? -Maxim gcc/testsuite/ChangeLog: 2014-10-09 Max Ostapenko * lib/asan-dg.exp (asan_finish): Remove restore_ld_library_path_env_vars. * lib/tsan-dg.exp (tsan_finish): Likewise. * lib/ubsan-dg.exp (ubsan_finish): Likewise. diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index 9769138..c98fd3c 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -132,7 +132,6 @@ proc asan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars } # Symbolize lines like diff --git a/gcc/testsuite/lib/tsan-dg.exp b/gcc/testsuite/lib/tsan-dg.exp index 54ec404..6f7a4d9 100644 --- a/gcc/testsuite/lib/tsan-dg.exp +++ b/gcc/testsuite/lib/tsan-dg.exp @@ -143,5 +143,4 @@ proc tsan_finish { args } { } else { unset dg-do-what-default } -restore_ld_library_path_env_vars } diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp index 5a7a653..87c460f 100644 --- a/gcc/testsuite/lib/ubsan-dg.exp +++ b/gcc/testsuite/lib/ubsan-dg.exp @@ -114,5 +114,4 @@ proc ubsan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars }
Re: [PATCH] Fix GCC tests fail for installed toolchain due to ASan, UBSan and TSan testsuites drop GCC_EXEC_PREFIX.
On 10/10/2014 11:30 AM, Jakub Jelinek wrote: On Fri, Oct 10, 2014 at 11:13:11AM +0400, Maxim Ostapenko wrote: Adding Jakub. -Maxim On 10/09/2014 04:34 PM, Maxim Ostapenko wrote: Hi, After enabling ASan, TSan and UBSan testsuites for installed toolchain, many tests started to fail. This is caused by wrong logic in {asan, ubsan, tsan}_finish functions. Here, restore_ld_library_path is called, that is wrong, because it drops some env variables ( GCC_EXEC_PREFIX, LD_LIBRARY_PATH, etc) to state that was before gcc-dg.exp initialized testing environment, so installed GCC will be confused to find some needed stuff later. Removing restore_ld_library_path from {asan, ubsan, tsan}_finish seems to fix the issue. Tested on x86_64-pc-linux-gnu, ok to commit? -Maxim gcc/testsuite/ChangeLog: 2014-10-09 Max Ostapenko * lib/asan-dg.exp (asan_finish): Remove restore_ld_library_path_env_vars. * lib/tsan-dg.exp (tsan_finish): Likewise. * lib/ubsan-dg.exp (ubsan_finish): Likewise. That looks wrong to me, we don't want to keep the libsanitizer paths in LD_LIBRARY_PATH* after we leave asan.exp etc. So, perhaps instead save ld_library_path into some global variable (like {a,t,ub}san_saved_ld_library_path) during {a,t,ub}san_link_flags before appending there anything, and replace restore_ld_library_path_env_vars with set ld_library_path ${a,t,ub}san_saved_ld_library_path set_ld_library_path_env_vars ? Jakub This works indeed. However, calling set_ld_library_path_env_vars in {asan, tsan, ubsan}_finish will lead to updating LD_LIBRARY_PATH_{32, 64}, LD_RUN_PATH etc. with "$ld_library_path:$orig_ld_{library_path_32, library_path_64, run, etc}". Is this fine? -Maxim gcc/testsuite/ChangeLog: 2014-10-10 Max Ostapenko * lib/asan-dg.exp (asan_link_flags): Save ld_library_path. * lib/tsan-dg.exp (tsan_link_flags): Likewise. * lib/ubsan-dg.exp (ubsan_link_flags): Likewise. * lib/asan-dg.exp (asan_finish): Remove restore_ld_library_path_env_vars. Restore ld_library_path with saved value. Restore LD_LIBRARY_PATH related env variables by calling set_ld_library_path_env_vars. * lib/tsan-dg.exp (tsan_finish): Likewise. * lib/ubsan-dg.exp (ubsan_finish): Likewise. diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index 9769138..4e8b4d6 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -47,11 +47,13 @@ proc asan_link_flags { paths } { global srcdir global ld_library_path global shlib_ext +global asan_saved_library_path set gccpath ${paths} set flags "" set shlib_ext [get_shlib_extension] +set asan_saved_library_path $ld_library_path if { $gccpath != "" } { if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"] @@ -122,6 +124,8 @@ proc asan_finish { args } { global TEST_ALWAYS_FLAGS global asan_saved_TEST_ALWAYS_FLAGS global asan_saved_ALWAYS_CXXFLAGS +global asan_saved_library_path +global ld_library_path if [info exists asan_saved_ALWAYS_CXXFLAGS ] { set ALWAYS_CXXFLAGS $asan_saved_ALWAYS_CXXFLAGS @@ -132,7 +136,8 @@ proc asan_finish { args } { unset TEST_ALWAYS_FLAGS } } -restore_ld_library_path_env_vars +set ld_library_path $asan_saved_library_path +set_ld_library_path_env_vars } # Symbolize lines like diff --git a/gcc/testsuite/lib/tsan-dg.exp b/gcc/testsuite/lib/tsan-dg.exp index 54ec404..77c85ff 100644 --- a/gcc/testsuite/lib/tsan-dg.exp +++ b/gcc/testsuite/lib/tsan-dg.exp @@ -32,11 +32,13 @@ proc tsan_link_flags { paths } { global srcdir global ld_library_path global shlib_ext +global tsan_saved_library_path set gccpath ${paths} set flags "" set shlib_ext [get_shlib_extension] +set tsan_saved_library_path $ld_library_path if { $gccpath != "" } { if { [file exists "${gccpath}/libsanitizer/tsan/.libs/libtsan.a"] @@ -127,6 +129,8 @@ proc tsan_finish { args } { global tsan_saved_ALWAYS_CXXFLAGS global dg-do-what-default global tsan_saved_dg-do-what-default +global tsan_saved_library_path +global ld_library_path if [info exists tsan_saved_ALWAYS_CXXFLAGS ] { set ALWAYS_CXXFLAGS $tsan_saved_ALWAYS_CXXFLAGS @@ -143,5 +147,6 @@ proc tsan_finish { args } { } else { unset dg-do-what-default } -restore_ld_library_path_env_vars +set ld_library_path $tsan_saved_library_path +set_ld_library_path_env_vars } diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp index 5a7a653..3bfdcc8 100644 --- a/gcc/testsuite/lib/ubsan-dg.exp +++ b/gcc/testsuite/lib/ubsan-dg.exp @@ -32,11 +32,13 @@ proc ubsan_link_flags { paths } { global srcdir global ld_library_path global shlib_ext +global ubsan_saved_library_path set gccpath ${paths} set flags "" set shlib_e
[PATCH] Don't expand string/memory builtins if ASan is enabled.
Hi, this patch disables string/memory builtin functions inlining if ASan is enabled. As described in my previous post (https://gcc.gnu.org/ml/gcc/2014-09/msg00020.html), this allow us to be sure that some dangerous builtins (strcpy, stpcpy, etc) will be handled correctly. Also, some redundant checks will be removed for builtin functions, that are instrumented but later not inlined for some reason. Patch also changes logic in asan_mem_ref_hash updating. I eliminated memory ref access size from hash computing, so all accesses for same memory reference have the same hash. Updating of asan_mem_ref_hash occurs only if new access size is greater then saved one. I've provided some performance testing (spec2006 v1.1) on x86_64-unknown-linux-gnu and attached results in test.res (sorry for this, I couldn't make my Thunderbird make a pretty table). Regtested / bootstrapped on x86_64-unknown-linux-gnu. Does this patch look sane? -Maxim $ ~/install/master-x86_64/bin/gcc -v Using built-in specs. COLLECT_GCC=/home/max/install/master-x86_64/bin/gcc COLLECT_LTO_WRAPPER=/home/max/install/master-x86_64/libexec/gcc/x86_64-unknown-linux-gnu/5.0.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: /home/max/workspace/downloads/gcc/configure --enable-multilib --enable-checking --target=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu --build=x86_64-unknown-linux-gnu --prefix=/home/max/install/master-x86_64 --disable-bootstrap --enable-languages=c,c++ Thread model: posix gcc version 5.0.0 20141014 (experimental) (GCC) Compile options: -O3 -fsanitize=address -static-libasan. testmaster nobuiltin % of slowdown 400.perlbench1044 10500,5747 401.bzip2682 676-0,8798 403.gcc 497 495-0,4024 429.mcf 488 489 0,2049 445.gobmk723 724 0,1383 456.hmmer783 750-4,2146 458.sjeng887 880-0,7892 462.libquantum 330 323-2,1212 464.h264ref 1108 11544,1516 471.omnetpp 545 559 2,5688 473.astar490 480-2,0408 483.xalancbmk411 400-2,6764 433.milc 517 509-1,5474 444.namd 419 419 0, 450.soplex 310 299-3,5484 453.povray 287 276-3,8328 470.lbm 299 306 2,3411 482.sphinx3 777 804 3,4749 Geomean: master nobuiltin% of increase 540538-0,50 gcc/ChangeLog: 2014-10-17 Max Ostapenko * asan.c (asan_mem_ref_hasher::hash): Remove MEM_REF access size from hash value construction. Call iterative_hash_expr instead of explicit hash building. (asan_mem_ref_hasher::equal): Change condition. (has_mem_ref_been_instrumented): Likewise. (update_mem_ref_hash_table): Likewise. (maybe_update_mem_ref_hash_table): New function. (instrument_strlen_call): Removed. (instrument_mem_region_access): Likewise. (instrument_builtin_call): Call maybe_update_mem_ref_hash_table instead of instrument_mem_region_access. * builtins.c (is_memory_builtin): New function. (expand_builtin): Don't expand string/memory builtin functions if ASan is enabled. * builtins.def: Add comment. gcc/testsuite/ChangeLog: 2014-10-17 Max Ostapenko * c-c++-common/asan/no-redundant-instrumentation-1.c: Updated test. * c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-2.c: Removed. * c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-10.c: New test. * c-c++-common/asan/no-redundant-instrumentation-11.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index 2a61a82..391f693 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -352,10 +352,7 @@ struct asan_mem_ref_hasher inline hashval_t asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref) { - inchash::hash hstate; - inchash::add_expr (mem_ref->start, hstate); - hstate.add_wide_int (mem_ref->access_size); - return hstate.end (); + return iterative_hash_expr (mem_ref->start, 0); } /* Compare two memory references. We accept the length of either @@ -365,8 +362,7 @@ inline bool asan_mem_ref_hasher::equal (const asan_mem_ref *m1, const asan_mem_ref *m2) { - return (m1->access_size == m2->access_size - && operand_equal_p (m1->start, m2->start, 0)); + return operand_equal_p (m1->start, m2->start, 0); } static hash_table *asan_mem_ref_ht; @@ -417,7 +413,8 @@ has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size) asan_mem_ref r; asan_mem_ref_init (&r, ref, access_size); - return (get_mem_ref_hash_table
[PATCHv2] Don't expand string/memory builtins if ASan is enabled.
Hi, this is the second version of the patch. Here the major changes from the previous one: 1) Added a new intercepted_p parameter in get_mem_refs_of_builtin_call to decide whether builtin function should/shouldn't be instrumented. 2) Changed instrument_mem_region_access function. Now, we update asan_mem_ref_ht with (base, size_in_bytes), if we can determine access size during compile time. 3) Removed ASAN_CHECK_START_INSTRUMENTED and ASAN_CHECK_END_INSTRUMENTED from asan_check_flags since we don't instrument base and end of memory region with access size 1 anymore. 4) Specified builtins that shouldn't be expanded explicitly in gcc/builtins.c. Regtested / bootrapped on x86_64-unknown-linux-gnu. -Maxim On 10/17/2014 05:03 PM, Jakub Jelinek wrote: On Fri, Oct 17, 2014 at 05:01:33PM +0400, Yury Gribov wrote: On 10/17/2014 04:24 PM, Jakub Jelinek wrote: +/* Returns TRUE if given FCODE corresponds to string or memory builtin function. + */ + +static inline bool +is_memory_builtin (enum built_in_function fcode) +{ + return fcode <= BUILT_IN_STRSTR && fcode >= BUILT_IN_BCMP; This is too fragile and ugly. IMHO you should list (supposedly not in a special inline, but directly where you use it) in a switch all the builtins you don't want to expand. We already do this for BUILT_IN_ASAN_REPORT_LOAD1 ... BUILT_IN_ASAN_STOREN I know, but it is still a coherent sent of builtins for very similar purposes, many of them sorted by increasing size number. but I agree that this one is more ugly. The memops builtins are just random bag of them, it is expected many people will add builtins into that range and outside of that range. Jakub gcc/ChangeLog: 2014-10-21 Max Ostapenko * asan.c (asan_mem_ref_hasher::hash): Remove MEM_REF access size from hash value construction. Call iterative_hash_expr instead of explicit hash building. (asan_mem_ref_hasher::equal): Change condition. (has_mem_ref_been_instrumented): Likewise. (update_mem_ref_hash_table): Likewise. (maybe_update_mem_ref_hash_table): New function. (instrument_strlen_call): Removed. (get_mem_refs_of_builtin_call): Handle new parameter. (instrument_builtin_call): Call maybe_update_mem_ref_hash_table instead of instrument_mem_region_access if intercepted_p is true. (instrument_mem_region_access): Instrument only base with len instead of base and end with 1. (build_check_stmt): Remove start_instrumented and end_instrumented parameters. (enum asan_check_flags): Remove ASAN_CHECK_START_INSTRUMENTED and ASAN_CHECK_END_INSTRUMENTED. Change ASAN_CHECK_LAST. (asan_expand_check_ifn): Remove start_instrumented and end_instrumented. * builtins.c (expand_builtin): Don't expand string/memory builtin functions that have interceptors in libsanitizer if ASan is enabled. gcc/testsuite/ChangeLog: 2014-10-21 Max Ostapenko * c-c++-common/asan/no-redundant-instrumentation-1.c: Updated test. * c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-2.c: Removed. * c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise. * c-c++-common/asan/no-redundant-instrumentation-10.c: New test. * c-c++-common/asan/no-redundant-instrumentation-11.c: Likewise. diff --git a/gcc/asan.c b/gcc/asan.c index 2a61a82..a9eb9aa 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -253,9 +253,7 @@ enum asan_check_flags ASAN_CHECK_STORE = 1 << 0, ASAN_CHECK_SCALAR_ACCESS = 1 << 1, ASAN_CHECK_NON_ZERO_LEN = 1 << 2, - ASAN_CHECK_START_INSTRUMENTED = 1 << 3, - ASAN_CHECK_END_INSTRUMENTED = 1 << 4, - ASAN_CHECK_LAST + ASAN_CHECK_LAST = 1 << 3 }; /* Hashtable support for memory references used by gimple @@ -352,10 +350,7 @@ struct asan_mem_ref_hasher inline hashval_t asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref) { - inchash::hash hstate; - inchash::add_expr (mem_ref->start, hstate); - hstate.add_wide_int (mem_ref->access_size); - return hstate.end (); + return iterative_hash_expr (mem_ref->start, 0); } /* Compare two memory references. We accept the length of either @@ -365,8 +360,7 @@ inline bool asan_mem_ref_hasher::equal (const asan_mem_ref *m1, const asan_mem_ref *m2) { - return (m1->access_size == m2->access_size - && operand_equal_p (m1->start, m2->start, 0)); + return operand_equal_p (m1->start, m2->start, 0); } static hash_table *asan_mem_ref_ht; @@ -417,7 +411,8 @@ has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size) asan_mem_ref r; asan_mem_ref_init (&r, ref, access_size); - return (get_mem_ref_hash_table ()->find (&r) != NULL); + asan_mem_ref *saved_ref = get_mem_ref_hash_table ()->find (&r); + return saved_ref && saved_ref->access_size >= access_
Re: [PATCH] PR58867 ASan and UBSan tests not run for installed testing.
On 10/24/2014 02:43 PM, Eric Botcazou wrote: some time ago, Andrew wrote a patch that fixes PR58867 (http://patchwork.ozlabs.org/patch/286866/), but for some reasons it wasn't committed to trunk. This is resurrected Andrew's patch, extended to support Tsan testsuite. This patch broke --disable-libsanitizer though, i.e. you now get gazillions of sanitizer failures in the C and C++ testsuites. Hi, do you have any other (system) version of GCC, configured without --disable-libsanitizer? If so, perhaps your GCC links with system asan_preinit.o and links dummy int main () { return 0; } in check_effective_target_fsanitize_address successfully, but fails to find libasan.so in execution tests because LD_LIBRARY_PATH does not contain any path to libasan.so.2. If so, I see two ways to fix this: 1) Add path to system libs in LD_LIBRARY_PATH explicitly. 2) Make check_effective_target_fsanitize_address not only link dummy executable, but also run it and verify that exit code equals zero. -Maxim