Index: cmake/config-ix.cmake =================================================================== --- cmake/config-ix.cmake +++ cmake/config-ix.cmake @@ -175,7 +175,7 @@ filter_available_targets(ASAN_SUPPORTED_ARCH x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el) filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el) -filter_available_targets(LSAN_SUPPORTED_ARCH x86_64) +filter_available_targets(LSAN_SUPPORTED_ARCH x86_64 mips64 mips64el) # LSan common files should be available on all architectures supported # by other sanitizers (even if they build into dummy object files). filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH Index: lib/lsan/lsan_allocator.cc =================================================================== --- lib/lsan/lsan_allocator.cc +++ lib/lsan/lsan_allocator.cc @@ -25,10 +25,6 @@ namespace __lsan { -static const uptr kMaxAllowedMallocSize = 8UL << 30; -static const uptr kAllocatorSpace = 0x600000000000ULL; -static const uptr kAllocatorSize = 0x40000000000ULL; // 4T. - struct ChunkMetadata { bool allocated : 8; // Must be first. ChunkTag tag : 2; @@ -36,8 +32,22 @@ u32 stack_trace_id; }; +#if defined(__mips64) +static const uptr kMaxAllowedMallocSize = 4UL << 30; +static const uptr kRegionSizeLog = 20; +static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; +typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; +typedef CompactSizeClassMap SizeClassMap; +typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, + sizeof(ChunkMetadata), SizeClassMap, kRegionSizeLog, ByteMap> + PrimaryAllocator; +#else +static const uptr kMaxAllowedMallocSize = 8UL << 30; +static const uptr kAllocatorSpace = 0x600000000000ULL; +static const uptr kAllocatorSize = 0x40000000000ULL; // 4T. typedef SizeClassAllocator64 PrimaryAllocator; +#endif typedef SizeClassAllocatorLocalCache AllocatorCache; typedef LargeMmapAllocator<> SecondaryAllocator; typedef CombinedAllocator> 47) == 0); +#elif defined(__mips64) + return ((p >> 40) == 0); #else return true; #endif Index: lib/sanitizer_common/sanitizer_linux.h =================================================================== --- lib/sanitizer_common/sanitizer_linux.h +++ lib/sanitizer_common/sanitizer_linux.h @@ -43,7 +43,7 @@ // internal_sigaction instead. int internal_sigaction_norestorer(int signum, const void *act, void *oldact); void internal_sigdelset(__sanitizer_sigset_t *set, int signum); -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(__mips__) uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr); #endif Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -900,6 +900,13 @@ : "rsp", "memory", "r11", "rcx"); return res; } +#elif defined(__mips__) +// TODO(sagarthakur): clone function is to be rewritten in assembly +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + return clone(fn, child_stack, flags, arg, parent_tidptr, + newtls, child_tidptr); +} #endif // defined(__x86_64__) && SANITIZER_LINUX #if SANITIZER_ANDROID Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -162,6 +162,20 @@ # define DL_INTERNAL_FUNCTION #endif +#if defined(__mips__) +// TlsPreTcbSize includes size of struct pthread_descr and size of tcb +// head structure. It lies before the static tls blocks. +uptr TlsPreTcbSize() { + const uptr kTcbHead = 16; + const uptr kTlsAlign = 16; + const uptr kTlsPreTcbSize = + (ThreadDescriptorSize() + kTcbHead + kTlsAlign - 1) & ~(kTlsAlign - 1); + InitTlsSize(); + g_tls_size = (g_tls_size + kTlsPreTcbSize + kTlsAlign -1) & ~(kTlsAlign - 1); + return kTlsPreTcbSize; +} +#endif + void InitTlsSize() { #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; @@ -178,7 +192,8 @@ #endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID } -#if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX +#if (defined(__x86_64__) || defined(__i386__) || defined(__mips__)) \ + && SANITIZER_LINUX // sizeof(struct thread) from glibc. static atomic_uintptr_t kThreadDescriptorSize; @@ -194,6 +209,7 @@ 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(__i386__) if (SANITIZER_X32) val = 1728; // Assume only one particular version for x32. else if (minor <= 3) @@ -210,6 +226,10 @@ val = FIRST_32_SECOND_64(1168, 2288); else val = FIRST_32_SECOND_64(1216, 2304); +#elif defined(__mips__) + // TODO(sagarthakur): add more values as per different glibc versions + val = FIRST_32_SECOND_64(1152, 1776); +#endif } if (val) atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed); @@ -232,13 +252,25 @@ asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); # elif defined(__x86_64__) asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset)); +# elif defined(__mips__) + // MIPS uses TLS variant I. The thread pointer (in hardware register $29) + // points to the end of the TCB + 0x7000. The pthread_descr structure is + // immediately in front of the TCB. TlsPreTcbSize() includes the size of the + // TCB and the size of pthread_descr + const uptr kTlsTcbOffset = 0x7000; + uptr thread_pointer; + asm volatile(".set push;\ + .set mips64r2;\ + rdhwr %0,$29;\ + .set pop" : "=r" (thread_pointer)); + descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); # else # error "unsupported CPU arch" # endif return descr_addr; } -#endif // (defined(__x86_64__) || defined(__i386__)) && SANITIZER_LINUX - +#endif // (defined(__x86_64__) || defined(__i386__) || defined(__mips__)) \ + // && SANITIZER_LINUX #if SANITIZER_FREEBSD static void **ThreadSelfSegbase() { void **segbase = 0; @@ -266,6 +298,9 @@ *size = GetTlsSize(); *addr -= *size; *addr += ThreadDescriptorSize(); +# elif defined(__mips__) + *addr = ThreadSelf(); + *size = GetTlsSize(); # else *addr = 0; *size = 0; Index: lib/sanitizer_common/sanitizer_platform_limits_posix.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -538,6 +538,10 @@ #if SANITIZER_FREEBSD typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t; +#elif defined(__mips__) + struct __sanitizer_kernel_sigset_t { + u8 sig[16]; + }; #else struct __sanitizer_kernel_sigset_t { u8 sig[8]; Index: lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -14,7 +14,7 @@ #include "sanitizer_platform.h" -#if SANITIZER_LINUX && defined(__x86_64__) +#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__)) #include "sanitizer_stoptheworld.h" @@ -459,4 +459,4 @@ } } // namespace __sanitizer -#endif // SANITIZER_LINUX && defined(__x86_64__) +#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__)) Index: lib/sanitizer_common/tests/sanitizer_linux_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_linux_test.cc +++ lib/sanitizer_common/tests/sanitizer_linux_test.cc @@ -255,6 +255,12 @@ } } +#if defined(__mips64) +TEST(SanitizerLinux, ThreadSelfTest) { + ASSERT_EQ(pthread_self(), ThreadSelf()); +} +#endif + } // namespace __sanitizer #endif // SANITIZER_LINUX