1705e310b98e85f893a69bccad1a9c066e2f4c277Peter Collingbourne//===-- sanitizer_stoptheworld_linux_libcdep.cc ---------------------------===//
23614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
33614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//                     The LLVM Compiler Infrastructure
43614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
53614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// This file is distributed under the University of Illinois Open Source
63614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// License. See LICENSE.TXT for details.
73614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
83614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//===----------------------------------------------------------------------===//
93614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
103614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// See sanitizer_stoptheworld.h for details.
113614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// This implementation was inspired by Markus Gutschke's linuxthreads.cc.
123614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
133614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//===----------------------------------------------------------------------===//
143614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h"
17cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev#if SANITIZER_LINUX && defined(__x86_64__)
183614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
193614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include "sanitizer_stoptheworld.h"
203614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
215f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov#include "sanitizer_platform_limits_posix.h"
225f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov
233614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <errno.h>
24cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev#include <sched.h> // for CLONE_* definitions
253614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <stddef.h>
263614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <sys/prctl.h> // for PR_* definitions
273614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <sys/ptrace.h> // for PTRACE_* definitions
283614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <sys/types.h> // for pid_t
29115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#if SANITIZER_ANDROID && defined(__arm__)
30bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov# include <linux/user.h>  // for pt_regs
31bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov#else
32bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov# include <sys/user.h>  // for user_regs_struct
33bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov#endif
343614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include <sys/wait.h> // for signal-related stuff
353614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
365f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov#ifdef sa_handler
375f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov# undef sa_handler
385f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov#endif
395f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov
405f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov#ifdef sa_sigaction
415f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov# undef sa_sigaction
425f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov#endif
435f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov
443614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include "sanitizer_common.h"
458f4cece84c528071202daae54593981e7677dcf9Dmitry Vyukov#include "sanitizer_flags.h"
463614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include "sanitizer_libc.h"
473614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include "sanitizer_linux.h"
483614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#include "sanitizer_mutex.h"
4949960be4dd7c038b26784cee046cc6637e32dc57Dmitry Vyukov#include "sanitizer_placement_new.h"
503614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
513614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// This module works by spawning a Linux task which then attaches to every
523614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// thread in the caller process with ptrace. This suspends the threads, and
533614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// PTRACE_GETREGS can then be used to obtain their register state. The callback
543614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// supplied to StopTheWorld() is run in the tracer task while the threads are
553614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// suspended.
563614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// The tracer task must be placed in a different thread group for ptrace to
573614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// work, so it cannot be spawned as a pthread. Instead, we use the low-level
583614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// clone() interface (we want to share the address space with the caller
593614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// process, so we prefer clone() over fork()).
603614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko//
612191fcaa9658166c0c6e9c91013fefc015741395Sergey Matveev// We don't use any libc functions, relying instead on direct syscalls. There
622191fcaa9658166c0c6e9c91013fefc015741395Sergey Matveev// are two reasons for this:
633614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// 1. calling a library function while threads are suspended could cause a
643614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// deadlock, if one of the treads happens to be holding a libc lock;
653614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// 2. it's generally not safe to call libc functions from the tracer task,
663614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// because clone() does not set up a thread-local storage for it. Any
673614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// thread-local variables used by libc will be shared between the tracer task
683614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// and the thread which spawned it.
693614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
703614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander PotapenkoCOMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t));
713614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
723614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkonamespace __sanitizer {
733614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// This class handles thread suspending/unsuspending in the tracer thread.
743614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkoclass ThreadSuspender {
753614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko public:
763614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  explicit ThreadSuspender(pid_t pid)
773614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    : pid_(pid) {
783614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      CHECK_GE(pid, 0);
793614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    }
803614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  bool SuspendAllThreads();
813614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  void ResumeAllThreads();
823614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  void KillAllThreads();
833614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  SuspendedThreadsList &suspended_threads_list() {
843614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    return suspended_threads_list_;
853614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
863614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko private:
873614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  SuspendedThreadsList suspended_threads_list_;
883614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  pid_t pid_;
893614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  bool SuspendThread(SuspendedThreadID thread_id);
903614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko};
913614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
923614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkobool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) {
933614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Are we already attached to this thread?
943614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Currently this check takes linear time, however the number of threads is
953614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // usually small.
963614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  if (suspended_threads_list_.Contains(thread_id))
973614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    return false;
989578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int pterrno;
999578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL),
1009578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                       &pterrno)) {
1013614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // Either the thread is dead, or something prevented us from attaching.
1023614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // Log this event and move on.
1032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    VReport(1, "Could not attach to thread %d (errno %d).\n", thread_id,
1042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            pterrno);
1053614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    return false;
1063614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  } else {
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    VReport(1, "Attached to thread %d.\n", thread_id);
1083614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // The thread is not guaranteed to stop before ptrace returns, so we must
1093614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // wait on it.
1109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    uptr waitpid_status;
1113614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL));
1129578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    int wperrno;
1139578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    if (internal_iserror(waitpid_status, &wperrno)) {
1143614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // Got a ECHILD error. I don't think this situation is possible, but it
1153614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // doesn't hurt to report it.
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      VReport(1, "Waiting on thread %d failed, detaching (errno %d).\n",
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines              thread_id, wperrno);
1183614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL);
1193614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      return false;
1203614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    }
1213614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    suspended_threads_list_.Append(thread_id);
1223614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    return true;
1233614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
1243614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
1253614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1263614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkovoid ThreadSuspender::ResumeAllThreads() {
1273614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) {
1283614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    pid_t tid = suspended_threads_list_.GetThreadID(i);
1299578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    int pterrno;
1309578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL),
1319578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                          &pterrno)) {
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      VReport(1, "Detached from thread %d.\n", tid);
1333614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    } else {
1343614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // Either the thread is dead, or we are already detached.
1353614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // The latter case is possible, for instance, if this function was called
1363614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // from a signal handler.
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      VReport(1, "Could not detach from thread %d (errno %d).\n", tid, pterrno);
1383614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    }
1393614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
1403614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
1413614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1423614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkovoid ThreadSuspender::KillAllThreads() {
1433614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++)
1443614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i),
1453614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko                    NULL, NULL);
1463614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
1473614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1483614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkobool ThreadSuspender::SuspendAllThreads() {
14910f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov  ThreadLister thread_lister(pid_);
1503614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  bool added_threads;
1513614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  do {
1523614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // Run through the directory entries once.
1533614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    added_threads = false;
15410f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    pid_t tid = thread_lister.GetNextTID();
1553614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    while (tid >= 0) {
1563614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      if (SuspendThread(tid))
1573614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko        added_threads = true;
15810f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov      tid = thread_lister.GetNextTID();
1593614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    }
16010f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    if (thread_lister.error()) {
1613614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      // Detach threads and fail.
1623614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      ResumeAllThreads();
1633614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      return false;
1643614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    }
16510f3ab775088bec69dd9e7b611f9b4e152f629bcAlexey Samsonov    thread_lister.Reset();
1663614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  } while (added_threads);
1673614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  return true;
1683614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
1693614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1703614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// Pointer to the ThreadSuspender instance for use in signal handler.
1713614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkostatic ThreadSuspender *thread_suspender_instance = NULL;
1723614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1733614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// Signals that should not be blocked (this is used in the parent thread as well
1743614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// as the tracer thread).
1753614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkostatic const int kUnblockedSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV,
1763614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko                                         SIGBUS, SIGXCPU, SIGXFSZ };
1773614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
1783614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// Structure for passing arguments into the tracer thread.
1793614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkostruct TracerThreadArgument {
1803614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  StopTheWorldCallback callback;
1813614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  void *callback_argument;
182d41fa1b7f2afe5dd78cd4e635e16fd5f079b0318Sergey Matveev  // The tracer thread waits on this mutex while the parent finishes its
1836d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  // preparations.
1846d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  BlockingMutex mutex;
185d41fa1b7f2afe5dd78cd4e635e16fd5f079b0318Sergey Matveev  uptr parent_pid;
1863614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko};
1873614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
18890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevstatic DieCallbackType old_die_callback;
18990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev
1903614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// Signal handler to wake up suspended threads when the tracer thread dies.
1915f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukovvoid TracerThreadSignalHandler(int signum, void *siginfo, void *) {
1923614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  if (thread_suspender_instance != NULL) {
1933614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    if (signum == SIGABRT)
1943614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      thread_suspender_instance->KillAllThreads();
1953614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    else
1963614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      thread_suspender_instance->ResumeAllThreads();
1973614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
1983614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  internal__exit((signum == SIGABRT) ? 1 : 2);
1993614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
2003614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
20190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevstatic void TracerThreadDieCallback() {
20290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // Generally a call to Die() in the tracer thread should be fatal to the
20390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // parent process as well, because they share the address space.
20490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // This really only works correctly if all the threads are suspended at this
20590629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // point. So we correctly handle calls to Die() from within the callback, but
20690629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // not those that happen before or after the callback. Hopefully there aren't
20790629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  // a lot of opportunities for that to happen...
20890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  if (thread_suspender_instance)
20990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    thread_suspender_instance->KillAllThreads();
21090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  if (old_die_callback)
21190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    old_die_callback();
21290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev}
21390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev
2143614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// Size of alternative stack for signal handlers in the tracer thread.
2153614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenkostatic const int kHandlerStackSize = 4096;
2163614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
2173614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko// This function will be run as a cloned task.
2186d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonovstatic int TracerThread(void* argument) {
2193614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  TracerThreadArgument *tracer_thread_argument =
2203614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko      (TracerThreadArgument *)argument;
2213614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
22223a7a43da615bceedefe42b8398b82939e6eeb2dSergey Matveev  internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
22323a7a43da615bceedefe42b8398b82939e6eeb2dSergey Matveev  // Check if parent is already dead.
224d41fa1b7f2afe5dd78cd4e635e16fd5f079b0318Sergey Matveev  if (internal_getppid() != tracer_thread_argument->parent_pid)
22523a7a43da615bceedefe42b8398b82939e6eeb2dSergey Matveev    internal__exit(4);
22623a7a43da615bceedefe42b8398b82939e6eeb2dSergey Matveev
2273614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Wait for the parent thread to finish preparations.
2286d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  tracer_thread_argument->mutex.Lock();
2296d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  tracer_thread_argument->mutex.Unlock();
2303614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
23190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  SetDieCallback(TracerThreadDieCallback);
23290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev
2333614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  ThreadSuspender thread_suspender(internal_getppid());
2343614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Global pointer for the signal handler.
2353614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  thread_suspender_instance = &thread_suspender;
2363614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
2373614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Alternate stack for signal handling.
2383614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize);
2393614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  struct sigaltstack handler_stack;
2403614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  internal_memset(&handler_stack, 0, sizeof(handler_stack));
2413614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  handler_stack.ss_sp = handler_stack_memory.data();
2423614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  handler_stack.ss_size = kHandlerStackSize;
2433614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  internal_sigaltstack(&handler_stack, NULL);
2443614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
2453614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Install our handler for fatal signals. Other signals should be blocked by
2463614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // the mask we inherited from the caller thread.
2473614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
2483614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko       signal_index++) {
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    __sanitizer_sigaction new_sigaction;
2503614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
2510f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov    new_sigaction.sigaction = TracerThreadSignalHandler;
2523614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO;
2530f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov    internal_sigfillset(&new_sigaction.sa_mask);
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    internal_sigaction_norestorer(kUnblockedSignals[signal_index],
2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                  &new_sigaction, NULL);
2563614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
2573614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
2583614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  int exit_code = 0;
2593614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  if (!thread_suspender.SuspendAllThreads()) {
2602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    VReport(1, "Failed suspending threads.\n");
2613614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    exit_code = 3;
2623614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  } else {
2633614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
2643614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko                                     tracer_thread_argument->callback_argument);
2653614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    thread_suspender.ResumeAllThreads();
2663614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    exit_code = 0;
2673614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
2683614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  thread_suspender_instance = NULL;
2693614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  handler_stack.ss_flags = SS_DISABLE;
2703614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  internal_sigaltstack(&handler_stack, NULL);
2713614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  return exit_code;
2723614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
2733614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
274fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenkoclass ScopedStackSpaceWithGuard {
275fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko public:
276fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  explicit ScopedStackSpaceWithGuard(uptr stack_size) {
277fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    stack_size_ = stack_size;
278fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    guard_size_ = GetPageSizeCached();
279fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    // FIXME: Omitting MAP_STACK here works in current kernels but might break
280fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    // in the future.
281fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_,
282fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko                                   "ScopedStackWithGuard");
283fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    CHECK_EQ(guard_start_, (uptr)Mprotect((uptr)guard_start_, guard_size_));
284fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  }
285fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  ~ScopedStackSpaceWithGuard() {
286fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_);
287fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  }
288fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  void *Bottom() const {
289fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko    return (void *)(guard_start_ + stack_size_ + guard_size_);
290fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  }
291fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko
292fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko private:
293fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  uptr stack_size_;
294fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  uptr guard_size_;
295fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  uptr guard_start_;
296fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko};
297fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko
29890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev// We have a limitation on the stack frame size, so some stuff had to be moved
29990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev// into globals.
3002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic __sanitizer_sigset_t blocked_sigset;
3012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic __sanitizer_sigset_t old_sigset;
3022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic __sanitizer_sigaction old_sigactions
3035f4984db88b7b67539f62d7653b928aeadf91b16Dmitry Vyukov    [ARRAY_SIZE(kUnblockedSignals)];
30449960be4dd7c038b26784cee046cc6637e32dc57Dmitry Vyukov
30590629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevclass StopTheWorldScope {
30690629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev public:
30790629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  StopTheWorldScope() {
308c154820b43052cfc54ee20752a3232aa8e6c7843Alexey Samsonov    // Block all signals that can be blocked safely, and install
309c154820b43052cfc54ee20752a3232aa8e6c7843Alexey Samsonov    // default handlers for the remaining signals.
31090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // We cannot allow user-defined handlers to run while the ThreadSuspender
31190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // thread is active, because they could conceivably call some libc functions
31290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // which modify errno (which is shared between the two threads).
3130f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov    internal_sigfillset(&blocked_sigset);
31490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
31590629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev         signal_index++) {
31690629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev      // Remove the signal from the set of blocked signals.
3170f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov      internal_sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]);
31890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev      // Install the default handler.
3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      __sanitizer_sigaction new_sigaction;
32090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev      internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
3210f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov      new_sigaction.handler = SIG_DFL;
3220f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov      internal_sigfillset(&new_sigaction.sa_mask);
3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      internal_sigaction_norestorer(kUnblockedSignals[signal_index],
3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          &new_sigaction, &old_sigactions[signal_index]);
32590629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    }
32690629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    int sigprocmask_status =
3270f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov        internal_sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
32890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail
32990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // Make this process dumpable. Processes that are not dumpable cannot be
33090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // attached to.
33190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
33290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    if (!process_was_dumpable_)
33390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev      internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
33490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    old_die_callback = GetDieCallback();
33590629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  }
33690629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev
33790629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  ~StopTheWorldScope() {
33890629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    SetDieCallback(old_die_callback);
33990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // Restore the dumpable flag.
34090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    if (!process_was_dumpable_)
34190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev      internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
34290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    // Restore the signal handlers.
34390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
34490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev         signal_index++) {
3452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      internal_sigaction_norestorer(kUnblockedSignals[signal_index],
3462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                    &old_sigactions[signal_index], NULL);
34790629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev    }
3480f7a2acb3326a5900d1a1339ebf959b14b372e0dDmitry Vyukov    internal_sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset);
3493614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
350c154820b43052cfc54ee20752a3232aa8e6c7843Alexey Samsonov
35190629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev private:
35290629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  int process_was_dumpable_;
35390629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev};
35490629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev
3552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// When sanitizer output is being redirected to file (i.e. by using log_path),
3562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// the tracer should write to the parent's log instead of trying to open a new
3572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// file. Alert the logging code to the fact that we have a tracer.
3582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct ScopedSetTracerPID {
3592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  explicit ScopedSetTracerPID(uptr tracer_pid) {
3602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stoptheworld_tracer_pid = tracer_pid;
3612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stoptheworld_tracer_ppid = internal_getpid();
3622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
3632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ~ScopedSetTracerPID() {
3642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stoptheworld_tracer_pid = 0;
3652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stoptheworld_tracer_ppid = 0;
3662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
3672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
3682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
36990629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveevvoid StopTheWorld(StopTheWorldCallback callback, void *argument) {
37090629fb8072efc95e46a0cbc641293511fbaba2eSergey Matveev  StopTheWorldScope in_stoptheworld;
3713614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  // Prepare the arguments for TracerThread.
3723614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  struct TracerThreadArgument tracer_thread_argument;
3733614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  tracer_thread_argument.callback = callback;
3743614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  tracer_thread_argument.callback_argument = argument;
375d41fa1b7f2afe5dd78cd4e635e16fd5f079b0318Sergey Matveev  tracer_thread_argument.parent_pid = internal_getpid();
376fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  const uptr kTracerStackSize = 2 * 1024 * 1024;
377fd8726cae237495a8f63d12e6e026290fd5f4787Alexander Potapenko  ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize);
3786d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  // Block the execution of TracerThread until after we have set ptrace
3796d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  // permissions.
3806d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov  tracer_thread_argument.mutex.Lock();
381cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  uptr tracer_pid = internal_clone(
382cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev      TracerThread, tracer_stack.Bottom(),
383cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
384cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev      &tracer_thread_argument, 0 /* parent_tidptr */, 0 /* newtls */, 0
385cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev      /* child_tidptr */);
386cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  int local_errno = 0;
387cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev  if (internal_iserror(tracer_pid, &local_errno)) {
3882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    VReport(1, "Failed spawning a tracer thread (errno %d).\n", local_errno);
3896d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov    tracer_thread_argument.mutex.Unlock();
3903614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  } else {
3912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ScopedSetTracerPID scoped_set_tracer_pid(tracer_pid);
3923614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // On some systems we have to explicitly declare that we want to be traced
3933614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // by the tracer thread.
3943614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#ifdef PR_SET_PTRACER
3953614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
3963614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko#endif
3973614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // Allow the tracer thread to start.
3986d036065e2ba85d9ad2a141596693b026f7ebbccAlexey Samsonov    tracer_thread_argument.mutex.Unlock();
3993614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // Since errno is shared between this thread and the tracer thread, we
4003614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // must avoid using errno while the tracer thread is running.
4013614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // At this point, any signal will either be blocked or kill us, so waitpid
4023614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko    // should never return (and set errno) while the tracer thread is alive.
4039578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
4042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (internal_iserror(waitpid_status, &local_errno))
4052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      VReport(1, "Waiting on the tracer thread failed (errno %d).\n",
4062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines              local_errno);
4073614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko  }
4083614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}
4093614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
41053c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko// Platform-specific methods from SuspendedThreadsList.
411115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#if SANITIZER_ANDROID && defined(__arm__)
412bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonovtypedef pt_regs regs_struct;
413115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#define REG_SP ARM_sp
414115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev
415115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#elif SANITIZER_LINUX && defined(__arm__)
416115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveevtypedef user_regs regs_struct;
417115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#define REG_SP uregs[13]
418115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev
419115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#elif defined(__i386__) || defined(__x86_64__)
420bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonovtypedef user_regs_struct regs_struct;
421115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#if defined(__i386__)
422115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#define REG_SP esp
423115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#else
424115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#define REG_SP rsp
425bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov#endif
426bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov
427f931da85ce8668751628ded926ecad013c5d6f1aKostya Serebryany#elif defined(__powerpc__) || defined(__powerpc64__)
428f931da85ce8668751628ded926ecad013c5d6f1aKostya Serebryanytypedef pt_regs regs_struct;
429f931da85ce8668751628ded926ecad013c5d6f1aKostya Serebryany#define REG_SP gpr[PT_R1]
430f931da85ce8668751628ded926ecad013c5d6f1aKostya Serebryany
43140527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany#elif defined(__mips__)
43240527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryanytypedef struct user regs_struct;
43340527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany#define REG_SP regs[EF_REG29]
43440527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany
435115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#else
436115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#error "Unsupported architecture"
437115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev#endif // SANITIZER_ANDROID && defined(__arm__)
438115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev
43953c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenkoint SuspendedThreadsList::GetRegistersAndSP(uptr index,
44053c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko                                            uptr *buffer,
44153c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko                                            uptr *sp) const {
44253c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko  pid_t tid = GetThreadID(index);
443bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov  regs_struct regs;
4449578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  int pterrno;
4459578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne  if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, &regs),
4469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne                       &pterrno)) {
4472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    VReport(1, "Could not get registers from thread %d (errno %d).\n", tid,
4482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            pterrno);
44953c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko    return -1;
45053c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko  }
451115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev
452115accb935dc1464d78e041d2aaf571044dfdc60Sergey Matveev  *sp = regs.REG_SP;
45353c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko  internal_memcpy(buffer, &regs, sizeof(regs));
45453c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko  return 0;
45553c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko}
45653c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko
45753c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenkouptr SuspendedThreadsList::RegisterCount() {
458bb090b56ca283396f17b9a3ef2e8f00544a21385Alexey Samsonov  return sizeof(regs_struct) / sizeof(uptr);
45953c18d7e051c7dfe3cc8a2351e6ee67a264dbb51Alexander Potapenko}
4603614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko}  // namespace __sanitizer
4613614c16084e8a0dc8ae3418402a2d0c6f8107e39Alexander Potapenko
462cb339108cca40fb4c1ed520656cb6cb75889a237Sergey Matveev#endif  // SANITIZER_LINUX && defined(__x86_64__)
463