This is an archive of the discontinued LLVM Phabricator instance.

[PATCH] [sanitizers] [msan] Enable MSAN for aarch64
ClosedPublic

Authored by zatrazz on Sep 8 2015, 2:18 PM.

Details

Summary

This patch enabled msan for aarch64 with 39-bit VMA and 42-bit VMA.
As defined by lib/msan/msan.h the memory layout used is for 39-bit is:

00 0000 0000 - 40 0000 0000:  invalid
40 0000 0000 - 43 0000 0000:  shadow
43 0000 0000 - 46 0000 0000:  origin
46 0000 0000 - 55 0000 0000:  invalid
55 0000 0000 - 56 0000 0000:  app (low)
56 0000 0000 - 70 0000 0000:  invalid
70 0000 0000 - 80 0000 0000:  app (high)

And for 42-bit VMA:

000 0000 0000 - 100 0000 0000:  invalid
100 0000 0000 - 11b 0000 0000:  shadow
11b 0000 0000 - 120 0000 0000:  invalid
120 0000 0000 - 13b 0000 0000:  origin
13b 0000 0000 - 2aa 0000 0000:  invalid
2aa 0000 0000 - 2ab 0000 0000:  app (low)
2ab 0000 0000 - 3f0 0000 0000:  invalid
3f0 0000 0000 - 400 0000 0000:  app (high)

Most of tests are passing with exception of:

  • Linux/mallinfo.cc
  • chained_origin_limits.cc
  • dlerror.cc
  • param_tls_limit.cc
  • signal_stress_test.cc
  • nonnull-arg.cpp

The 'Linux/mallinfo.cc' is due the fact AArch64 returns the sret in 'x8'
instead of default first argument 'x1'. So a function prototype that
aims to mimic (by using first argument as the return of function) won't
work. For GCC one can make a register alias (register var asm ("r8")), but
for clang it detects it an unused variable and generate wrong code.

The 'chained_origin_limits' is probably due a wrong code generation,
since it fails only when origin memory is used
(-fsanitize-memory-track-origins=2) and only in the returned code
(return buf[50]).

The 'signal_streess_test' and 'nonnull-arg' are due currently missing variadic
argument handling in memory sanitizer code instrumentation on LLVM side.

Both 'dlerror' and 'param_tls_test' are unknown failures that require
further investigation.

All the failures are XFAIL for aarch64 for now.

Diff Detail

Event Timeline

zatrazz updated this revision to Diff 34263.Sep 8 2015, 2:18 PM
zatrazz retitled this revision from to [PATCH] [sanitizers] [msan] Enable MSAN for aarch64.
zatrazz updated this object.
zatrazz added reviewers: kcc, rengolin, dvyukov, eugenis, pcc.
zatrazz added a subscriber: llvm-commits.
rengolin edited edge metadata.Sep 9 2015, 3:54 AM

Hi Adhemerval,

About named register variables, if you use the variable in a piece of inline asm, it works in LLVM, too. If you just declare it, Clang ignores and LLVM optimises it away.

cheers,
--renato

Adding Tim as a reviewer for the Darwin part of the XFAILs.

lib/msan/msan_interceptors.cc
254

implement this in asm and it will work on both gcc and clang.

test/msan/chained_origin_limits.cc
65

I think this is "arm64" for Darwin. It'd be good if someone could test this in Darwin and make sure we need the same XFAILs, and if so, we should add their arch-name, too.

test/msan/strlen_of_shadow.cc
26

Can't you re-use the one you have above? Maybe this should even be in compiler-rt?

test/sanitizer_common/TestCases/Linux/ptrace.cc
82

#endif // (aarch64)

Hi Adhemerval,

About named register variables, if you use the variable in a piece of inline asm, it works in LLVM, too. If you just declare it, Clang ignores and LLVM optimises it away.

cheers,
--renato

In this case the variable will not be used for attribution , but instead to catch the value of 'x8'. My understanding is clang should not mark the variable as unused if it is used as a named register variable, otherwise it will not be able to catch registers values as is in function calling.

Another option that came to my mind is to use an volatile inline assembly to explicit get the register value:

INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) {
#ifdef __aarch64__
  uptr r8;
  asm volatile("mov %0,x8" : "=r" (r8));
  sret = reinterpret_cast<__sanitizer_mallinfo*>(r8);
#endif
  REAL(memset)(sret, 0, sizeof(*sret));
  __msan_unpoison(sret, sizeof(*sret));
}

