[RISCV][ASAN] implementation of ThreadSelf for riscv64
[6/11] patch series to port ASAN for riscv64 Depends On D87574 Reviewed By: eugenis Differential Revision: https://reviews.llvm.org/D87575
This commit is contained in:
parent
aa1b1d35cb
commit
00f6ebef6e
|
@ -16,6 +16,13 @@
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
||||||
SANITIZER_OPENBSD || SANITIZER_SOLARIS
|
SANITIZER_OPENBSD || SANITIZER_SOLARIS
|
||||||
|
|
||||||
|
#include <dlfcn.h> // for dlsym()
|
||||||
|
#include <link.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "sanitizer_allocator_internal.h"
|
#include "sanitizer_allocator_internal.h"
|
||||||
#include "sanitizer_atomic.h"
|
#include "sanitizer_atomic.h"
|
||||||
#include "sanitizer_common.h"
|
#include "sanitizer_common.h"
|
||||||
|
@ -28,20 +35,13 @@
|
||||||
#include "sanitizer_placement_new.h"
|
#include "sanitizer_placement_new.h"
|
||||||
#include "sanitizer_procmaps.h"
|
#include "sanitizer_procmaps.h"
|
||||||
|
|
||||||
#include <dlfcn.h> // for dlsym()
|
|
||||||
#include <link.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#if !defined(ElfW)
|
#if !defined(ElfW)
|
||||||
#define ElfW(type) Elf_##type
|
#define ElfW(type) Elf_##type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_FREEBSD
|
#if SANITIZER_FREEBSD
|
||||||
#include <pthread_np.h>
|
|
||||||
#include <osreldate.h>
|
#include <osreldate.h>
|
||||||
|
#include <pthread_np.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#define pthread_getattr_np pthread_attr_get_np
|
#define pthread_getattr_np pthread_attr_get_np
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,9 +52,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_NETBSD
|
#if SANITIZER_NETBSD
|
||||||
|
#include <lwp.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/tls.h>
|
#include <sys/tls.h>
|
||||||
#include <lwp.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_SOLARIS
|
#if SANITIZER_SOLARIS
|
||||||
|
@ -83,8 +83,8 @@ struct __sanitizer::linux_dirent {
|
||||||
|
|
||||||
namespace __sanitizer {
|
namespace __sanitizer {
|
||||||
|
|
||||||
SANITIZER_WEAK_ATTRIBUTE int
|
SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act,
|
||||||
real_sigaction(int signum, const void *act, void *oldact);
|
void *oldact);
|
||||||
|
|
||||||
int internal_sigaction(int signum, const void *act, void *oldact) {
|
int internal_sigaction(int signum, const void *act, void *oldact) {
|
||||||
#if !SANITIZER_GO
|
#if !SANITIZER_GO
|
||||||
|
@ -113,7 +113,8 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
|
||||||
MemoryMappedSegment segment;
|
MemoryMappedSegment segment;
|
||||||
uptr prev_end = 0;
|
uptr prev_end = 0;
|
||||||
while (proc_maps.Next(&segment)) {
|
while (proc_maps.Next(&segment)) {
|
||||||
if ((uptr)&rl < segment.end) break;
|
if ((uptr)&rl < segment.end)
|
||||||
|
break;
|
||||||
prev_end = segment.end;
|
prev_end = segment.end;
|
||||||
}
|
}
|
||||||
CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);
|
CHECK((uptr)&rl >= segment.start && (uptr)&rl < segment.end);
|
||||||
|
@ -121,7 +122,8 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
|
||||||
// Get stacksize from rlimit, but clip it so that it does not overlap
|
// Get stacksize from rlimit, but clip it so that it does not overlap
|
||||||
// with other mappings.
|
// with other mappings.
|
||||||
uptr stacksize = rl.rlim_cur;
|
uptr stacksize = rl.rlim_cur;
|
||||||
if (stacksize > segment.end - prev_end) stacksize = segment.end - prev_end;
|
if (stacksize > segment.end - prev_end)
|
||||||
|
stacksize = segment.end - prev_end;
|
||||||
// When running with unlimited stack size, we still want to set some limit.
|
// When running with unlimited stack size, we still want to set some limit.
|
||||||
// The unlimited stack size is caused by 'ulimit -s unlimited'.
|
// The unlimited stack size is caused by 'ulimit -s unlimited'.
|
||||||
// Also, for some reason, GNU make spawns subprocesses with unlimited stack.
|
// Also, for some reason, GNU make spawns subprocesses with unlimited stack.
|
||||||
|
@ -251,11 +253,11 @@ void InitTlsSize() {
|
||||||
// __attribute__((regparm(3), stdcall)) before glibc 2.27 and is normal
|
// __attribute__((regparm(3), stdcall)) before glibc 2.27 and is normal
|
||||||
// function in 2.27 and later.
|
// function in 2.27 and later.
|
||||||
if (CHECK_GET_TLS_STATIC_INFO_VERSION && !CmpLibcVersion(2, 27, 0))
|
if (CHECK_GET_TLS_STATIC_INFO_VERSION && !CmpLibcVersion(2, 27, 0))
|
||||||
CallGetTls<GetTlsStaticInfoRegparmCall>(get_tls_static_info_ptr,
|
CallGetTls<GetTlsStaticInfoRegparmCall>(get_tls_static_info_ptr, &tls_size,
|
||||||
&tls_size, &tls_align);
|
&tls_align);
|
||||||
else
|
else
|
||||||
CallGetTls<GetTlsStaticInfoCall>(get_tls_static_info_ptr,
|
CallGetTls<GetTlsStaticInfoCall>(get_tls_static_info_ptr, &tls_size,
|
||||||
&tls_size, &tls_align);
|
&tls_align);
|
||||||
if (tls_align < kStackAlign)
|
if (tls_align < kStackAlign)
|
||||||
tls_align = kStackAlign;
|
tls_align = kStackAlign;
|
||||||
g_tls_size = RoundUpTo(tls_size, tls_align);
|
g_tls_size = RoundUpTo(tls_size, tls_align);
|
||||||
|
@ -323,11 +325,9 @@ uptr ThreadDescriptorSize() {
|
||||||
// The offset at which pointer to self is located in the thread descriptor.
|
// The offset at which pointer to self is located in the thread descriptor.
|
||||||
const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
|
const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
|
||||||
|
|
||||||
uptr ThreadSelfOffset() {
|
uptr ThreadSelfOffset() { return kThreadSelfOffset; }
|
||||||
return kThreadSelfOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__mips__) || defined(__powerpc64__)
|
#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64
|
||||||
// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
|
// TlsPreTcbSize includes size of struct pthread_descr and size of tcb
|
||||||
// head structure. It lies before the static tls blocks.
|
// head structure. It lies before the static tls blocks.
|
||||||
static uptr TlsPreTcbSize() {
|
static uptr TlsPreTcbSize() {
|
||||||
|
@ -335,6 +335,8 @@ static uptr TlsPreTcbSize() {
|
||||||
const uptr kTcbHead = 16; // sizeof (tcbhead_t)
|
const uptr kTcbHead = 16; // sizeof (tcbhead_t)
|
||||||
#elif defined(__powerpc64__)
|
#elif defined(__powerpc64__)
|
||||||
const uptr kTcbHead = 88; // sizeof (tcbhead_t)
|
const uptr kTcbHead = 88; // sizeof (tcbhead_t)
|
||||||
|
#elif SANITIZER_RISCV64
|
||||||
|
const uptr kTcbHead = 16; // sizeof (tcbhead_t)
|
||||||
#endif
|
#endif
|
||||||
const uptr kTlsAlign = 16;
|
const uptr kTlsAlign = 16;
|
||||||
const uptr kTlsPreTcbSize =
|
const uptr kTlsPreTcbSize =
|
||||||
|
@ -356,14 +358,23 @@ uptr ThreadSelf() {
|
||||||
// TCB and the size of pthread_descr.
|
// TCB and the size of pthread_descr.
|
||||||
const uptr kTlsTcbOffset = 0x7000;
|
const uptr kTlsTcbOffset = 0x7000;
|
||||||
uptr thread_pointer;
|
uptr thread_pointer;
|
||||||
asm volatile(".set push;\
|
asm volatile(
|
||||||
|
".set push;\
|
||||||
.set mips64r2;\
|
.set mips64r2;\
|
||||||
rdhwr %0,$29;\
|
rdhwr %0,$29;\
|
||||||
.set pop" : "=r" (thread_pointer));
|
.set pop"
|
||||||
|
: "=r"(thread_pointer));
|
||||||
descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize();
|
descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize();
|
||||||
#elif defined(__aarch64__) || defined(__arm__)
|
#elif defined(__aarch64__) || defined(__arm__)
|
||||||
descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
|
descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer()) -
|
||||||
ThreadDescriptorSize();
|
ThreadDescriptorSize();
|
||||||
|
#elif SANITIZER_RISCV64
|
||||||
|
uptr tcb_end;
|
||||||
|
asm volatile("mv %0, tp;\n" : "=r"(tcb_end));
|
||||||
|
// https://github.com/riscv/riscv-elf-psabi-doc/issues/53
|
||||||
|
const uptr kTlsTcbOffset = 0x800;
|
||||||
|
descr_addr =
|
||||||
|
reinterpret_cast<uptr>(tcb_end - kTlsTcbOffset - TlsPreTcbSize());
|
||||||
#elif defined(__s390__)
|
#elif defined(__s390__)
|
||||||
descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer());
|
descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer());
|
||||||
#elif defined(__powerpc64__)
|
#elif defined(__powerpc64__)
|
||||||
|
@ -397,9 +408,7 @@ static void **ThreadSelfSegbase() {
|
||||||
return segbase;
|
return segbase;
|
||||||
}
|
}
|
||||||
|
|
||||||
uptr ThreadSelf() {
|
uptr ThreadSelf() { return (uptr)ThreadSelfSegbase()[2]; }
|
||||||
return (uptr)ThreadSelfSegbase()[2];
|
|
||||||
}
|
|
||||||
#endif // SANITIZER_FREEBSD
|
#endif // SANITIZER_FREEBSD
|
||||||
|
|
||||||
#if SANITIZER_NETBSD
|
#if SANITIZER_NETBSD
|
||||||
|
@ -407,9 +416,7 @@ static struct tls_tcb * ThreadSelfTlsTcb() {
|
||||||
return (struct tls_tcb *)_lwp_getprivate();
|
return (struct tls_tcb *)_lwp_getprivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
uptr ThreadSelf() {
|
uptr ThreadSelf() { return (uptr)ThreadSelfTlsTcb()->tcb_pthread; }
|
||||||
return (uptr)ThreadSelfTlsTcb()->tcb_pthread;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
|
int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
|
||||||
const Elf_Phdr *hdr = info->dlpi_phdr;
|
const Elf_Phdr *hdr = info->dlpi_phdr;
|
||||||
|
@ -433,8 +440,8 @@ static void GetTls(uptr *addr, uptr *size) {
|
||||||
*size = GetTlsSize();
|
*size = GetTlsSize();
|
||||||
*addr -= *size;
|
*addr -= *size;
|
||||||
*addr += ThreadDescriptorSize();
|
*addr += ThreadDescriptorSize();
|
||||||
# elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) \
|
#elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) || \
|
||||||
|| defined(__arm__)
|
defined(__arm__)
|
||||||
*addr = ThreadSelf();
|
*addr = ThreadSelf();
|
||||||
*size = GetTlsSize();
|
*size = GetTlsSize();
|
||||||
#else
|
#else
|
||||||
|
@ -558,8 +565,7 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
|
||||||
uptr cur_end = cur_beg + phdr->p_memsz;
|
uptr cur_end = cur_beg + phdr->p_memsz;
|
||||||
bool executable = phdr->p_flags & PF_X;
|
bool executable = phdr->p_flags & PF_X;
|
||||||
bool writable = phdr->p_flags & PF_W;
|
bool writable = phdr->p_flags & PF_W;
|
||||||
cur_module.addAddressRange(cur_beg, cur_end, executable,
|
cur_module.addAddressRange(cur_beg, cur_end, executable, writable);
|
||||||
writable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->modules->push_back(cur_module);
|
data->modules->push_back(cur_module);
|
||||||
|
@ -635,15 +641,12 @@ uptr GetRSS() {
|
||||||
// We need the second number which is RSS in pages.
|
// We need the second number which is RSS in pages.
|
||||||
char *pos = buf;
|
char *pos = buf;
|
||||||
// Skip the first number.
|
// Skip the first number.
|
||||||
while (*pos >= '0' && *pos <= '9')
|
while (*pos >= '0' && *pos <= '9') pos++;
|
||||||
pos++;
|
|
||||||
// Skip whitespaces.
|
// Skip whitespaces.
|
||||||
while (!(*pos >= '0' && *pos <= '9') && *pos != 0)
|
while (!(*pos >= '0' && *pos <= '9') && *pos != 0) pos++;
|
||||||
pos++;
|
|
||||||
// Read the number.
|
// Read the number.
|
||||||
uptr rss = 0;
|
uptr rss = 0;
|
||||||
while (*pos >= '0' && *pos <= '9')
|
while (*pos >= '0' && *pos <= '9') rss = rss * 10 + *pos++ - '0';
|
||||||
rss = rss * 10 + *pos++ - '0';
|
|
||||||
return rss * GetPageSizeCached();
|
return rss * GetPageSizeCached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,8 +689,8 @@ u32 GetNumberOfCPUs() {
|
||||||
break;
|
break;
|
||||||
if (entry->d_ino != 0 && *d_type == DT_DIR) {
|
if (entry->d_ino != 0 && *d_type == DT_DIR) {
|
||||||
if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
|
if (entry->d_name[0] == 'c' && entry->d_name[1] == 'p' &&
|
||||||
entry->d_name[2] == 'u' &&
|
entry->d_name[2] == 'u' && entry->d_name[3] >= '0' &&
|
||||||
entry->d_name[3] >= '0' && entry->d_name[3] <= '9')
|
entry->d_name[3] <= '9')
|
||||||
n_cpus++;
|
n_cpus++;
|
||||||
}
|
}
|
||||||
entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
|
entry = (struct linux_dirent *)(((u8 *)entry) + entry->d_reclen);
|
||||||
|
@ -717,10 +720,12 @@ static bool ShouldLogAfterPrintf() {
|
||||||
return atomic_load(&android_log_initialized, memory_order_acquire);
|
return atomic_load(&android_log_initialized, memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
extern "C" SANITIZER_WEAK_ATTRIBUTE int async_safe_write_log(int pri,
|
||||||
int async_safe_write_log(int pri, const char* tag, const char* msg);
|
const char *tag,
|
||||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
const char *msg);
|
||||||
int __android_log_write(int prio, const char* tag, const char* msg);
|
extern "C" SANITIZER_WEAK_ATTRIBUTE int __android_log_write(int prio,
|
||||||
|
const char *tag,
|
||||||
|
const char *msg);
|
||||||
|
|
||||||
// ANDROID_LOG_INFO is 4, but can't be resolved at runtime.
|
// ANDROID_LOG_INFO is 4, but can't be resolved at runtime.
|
||||||
#define SANITIZER_ANDROID_LOG_INFO 4
|
#define SANITIZER_ANDROID_LOG_INFO 4
|
||||||
|
@ -742,8 +747,8 @@ void WriteOneLineToSyslog(const char *s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
extern "C" SANITIZER_WEAK_ATTRIBUTE void android_set_abort_message(
|
||||||
void android_set_abort_message(const char *);
|
const char *);
|
||||||
|
|
||||||
void SetAbortMessage(const char *str) {
|
void SetAbortMessage(const char *str) {
|
||||||
if (&android_set_abort_message)
|
if (&android_set_abort_message)
|
||||||
|
@ -784,8 +789,8 @@ inline bool CanUseVDSO() {
|
||||||
// MonotonicNanoTime is a timing function that can leverage the vDSO by calling
|
// MonotonicNanoTime is a timing function that can leverage the vDSO by calling
|
||||||
// clock_gettime. real_clock_gettime only exists if clock_gettime is
|
// clock_gettime. real_clock_gettime only exists if clock_gettime is
|
||||||
// intercepted, so define it weakly and use it if available.
|
// intercepted, so define it weakly and use it if available.
|
||||||
extern "C" SANITIZER_WEAK_ATTRIBUTE
|
extern "C" SANITIZER_WEAK_ATTRIBUTE int real_clock_gettime(u32 clk_id,
|
||||||
int real_clock_gettime(u32 clk_id, void *tp);
|
void *tp);
|
||||||
u64 MonotonicNanoTime() {
|
u64 MonotonicNanoTime() {
|
||||||
timespec ts;
|
timespec ts;
|
||||||
if (CanUseVDSO()) {
|
if (CanUseVDSO()) {
|
||||||
|
|
Loading…
Reference in New Issue