Add support for lsan (Leak Sanitizer), crashes on exit, but works from gdb...
This commit is contained in:
parent
748fe90b99
commit
92d3d99452
@ -20,7 +20,7 @@
|
||||
#include "sanitizer_common/sanitizer_stoptheworld.h"
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
|
||||
#if (SANITIZER_LINUX && !SANITIZER_ANDROID) && (SANITIZER_WORDSIZE == 64) \
|
||||
#if (SANITIZER_NETBSD || SANITIZER_LINUX) && !SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 64) \
|
||||
&& (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__))
|
||||
#define CAN_SANITIZE_LEAKS 1
|
||||
#else
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#include "lsan_common.h"
|
||||
|
||||
#if CAN_SANITIZE_LEAKS && SANITIZER_LINUX
|
||||
#if CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD)
|
||||
#include <link.h>
|
||||
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
@ -174,4 +174,4 @@ void DoStopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
#endif // CAN_SANITIZE_LEAKS && SANITIZER_LINUX
|
||||
#endif // CAN_SANITIZE_LEAKS && (SANITIZER_LINUX || SANITIZER_NETBSD)
|
||||
|
@ -633,6 +633,16 @@ int internal_fork() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SANITIZER_NETBSD
|
||||
#include <signal.h>
|
||||
extern "C" int __sigaction14(int, const struct sigaction *, struct sigaction *);
|
||||
int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
|
||||
|
||||
return __sigaction14(signum,
|
||||
reinterpret_cast<const struct sigaction *>(act),
|
||||
reinterpret_cast<struct sigaction *>(oldact));
|
||||
}
|
||||
#endif
|
||||
#if SANITIZER_LINUX
|
||||
#define SA_RESTORER 0x04000000
|
||||
// Doesn't set sa_restorer, use with caution (see below).
|
||||
|
@ -48,6 +48,15 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
|
||||
#endif
|
||||
#endif // SANITIZER_LINUX
|
||||
|
||||
#ifdef SANITIZER_NETBSD
|
||||
int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
|
||||
#define internal_sigdelset(set, signum) \
|
||||
__sigdelset(set, signum)
|
||||
#define internal_clone(fn, child_stack, flags, arg, \
|
||||
parent_tidptr, newtls, child_tidptr) \
|
||||
__clone(fn, child_stack, flags, arg)
|
||||
#endif
|
||||
|
||||
// This class reads thread IDs from /proc/<pid>/task using only syscalls.
|
||||
class ThreadLister {
|
||||
public:
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
#include "sanitizer_platform.h"
|
||||
|
||||
#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \
|
||||
defined(__aarch64__))
|
||||
#if (SANITIZER_NETBSD || SANITIZER_LINUX) && \
|
||||
(defined(__x86_64__) || defined(__mips__) || defined(__aarch64__))
|
||||
|
||||
#include "sanitizer_stoptheworld.h"
|
||||
|
||||
@ -23,7 +23,10 @@
|
||||
#include <errno.h>
|
||||
#include <sched.h> // for CLONE_* definitions
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#if SANITIZER_LINUX
|
||||
#include <sys/prctl.h> // for PR_* definitions
|
||||
#endif
|
||||
#include <sys/ptrace.h> // for PTRACE_* definitions
|
||||
#include <sys/types.h> // for pid_t
|
||||
#include <sys/uio.h> // for iovec
|
||||
@ -35,7 +38,19 @@
|
||||
// GLIBC 2.20+ sys/user does not include asm/ptrace.h
|
||||
# include <asm/ptrace.h>
|
||||
# endif
|
||||
# include <sys/user.h> // for user_regs_struct
|
||||
# if !SANITIZER_NETBSD
|
||||
# include <sys/user.h> // for user_regs_struct
|
||||
# else
|
||||
# define PTRACE_ATTACH PT_ATTACH
|
||||
# define PTRACE_GETREGS PT_GETREGS
|
||||
# define PTRACE_KILL PT_KILL
|
||||
# define PTRACE_DETACH PT_DETACH
|
||||
# define PTRACE_CONT PT_CONTINUE
|
||||
# define CLONE_UNTRACED 0
|
||||
# include <machine/reg.h>
|
||||
typedef struct reg user_regs;
|
||||
typedef struct reg user_regs_struct;
|
||||
# endif
|
||||
#endif
|
||||
#include <sys/wait.h> // for signal-related stuff
|
||||
|
||||
@ -250,7 +265,9 @@ static int TracerThread(void* argument) {
|
||||
TracerThreadArgument *tracer_thread_argument =
|
||||
(TracerThreadArgument *)argument;
|
||||
|
||||
#ifdef PR_SET_PDEADTHSIG
|
||||
internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
|
||||
#endif
|
||||
// Check if parent is already dead.
|
||||
if (internal_getppid() != tracer_thread_argument->parent_pid)
|
||||
internal__exit(4);
|
||||
@ -333,15 +350,19 @@ class StopTheWorldScope {
|
||||
StopTheWorldScope() {
|
||||
// Make this process dumpable. Processes that are not dumpable cannot be
|
||||
// attached to.
|
||||
#ifdef PR_GET_DUMPABLE
|
||||
process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
|
||||
if (!process_was_dumpable_)
|
||||
internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
~StopTheWorldScope() {
|
||||
#ifdef PR_GET_DUMPABLE
|
||||
// Restore the dumpable flag.
|
||||
if (!process_was_dumpable_)
|
||||
internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@ -443,38 +464,39 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
|
||||
}
|
||||
|
||||
// Platform-specific methods from SuspendedThreadsList.
|
||||
#if SANITIZER_ANDROID && defined(__arm__)
|
||||
#if SANITIZER_ANDROID
|
||||
# if defined(__arm__)
|
||||
typedef pt_regs regs_struct;
|
||||
#define REG_SP ARM_sp
|
||||
|
||||
#elif SANITIZER_LINUX && defined(__arm__)
|
||||
# define PTRACE_REG_SP(r) (r)->ARM_sp
|
||||
# endif
|
||||
#elif SANITIZER_LINUX
|
||||
# if defined(__arm__)
|
||||
typedef user_regs regs_struct;
|
||||
#define REG_SP uregs[13]
|
||||
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
# define PTRACE_REG_SP(r) (r)->uregs[13]
|
||||
# elif defined(__i386__)
|
||||
typedef user_regs_struct regs_struct;
|
||||
#if defined(__i386__)
|
||||
#define REG_SP esp
|
||||
#else
|
||||
#define REG_SP rsp
|
||||
# define PTRACE_REG_SP(r) (r)->esp
|
||||
# elif defined(__x86_64__)
|
||||
typedef user_regs_struct regs_struct;
|
||||
# define PTRACE_REG_SP(r) (r)->rsp
|
||||
# elif defined(__powerpc__) || defined(__powerpc64__)
|
||||
typedef pt_regs regs_struct;
|
||||
# define PTRACE_REG_SP(r) (r)->gpr[PT_R1]
|
||||
# elif defined(__mips__)
|
||||
typedef struct user regs_struct;
|
||||
# define PTRACE_REG_SP(r) (r)->regs[EF_REG29]
|
||||
# elif defined(__aarch64__)
|
||||
typedef struct user_pt_regs regs_struct;
|
||||
# define PTRACE_REG_SP(r) (r)->sp
|
||||
# define ARCH_IOVEC_FOR_GETREGSET
|
||||
# endif
|
||||
#elif SANITIZER_NETBSD
|
||||
typedef reg regs_struct;
|
||||
#endif
|
||||
|
||||
#elif defined(__powerpc__) || defined(__powerpc64__)
|
||||
typedef pt_regs regs_struct;
|
||||
#define REG_SP gpr[PT_R1]
|
||||
|
||||
#elif defined(__mips__)
|
||||
typedef struct user regs_struct;
|
||||
#define REG_SP regs[EF_REG29]
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
typedef struct user_pt_regs regs_struct;
|
||||
#define REG_SP sp
|
||||
#define ARCH_IOVEC_FOR_GETREGSET
|
||||
|
||||
#else
|
||||
#ifndef PTRACE_REG_SP
|
||||
#error "Unsupported architecture"
|
||||
#endif // SANITIZER_ANDROID && defined(__arm__)
|
||||
#endif
|
||||
|
||||
int SuspendedThreadsList::GetRegistersAndSP(uptr index,
|
||||
uptr *buffer,
|
||||
@ -499,7 +521,7 @@ int SuspendedThreadsList::GetRegistersAndSP(uptr index,
|
||||
return -1;
|
||||
}
|
||||
|
||||
*sp = regs.REG_SP;
|
||||
*sp = PTRACE_REG_SP(®s);
|
||||
internal_memcpy(buffer, ®s, sizeof(regs));
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user