This is an archive of the discontinued LLVM Phabricator instance.

[ASan] Get fake stack code working with GCC 4.8.2.
ClosedPublic

Authored by foad on Nov 14 2014, 5:28 AM.

Details

Summary

TestCases/Linux/heavy_uar_test.cc was failing on my
PowerPC64 box with GCC 4.8.2, because the compiler recognised
a memset-like loop and turned it into a call to memset, which
got intercepted by __asan_memset, which got upset because it was
being called on an address in high shadow memory.

Use break_optimization to stop the compiler from doing this.

Diff Detail

Event Timeline

foad updated this revision to Diff 16205.Nov 14 2014, 5:28 AM
foad retitled this revision from to [ASan] Get fake stack code working with GCC 4.8.2..
foad updated this object.
foad edited the test plan for this revision. (Show Details)
foad added reviewers: kcc, samsonov.
foad added a subscriber: Unknown Object (MLST).
kcc edited edge metadata.Nov 14 2014, 8:46 AM

I think that instead of adding an option to one of N supported build systems we need to make the code more compiler-resistant

foad added a comment.Nov 14 2014, 11:39 AM
In D6266#4, @kcc wrote:

I think that instead of adding an option to one of N supported build systems we need to make the code more compiler-resistant

Do you mean changing the code in SetShadow? I suppose I could try adding "volatile" or something. (Yuck!)

The only other approach I can think of is for __asan_memset to detect whether it has been called from the application or from libasan itself; either by looking at the return address, or by changing every entry point in the sanitizer to set some "in asan" flag.

kcc added a comment.Nov 14 2014, 12:04 PM
In D6266#5, @foad wrote:
In D6266#4, @kcc wrote:

I think that instead of adding an option to one of N supported build systems we need to make the code more compiler-resistant

Do you mean changing the code in SetShadow? I suppose I could try adding "volatile" or something. (Yuck!)

Slightly better way is to move break_optimization from sanitizer_common/sanitizer_libc.cc
to sanitizer_common/sanitizer_common.h and use it inside the loop.

It's not perfect either, because this will not let the compiler use wider stores.

Ideally, I would introduce internal_memset_aligned64, similar to internal_bzero_aligned16 in sanitizer_common/sanitizer_libc.cc.
Then for small class_id (0, 1, 2) use explicit assignments and for large ones (3, 4, 5, 6) use internal_memset_aligned64

The only other approach I can think of is for __asan_memset to detect whether it has been called from the application or from libasan itself; either by looking at the return address, or by changing every entry point in the sanitizer to set some "in asan" flag.

God forbid :)

foad updated this revision to Diff 16268.Nov 15 2014, 12:29 PM
foad edited edge metadata.

Use break_optimisation instead of compiler flags.

foad updated this object.Nov 15 2014, 12:33 PM
foad updated this revision to Diff 16276.Nov 16 2014, 2:39 AM

Fix build failure by removing another competing definition of
break_optimization.

samsonov edited edge metadata.Nov 16 2014, 3:29 PM

Did you try -ffreestanding flag?

foad added a comment.Nov 17 2014, 1:59 AM
In D6266#12, @samsonov wrote:

Did you try -ffreestanding flag?

Yes. It doesn't help.

To quote the GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888
"Thus, from 4.8.3, 4.9.1 and 4.10.0 on -ffreestanding, -fno-hosted and -fno-builtin
will cause -ftree-loop-distribute-patterns to _not_ be enabled by default
with -O3+ (you can still enable it manually)."

kcc accepted this revision.Nov 19 2014, 2:39 PM
kcc edited edge metadata.

LGTM

This revision is now accepted and ready to land.Nov 19 2014, 2:39 PM
foad added a comment.Nov 20 2014, 6:34 AM

Unfortunately the current patch still doesn't build cleanly.

The problem is that I'm trying to move the definition of break_optimization into lib/sanitizer_common/sanitizer_common.h, but there is already another definition of break_optimization in lib/sanitizer_common/tests/sanitizer_test_utils.h.

Some tests, like lib/sanitizer_common/tests/sanitizer_allocator_test.cc, include both of these headers.

Others, like lib/asan/tests/asan_test.cc, only include sanitizer_test_utils.h.

I tried including sanitizer_common.h from sanitizer_test_utils.h but I ran into this, and I don't know how to fix it:

In file included from /home/jay/svn/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_interface_test.cc:15:
In file included from /home/jay/svn/llvm-project/llvm/trunk/projects/compiler-rt/include/sanitizer/asan_interface.h:17:
/home/jay/svn/llvm-project/llvm/trunk/projects/compiler-rt/include/sanitizer/common_interface_defs.h:40:5: error: typedef redefinition with different types ('struct __sanitizer_sandbox_arguments' vs 'struct __sanitizer_sandbox_arguments')
  } __sanitizer_sandbox_arguments;
    ^
/home/jay/svn/llvm-project/llvm/trunk/projects/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h:109:5: note: previous definition is here
  } __sanitizer_sandbox_arguments;
    ^
kcc added a comment.Nov 20 2014, 10:04 AM

leave sanitizer_test_utils.h unchanged, remove break_optimization from sanitizer_libc.cc,
introduce SanitizerBreakOptimization or some such to sanitizer_common.h

foad updated this revision to Diff 16449.Nov 20 2014, 1:41 PM
foad edited edge metadata.

Follow Kostya's advice.

kcc added a comment.Nov 21 2014, 11:32 AM

LGTM, thanks!

foad closed this revision.Nov 21 2014, 1:25 PM