This is an archive of the discontinued LLVM Phabricator instance.

Test failures in GCC ASan testsuite on ARM Linux due to FP format mismatch between libsanitizer and GCC.
ClosedPublic

Authored by m.ostapenko on Jul 27 2014, 11:44 PM.

Details

Summary

Fast unwind works wrong in GCC 4.10 on ARM Linux due to FP format mismatch between libsanitizer and GCC. This is related bug in GCC (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61771).

Diff Detail

Event Timeline

m.ostapenko retitled this revision from to Test failures in GCC ASan testsuite on ARM Linux due to FP format mismatch between libsanitizer and GCC..
m.ostapenko updated this object.
m.ostapenko edited the test plan for this revision. (Show Details)
m.ostapenko added reviewers: kcc, samsonov.
m.ostapenko set the repository for this revision to rL LLVM.
m.ostapenko added a project: deleted.
m.ostapenko added subscribers: ygribov, Unknown Object (MLST).

Can we add tests?
Evgeniy suggests that a test may be implemented with a set of assembly files that have different ABIs (GCC's and Clang's)

I agree with tests, no regressions on current tests don't mean much.

cheers,
--renato

lib/sanitizer_common/sanitizer_stacktrace.cc
53

It's not clear how this will separate a GCC logic from LLVM one (or rather, different FP logics), on ARM.

It'll also make the second IsValidFrame() call redundant on anything _but_ ARM. Maybe you should move all of it inside the #ifdef block?

#ifdef __arm__
  if (IsValidFrame((uptr)bp_prev[0], stack_top, stack_bottom))
    return bp_prev;
  --bp_prev;
#endif
  return bp_prev;
m.ostapenko edited edge metadata.

Thanks, Renato, you are right, I've also added a small test. Should I add more tests?

ygribov added inline comments.Jul 29 2014, 1:30 AM
test/asan/TestCases/Linux/clang_gcc_abi.cc
5

Do we really need to check all optimization levels?

11

Perhaps make this local?

14

Contents of s is undefined so compiler could optimize this access out.

18

I think this should better be asm volatile.

30

Likewise.

samsonov added inline comments.Jul 29 2014, 4:41 PM
lib/sanitizer_common/sanitizer_stacktrace.cc
40

this function returns bool

65–66

This line is wrong. It assumes that FastUnwindStack() is called in the same thread for which we provide stack_top/stack_bottom. I believe this function describes a generic unwinding algorithm, and there's no place for hack like this here.

Why do you need it?

m.ostapenko added inline comments.Jul 30 2014, 12:20 AM
lib/sanitizer_common/sanitizer_stacktrace.cc
65–66

Hm, stack_bottom is simply stack_top - kStackSize (8 MB), isn't it? So, we have 8 MB interval for "valid" stack addresses. But in Linux stack grows dynamically, so if access address is, for example, in the middle of this interval, this can cause a segmentation fault, because libc hasn't mapped this memory yet. So we need something like this to prevent this error. You are right, this will work only in case if FastUnwindStack() is called in the same thread for which we provide stack_top/stack_bottom, but if it is called in another thread, how can we implement such kind of protection?

ygribov added inline comments.Jul 30 2014, 12:28 AM
lib/sanitizer_common/sanitizer_stacktrace.cc
65–66

Can we do stack_bottom = Max(stack_bottom, bp) instead?

Updated patch according to Renato's and Yury's comments. Regarding the issue about stack_bottom, I still believe that we need something like the protection was suggested.

ygribov added inline comments.Aug 6 2014, 3:30 AM
lib/sanitizer_common/sanitizer_stacktrace.cc
65–66

I'd still ask for bp instead of &size here.

test/asan/TestCases/Linux/clang_gcc_abi.cc
31

Broken formatting.

ygribov added inline comments.Aug 6 2014, 7:34 AM
lib/sanitizer_common/sanitizer_stacktrace.cc
41

Should this be 2 * sizeof(uhwptr)?

samsonov added inline comments.Aug 6 2014, 3:43 PM
lib/sanitizer_common/sanitizer_stacktrace.cc
65–66

Stack size is not always 8Mb, it's configurable in many ways. And, yes, it grows dynamically. But we don't assume that the whole interval from stack_top to stack_bottom is accessible. We would access unmapped memory only if there's a bug in unwinding algorithm or the frame pointers are broken. Do you actually observe such cases?

ygribov added inline comments.Aug 6 2014, 9:55 PM
lib/sanitizer_common/sanitizer_stacktrace.cc
65–66

We could also access unmapped area if code was compiled without fp support. And yes, we saw this in our ARM tests.

Alexey, you are right, this is a really specific situation. Removed the line. Is it OK now?

samsonov added inline comments.Aug 20 2014, 9:57 AM
lib/sanitizer_common/sanitizer_stacktrace.cc
47

Make this inline.

48

This check is not needed if we're not on ARM. Can you keep the original behavior on non-ARM platforms?

#ifdef __arm__
  if (!IsValidFrame(bp, stack_top, stack_bottom) return 0;
  uhwptr *bp_prev = (uhwptr *)bp;
  if (IsValidFrame((uptr)bp_prev[0], stack_top, stack_bottom) return bp_prev;
  return bp_prev - 1;
#else
  return (uhwptr*)bp;
#endif
66–68

Move this line upper (before calling GetCanonicFrame for the first time).

test/asan/TestCases/Linux/clang_gcc_abi.cc
41

Put CHECK-lines closer to the actual source code lines

Update according to last review notes.

samsonov edited edge metadata.Aug 26 2014, 5:36 PM

Looks reasonable. Please fix the test case and let me know if I should land this for you.

test/asan/TestCases/Linux/clang_gcc_abi.cc
15

[[@LINE]] directives don't look right now.

m.ostapenko edited edge metadata.

Thanks, fixed. Could you apply it when you have a time?

samsonov added inline comments.Aug 29 2014, 5:22 PM
test/asan/TestCases/Linux/clang_gcc_abi.cc
15

Just sanity checking: doesn't ASan output line 13 in the error report? (the one with the BOOM)

28

This can be [[@LINE+1]] if you put it immediately after the asm blob (which would probably be more appropriate/clear).

m.ostapenko added inline comments.Sep 1 2014, 12:11 AM
test/asan/TestCases/Linux/clang_gcc_abi.cc
15

Yes, it does.

=================================================================
==12410==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x422007f3 at pc 0x000c1444 bp 0x40800118 sp 0x40800110
READ of size 1 at 0x422007f3 thread T0
    #0 0xc1443 in boom /home/max/workspace/downloads/llvm/projects/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc:13:3
    #1 0xc1453 in gcc_abi /home/max/workspace/downloads/llvm/projects/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc:19:3
    #2 0xc1453 in gcc_abi /home/max/workspace/downloads/llvm/projects/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc:19:3
    #3 0xc1453 in gcc_abi /home/max/workspace/downloads/llvm/projects/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc:19:3
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/max/workspace/downloads/llvm/projects/compiler-rt/test/asan/TestCases/Linux/clang_gcc_abi.cc:13 boom

However, ASan unable to unwind the stack deeper then gcc_abi function. Should I do something about it?

ygribov added inline comments.Sep 1 2014, 12:37 AM
test/asan/TestCases/Linux/clang_gcc_abi.cc
15

That's expected - your inline asm lacks frame info so assembler can't generate proper unwind instructions which puzzles slow unwinder.

m.ostapenko updated this revision to Diff 13155.Sep 2 2014, 2:07 AM

Moved check lines.

samsonov accepted this revision.Sep 3 2014, 2:20 PM
samsonov edited edge metadata.

Landed in r217079. Thanks for working on this!

This revision is now accepted and ready to land.Sep 3 2014, 2:20 PM
m.ostapenko closed this revision.Oct 22 2015, 5:28 AM