2013-05-20 23:57:44 +08:00
|
|
|
//===-- sanitizer_linux_libcdep.cc ----------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is shared between AddressSanitizer and ThreadSanitizer
|
|
|
|
// run-time libraries and implements linux-specific functions from
|
|
|
|
// sanitizer_libc.h.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "sanitizer_platform.h"
|
2015-10-01 07:52:54 +08:00
|
|
|
|
2014-03-07 19:47:32 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX
|
2013-05-20 23:57:44 +08:00
|
|
|
|
2015-07-24 06:05:20 +08:00
|
|
|
#include "sanitizer_allocator_internal.h"
|
2015-04-02 01:56:29 +08:00
|
|
|
#include "sanitizer_atomic.h"
|
2013-05-20 23:57:44 +08:00
|
|
|
#include "sanitizer_common.h"
|
2013-10-15 22:12:26 +08:00
|
|
|
#include "sanitizer_flags.h"
|
2014-07-25 20:29:04 +08:00
|
|
|
#include "sanitizer_freebsd.h"
|
2013-09-10 22:36:16 +08:00
|
|
|
#include "sanitizer_linux.h"
|
|
|
|
#include "sanitizer_placement_new.h"
|
2013-05-20 23:57:44 +08:00
|
|
|
#include "sanitizer_procmaps.h"
|
|
|
|
#include "sanitizer_stacktrace.h"
|
|
|
|
|
2014-09-04 21:58:59 +08:00
|
|
|
#if SANITIZER_ANDROID || SANITIZER_FREEBSD
|
2014-09-01 23:38:16 +08:00
|
|
|
#include <dlfcn.h> // for dlsym()
|
|
|
|
#endif
|
|
|
|
|
2015-04-29 02:50:32 +08:00
|
|
|
#include <link.h>
|
2013-05-20 23:57:44 +08:00
|
|
|
#include <pthread.h>
|
2014-01-31 21:10:07 +08:00
|
|
|
#include <signal.h>
|
2013-05-20 23:57:44 +08:00
|
|
|
#include <sys/resource.h>
|
|
|
|
|
2014-03-07 19:47:32 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
#include <pthread_np.h>
|
2014-07-25 20:29:04 +08:00
|
|
|
#include <osreldate.h>
|
2014-03-07 19:47:32 +08:00
|
|
|
#define pthread_getattr_np pthread_attr_get_np
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_LINUX
|
|
|
|
#include <sys/prctl.h>
|
|
|
|
#endif
|
|
|
|
|
2015-04-29 02:50:32 +08:00
|
|
|
#if SANITIZER_ANDROID
|
|
|
|
#include <android/api-level.h>
|
|
|
|
#endif
|
|
|
|
|
2015-07-24 06:05:20 +08:00
|
|
|
#if SANITIZER_ANDROID && __ANDROID_API__ < 21
|
|
|
|
#include <android/log.h>
|
|
|
|
#else
|
|
|
|
#include <syslog.h>
|
|
|
|
#endif
|
|
|
|
|
2013-09-10 22:36:16 +08:00
|
|
|
#if !SANITIZER_ANDROID
|
|
|
|
#include <elf.h>
|
2014-02-04 12:09:38 +08:00
|
|
|
#include <unistd.h>
|
2013-09-10 22:36:16 +08:00
|
|
|
#endif
|
|
|
|
|
2014-02-05 23:06:32 +08:00
|
|
|
namespace __sanitizer {
|
|
|
|
|
|
|
|
SANITIZER_WEAK_ATTRIBUTE int
|
|
|
|
real_sigaction(int signum, const void *act, void *oldact);
|
2014-01-31 21:10:07 +08:00
|
|
|
|
|
|
|
int internal_sigaction(int signum, const void *act, void *oldact) {
|
2015-01-31 07:04:57 +08:00
|
|
|
#if !SANITIZER_GO
|
2015-02-03 04:37:26 +08:00
|
|
|
if (&real_sigaction)
|
2014-02-05 23:06:32 +08:00
|
|
|
return real_sigaction(signum, act, oldact);
|
2015-01-31 07:04:57 +08:00
|
|
|
#endif
|
2014-11-14 06:40:59 +08:00
|
|
|
return sigaction(signum, (const struct sigaction *)act,
|
|
|
|
(struct sigaction *)oldact);
|
2014-01-31 21:10:07 +08:00
|
|
|
}
|
|
|
|
|
2013-05-20 23:57:44 +08:00
|
|
|
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
|
|
|
|
uptr *stack_bottom) {
|
|
|
|
CHECK(stack_top);
|
|
|
|
CHECK(stack_bottom);
|
|
|
|
if (at_initialization) {
|
|
|
|
// This is the main thread. Libpthread may not be initialized yet.
|
|
|
|
struct rlimit rl;
|
|
|
|
CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
|
|
|
|
|
|
|
|
// Find the mapping that contains a stack variable.
|
|
|
|
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
|
|
|
|
uptr start, end, offset;
|
|
|
|
uptr prev_end = 0;
|
2015-10-01 08:48:07 +08:00
|
|
|
while (proc_maps.Next(&start, &end, &offset, nullptr, 0,
|
|
|
|
/* protection */nullptr)) {
|
2013-05-20 23:57:44 +08:00
|
|
|
if ((uptr)&rl < end)
|
|
|
|
break;
|
|
|
|
prev_end = end;
|
|
|
|
}
|
|
|
|
CHECK((uptr)&rl >= start && (uptr)&rl < end);
|
|
|
|
|
|
|
|
// Get stacksize from rlimit, but clip it so that it does not overlap
|
|
|
|
// with other mappings.
|
|
|
|
uptr stacksize = rl.rlim_cur;
|
|
|
|
if (stacksize > end - prev_end)
|
|
|
|
stacksize = end - prev_end;
|
|
|
|
// When running with unlimited stack size, we still want to set some limit.
|
|
|
|
// The unlimited stack size is caused by 'ulimit -s unlimited'.
|
|
|
|
// Also, for some reason, GNU make spawns subprocesses with unlimited stack.
|
|
|
|
if (stacksize > kMaxThreadStackSize)
|
|
|
|
stacksize = kMaxThreadStackSize;
|
|
|
|
*stack_top = end;
|
|
|
|
*stack_bottom = end - stacksize;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pthread_attr_t attr;
|
2014-03-24 18:01:54 +08:00
|
|
|
pthread_attr_init(&attr);
|
2013-05-20 23:57:44 +08:00
|
|
|
CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
|
|
|
|
uptr stacksize = 0;
|
2015-10-01 07:52:54 +08:00
|
|
|
void *stackaddr = nullptr;
|
2015-11-03 22:33:39 +08:00
|
|
|
my_pthread_attr_getstack(&attr, &stackaddr, &stacksize);
|
2013-05-20 23:57:44 +08:00
|
|
|
pthread_attr_destroy(&attr);
|
|
|
|
|
2013-07-30 17:01:18 +08:00
|
|
|
CHECK_LE(stacksize, kMaxThreadStackSize); // Sanity check.
|
2013-05-20 23:57:44 +08:00
|
|
|
*stack_top = (uptr)stackaddr + stacksize;
|
|
|
|
*stack_bottom = (uptr)stackaddr;
|
|
|
|
}
|
|
|
|
|
2015-01-31 09:27:18 +08:00
|
|
|
#if !SANITIZER_GO
|
|
|
|
bool SetEnv(const char *name, const char *value) {
|
|
|
|
void *f = dlsym(RTLD_NEXT, "setenv");
|
2015-10-01 07:52:54 +08:00
|
|
|
if (!f)
|
2015-01-31 09:27:18 +08:00
|
|
|
return false;
|
|
|
|
typedef int(*setenv_ft)(const char *name, const char *value, int overwrite);
|
|
|
|
setenv_ft setenv_f;
|
|
|
|
CHECK_EQ(sizeof(setenv_f), sizeof(f));
|
|
|
|
internal_memcpy(&setenv_f, &f, sizeof(f));
|
|
|
|
return setenv_f(name, value, 1) == 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-05-20 23:57:44 +08:00
|
|
|
bool SanitizerSetThreadName(const char *name) {
|
|
|
|
#ifdef PR_SET_NAME
|
|
|
|
return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); // NOLINT
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SanitizerGetThreadName(char *name, int max_len) {
|
|
|
|
#ifdef PR_GET_NAME
|
|
|
|
char buff[17];
|
|
|
|
if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0)) // NOLINT
|
|
|
|
return false;
|
|
|
|
internal_strncpy(name, buff, max_len);
|
|
|
|
name[max_len] = 0;
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-07-24 06:05:20 +08:00
|
|
|
#if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO
|
2013-05-20 23:57:44 +08:00
|
|
|
static uptr g_tls_size;
|
|
|
|
|
|
|
|
#ifdef __i386__
|
|
|
|
# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
|
|
|
|
#else
|
|
|
|
# define DL_INTERNAL_FUNCTION
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void InitTlsSize() {
|
2015-08-05 23:17:59 +08:00
|
|
|
// all current supported platforms have 16 bytes stack alignment
|
|
|
|
const size_t kStackAlign = 16;
|
2013-05-20 23:57:44 +08:00
|
|
|
typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
|
|
|
|
get_tls_func get_tls;
|
|
|
|
void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
|
|
|
|
CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
|
|
|
|
internal_memcpy(&get_tls, &get_tls_static_info_ptr,
|
|
|
|
sizeof(get_tls_static_info_ptr));
|
|
|
|
CHECK_NE(get_tls, 0);
|
|
|
|
size_t tls_size = 0;
|
|
|
|
size_t tls_align = 0;
|
2014-11-18 18:33:15 +08:00
|
|
|
get_tls(&tls_size, &tls_align);
|
2015-08-05 23:17:59 +08:00
|
|
|
if (tls_align < kStackAlign)
|
|
|
|
tls_align = kStackAlign;
|
|
|
|
g_tls_size = RoundUpTo(tls_size, tls_align);
|
2013-05-20 23:57:44 +08:00
|
|
|
}
|
2016-03-16 16:23:10 +08:00
|
|
|
#else
|
|
|
|
void InitTlsSize() { }
|
|
|
|
#endif // !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO
|
2013-05-20 23:57:44 +08:00
|
|
|
|
2015-08-05 23:17:59 +08:00
|
|
|
#if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) \
|
2016-06-18 04:24:32 +08:00
|
|
|
|| defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__)) \
|
2015-09-09 03:32:37 +08:00
|
|
|
&& SANITIZER_LINUX && !SANITIZER_ANDROID
|
2015-11-11 23:37:47 +08:00
|
|
|
// sizeof(struct pthread) from glibc.
|
2014-02-04 12:09:38 +08:00
|
|
|
static atomic_uintptr_t kThreadDescriptorSize;
|
2013-05-20 23:57:44 +08:00
|
|
|
|
|
|
|
uptr ThreadDescriptorSize() {
|
2014-02-04 12:09:38 +08:00
|
|
|
uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed);
|
|
|
|
if (val)
|
|
|
|
return val;
|
2015-02-19 15:30:39 +08:00
|
|
|
#if defined(__x86_64__) || defined(__i386__)
|
2014-02-04 12:09:38 +08:00
|
|
|
#ifdef _CS_GNU_LIBC_VERSION
|
2014-07-03 22:14:59 +08:00
|
|
|
char buf[64];
|
2014-02-04 12:09:38 +08:00
|
|
|
uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
|
|
|
|
if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) {
|
|
|
|
char *end;
|
|
|
|
int minor = internal_simple_strtoll(buf + 8, &end, 10);
|
|
|
|
if (end != buf + 8 && (*end == '\0' || *end == '.')) {
|
2016-02-18 15:08:26 +08:00
|
|
|
int patch = 0;
|
|
|
|
if (*end == '.')
|
|
|
|
// strtoll will return 0 if no valid conversion could be performed
|
|
|
|
patch = internal_simple_strtoll(end + 1, nullptr, 10);
|
|
|
|
|
2015-11-11 23:37:47 +08:00
|
|
|
/* sizeof(struct pthread) values from various glibc versions. */
|
2014-05-21 16:01:44 +08:00
|
|
|
if (SANITIZER_X32)
|
|
|
|
val = 1728; // Assume only one particular version for x32.
|
|
|
|
else if (minor <= 3)
|
2014-02-04 12:09:38 +08:00
|
|
|
val = FIRST_32_SECOND_64(1104, 1696);
|
|
|
|
else if (minor == 4)
|
|
|
|
val = FIRST_32_SECOND_64(1120, 1728);
|
|
|
|
else if (minor == 5)
|
|
|
|
val = FIRST_32_SECOND_64(1136, 1728);
|
|
|
|
else if (minor <= 9)
|
|
|
|
val = FIRST_32_SECOND_64(1136, 1712);
|
|
|
|
else if (minor == 10)
|
|
|
|
val = FIRST_32_SECOND_64(1168, 1776);
|
2016-02-18 15:08:26 +08:00
|
|
|
else if (minor == 11 || (minor == 12 && patch == 1))
|
2014-02-04 12:09:38 +08:00
|
|
|
val = FIRST_32_SECOND_64(1168, 2288);
|
2016-02-18 15:08:26 +08:00
|
|
|
else if (minor <= 13)
|
2015-01-24 05:12:39 +08:00
|
|
|
val = FIRST_32_SECOND_64(1168, 2304);
|
2014-02-04 12:09:38 +08:00
|
|
|
else
|
|
|
|
val = FIRST_32_SECOND_64(1216, 2304);
|
|
|
|
}
|
|
|
|
if (val)
|
|
|
|
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
|
|
|
|
return val;
|
|
|
|
}
|
2015-02-19 15:30:39 +08:00
|
|
|
#endif
|
|
|
|
#elif defined(__mips__)
|
|
|
|
// TODO(sagarthakur): add more values as per different glibc versions.
|
|
|
|
val = FIRST_32_SECOND_64(1152, 1776);
|
|
|
|
if (val)
|
|
|
|
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
|
|
|
|
return val;
|
2015-08-05 23:17:59 +08:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
// The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22.
|
|
|
|
val = 1776;
|
|
|
|
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
|
|
|
|
return val;
|
2015-11-11 23:37:47 +08:00
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
val = 1776; // from glibc.ppc64le 2.20-8.fc21
|
|
|
|
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
|
|
|
|
return val;
|
2016-06-18 04:24:32 +08:00
|
|
|
#elif defined(__s390__)
|
|
|
|
val = FIRST_32_SECOND_64(1152, 1776); // valid for glibc 2.22
|
|
|
|
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
|
2014-02-04 12:09:38 +08:00
|
|
|
#endif
|
|
|
|
return 0;
|
2013-05-20 23:57:44 +08:00
|
|
|
}
|
2013-05-29 21:07:42 +08:00
|
|
|
|
|
|
|
// The offset at which pointer to self is located in the thread descriptor.
|
|
|
|
const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
|
|
|
|
|
|
|
|
uptr ThreadSelfOffset() {
|
|
|
|
return kThreadSelfOffset;
|
|
|
|
}
|
|
|
|
|
2016-03-16 16:23:10 +08:00
|
|
|
#if defined(__mips__) || defined(__powerpc64__)
|
|
|
|
// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
|
|
|
|
// head structure. It lies before the static tls blocks.
|
|
|
|
static uptr TlsPreTcbSize() {
|
|
|
|
# if defined(__mips__)
|
|
|
|
const uptr kTcbHead = 16; // sizeof (tcbhead_t)
|
|
|
|
# elif defined(__powerpc64__)
|
|
|
|
const uptr kTcbHead = 88; // sizeof (tcbhead_t)
|
|
|
|
# endif
|
|
|
|
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
|
|
|
|
|
2013-05-29 21:07:42 +08:00
|
|
|
uptr ThreadSelf() {
|
|
|
|
uptr descr_addr;
|
2014-03-07 19:47:32 +08:00
|
|
|
# if defined(__i386__)
|
2013-05-29 21:07:42 +08:00
|
|
|
asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
|
2014-03-07 19:47:32 +08:00
|
|
|
# elif defined(__x86_64__)
|
2013-05-29 21:07:42 +08:00
|
|
|
asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
|
2015-02-19 15:30:39 +08:00
|
|
|
# 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();
|
2016-06-18 04:24:32 +08:00
|
|
|
# elif defined(__aarch64__) || defined(__s390__)
|
2015-08-05 23:17:59 +08:00
|
|
|
descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer());
|
2015-11-11 23:37:47 +08:00
|
|
|
# elif defined(__powerpc64__)
|
|
|
|
// PPC64LE uses TLS variant I. The thread pointer (in GPR 13)
|
|
|
|
// 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("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset));
|
|
|
|
descr_addr = thread_pointer - TlsPreTcbSize();
|
2014-03-07 19:47:32 +08:00
|
|
|
# else
|
|
|
|
# error "unsupported CPU arch"
|
|
|
|
# endif
|
2013-05-29 21:07:42 +08:00
|
|
|
return descr_addr;
|
|
|
|
}
|
2015-02-20 09:45:51 +08:00
|
|
|
#endif // (x86_64 || i386 || MIPS) && SANITIZER_LINUX
|
2014-03-07 19:47:32 +08:00
|
|
|
|
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
static void **ThreadSelfSegbase() {
|
|
|
|
void **segbase = 0;
|
|
|
|
# if defined(__i386__)
|
|
|
|
// sysarch(I386_GET_GSBASE, segbase);
|
|
|
|
__asm __volatile("mov %%gs:0, %0" : "=r" (segbase));
|
|
|
|
# elif defined(__x86_64__)
|
|
|
|
// sysarch(AMD64_GET_FSBASE, segbase);
|
|
|
|
__asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
|
|
|
|
# else
|
|
|
|
# error "unsupported CPU arch for FreeBSD platform"
|
|
|
|
# endif
|
|
|
|
return segbase;
|
|
|
|
}
|
|
|
|
|
|
|
|
uptr ThreadSelf() {
|
|
|
|
return (uptr)ThreadSelfSegbase()[2];
|
|
|
|
}
|
|
|
|
#endif // SANITIZER_FREEBSD
|
|
|
|
|
2015-01-31 07:04:57 +08:00
|
|
|
#if !SANITIZER_GO
|
2014-03-07 19:47:32 +08:00
|
|
|
static void GetTls(uptr *addr, uptr *size) {
|
2015-08-22 08:47:12 +08:00
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
2016-06-18 04:24:32 +08:00
|
|
|
# if defined(__x86_64__) || defined(__i386__) || defined(__s390__)
|
2014-03-07 19:47:32 +08:00
|
|
|
*addr = ThreadSelf();
|
|
|
|
*size = GetTlsSize();
|
|
|
|
*addr -= *size;
|
|
|
|
*addr += ThreadDescriptorSize();
|
2015-11-11 23:37:47 +08:00
|
|
|
# elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__)
|
2015-02-19 15:30:39 +08:00
|
|
|
*addr = ThreadSelf();
|
|
|
|
*size = GetTlsSize();
|
2014-03-07 19:47:32 +08:00
|
|
|
# else
|
|
|
|
*addr = 0;
|
|
|
|
*size = 0;
|
|
|
|
# endif
|
|
|
|
#elif SANITIZER_FREEBSD
|
|
|
|
void** segbase = ThreadSelfSegbase();
|
|
|
|
*addr = 0;
|
|
|
|
*size = 0;
|
|
|
|
if (segbase != 0) {
|
|
|
|
// tcbalign = 16
|
|
|
|
// tls_size = round(tls_static_space, tcbalign);
|
|
|
|
// dtv = segbase[1];
|
|
|
|
// dtv[2] = segbase - tls_static_space;
|
|
|
|
void **dtv = (void**) segbase[1];
|
|
|
|
*addr = (uptr) dtv[2];
|
|
|
|
*size = (*addr == 0) ? 0 : ((uptr) segbase[0] - (uptr) dtv[2]);
|
|
|
|
}
|
2015-08-22 08:47:12 +08:00
|
|
|
#elif SANITIZER_ANDROID
|
|
|
|
*addr = 0;
|
|
|
|
*size = 0;
|
2014-03-07 19:47:32 +08:00
|
|
|
#else
|
|
|
|
# error "Unknown OS"
|
|
|
|
#endif
|
|
|
|
}
|
2015-01-31 07:04:57 +08:00
|
|
|
#endif
|
2013-05-20 23:57:44 +08:00
|
|
|
|
2015-02-16 22:35:51 +08:00
|
|
|
#if !SANITIZER_GO
|
2014-03-24 18:01:54 +08:00
|
|
|
uptr GetTlsSize() {
|
2015-07-24 06:05:20 +08:00
|
|
|
#if SANITIZER_FREEBSD || SANITIZER_ANDROID
|
2014-03-24 18:01:54 +08:00
|
|
|
uptr addr, size;
|
|
|
|
GetTls(&addr, &size);
|
|
|
|
return size;
|
|
|
|
#else
|
|
|
|
return g_tls_size;
|
|
|
|
#endif
|
|
|
|
}
|
2015-02-16 22:35:51 +08:00
|
|
|
#endif
|
2014-03-24 18:01:54 +08:00
|
|
|
|
2013-05-20 23:57:44 +08:00
|
|
|
void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
|
|
|
|
uptr *tls_addr, uptr *tls_size) {
|
2015-01-31 07:04:57 +08:00
|
|
|
#if SANITIZER_GO
|
|
|
|
// Stub implementation for Go.
|
|
|
|
*stk_addr = *stk_size = *tls_addr = *tls_size = 0;
|
|
|
|
#else
|
2014-03-07 19:47:32 +08:00
|
|
|
GetTls(tls_addr, tls_size);
|
2013-05-20 23:57:44 +08:00
|
|
|
|
|
|
|
uptr stack_top, stack_bottom;
|
|
|
|
GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
|
|
|
|
*stk_addr = stack_bottom;
|
|
|
|
*stk_size = stack_top - stack_bottom;
|
|
|
|
|
|
|
|
if (!main) {
|
|
|
|
// If stack and tls intersect, make them non-intersecting.
|
|
|
|
if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
|
|
|
|
CHECK_GT(*tls_addr + *tls_size, *stk_addr);
|
|
|
|
CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
|
|
|
|
*stk_size -= *tls_size;
|
|
|
|
*tls_addr = *stk_addr + *stk_size;
|
|
|
|
}
|
|
|
|
}
|
2015-01-31 07:04:57 +08:00
|
|
|
#endif
|
2013-05-20 23:57:44 +08:00
|
|
|
}
|
|
|
|
|
2014-03-07 19:47:32 +08:00
|
|
|
# if !SANITIZER_FREEBSD
|
2013-09-10 22:36:16 +08:00
|
|
|
typedef ElfW(Phdr) Elf_Phdr;
|
2014-07-25 20:29:04 +08:00
|
|
|
# elif SANITIZER_WORDSIZE == 32 && __FreeBSD_version <= 902001 // v9.2
|
|
|
|
# define Elf_Phdr XElf32_Phdr
|
|
|
|
# define dl_phdr_info xdl_phdr_info
|
|
|
|
# define dl_iterate_phdr(c, b) xdl_iterate_phdr((c), (b))
|
2014-03-07 19:47:32 +08:00
|
|
|
# endif
|
2013-09-10 22:36:16 +08:00
|
|
|
|
|
|
|
struct DlIteratePhdrData {
|
2016-02-23 02:52:51 +08:00
|
|
|
InternalMmapVector<LoadedModule> *modules;
|
2013-09-10 22:36:16 +08:00
|
|
|
bool first;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
|
|
|
|
DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
|
2014-12-03 06:20:11 +08:00
|
|
|
InternalScopedString module_name(kMaxPathLength);
|
2013-09-10 22:36:16 +08:00
|
|
|
if (data->first) {
|
|
|
|
data->first = false;
|
|
|
|
// First module is the binary itself.
|
2015-06-29 23:58:16 +08:00
|
|
|
ReadBinaryNameCached(module_name.data(), module_name.size());
|
2013-09-10 22:36:16 +08:00
|
|
|
} else if (info->dlpi_name) {
|
2014-12-03 06:20:11 +08:00
|
|
|
module_name.append("%s", info->dlpi_name);
|
2013-09-10 22:36:16 +08:00
|
|
|
}
|
2014-12-03 06:20:11 +08:00
|
|
|
if (module_name[0] == '\0')
|
2013-09-10 22:36:16 +08:00
|
|
|
return 0;
|
2016-02-23 02:52:51 +08:00
|
|
|
LoadedModule cur_module;
|
|
|
|
cur_module.set(module_name.data(), info->dlpi_addr);
|
2013-09-10 22:36:16 +08:00
|
|
|
for (int i = 0; i < info->dlpi_phnum; i++) {
|
|
|
|
const Elf_Phdr *phdr = &info->dlpi_phdr[i];
|
|
|
|
if (phdr->p_type == PT_LOAD) {
|
|
|
|
uptr cur_beg = info->dlpi_addr + phdr->p_vaddr;
|
|
|
|
uptr cur_end = cur_beg + phdr->p_memsz;
|
2014-06-11 18:11:51 +08:00
|
|
|
bool executable = phdr->p_flags & PF_X;
|
2016-02-23 02:52:51 +08:00
|
|
|
cur_module.addAddressRange(cur_beg, cur_end, executable);
|
2013-09-10 22:36:16 +08:00
|
|
|
}
|
|
|
|
}
|
2016-02-23 02:52:51 +08:00
|
|
|
data->modules->push_back(cur_module);
|
2013-09-10 22:36:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-29 02:50:32 +08:00
|
|
|
#if SANITIZER_ANDROID && __ANDROID_API__ < 21
|
|
|
|
extern "C" __attribute__((weak)) int dl_iterate_phdr(
|
|
|
|
int (*)(struct dl_phdr_info *, size_t, void *), void *);
|
|
|
|
#endif
|
|
|
|
|
2016-02-23 02:52:51 +08:00
|
|
|
void ListOfModules::init() {
|
|
|
|
clear();
|
2015-08-01 05:35:15 +08:00
|
|
|
#if SANITIZER_ANDROID && __ANDROID_API__ <= 22
|
2015-05-07 02:55:31 +08:00
|
|
|
u32 api_level = AndroidGetApiLevel();
|
|
|
|
// Fall back to /proc/maps if dl_iterate_phdr is unavailable or broken.
|
2015-04-29 02:50:32 +08:00
|
|
|
// The runtime check allows the same library to work with
|
|
|
|
// both K and L (and future) Android releases.
|
2015-06-30 04:28:55 +08:00
|
|
|
if (api_level <= ANDROID_LOLLIPOP_MR1) { // L or earlier
|
2015-04-29 02:50:32 +08:00
|
|
|
MemoryMappingLayout memory_mapping(false);
|
2016-02-23 02:52:51 +08:00
|
|
|
memory_mapping.DumpListOfModules(&modules_);
|
|
|
|
return;
|
2015-04-29 02:50:32 +08:00
|
|
|
}
|
|
|
|
#endif
|
2016-02-23 02:52:51 +08:00
|
|
|
DlIteratePhdrData data = {&modules_, true};
|
2013-09-10 22:36:16 +08:00
|
|
|
dl_iterate_phdr(dl_iterate_phdr_cb, &data);
|
|
|
|
}
|
|
|
|
|
2015-01-29 10:54:39 +08:00
|
|
|
// getrusage does not give us the current RSS, only the max RSS.
|
|
|
|
// Still, this is better than nothing if /proc/self/statm is not available
|
|
|
|
// for some reason, e.g. due to a sandbox.
|
|
|
|
static uptr GetRSSFromGetrusage() {
|
|
|
|
struct rusage usage;
|
|
|
|
if (getrusage(RUSAGE_SELF, &usage)) // Failed, probably due to a sandbox.
|
|
|
|
return 0;
|
|
|
|
return usage.ru_maxrss << 10; // ru_maxrss is in Kb.
|
|
|
|
}
|
|
|
|
|
|
|
|
uptr GetRSS() {
|
|
|
|
if (!common_flags()->can_use_proc_maps_statm)
|
|
|
|
return GetRSSFromGetrusage();
|
2015-04-09 00:03:22 +08:00
|
|
|
fd_t fd = OpenFile("/proc/self/statm", RdOnly);
|
|
|
|
if (fd == kInvalidFd)
|
2015-01-29 10:54:39 +08:00
|
|
|
return GetRSSFromGetrusage();
|
|
|
|
char buf[64];
|
|
|
|
uptr len = internal_read(fd, buf, sizeof(buf) - 1);
|
|
|
|
internal_close(fd);
|
|
|
|
if ((sptr)len <= 0)
|
|
|
|
return 0;
|
|
|
|
buf[len] = 0;
|
|
|
|
// The format of the file is:
|
|
|
|
// 1084 89 69 11 0 79 0
|
|
|
|
// We need the second number which is RSS in pages.
|
|
|
|
char *pos = buf;
|
|
|
|
// Skip the first number.
|
|
|
|
while (*pos >= '0' && *pos <= '9')
|
|
|
|
pos++;
|
|
|
|
// Skip whitespaces.
|
|
|
|
while (!(*pos >= '0' && *pos <= '9') && *pos != 0)
|
|
|
|
pos++;
|
|
|
|
// Read the number.
|
|
|
|
uptr rss = 0;
|
|
|
|
while (*pos >= '0' && *pos <= '9')
|
|
|
|
rss = rss * 10 + *pos++ - '0';
|
|
|
|
return rss * GetPageSizeCached();
|
|
|
|
}
|
|
|
|
|
2015-07-24 06:05:20 +08:00
|
|
|
// 64-bit Android targets don't provide the deprecated __android_log_write.
|
|
|
|
// Starting with the L release, syslog() works and is preferable to
|
|
|
|
// __android_log_write.
|
2015-07-28 08:29:47 +08:00
|
|
|
#if SANITIZER_LINUX
|
2015-09-04 09:15:25 +08:00
|
|
|
|
|
|
|
#if SANITIZER_ANDROID
|
2015-07-24 06:05:20 +08:00
|
|
|
static atomic_uint8_t android_log_initialized;
|
|
|
|
|
|
|
|
void AndroidLogInit() {
|
|
|
|
atomic_store(&android_log_initialized, 1, memory_order_release);
|
|
|
|
}
|
|
|
|
|
2016-01-07 07:15:01 +08:00
|
|
|
static bool ShouldLogAfterPrintf() {
|
2015-07-24 06:05:20 +08:00
|
|
|
return atomic_load(&android_log_initialized, memory_order_acquire);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void AndroidLogInit() {}
|
|
|
|
|
2016-01-07 07:15:01 +08:00
|
|
|
static bool ShouldLogAfterPrintf() { return true; }
|
2015-09-04 09:15:25 +08:00
|
|
|
#endif // SANITIZER_ANDROID
|
2015-07-24 06:05:20 +08:00
|
|
|
|
Reapply: [asan] On OS X, log reports to syslog and os_trace
When ASan currently detects a bug, by default it will only print out the text
of the report to stderr. This patch changes this behavior and writes the full
text of the report to syslog before we terminate the process. It also calls
os_trace (Activity Tracing available on OS X and iOS) with a message saying
that the report is available in syslog. This is useful, because this message
will be shown in the crash log.
For this to work, the patch makes sure we store the full report into
error_message_buffer unconditionally, and it also strips out ANSI escape
sequences from the report (they are used when producing colored reports).
I've initially tried to log to syslog during printing, which is done on Android
right now. The advantage is that if we crash during error reporting or the
produced error does not go through ScopedInErrorReport, we would still get a
(partial) message in the syslog. However, that solution is very problematic on
OS X. One issue is that the logging routine uses GCD, which may spawn a new
thread on its behalf. In many cases, the reporting logic locks threadRegistry,
which leads to deadlocks.
Reviewed at http://reviews.llvm.org/D13452
(In addition, add sanitizer_common_libcdep.cc to buildgo.sh to avoid
build failures on Linux.)
llvm-svn: 253688
2015-11-21 02:41:44 +08:00
|
|
|
void WriteOneLineToSyslog(const char *s) {
|
2015-09-04 09:15:25 +08:00
|
|
|
#if SANITIZER_ANDROID &&__ANDROID_API__ < 21
|
|
|
|
__android_log_write(ANDROID_LOG_INFO, NULL, s);
|
|
|
|
#else
|
|
|
|
syslog(LOG_INFO, "%s", s);
|
2015-07-24 06:05:20 +08:00
|
|
|
#endif
|
2015-09-04 09:15:25 +08:00
|
|
|
}
|
2015-07-24 06:05:20 +08:00
|
|
|
|
2016-01-07 07:15:01 +08:00
|
|
|
void LogMessageOnPrintf(const char *str) {
|
|
|
|
if (common_flags()->log_to_syslog && ShouldLogAfterPrintf())
|
|
|
|
WriteToSyslog(str);
|
|
|
|
}
|
|
|
|
|
2015-10-01 07:52:54 +08:00
|
|
|
#endif // SANITIZER_LINUX
|
2015-07-24 06:05:20 +08:00
|
|
|
|
2015-10-01 07:52:54 +08:00
|
|
|
} // namespace __sanitizer
|
2013-05-20 23:57:44 +08:00
|
|
|
|
2015-10-01 07:52:54 +08:00
|
|
|
#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
|