On Tue, May 13, 2014 at 2:02 AM, Konstantin Serebryany <konstantin.s.serebry...@gmail.com> wrote: > New patch attached. > It is based on r208674 which enables LeakSanitizer > (https://code.google.com/p/address-sanitizer/wiki/LeakSanitizer) by > default in asan mode.
There are a couple issues for x32: 1. This change @@ -56,13 +55,6 @@ typedef signed long long sptr; // NOLINT typedef unsigned long uptr; // NOLINT typedef signed long sptr; // NOLINT #endif // defined(_WIN64) -#if defined(__x86_64__) -// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use -// 64-bit pointer to unwind stack frame. -typedef unsigned long long uhwptr; // NOLINT -#else -typedef uptr uhwptr; // NOLINT -#endif typedef unsigned char u8; typedef unsigned short u16; // NOLINT typedef unsigned int u32; @@ -120,46 +34,43 @@ uptr StackTrace::GetCurrentPc() { void StackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, uptr max_depth) { - if (max_depth == 0) { - size = 0; - return; - } + CHECK_GE(max_depth, 2); trace[0] = pc; size = 1; - uhwptr *frame = (uhwptr *)bp; - uhwptr *prev_frame = frame - 1; + uptr *frame = (uptr *)bp; + uptr *prev_frame = frame - 1; if (stack_top < 4096) return; // Sanity check for stack top. // Avoid infinite loop when frame == frame[0] by using frame > prev_frame. while (frame > prev_frame && - frame < (uhwptr *)stack_top - 2 && - frame > (uhwptr *)stack_bottom && + frame < (uptr *)stack_top - 2 && + frame > (uptr *)stack_bottom && IsAligned((uptr)frame, sizeof(*frame)) && size < max_depth) { - uhwptr pc1 = frame[1]; + uptr pc1 = frame[1]; if (pc1 != pc) { - trace[size++] = (uptr) pc1; + trace[size++] = pc1; } prev_frame = frame; - frame = (uhwptr *)frame[0]; + frame = (uptr*)frame[0]; } } reverted: 2012-11-16 H.J. Lu <hongjiu...@intel.com> PR other/55333 * include/sanitizer/common_interface_defs.h (uhwptr): New type for hardware pointer. * sanitizer_common/sanitizer_stacktrace.cc (StackTrace::FastUnwindStack): Replace uptr with uhwptr for stack unwind. 2. struct linux_dirent is incorrect for x32. We need something like struct linux_dirent { #if defined(__x86_64__) && !defined(_LP64) unsigned long long d_ino; unsigned long long d_off; #else unsigned long d_ino; unsigned long d_off; #endif unsigned short d_reclen; char d_name[256]; }; 3. Pointers passed to internal_syscall should be casted to (uptr). Otherwise, they won't be properly extended to 64-bit. We need to use (uptr) in internal_sigprocmask, like uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) { #if SANITIZER_FREEBSD return internal_syscall(SYSCALL(sigprocmask), how, set, oldset); #else __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)&k_set->sig[0], (uptr)&k_oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t)); #endif } 4. ThreadDescriptorSize returns wrong value for x32. Size of struct pthread should be 1728. I am enclosing patches for those issues. -- H.J.
--- ./sanitizer_common/sanitizer_internal_defs.h.x32 2014-05-13 08:03:33.531933986 -0700 +++ ./sanitizer_common/sanitizer_internal_defs.h 2014-05-13 13:02:17.552659366 -0700 @@ -55,6 +55,13 @@ typedef signed long long sptr; // NOL typedef unsigned long uptr; // NOLINT typedef signed long sptr; // NOLINT #endif // defined(_WIN64) +#if defined(__x86_64__) +// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use +// 64-bit pointer to unwind stack frame. +typedef unsigned long long uhwptr; // NOLINT +#else +typedef uptr uhwptr; // NOLINT +#endif typedef unsigned char u8; typedef unsigned short u16; // NOLINT typedef unsigned int u32; --- ./sanitizer_common/sanitizer_stacktrace.cc.x32 2014-05-13 08:03:33.532933986 -0700 +++ ./sanitizer_common/sanitizer_stacktrace.cc 2014-05-13 13:04:59.109780837 -0700 @@ -37,21 +37,21 @@ void StackTrace::FastUnwindStack(uptr pc CHECK_GE(max_depth, 2); trace[0] = pc; size = 1; - uptr *frame = (uptr *)bp; - uptr *prev_frame = frame - 1; + uhwptr *frame = (uhwptr *)bp; + uhwptr *prev_frame = frame - 1; if (stack_top < 4096) return; // Sanity check for stack top. // Avoid infinite loop when frame == frame[0] by using frame > prev_frame. while (frame > prev_frame && - frame < (uptr *)stack_top - 2 && - frame > (uptr *)stack_bottom && + frame < (uhwptr *)stack_top - 2 && + frame > (uhwptr *)stack_bottom && IsAligned((uptr)frame, sizeof(*frame)) && size < max_depth) { - uptr pc1 = frame[1]; + uhwptr pc1 = frame[1]; if (pc1 != pc) { - trace[size++] = pc1; + trace[size++] = (uptr) pc1; } prev_frame = frame; - frame = (uptr*)frame[0]; + frame = (uhwptr *)frame[0]; } }
--- ./sanitizer_common/sanitizer_linux.cc.x32 2014-05-13 08:03:33.528933987 -0700 +++ ./sanitizer_common/sanitizer_linux.cc 2014-05-13 11:26:03.033181658 -0700 @@ -451,8 +451,13 @@ void BlockingMutex::CheckLocked() { // Note that getdents64 uses a different structure format. We only provide the // 32-bit syscall here. struct linux_dirent { +#if defined(__x86_64__) && !defined(_LP64) + unsigned long long d_ino; + unsigned long long d_off; +#else unsigned long d_ino; unsigned long d_off; +#endif unsigned short d_reclen; char d_name[256]; };
--- ./sanitizer_common/sanitizer_linux.cc.x32 2014-05-13 08:03:33.528933987 -0700 +++ ./sanitizer_common/sanitizer_linux.cc 2014-05-13 11:26:03.033181658 -0700 @@ -548,8 +553,8 @@ uptr internal_sigprocmask(int how, __san #else __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; - return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, &k_set->sig[0], - &k_oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t)); + return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, (uptr)&k_set->sig[0], + (uptr)&k_oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t)); #endif }
--- sanitizer_common/sanitizer_linux_libcdep.cc.x32 2014-05-13 08:03:33.524933988 -0700 +++ sanitizer_common/sanitizer_linux_libcdep.cc 2014-05-13 14:58:22.483884958 -0700 @@ -310,6 +310,9 @@ uptr ThreadDescriptorSize() { int minor = internal_simple_strtoll(buf + 8, &end, 10); if (end != buf + 8 && (*end == '\0' || *end == '.')) { /* sizeof(struct thread) values from various glibc versions. */ +#if defined(__x86_64__) && !defined(_LP64) + val = 1728; +#else if (minor <= 3) val = FIRST_32_SECOND_64(1104, 1696); else if (minor == 4) @@ -324,6 +327,7 @@ uptr ThreadDescriptorSize() { val = FIRST_32_SECOND_64(1168, 2288); else val = FIRST_32_SECOND_64(1216, 2304); +#endif } if (val) atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);