This works and make the test pass. I will use it instead.

zatrazz added inline comments.Sep 9 2015, 5:49 AM
test/msan/strlen_of_shadow.cc
26

This is for tests only, so I see the best option to add on 'test/msan/test.h'. I will change it.

In this case the variable will not be used for attribution , but instead to catch the value of 'x8'. My understanding is clang should not mark the variable as unused if it is used as a named register variable, otherwise it will not be able to catch registers values as is in function calling.

This is a lost battle, let's not go there.

Another option that came to my mind is to use an volatile inline assembly to explicit get the register value:

Yup, that's what I was referring to.

uptr r8;
asm volatile("mov %0,x8" : "=r" (r8));
sret = reinterpret_cast<__sanitizer_mallinfo*>(r8);

You can use named registers here:

register uptr x8 asm("x8");
asm volatile("mov %0, %1\n" : "=r" (sret), "r" (x8));
zatrazz updated this revision to Diff 34334.Sep 9 2015, 7:27 AM
zatrazz edited edge metadata.

Updated patch with rengolin comments.

One comment inline, another here:

Could you add a comment to the XFAILs stating very briefly what's wrong with it? I'd like to know what's an error you think you can fix it versus one that cannot be implemented due to hardware / architecture restrictions. Even if they all fall into temporary errors, would be good to know what exactly is breaking, to make it easier for people to pick them up and fix them, or even if some unrelated patch does fix them, they can know it's not unrelated after all.

I guess about Darwin names, we shall see if it breaks the Darwin bots.

cheers,
--renato

test/msan/strlen_of_shadow.cc
31

Can't you just use the macro for now?

One comment inline, another here:

Which macro do you mean ?

Could you add a comment to the XFAILs stating very briefly what's wrong with it? I'd like to know what's an error you think you can fix it versus one that cannot be implemented due to hardware / architecture restrictions. Even if they all fall into temporary errors, would be good to know what exactly is breaking, to make it easier for people to pick them up and fix them, or even if some unrelated patch does fix them, they can know it's not unrelated after all.

Right, I will add comment about the failures reason (the ones I debugged at least).

I guess about Darwin names, we shall see if it breaks the Darwin bots.

cheers,
--renato

rengolin added inline comments.Sep 15 2015, 12:25 PM
test/msan/strlen_of_shadow.cc
31

Something like:

#elif defined(__aarch64__)
  #if SANITIZER_AARCH64_VMA == 39
  #define LINEARIZE_MEM(mem) (((uintptr_t)(mem) & ~0x7C00000000ULL) ^ 0x100000000ULL)
  #else
  #define LINEARIZE_MEM(mem) (((uintptr_t)(mem) & ~0x3E000000000ULL) ^ 0x1000000000ULL)
  #endif
return (char *)(LINEARIZE_MEM(p) + 0x4000000000ULL);
...
zatrazz added inline comments.Sep 15 2015, 12:50 PM
test/msan/strlen_of_shadow.cc
31

SANITIZER_AARCH64_VMA is used within compiler-rt itself, not exported for tests.

rengolin accepted this revision.Sep 15 2015, 1:16 PM
rengolin edited edge metadata.

Right, ok. LGTM with the extra comments on the FIXME lines.

This revision is now accepted and ready to land.Sep 15 2015, 1:16 PM
eugenis added inline comments.Sep 15 2015, 3:12 PM
lib/sanitizer_common/sanitizer_platform_limits_posix.cc
332

did you mean PT_GETFPREGS here and PT_GETFPXREGS below?

lib/sanitizer_common/sanitizer_stacktrace.h
22

Oh, are you saying the current fast unwind implementation simply works on aarch64? Nice.

zatrazz added inline comments.Sep 16 2015, 6:16 AM
lib/sanitizer_common/sanitizer_platform_limits_posix.cc
332

Yes and '#if defined(PT_GETFPXREGS) && defined(PT_SETFPXREGS)' below as well. I will fix it.

lib/sanitizer_common/sanitizer_stacktrace.h
22

I saw no regressions or failures tests that indicate otherwise. In fact it fixes 'MemorySanitizer :: fork.cc' which stucks in _Unwind_Backtrace from libgcc with SlowUnwinder.

zatrazz closed this revision.Sep 16 2015, 8:13 AM