On Tue, Nov 20, 2012 at 12:04 AM, Peter Bergner <berg...@vnet.ibm.com> wrote: > On Fri, 2012-11-16 at 15:47 -0800, Konstantin Serebryany wrote: >> On Fri, Nov 16, 2012 at 3:08 PM, Peter Bergner <berg...@vnet.ibm.com> wrote: >> > The lone ASAN >> > test case does fail, but it seems to be related to us using >> > _Unwind_Backtrace() and we end up with two extra frames at the >> > bottom of our stack frame, so we don't match the expected >> > results. >> >> Maybe just drop those two frames before reporting them? >> (if we always have them) > > I was worried about whether we always have to extra frames from the > ASAN runtime or not, but looking at the code, it seems we do, so I > added a StackTrace::PopStackFrames(uptr count) method that can be > called after the call to _Unwind_Backtrace() pop off the offending > frames. With this change, we now pass the ASAN testsuite...all 1 > of them. :)
Test suite is a separate issue. Our largest piece of testing in LLVM uses gtest (very convenient!), which gcc doesn't have. > > > >> > One question that I have is that the toplev.c test for port support >> > tests for !FRAME_GROWS_DOWNWARD. The rs6000 port has FRAME_GROWS_DOWNWARD >> > defined as (flag_stack_protect != 0), so ASAN only works when we use >> > -fstack-protector. Is there a technical reason why FRAME_GROWS_DOWNWARD >> > must be false? > > Jakub answered this and I took his suggestion and redefined our target's > FRAME_GROWS_DOWNWARD to include !flag_asan so we no longer need to use > -fstack-protector. > > > > >> > I also don't like all the #ifdef's sprinkling the code. Can't we >> > use some configure fragments to help remove many/most of these? >> >> We'll probably have to add some config-like headers as we get more platforms. >> Not necessarily now. > > With the SANITIZER_LINUX_USES_64BIT_SYSCALLS patch, I see you started > to address this. Nice. I look forward to more of that. > > > >> > +#if defined(__powerpc__) || defined(__powerpc64__) >> > +// Current PPC64 kernels use 64K pages sizes, but they can be >> > +// configured with 4K or even other sizes, so we should probably >> > +// use getpagesize() or sysconf(_SC_PAGESIZE) here rather than >> > +// hardcoding the values. >> > +const uptr kPageSizeBits = 16; >> >> Interesting. This may have some unexpected side effects. (or maybe not?) >> It's of course ok to try like this and change it later if something got >> broken. > > Well, we _have_ to make this change, since without it, we attempt to do > an mmap of 4K and that will fail on any system with a page size larger > than 4k, since page size is the minimum mmap quantity. Or, sure we have to. I just say that this still may cause some troubles. > > > I have attached our current patch which does not include your change that > added SANITIZER_LINUX_USES_64BIT_SYSCALLS, since that isn't upstream yet. I've applied your patch (with minor style and comment changes) upstream: http://llvm.org/viewvc/llvm-project?view=rev&revision=168356 I did not have any way to test it though. Also, gmail does something horrible with patches inlined in a message, so I might have missed something. Soon I hope to learn how to pull the upstream changes to gcc tree and do it myself. (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55376) In the meantime, you are welcome to apply the same patch to gcc manually. Same for the gcc-specific parts of you patch. Thanks! --kcc > > Peter > > > Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.h > =================================================================== > --- libsanitizer/sanitizer_common/sanitizer_stacktrace.h (revision > 193626) > +++ libsanitizer/sanitizer_common/sanitizer_stacktrace.h (working copy) > @@ -43,6 +43,8 @@ > > void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom); > > + void PopStackFrames(uptr count); > + > static uptr GetCurrentPc(); > > static uptr CompressStack(StackTrace *stack, > Index: libsanitizer/sanitizer_common/sanitizer_common.h > =================================================================== > --- libsanitizer/sanitizer_common/sanitizer_common.h (revision 193626) > +++ libsanitizer/sanitizer_common/sanitizer_common.h (working copy) > @@ -21,12 +21,24 @@ > // Constants. > const uptr kWordSize = __WORDSIZE / 8; > const uptr kWordSizeInBits = 8 * kWordSize; > +#if defined(__powerpc__) || defined(__powerpc64__) > +// Current PPC64 kernels use 64K pages sizes, but they can be > +// configured with 4K or even other sizes, so we should probably > +// use getpagesize() or sysconf(_SC_PAGESIZE) here rather than > +// hardcoding the values. > +const uptr kPageSizeBits = 16; > +const uptr kPageSize = 1UL << kPageSizeBits; > +const uptr kCacheLineSize = 128; > +const uptr kMmapGranularity = kPageSize; > +#elif !defined( _WIN32) > const uptr kPageSizeBits = 12; > const uptr kPageSize = 1UL << kPageSizeBits; > const uptr kCacheLineSize = 64; > -#ifndef _WIN32 > const uptr kMmapGranularity = kPageSize; > #else > +const uptr kPageSizeBits = 12; > +const uptr kPageSize = 1UL << kPageSizeBits; > +const uptr kCacheLineSize = 64; > const uptr kMmapGranularity = 1UL << 16; > #endif > > Index: libsanitizer/sanitizer_common/sanitizer_linux.cc > =================================================================== > --- libsanitizer/sanitizer_common/sanitizer_linux.cc (revision 193626) > +++ libsanitizer/sanitizer_common/sanitizer_linux.cc (working copy) > @@ -34,7 +34,7 @@ > // --------------- sanitizer_libc.h > void *internal_mmap(void *addr, uptr length, int prot, int flags, > int fd, u64 offset) { > -#if defined __x86_64__ > +#if defined(__x86_64__) || defined(__powerpc64__) > return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); > #else > return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); > @@ -67,7 +67,7 @@ > } > > uptr internal_filesize(fd_t fd) { > -#if defined __x86_64__ > +#if defined(__x86_64__) || defined(__powerpc64__) > struct stat st; > if (syscall(__NR_fstat, fd, &st)) > return -1; > Index: libsanitizer/sanitizer_common/sanitizer_stacktrace.cc > =================================================================== > --- libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (revision > 193626) > +++ libsanitizer/sanitizer_common/sanitizer_stacktrace.cc (working copy) > @@ -31,7 +31,12 @@ > // Cancel Thumb bit. > pc = pc & (~1); > #endif > +#if defined(__powerpc__) || defined(__powerpc64__) > + // PCs are always 4 byte aligned. > + return pc - 4; > +#else > return pc - 1; > +#endif > } > > static void PrintStackFramePrefix(uptr frame_num, uptr pc) { > @@ -135,6 +140,16 @@ > } > } > > +void StackTrace::PopStackFrames(uptr count) { > + CHECK(size > count); > + size -= count; > + uptr i; > + > + for (i = 0; i < size; i++) { > + trace[i] = trace[i+count]; > + } > +} > + > // On 32-bits we don't compress stack traces. > // On 64-bits we compress stack traces: if a given pc differes slightly from > // the previous one, we record a 31-bit offset instead of the full pc. > Index: libsanitizer/asan/asan_mapping.h > =================================================================== > --- libsanitizer/asan/asan_mapping.h (revision 193626) > +++ libsanitizer/asan/asan_mapping.h (working copy) > @@ -31,7 +31,11 @@ > # if __WORDSIZE == 32 > # define SHADOW_OFFSET (1 << 29) > # else > -# define SHADOW_OFFSET (1ULL << 44) > +# if defined(__powerpc64__) > +# define SHADOW_OFFSET (1ULL << 41) > +# else > +# define SHADOW_OFFSET (1ULL << 44) > +# endif > # endif > # endif > #endif // ASAN_FLEXIBLE_MAPPING_AND_OFFSET > @@ -41,7 +45,11 @@ > #define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) > > #if __WORDSIZE == 64 > +# if defined(__powerpc64__) > + static const uptr kHighMemEnd = 0x00000fffffffffffUL; > +# else > static const uptr kHighMemEnd = 0x00007fffffffffffUL; > +# endif > #else // __WORDSIZE == 32 > static const uptr kHighMemEnd = 0xffffffff; > #endif // __WORDSIZE > Index: libsanitizer/asan/asan_linux.cc > =================================================================== > --- libsanitizer/asan/asan_linux.cc (revision 193626) > +++ libsanitizer/asan/asan_linux.cc (working copy) > @@ -66,6 +66,13 @@ > *pc = ucontext->uc_mcontext.gregs[REG_EIP]; > *bp = ucontext->uc_mcontext.gregs[REG_EBP]; > *sp = ucontext->uc_mcontext.gregs[REG_ESP]; > +# elif defined(__powerpc__) || defined(__powerpc64__) > + ucontext_t *ucontext = (ucontext_t*)context; > + *pc = ucontext->uc_mcontext.regs->nip; > + *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; > + // The powerpc{,64}-linux ABIs do not specify r31 as the frame > + // pointer, but GCC always uses r31 when we need a frame pointer. > + *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; > # elif defined(__sparc__) > ucontext_t *ucontext = (ucontext_t*)context; > uptr *stk_ptr; > @@ -149,8 +156,10 @@ > stack->trace[0] = pc; > if ((max_s) > 1) { > stack->max_size = max_s; > -#ifdef __arm__ > +#if defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__) > _Unwind_Backtrace(Unwind_Trace, stack); > + // Pop off the two ASAN functions from the backtrace. > + stack->PopStackFrames(2); > #else > if (!asan_inited) return; > if (AsanThread *t = asanThreadRegistry().GetCurrent()) > Index: libsanitizer/configure.tgt > =================================================================== > --- libsanitizer/configure.tgt (revision 193626) > +++ libsanitizer/configure.tgt (working copy) > @@ -20,6 +20,8 @@ > > # Filter out unsupported systems. > case "${target}" in > + powerpc*-*-linux*) > + ;; > x86_64-*-linux* | i?86-*-linux* | sparc*-*-linux*) > ;; > *) > Index: gcc/config/rs6000/rs6000.c > =================================================================== > --- gcc/config/rs6000/rs6000.c (revision 193626) > +++ gcc/config/rs6000/rs6000.c (working copy) > @@ -1186,6 +1186,9 @@ > #undef TARGET_DELEGITIMIZE_ADDRESS > #define TARGET_DELEGITIMIZE_ADDRESS rs6000_delegitimize_address > > +#undef TARGET_ASAN_SHADOW_OFFSET > +#define TARGET_ASAN_SHADOW_OFFSET rs6000_asan_shadow_offset > + > #undef TARGET_CONST_NOT_OK_FOR_DEBUG_P > #define TARGET_CONST_NOT_OK_FOR_DEBUG_P rs6000_const_not_ok_for_debug_p > > @@ -27370,6 +27373,13 @@ > } > } > > +/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ > + > +static unsigned HOST_WIDE_INT > +rs6000_asan_shadow_offset (void) > +{ > + return (unsigned HOST_WIDE_INT) 1 << (TARGET_64BIT ? 41 : 29); > +} > > /* Mask options that we want to support inside of attribute((target)) and > #pragma GCC target operations. Note, we do not include things like > Index: gcc/config/rs6000/rs6000.h > =================================================================== > --- gcc/config/rs6000/rs6000.h (revision 193626) > +++ gcc/config/rs6000/rs6000.h (working copy) > @@ -1406,7 +1406,7 @@ > > On the RS/6000, we grow upwards, from the area after the outgoing > arguments. */ > -#define FRAME_GROWS_DOWNWARD (flag_stack_protect != 0) > +#define FRAME_GROWS_DOWNWARD (flag_stack_protect != 0 || flag_asan != 0) > > /* Size of the outgoing register save area */ > #define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX \ > > >