Index: lib/asan/asan_mapping.h =================================================================== --- lib/asan/asan_mapping.h +++ lib/asan/asan_mapping.h @@ -217,7 +217,7 @@ # define SHADOW_OFFSET kPPC64_ShadowOffset64 # elif defined(__s390x__) # define SHADOW_OFFSET kSystemZ_ShadowOffset64 -# elif SANITIZER_FREEBSD +# elif SANITIZER_FREEBSD && !defined(__mips64) # define SHADOW_OFFSET kFreeBSD_ShadowOffset64 # elif SANITIZER_NETBSD # define SHADOW_OFFSET kNetBSD_ShadowOffset64 Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -39,7 +39,7 @@ // format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To // access stat from asm/stat.h, without conflicting with definition in // sys/stat.h, we use this trick. -#if defined(__mips64) +#if defined(__mips64) && SANITIZER_LINUX #include #include #define stat kernel_stat @@ -263,7 +263,7 @@ } #endif -#if defined(__mips64) +#if defined(__mips64) && SANITIZER_LINUX // Undefine compatibility macros from // so that they would not clash with the kernel_stat // st_[a|m|c]time fields @@ -366,7 +366,7 @@ uptr internal_fstat(fd_t fd, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ SANITIZER_LINUX_USES_64BIT_SYSCALLS -#if SANITIZER_MIPS64 && !SANITIZER_NETBSD && !SANITIZER_OPENBSD +#if SANITIZER_MIPS64 && SANITIZER_LINUX_USES_64BIT_SYSCALLS // For mips64, fstat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(fstat), fd, &kbuf); @@ -1246,7 +1246,7 @@ : "rsp", "memory", "r11", "rcx"); return res; } -#elif defined(__mips__) +#elif defined(__mips__) && SANITIZER_LINUX uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr) { long long res; @@ -1760,7 +1760,11 @@ uint32_t faulty_instruction; uint32_t op_code; +# if SANITIZER_FREEBSD + exception_source = (uint32_t *)ucontext->uc_mcontext.mc_pc; +# else exception_source = (uint32_t *)ucontext->uc_mcontext.pc; +# endif faulty_instruction = (uint32_t)(*exception_source); op_code = (faulty_instruction >> 26) & 0x3f; @@ -1930,10 +1934,17 @@ *bp = stk_ptr[15]; # endif #elif defined(__mips__) +# if SANITIZER_FREEBSD + ucontext_t *ucontext = (ucontext_t*)context; + *pc = ucontext->uc_mcontext.mc_pc; + *bp = ucontext->uc_mcontext.mc_regs[30]; + *sp = ucontext->uc_mcontext.mc_regs[29]; +# else ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.pc; *bp = ucontext->uc_mcontext.gregs[30]; *sp = ucontext->uc_mcontext.gregs[29]; +# endif #elif defined(__s390__) ucontext_t *ucontext = (ucontext_t*)context; # if defined(__s390x__) Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -384,6 +384,18 @@ # elif defined(__x86_64__) // sysarch(AMD64_GET_FSBASE, segbase); __asm __volatile("movq %%fs:0, %0" : "=r" (segbase)); +# elif defined(__mips64__) + // MIPS uses TLS variant I. The thread pointer (in hardware register $29) + // points to the end of the TCB + 0x7000. The TCB contains two pointers, + // one to the dtv and the second to the struct pthread. + const uptr kTlsTcbOffset = 0x7000; + const uptr kTlsTcbSize = sizeof(void *) * 2; + uptr thread_pointer; + asm volatile(".set push;\ + .set mips64r2;\ + rdhwr %0,$29;\ + .set pop" : "=r" (thread_pointer)); + segbase = (void **)(thread_pointer - kTlsTcbOffset - kTlsTcbSize); # else # error "unsupported CPU arch" # endif @@ -391,7 +403,11 @@ } uptr ThreadSelf() { +#if defined(__mips__) + return (uptr)ThreadSelfSegbase()[1]; +#else return (uptr)ThreadSelfSegbase()[2]; +#endif } #endif // SANITIZER_FREEBSD @@ -409,7 +425,9 @@ uptr ThreadSelf() { return (uptr)ThreadSelfTlsTcb()->tcb_pthread; } +#endif // SANITIZER_NETBSD +#if SANITIZER_NETBSD || (SANITIZER_FREEBSD && defined(__mips__)) int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) { const Elf_Phdr *hdr = info->dlpi_phdr; const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum; @@ -422,7 +440,7 @@ } return 0; } -#endif // SANITIZER_NETBSD +#endif // SANITIZER_NETBSD || (SANITIZER_FREEBSD && defined(__mips__)) #if !SANITIZER_GO static void GetTls(uptr *addr, uptr *size) { @@ -445,6 +463,22 @@ *addr = 0; *size = 0; if (segbase != 0) { +# if defined(__mips__) + // Variant I + // + // dtv = segbase[0]; + // dtv[2] = base of TLS block of the main program + void **dtv = (void**) segbase[0]; + if ((uptr) dtv[1] >= 2) { + // Find size (p_memsz) of TLS block of the main program. + dl_iterate_phdr(GetSizeFromHdr, size); + + if (*size != 0) + *addr = (uptr) dtv[2]; + } +# else + // Variant II + // // tcbalign = 16 // tls_size = round(tls_static_space, tcbalign); // dtv = segbase[1]; @@ -452,6 +486,7 @@ void **dtv = (void**) segbase[1]; *addr = (uptr) dtv[2]; *size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]); +# endif } #elif SANITIZER_NETBSD struct tls_tcb * const tcb = ThreadSelfTlsTcb(); Index: lib/sanitizer_common/sanitizer_platform_limits_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -117,7 +117,8 @@ #if SANITIZER_LINUX || SANITIZER_FREEBSD # include # include -# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) +# if SANITIZER_LINUX && (defined(__mips64) || defined(__aarch64__) || \ + defined(__arm__)) # include # ifdef __arm__ typedef struct user_fpregs elf_fpregset_t; Index: lib/sanitizer_common/sanitizer_syscall_generic.inc =================================================================== --- lib/sanitizer_common/sanitizer_syscall_generic.inc +++ lib/sanitizer_common/sanitizer_syscall_generic.inc @@ -43,7 +43,7 @@ # else # define internal_syscall_ptr syscall # endif -#elif defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_MAC) +#elif SANITIZER_FREEBSD || (defined(__x86_64__) && SANITIZER_MAC) # define internal_syscall __syscall # define internal_syscall64 __syscall # define internal_syscall_ptr __syscall