180814287SRaphael Isemann //===-- NativeProcessLinux.cpp --------------------------------------------===//
2af245d11STodd Fiala //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6af245d11STodd Fiala //
7af245d11STodd Fiala //===----------------------------------------------------------------------===//
8af245d11STodd Fiala 
9af245d11STodd Fiala #include "NativeProcessLinux.h"
10af245d11STodd Fiala 
11af245d11STodd Fiala #include <errno.h>
12af245d11STodd Fiala #include <stdint.h>
13b9c1b51eSKate Stone #include <string.h>
14af245d11STodd Fiala #include <unistd.h>
15af245d11STodd Fiala 
16af245d11STodd Fiala #include <fstream>
17df7c6995SPavel Labath #include <mutex>
18c076559aSPavel Labath #include <sstream>
19af245d11STodd Fiala #include <string>
205b981ab9SPavel Labath #include <unordered_map>
21af245d11STodd Fiala 
222c4226f8SPavel Labath #include "NativeThreadLinux.h"
232c4226f8SPavel Labath #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
242c4226f8SPavel Labath #include "Plugins/Process/Utility/LinuxProcMaps.h"
252c4226f8SPavel Labath #include "Procfs.h"
266edef204SOleksiy Vyalov #include "lldb/Core/ModuleSpec.h"
27af245d11STodd Fiala #include "lldb/Host/Host.h"
285ad891f7SPavel Labath #include "lldb/Host/HostProcess.h"
29eef758e9SPavel Labath #include "lldb/Host/ProcessLaunchInfo.h"
3024ae6294SZachary Turner #include "lldb/Host/PseudoTerminal.h"
3139de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
322a86b555SPavel Labath #include "lldb/Host/common/NativeRegisterContext.h"
334ee1c952SPavel Labath #include "lldb/Host/linux/Ptrace.h"
344ee1c952SPavel Labath #include "lldb/Host/linux/Uio.h"
35816ae4b0SKamil Rytarowski #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
362a86b555SPavel Labath #include "lldb/Symbol/ObjectFile.h"
3790aff47cSZachary Turner #include "lldb/Target/Process.h"
385b981ab9SPavel Labath #include "lldb/Target/Target.h"
39c16f5dcaSChaoren Lin #include "lldb/Utility/LLDBAssert.h"
40d821c997SPavel Labath #include "lldb/Utility/State.h"
4197206d57SZachary Turner #include "lldb/Utility/Status.h"
42f805e190SPavel Labath #include "lldb/Utility/StringExtractor.h"
432c4226f8SPavel Labath #include "llvm/ADT/ScopeExit.h"
4410c41f37SPavel Labath #include "llvm/Support/Errno.h"
4510c41f37SPavel Labath #include "llvm/Support/FileSystem.h"
4610c41f37SPavel Labath #include "llvm/Support/Threading.h"
47af245d11STodd Fiala 
48d858487eSTamas Berghammer #include <linux/unistd.h>
49d858487eSTamas Berghammer #include <sys/socket.h>
50df7c6995SPavel Labath #include <sys/syscall.h>
51d858487eSTamas Berghammer #include <sys/types.h>
52d858487eSTamas Berghammer #include <sys/user.h>
53d858487eSTamas Berghammer #include <sys/wait.h>
54d858487eSTamas Berghammer 
55af245d11STodd Fiala // Support hardware breakpoints in case it has not been defined
56af245d11STodd Fiala #ifndef TRAP_HWBKPT
57af245d11STodd Fiala #define TRAP_HWBKPT 4
58af245d11STodd Fiala #endif
59af245d11STodd Fiala 
607cb18bf5STamas Berghammer using namespace lldb;
617cb18bf5STamas Berghammer using namespace lldb_private;
62db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
637cb18bf5STamas Berghammer using namespace llvm;
647cb18bf5STamas Berghammer 
65af245d11STodd Fiala // Private bits we only need internally.
66df7c6995SPavel Labath 
67b9c1b51eSKate Stone static bool ProcessVmReadvSupported() {
68df7c6995SPavel Labath   static bool is_supported;
69c5f28e2aSKamil Rytarowski   static llvm::once_flag flag;
70df7c6995SPavel Labath 
71c5f28e2aSKamil Rytarowski   llvm::call_once(flag, [] {
72a6321a8eSPavel Labath     Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
73df7c6995SPavel Labath 
74df7c6995SPavel Labath     uint32_t source = 0x47424742;
75df7c6995SPavel Labath     uint32_t dest = 0;
76df7c6995SPavel Labath 
77df7c6995SPavel Labath     struct iovec local, remote;
78df7c6995SPavel Labath     remote.iov_base = &source;
79df7c6995SPavel Labath     local.iov_base = &dest;
80df7c6995SPavel Labath     remote.iov_len = local.iov_len = sizeof source;
81df7c6995SPavel Labath 
82b9c1b51eSKate Stone     // We shall try if cross-process-memory reads work by attempting to read a
83b9c1b51eSKate Stone     // value from our own process.
84df7c6995SPavel Labath     ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0);
85df7c6995SPavel Labath     is_supported = (res == sizeof(source) && source == dest);
86df7c6995SPavel Labath     if (is_supported)
87a6321a8eSPavel Labath       LLDB_LOG(log,
88a6321a8eSPavel Labath                "Detected kernel support for process_vm_readv syscall. "
89a6321a8eSPavel Labath                "Fast memory reads enabled.");
90df7c6995SPavel Labath     else
91a6321a8eSPavel Labath       LLDB_LOG(log,
92a6321a8eSPavel Labath                "syscall process_vm_readv failed (error: {0}). Fast memory "
93a6321a8eSPavel Labath                "reads disabled.",
9410c41f37SPavel Labath                llvm::sys::StrError());
95df7c6995SPavel Labath   });
96df7c6995SPavel Labath 
97df7c6995SPavel Labath   return is_supported;
98df7c6995SPavel Labath }
99df7c6995SPavel Labath 
100b9c1b51eSKate Stone namespace {
101b9c1b51eSKate Stone void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) {
102a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1034abe5d69SPavel Labath   if (!log)
1044abe5d69SPavel Labath     return;
1054abe5d69SPavel Labath 
1064abe5d69SPavel Labath   if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO))
107a6321a8eSPavel Labath     LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec());
1084abe5d69SPavel Labath   else
109a6321a8eSPavel Labath     LLDB_LOG(log, "leaving STDIN as is");
1104abe5d69SPavel Labath 
1114abe5d69SPavel Labath   if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO))
112a6321a8eSPavel Labath     LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec());
1134abe5d69SPavel Labath   else
114a6321a8eSPavel Labath     LLDB_LOG(log, "leaving STDOUT as is");
1154abe5d69SPavel Labath 
1164abe5d69SPavel Labath   if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO))
117a6321a8eSPavel Labath     LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec());
1184abe5d69SPavel Labath   else
119a6321a8eSPavel Labath     LLDB_LOG(log, "leaving STDERR as is");
1204abe5d69SPavel Labath 
1214abe5d69SPavel Labath   int i = 0;
122b9c1b51eSKate Stone   for (const char **args = info.GetArguments().GetConstArgumentVector(); *args;
123b9c1b51eSKate Stone        ++args, ++i)
124a6321a8eSPavel Labath     LLDB_LOG(log, "arg {0}: '{1}'", i, *args);
1254abe5d69SPavel Labath }
1264abe5d69SPavel Labath 
127b9c1b51eSKate Stone void DisplayBytes(StreamString &s, void *bytes, uint32_t count) {
128af245d11STodd Fiala   uint8_t *ptr = (uint8_t *)bytes;
129af245d11STodd Fiala   const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count);
130b9c1b51eSKate Stone   for (uint32_t i = 0; i < loop_count; i++) {
131af245d11STodd Fiala     s.Printf("[%x]", *ptr);
132af245d11STodd Fiala     ptr++;
133af245d11STodd Fiala   }
134af245d11STodd Fiala }
135af245d11STodd Fiala 
136b9c1b51eSKate Stone void PtraceDisplayBytes(int &req, void *data, size_t data_size) {
137aafe053cSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
138a6321a8eSPavel Labath   if (!log)
139a6321a8eSPavel Labath     return;
140af245d11STodd Fiala   StreamString buf;
141af245d11STodd Fiala 
142b9c1b51eSKate Stone   switch (req) {
143b9c1b51eSKate Stone   case PTRACE_POKETEXT: {
144af245d11STodd Fiala     DisplayBytes(buf, &data, 8);
145aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData());
146af245d11STodd Fiala     break;
147af245d11STodd Fiala   }
148b9c1b51eSKate Stone   case PTRACE_POKEDATA: {
149af245d11STodd Fiala     DisplayBytes(buf, &data, 8);
150aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData());
151af245d11STodd Fiala     break;
152af245d11STodd Fiala   }
153b9c1b51eSKate Stone   case PTRACE_POKEUSER: {
154af245d11STodd Fiala     DisplayBytes(buf, &data, 8);
155aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData());
156af245d11STodd Fiala     break;
157af245d11STodd Fiala   }
158b9c1b51eSKate Stone   case PTRACE_SETREGS: {
159af245d11STodd Fiala     DisplayBytes(buf, data, data_size);
160aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData());
161af245d11STodd Fiala     break;
162af245d11STodd Fiala   }
163b9c1b51eSKate Stone   case PTRACE_SETFPREGS: {
164af245d11STodd Fiala     DisplayBytes(buf, data, data_size);
165aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData());
166af245d11STodd Fiala     break;
167af245d11STodd Fiala   }
168b9c1b51eSKate Stone   case PTRACE_SETSIGINFO: {
169af245d11STodd Fiala     DisplayBytes(buf, data, sizeof(siginfo_t));
170aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_SETSIGINFO {0}", buf.GetData());
171af245d11STodd Fiala     break;
172af245d11STodd Fiala   }
173b9c1b51eSKate Stone   case PTRACE_SETREGSET: {
17411edb4eeSPavel Labath     // Extract iov_base from data, which is a pointer to the struct iovec
175af245d11STodd Fiala     DisplayBytes(buf, *(void **)data, data_size);
176aafe053cSPavel Labath     LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData());
177af245d11STodd Fiala     break;
178af245d11STodd Fiala   }
179b9c1b51eSKate Stone   default: {}
180af245d11STodd Fiala   }
181af245d11STodd Fiala }
182af245d11STodd Fiala 
18319cbe96aSPavel Labath static constexpr unsigned k_ptrace_word_size = sizeof(void *);
184b9c1b51eSKate Stone static_assert(sizeof(long) >= k_ptrace_word_size,
185b9c1b51eSKate Stone               "Size of long must be larger than ptrace word size");
1861107b5a5SPavel Labath } // end of anonymous namespace
1871107b5a5SPavel Labath 
188bd7cbc5aSPavel Labath // Simple helper function to ensure flags are enabled on the given file
189bd7cbc5aSPavel Labath // descriptor.
19097206d57SZachary Turner static Status EnsureFDFlags(int fd, int flags) {
19197206d57SZachary Turner   Status error;
192bd7cbc5aSPavel Labath 
193bd7cbc5aSPavel Labath   int status = fcntl(fd, F_GETFL);
194b9c1b51eSKate Stone   if (status == -1) {
195bd7cbc5aSPavel Labath     error.SetErrorToErrno();
196bd7cbc5aSPavel Labath     return error;
197bd7cbc5aSPavel Labath   }
198bd7cbc5aSPavel Labath 
199b9c1b51eSKate Stone   if (fcntl(fd, F_SETFL, status | flags) == -1) {
200bd7cbc5aSPavel Labath     error.SetErrorToErrno();
201bd7cbc5aSPavel Labath     return error;
202bd7cbc5aSPavel Labath   }
203bd7cbc5aSPavel Labath 
204bd7cbc5aSPavel Labath   return error;
205bd7cbc5aSPavel Labath }
206bd7cbc5aSPavel Labath 
207af245d11STodd Fiala // Public Static Methods
208af245d11STodd Fiala 
20982abefa4SPavel Labath llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
21096e600fcSPavel Labath NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
21196e600fcSPavel Labath                                     NativeDelegate &native_delegate,
21296e600fcSPavel Labath                                     MainLoop &mainloop) const {
213a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
214af245d11STodd Fiala 
21596e600fcSPavel Labath   MaybeLogLaunchInfo(launch_info);
216af245d11STodd Fiala 
21796e600fcSPavel Labath   Status status;
21896e600fcSPavel Labath   ::pid_t pid = ProcessLauncherPosixFork()
21996e600fcSPavel Labath                     .LaunchProcess(launch_info, status)
22096e600fcSPavel Labath                     .GetProcessId();
22196e600fcSPavel Labath   LLDB_LOG(log, "pid = {0:x}", pid);
22296e600fcSPavel Labath   if (status.Fail()) {
22396e600fcSPavel Labath     LLDB_LOG(log, "failed to launch process: {0}", status);
22496e600fcSPavel Labath     return status.ToError();
225af245d11STodd Fiala   }
226af245d11STodd Fiala 
22796e600fcSPavel Labath   // Wait for the child process to trap on its call to execve.
22896e600fcSPavel Labath   int wstatus;
22996e600fcSPavel Labath   ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
23096e600fcSPavel Labath   assert(wpid == pid);
23196e600fcSPavel Labath   (void)wpid;
23296e600fcSPavel Labath   if (!WIFSTOPPED(wstatus)) {
23396e600fcSPavel Labath     LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
23496e600fcSPavel Labath              WaitStatus::Decode(wstatus));
23596e600fcSPavel Labath     return llvm::make_error<StringError>("Could not sync with inferior process",
23696e600fcSPavel Labath                                          llvm::inconvertibleErrorCode());
23796e600fcSPavel Labath   }
23896e600fcSPavel Labath   LLDB_LOG(log, "inferior started, now in stopped state");
239af245d11STodd Fiala 
24036e82208SPavel Labath   ProcessInstanceInfo Info;
24136e82208SPavel Labath   if (!Host::GetProcessInfo(pid, Info)) {
24236e82208SPavel Labath     return llvm::make_error<StringError>("Cannot get process architecture",
24336e82208SPavel Labath                                          llvm::inconvertibleErrorCode());
24436e82208SPavel Labath   }
24596e600fcSPavel Labath 
24696e600fcSPavel Labath   // Set the architecture to the exe architecture.
24796e600fcSPavel Labath   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
24836e82208SPavel Labath            Info.GetArchitecture().GetArchitectureName());
24996e600fcSPavel Labath 
25096e600fcSPavel Labath   status = SetDefaultPtraceOpts(pid);
25196e600fcSPavel Labath   if (status.Fail()) {
25296e600fcSPavel Labath     LLDB_LOG(log, "failed to set default ptrace options: {0}", status);
25396e600fcSPavel Labath     return status.ToError();
254af245d11STodd Fiala   }
255af245d11STodd Fiala 
25682abefa4SPavel Labath   return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
25764ec505dSJonas Devlieghere       pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
25836e82208SPavel Labath       Info.GetArchitecture(), mainloop, {pid}));
259af245d11STodd Fiala }
260af245d11STodd Fiala 
26182abefa4SPavel Labath llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
26282abefa4SPavel Labath NativeProcessLinux::Factory::Attach(
263b9c1b51eSKate Stone     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
26496e600fcSPavel Labath     MainLoop &mainloop) const {
265a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
266a6321a8eSPavel Labath   LLDB_LOG(log, "pid = {0:x}", pid);
267af245d11STodd Fiala 
268af245d11STodd Fiala   // Retrieve the architecture for the running process.
26936e82208SPavel Labath   ProcessInstanceInfo Info;
27036e82208SPavel Labath   if (!Host::GetProcessInfo(pid, Info)) {
27136e82208SPavel Labath     return llvm::make_error<StringError>("Cannot get process architecture",
27236e82208SPavel Labath                                          llvm::inconvertibleErrorCode());
27336e82208SPavel Labath   }
274af245d11STodd Fiala 
27596e600fcSPavel Labath   auto tids_or = NativeProcessLinux::Attach(pid);
27696e600fcSPavel Labath   if (!tids_or)
27796e600fcSPavel Labath     return tids_or.takeError();
278af245d11STodd Fiala 
27982abefa4SPavel Labath   return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
28036e82208SPavel Labath       pid, -1, native_delegate, Info.GetArchitecture(), mainloop, *tids_or));
281af245d11STodd Fiala }
282af245d11STodd Fiala 
283af245d11STodd Fiala // Public Instance Methods
284af245d11STodd Fiala 
28596e600fcSPavel Labath NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
28696e600fcSPavel Labath                                        NativeDelegate &delegate,
28782abefa4SPavel Labath                                        const ArchSpec &arch, MainLoop &mainloop,
28882abefa4SPavel Labath                                        llvm::ArrayRef<::pid_t> tids)
289*0b697561SWalter Erquinigo     : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
290*0b697561SWalter Erquinigo       m_intel_pt_manager(pid) {
291b9c1b51eSKate Stone   if (m_terminal_fd != -1) {
29296e600fcSPavel Labath     Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
29396e600fcSPavel Labath     assert(status.Success());
2945ad891f7SPavel Labath   }
295af245d11STodd Fiala 
29696e600fcSPavel Labath   Status status;
29796e600fcSPavel Labath   m_sigchld_handle = mainloop.RegisterSignal(
29896e600fcSPavel Labath       SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
29996e600fcSPavel Labath   assert(m_sigchld_handle && status.Success());
30096e600fcSPavel Labath 
30196e600fcSPavel Labath   for (const auto &tid : tids) {
302*0b697561SWalter Erquinigo     NativeThreadLinux &thread = AddThread(tid, /*resume*/ false);
303a5be48b3SPavel Labath     ThreadWasCreated(thread);
304af245d11STodd Fiala   }
305af245d11STodd Fiala 
30696e600fcSPavel Labath   // Let our process instance know the thread has stopped.
30796e600fcSPavel Labath   SetCurrentThreadID(tids[0]);
30896e600fcSPavel Labath   SetState(StateType::eStateStopped, false);
30996e600fcSPavel Labath 
31096e600fcSPavel Labath   // Proccess any signals we received before installing our handler
31196e600fcSPavel Labath   SigchldHandler();
31296e600fcSPavel Labath }
31396e600fcSPavel Labath 
31496e600fcSPavel Labath llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
315a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
316af245d11STodd Fiala 
31796e600fcSPavel Labath   Status status;
318b9c1b51eSKate Stone   // Use a map to keep track of the threads which we have attached/need to
319b9c1b51eSKate Stone   // attach.
320af245d11STodd Fiala   Host::TidMap tids_to_attach;
321b9c1b51eSKate Stone   while (Host::FindProcessThreads(pid, tids_to_attach)) {
322af245d11STodd Fiala     for (Host::TidMap::iterator it = tids_to_attach.begin();
323b9c1b51eSKate Stone          it != tids_to_attach.end();) {
324b9c1b51eSKate Stone       if (it->second == false) {
325af245d11STodd Fiala         lldb::tid_t tid = it->first;
326af245d11STodd Fiala 
327af245d11STodd Fiala         // Attach to the requested process.
328af245d11STodd Fiala         // An attach will cause the thread to stop with a SIGSTOP.
32996e600fcSPavel Labath         if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) {
33005097246SAdrian Prantl           // No such thread. The thread may have exited. More error handling
33105097246SAdrian Prantl           // may be needed.
33296e600fcSPavel Labath           if (status.GetError() == ESRCH) {
333af245d11STodd Fiala             it = tids_to_attach.erase(it);
334af245d11STodd Fiala             continue;
33596e600fcSPavel Labath           }
33696e600fcSPavel Labath           return status.ToError();
337af245d11STodd Fiala         }
338af245d11STodd Fiala 
33996e600fcSPavel Labath         int wpid =
34096e600fcSPavel Labath             llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
34105097246SAdrian Prantl         // Need to use __WALL otherwise we receive an error with errno=ECHLD At
34205097246SAdrian Prantl         // this point we should have a thread stopped if waitpid succeeds.
34396e600fcSPavel Labath         if (wpid < 0) {
34405097246SAdrian Prantl           // No such thread. The thread may have exited. More error handling
34505097246SAdrian Prantl           // may be needed.
346b9c1b51eSKate Stone           if (errno == ESRCH) {
347af245d11STodd Fiala             it = tids_to_attach.erase(it);
348af245d11STodd Fiala             continue;
349af245d11STodd Fiala           }
35096e600fcSPavel Labath           return llvm::errorCodeToError(
35196e600fcSPavel Labath               std::error_code(errno, std::generic_category()));
352af245d11STodd Fiala         }
353af245d11STodd Fiala 
35496e600fcSPavel Labath         if ((status = SetDefaultPtraceOpts(tid)).Fail())
35596e600fcSPavel Labath           return status.ToError();
356af245d11STodd Fiala 
357a6321a8eSPavel Labath         LLDB_LOG(log, "adding tid = {0}", tid);
358af245d11STodd Fiala         it->second = true;
359af245d11STodd Fiala       }
360af245d11STodd Fiala 
361af245d11STodd Fiala       // move the loop forward
362af245d11STodd Fiala       ++it;
363af245d11STodd Fiala     }
364af245d11STodd Fiala   }
365af245d11STodd Fiala 
36696e600fcSPavel Labath   size_t tid_count = tids_to_attach.size();
36796e600fcSPavel Labath   if (tid_count == 0)
36896e600fcSPavel Labath     return llvm::make_error<StringError>("No such process",
36996e600fcSPavel Labath                                          llvm::inconvertibleErrorCode());
370af245d11STodd Fiala 
37196e600fcSPavel Labath   std::vector<::pid_t> tids;
37296e600fcSPavel Labath   tids.reserve(tid_count);
37396e600fcSPavel Labath   for (const auto &p : tids_to_attach)
37496e600fcSPavel Labath     tids.push_back(p.first);
37596e600fcSPavel Labath   return std::move(tids);
376af245d11STodd Fiala }
377af245d11STodd Fiala 
37897206d57SZachary Turner Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
379af245d11STodd Fiala   long ptrace_opts = 0;
380af245d11STodd Fiala 
381af245d11STodd Fiala   // Have the child raise an event on exit.  This is used to keep the child in
382af245d11STodd Fiala   // limbo until it is destroyed.
383af245d11STodd Fiala   ptrace_opts |= PTRACE_O_TRACEEXIT;
384af245d11STodd Fiala 
385af245d11STodd Fiala   // Have the tracer trace threads which spawn in the inferior process.
386af245d11STodd Fiala   // TODO: if we want to support tracing the inferiors' child, add the
387af245d11STodd Fiala   // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
388af245d11STodd Fiala   ptrace_opts |= PTRACE_O_TRACECLONE;
389af245d11STodd Fiala 
39005097246SAdrian Prantl   // Have the tracer notify us before execve returns (needed to disable legacy
39105097246SAdrian Prantl   // SIGTRAP generation)
392af245d11STodd Fiala   ptrace_opts |= PTRACE_O_TRACEEXEC;
393af245d11STodd Fiala 
3944a9babb2SPavel Labath   return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
395af245d11STodd Fiala }
396af245d11STodd Fiala 
3971107b5a5SPavel Labath // Handles all waitpid events from the inferior process.
398b9c1b51eSKate Stone void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
3993508fc8cSPavel Labath                                          WaitStatus status) {
400af245d11STodd Fiala   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
401af245d11STodd Fiala 
402b9c1b51eSKate Stone   // Certain activities differ based on whether the pid is the tid of the main
403b9c1b51eSKate Stone   // thread.
4041107b5a5SPavel Labath   const bool is_main_thread = (pid == GetID());
405af245d11STodd Fiala 
406af245d11STodd Fiala   // Handle when the thread exits.
407b9c1b51eSKate Stone   if (exited) {
408d8b3c1a1SPavel Labath     LLDB_LOG(log,
4099303afb3SPavel Labath              "got exit status({0}) , tid = {1} ({2} main thread), process "
410d8b3c1a1SPavel Labath              "state = {3}",
4119303afb3SPavel Labath              status, pid, is_main_thread ? "is" : "is not", GetState());
412af245d11STodd Fiala 
413af245d11STodd Fiala     // This is a thread that exited.  Ensure we're not tracking it anymore.
414d8b3c1a1SPavel Labath     StopTrackingThread(pid);
415af245d11STodd Fiala 
416b9c1b51eSKate Stone     if (is_main_thread) {
417af245d11STodd Fiala       // The main thread exited.  We're done monitoring.  Report to delegate.
4183508fc8cSPavel Labath       SetExitStatus(status, true);
419af245d11STodd Fiala 
420af245d11STodd Fiala       // Notify delegate that our process has exited.
4211107b5a5SPavel Labath       SetState(StateType::eStateExited, true);
422af245d11STodd Fiala     }
4231107b5a5SPavel Labath     return;
424af245d11STodd Fiala   }
425af245d11STodd Fiala 
426af245d11STodd Fiala   siginfo_t info;
427b9cc0c75SPavel Labath   const auto info_err = GetSignalInfo(pid, &info);
428b9cc0c75SPavel Labath   auto thread_sp = GetThreadByID(pid);
429b9cc0c75SPavel Labath 
430b9c1b51eSKate Stone   if (!thread_sp) {
43105097246SAdrian Prantl     // Normally, the only situation when we cannot find the thread is if we
43205097246SAdrian Prantl     // have just received a new thread notification. This is indicated by
433a6321a8eSPavel Labath     // GetSignalInfo() returning si_code == SI_USER and si_pid == 0
434a6321a8eSPavel Labath     LLDB_LOG(log, "received notification about an unknown tid {0}.", pid);
435b9cc0c75SPavel Labath 
436b9c1b51eSKate Stone     if (info_err.Fail()) {
437a6321a8eSPavel Labath       LLDB_LOG(log,
438a6321a8eSPavel Labath                "(tid {0}) GetSignalInfo failed ({1}). "
439a6321a8eSPavel Labath                "Ingoring this notification.",
440a6321a8eSPavel Labath                pid, info_err);
441b9cc0c75SPavel Labath       return;
442b9cc0c75SPavel Labath     }
443b9cc0c75SPavel Labath 
444a6321a8eSPavel Labath     LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code,
445a6321a8eSPavel Labath              info.si_pid);
446b9cc0c75SPavel Labath 
447*0b697561SWalter Erquinigo     NativeThreadLinux &thread = AddThread(pid, /*resume*/ true);
448a5be48b3SPavel Labath     ThreadWasCreated(thread);
449b9cc0c75SPavel Labath     return;
450b9cc0c75SPavel Labath   }
451b9cc0c75SPavel Labath 
452b9cc0c75SPavel Labath   // Get details on the signal raised.
453b9c1b51eSKate Stone   if (info_err.Success()) {
454fa03ad2eSChaoren Lin     // We have retrieved the signal info.  Dispatch appropriately.
455fa03ad2eSChaoren Lin     if (info.si_signo == SIGTRAP)
456b9cc0c75SPavel Labath       MonitorSIGTRAP(info, *thread_sp);
457fa03ad2eSChaoren Lin     else
458b9cc0c75SPavel Labath       MonitorSignal(info, *thread_sp, exited);
459b9c1b51eSKate Stone   } else {
460b9c1b51eSKate Stone     if (info_err.GetError() == EINVAL) {
46105097246SAdrian Prantl       // This is a group stop reception for this tid. We can reach here if we
46205097246SAdrian Prantl       // reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the tracee,
46305097246SAdrian Prantl       // triggering the group-stop mechanism. Normally receiving these would
46405097246SAdrian Prantl       // stop the process, pending a SIGCONT. Simulating this state in a
46505097246SAdrian Prantl       // debugger is hard and is generally not needed (one use case is
46605097246SAdrian Prantl       // debugging background task being managed by a shell). For general use,
46705097246SAdrian Prantl       // it is sufficient to stop the process in a signal-delivery stop which
46805097246SAdrian Prantl       // happens before the group stop. This done by MonitorSignal and works
46905097246SAdrian Prantl       // correctly for all signals.
470a6321a8eSPavel Labath       LLDB_LOG(log,
471a6321a8eSPavel Labath                "received a group stop for pid {0} tid {1}. Transparent "
472a6321a8eSPavel Labath                "handling of group stops not supported, resuming the "
473a6321a8eSPavel Labath                "thread.",
474a6321a8eSPavel Labath                GetID(), pid);
475b9c1b51eSKate Stone       ResumeThread(*thread_sp, thread_sp->GetState(),
476b9c1b51eSKate Stone                    LLDB_INVALID_SIGNAL_NUMBER);
477b9c1b51eSKate Stone     } else {
478af245d11STodd Fiala       // ptrace(GETSIGINFO) failed (but not due to group-stop).
479af245d11STodd Fiala 
480b9c1b51eSKate Stone       // A return value of ESRCH means the thread/process is no longer on the
481a6321a8eSPavel Labath       // system, so it was killed somehow outside of our control.  Either way,
482a6321a8eSPavel Labath       // we can't do anything with it anymore.
483af245d11STodd Fiala 
484b9c1b51eSKate Stone       // Stop tracking the metadata for the thread since it's entirely off the
485b9c1b51eSKate Stone       // system now.
4861107b5a5SPavel Labath       const bool thread_found = StopTrackingThread(pid);
487af245d11STodd Fiala 
488a6321a8eSPavel Labath       LLDB_LOG(log,
4899303afb3SPavel Labath                "GetSignalInfo failed: {0}, tid = {1}, status = {2}, "
490a6321a8eSPavel Labath                "status = {3}, main_thread = {4}, thread_found: {5}",
4919303afb3SPavel Labath                info_err, pid, status, status, is_main_thread, thread_found);
492af245d11STodd Fiala 
493b9c1b51eSKate Stone       if (is_main_thread) {
494b9c1b51eSKate Stone         // Notify the delegate - our process is not available but appears to
49505097246SAdrian Prantl         // have been killed outside our control.  Is eStateExited the right
49605097246SAdrian Prantl         // exit state in this case?
4973508fc8cSPavel Labath         SetExitStatus(status, true);
4981107b5a5SPavel Labath         SetState(StateType::eStateExited, true);
499b9c1b51eSKate Stone       } else {
500b9c1b51eSKate Stone         // This thread was pulled out from underneath us.  Anything to do here?
501b9c1b51eSKate Stone         // Do we want to do an all stop?
502a6321a8eSPavel Labath         LLDB_LOG(log,
503a6321a8eSPavel Labath                  "pid {0} tid {1} non-main thread exit occurred, didn't "
504a6321a8eSPavel Labath                  "tell delegate anything since thread disappeared out "
505a6321a8eSPavel Labath                  "from underneath us",
506a6321a8eSPavel Labath                  GetID(), pid);
507af245d11STodd Fiala       }
508af245d11STodd Fiala     }
509af245d11STodd Fiala   }
510af245d11STodd Fiala }
511af245d11STodd Fiala 
512b9c1b51eSKate Stone void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
513a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
514426bdf88SPavel Labath 
515a5be48b3SPavel Labath   if (GetThreadByID(tid)) {
516b9c1b51eSKate Stone     // We are already tracking the thread - we got the event on the new thread
517a5be48b3SPavel Labath     // (see MonitorSignal) before this one. We are done.
518426bdf88SPavel Labath     return;
519426bdf88SPavel Labath   }
520426bdf88SPavel Labath 
521426bdf88SPavel Labath   // The thread is not tracked yet, let's wait for it to appear.
522426bdf88SPavel Labath   int status = -1;
523a6321a8eSPavel Labath   LLDB_LOG(log,
524a6321a8eSPavel Labath            "received thread creation event for tid {0}. tid not tracked "
525a6321a8eSPavel Labath            "yet, waiting for thread to appear...",
526a6321a8eSPavel Labath            tid);
527c1a6b128SPavel Labath   ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
528b9c1b51eSKate Stone   // Since we are waiting on a specific tid, this must be the creation event.
529a6321a8eSPavel Labath   // But let's do some checks just in case.
530426bdf88SPavel Labath   if (wait_pid != tid) {
531a6321a8eSPavel Labath     LLDB_LOG(log,
532a6321a8eSPavel Labath              "waiting for tid {0} failed. Assuming the thread has "
533a6321a8eSPavel Labath              "disappeared in the meantime",
534a6321a8eSPavel Labath              tid);
535426bdf88SPavel Labath     // The only way I know of this could happen is if the whole process was
536b9c1b51eSKate Stone     // SIGKILLed in the mean time. In any case, we can't do anything about that
537b9c1b51eSKate Stone     // now.
538426bdf88SPavel Labath     return;
539426bdf88SPavel Labath   }
540b9c1b51eSKate Stone   if (WIFEXITED(status)) {
541a6321a8eSPavel Labath     LLDB_LOG(log,
542a6321a8eSPavel Labath              "waiting for tid {0} returned an 'exited' event. Not "
543a6321a8eSPavel Labath              "tracking the thread.",
544a6321a8eSPavel Labath              tid);
545426bdf88SPavel Labath     // Also a very improbable event.
546426bdf88SPavel Labath     return;
547426bdf88SPavel Labath   }
548426bdf88SPavel Labath 
549a6321a8eSPavel Labath   LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid);
550*0b697561SWalter Erquinigo   NativeThreadLinux &new_thread = AddThread(tid, /*resume*/ true);
55199e37695SRavitheja Addepally 
552a5be48b3SPavel Labath   ThreadWasCreated(new_thread);
553426bdf88SPavel Labath }
554426bdf88SPavel Labath 
555b9c1b51eSKate Stone void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
556b9c1b51eSKate Stone                                         NativeThreadLinux &thread) {
557a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
558b9cc0c75SPavel Labath   const bool is_main_thread = (thread.GetID() == GetID());
559af245d11STodd Fiala 
560b9cc0c75SPavel Labath   assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
561af245d11STodd Fiala 
562b9c1b51eSKate Stone   switch (info.si_code) {
563b9c1b51eSKate Stone   // TODO: these two cases are required if we want to support tracing of the
56405097246SAdrian Prantl   // inferiors' children.  We'd need this to debug a monitor. case (SIGTRAP |
56505097246SAdrian Prantl   // (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
566af245d11STodd Fiala 
567b9c1b51eSKate Stone   case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
568b9c1b51eSKate Stone     // This is the notification on the parent thread which informs us of new
56905097246SAdrian Prantl     // thread creation. We don't want to do anything with the parent thread so
57005097246SAdrian Prantl     // we just resume it. In case we want to implement "break on thread
57105097246SAdrian Prantl     // creation" functionality, we would need to stop here.
572af245d11STodd Fiala 
573af245d11STodd Fiala     unsigned long event_message = 0;
574b9c1b51eSKate Stone     if (GetEventMessage(thread.GetID(), &event_message).Fail()) {
575a6321a8eSPavel Labath       LLDB_LOG(log,
576a6321a8eSPavel Labath                "pid {0} received thread creation event but "
577a6321a8eSPavel Labath                "GetEventMessage failed so we don't know the new tid",
578a6321a8eSPavel Labath                thread.GetID());
579426bdf88SPavel Labath     } else
580426bdf88SPavel Labath       WaitForNewThread(event_message);
581af245d11STodd Fiala 
582b9cc0c75SPavel Labath     ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
583af245d11STodd Fiala     break;
584af245d11STodd Fiala   }
585af245d11STodd Fiala 
586b9c1b51eSKate Stone   case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): {
587a6321a8eSPavel Labath     LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP);
588a9882ceeSTodd Fiala 
5891dbc6c9cSPavel Labath     // Exec clears any pending notifications.
5900e1d729bSPavel Labath     m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
591fa03ad2eSChaoren Lin 
592b9c1b51eSKate Stone     // Remove all but the main thread here.  Linux fork creates a new process
593b9c1b51eSKate Stone     // which only copies the main thread.
594a6321a8eSPavel Labath     LLDB_LOG(log, "exec received, stop tracking all but main thread");
595a9882ceeSTodd Fiala 
596ee74c9e5SPavel Labath     llvm::erase_if(m_threads, [&](std::unique_ptr<NativeThreadProtocol> &t) {
597ee74c9e5SPavel Labath       return t->GetID() != GetID();
598ee74c9e5SPavel Labath     });
599a5be48b3SPavel Labath     assert(m_threads.size() == 1);
600a5be48b3SPavel Labath     auto *main_thread = static_cast<NativeThreadLinux *>(m_threads[0].get());
601a9882ceeSTodd Fiala 
602a5be48b3SPavel Labath     SetCurrentThreadID(main_thread->GetID());
603a5be48b3SPavel Labath     main_thread->SetStoppedByExec();
604a9882ceeSTodd Fiala 
605fa03ad2eSChaoren Lin     // Tell coordinator about about the "new" (since exec) stopped main thread.
606a5be48b3SPavel Labath     ThreadWasCreated(*main_thread);
607fa03ad2eSChaoren Lin 
608a9882ceeSTodd Fiala     // Let our delegate know we have just exec'd.
609a9882ceeSTodd Fiala     NotifyDidExec();
610a9882ceeSTodd Fiala 
611fa03ad2eSChaoren Lin     // Let the process know we're stopped.
612a5be48b3SPavel Labath     StopRunningThreads(main_thread->GetID());
613a9882ceeSTodd Fiala 
614af245d11STodd Fiala     break;
615a9882ceeSTodd Fiala   }
616af245d11STodd Fiala 
617b9c1b51eSKate Stone   case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
61805097246SAdrian Prantl     // The inferior process or one of its threads is about to exit. We don't
61905097246SAdrian Prantl     // want to do anything with the thread so we just resume it. In case we
62005097246SAdrian Prantl     // want to implement "break on thread exit" functionality, we would need to
62105097246SAdrian Prantl     // stop here.
622fa03ad2eSChaoren Lin 
623af245d11STodd Fiala     unsigned long data = 0;
624b9cc0c75SPavel Labath     if (GetEventMessage(thread.GetID(), &data).Fail())
625af245d11STodd Fiala       data = -1;
626af245d11STodd Fiala 
627a6321a8eSPavel Labath     LLDB_LOG(log,
628a6321a8eSPavel Labath              "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, "
629a6321a8eSPavel Labath              "WIFSIGNALED={2}, pid = {3}, main_thread = {4}",
630a6321a8eSPavel Labath              data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(),
631a6321a8eSPavel Labath              is_main_thread);
632af245d11STodd Fiala 
63375f47c3aSTodd Fiala 
63486852d36SPavel Labath     StateType state = thread.GetState();
635b9c1b51eSKate Stone     if (!StateIsRunningState(state)) {
636b9c1b51eSKate Stone       // Due to a kernel bug, we may sometimes get this stop after the inferior
637d8b3c1a1SPavel Labath       // gets a SIGKILL. This confuses our state tracking logic in
638d8b3c1a1SPavel Labath       // ResumeThread(), since normally, we should not be receiving any ptrace
63905097246SAdrian Prantl       // events while the inferior is stopped. This makes sure that the
64005097246SAdrian Prantl       // inferior is resumed and exits normally.
64186852d36SPavel Labath       state = eStateRunning;
64286852d36SPavel Labath     }
64386852d36SPavel Labath     ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER);
644af245d11STodd Fiala 
645af245d11STodd Fiala     break;
646af245d11STodd Fiala   }
647af245d11STodd Fiala 
648af245d11STodd Fiala   case 0:
649c16f5dcaSChaoren Lin   case TRAP_TRACE:  // We receive this on single stepping.
650c16f5dcaSChaoren Lin   case TRAP_HWBKPT: // We receive this on watchpoint hit
65186fd8e45SChaoren Lin   {
652c16f5dcaSChaoren Lin     // If a watchpoint was hit, report it
653c16f5dcaSChaoren Lin     uint32_t wp_index;
654d37349f3SPavel Labath     Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
655b9c1b51eSKate Stone         wp_index, (uintptr_t)info.si_addr);
656a6321a8eSPavel Labath     if (error.Fail())
657a6321a8eSPavel Labath       LLDB_LOG(log,
658a6321a8eSPavel Labath                "received error while checking for watchpoint hits, pid = "
659a6321a8eSPavel Labath                "{0}, error = {1}",
660a6321a8eSPavel Labath                thread.GetID(), error);
661b9c1b51eSKate Stone     if (wp_index != LLDB_INVALID_INDEX32) {
662b9cc0c75SPavel Labath       MonitorWatchpoint(thread, wp_index);
663c16f5dcaSChaoren Lin       break;
664c16f5dcaSChaoren Lin     }
665b9cc0c75SPavel Labath 
666d5ffbad2SOmair Javaid     // If a breakpoint was hit, report it
667d5ffbad2SOmair Javaid     uint32_t bp_index;
668d37349f3SPavel Labath     error = thread.GetRegisterContext().GetHardwareBreakHitIndex(
669d5ffbad2SOmair Javaid         bp_index, (uintptr_t)info.si_addr);
670d5ffbad2SOmair Javaid     if (error.Fail())
671d5ffbad2SOmair Javaid       LLDB_LOG(log, "received error while checking for hardware "
672d5ffbad2SOmair Javaid                     "breakpoint hits, pid = {0}, error = {1}",
673d5ffbad2SOmair Javaid                thread.GetID(), error);
674d5ffbad2SOmair Javaid     if (bp_index != LLDB_INVALID_INDEX32) {
675d5ffbad2SOmair Javaid       MonitorBreakpoint(thread);
676d5ffbad2SOmair Javaid       break;
677d5ffbad2SOmair Javaid     }
678d5ffbad2SOmair Javaid 
679be379e15STamas Berghammer     // Otherwise, report step over
680be379e15STamas Berghammer     MonitorTrace(thread);
681af245d11STodd Fiala     break;
682b9cc0c75SPavel Labath   }
683af245d11STodd Fiala 
684af245d11STodd Fiala   case SI_KERNEL:
68535799963SMohit K. Bhakkad #if defined __mips__
68605097246SAdrian Prantl     // For mips there is no special signal for watchpoint So we check for
68705097246SAdrian Prantl     // watchpoint in kernel trap
68835799963SMohit K. Bhakkad     {
68935799963SMohit K. Bhakkad       // If a watchpoint was hit, report it
69035799963SMohit K. Bhakkad       uint32_t wp_index;
691d37349f3SPavel Labath       Status error = thread.GetRegisterContext().GetWatchpointHitIndex(
692b9c1b51eSKate Stone           wp_index, LLDB_INVALID_ADDRESS);
693a6321a8eSPavel Labath       if (error.Fail())
694a6321a8eSPavel Labath         LLDB_LOG(log,
695a6321a8eSPavel Labath                  "received error while checking for watchpoint hits, pid = "
696a6321a8eSPavel Labath                  "{0}, error = {1}",
697a6321a8eSPavel Labath                  thread.GetID(), error);
698b9c1b51eSKate Stone       if (wp_index != LLDB_INVALID_INDEX32) {
699b9cc0c75SPavel Labath         MonitorWatchpoint(thread, wp_index);
70035799963SMohit K. Bhakkad         break;
70135799963SMohit K. Bhakkad       }
70235799963SMohit K. Bhakkad     }
70335799963SMohit K. Bhakkad // NO BREAK
70435799963SMohit K. Bhakkad #endif
705af245d11STodd Fiala   case TRAP_BRKPT:
706b9cc0c75SPavel Labath     MonitorBreakpoint(thread);
707af245d11STodd Fiala     break;
708af245d11STodd Fiala 
709af245d11STodd Fiala   case SIGTRAP:
710af245d11STodd Fiala   case (SIGTRAP | 0x80):
711a6321a8eSPavel Labath     LLDB_LOG(
712a6321a8eSPavel Labath         log,
713a6321a8eSPavel Labath         "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
714a6321a8eSPavel Labath         info.si_code, GetID(), thread.GetID());
715fa03ad2eSChaoren Lin 
716af245d11STodd Fiala     // Ignore these signals until we know more about them.
717b9cc0c75SPavel Labath     ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
718af245d11STodd Fiala     break;
719af245d11STodd Fiala 
720af245d11STodd Fiala   default:
72121a365baSPavel Labath     LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}",
722a6321a8eSPavel Labath              info.si_code, GetID(), thread.GetID());
72321a365baSPavel Labath     MonitorSignal(info, thread, false);
724af245d11STodd Fiala     break;
725af245d11STodd Fiala   }
726af245d11STodd Fiala }
727af245d11STodd Fiala 
728b9c1b51eSKate Stone void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) {
729a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
730a6321a8eSPavel Labath   LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID());
731c16f5dcaSChaoren Lin 
7320e1d729bSPavel Labath   // This thread is currently stopped.
733b9cc0c75SPavel Labath   thread.SetStoppedByTrace();
734c16f5dcaSChaoren Lin 
735b9cc0c75SPavel Labath   StopRunningThreads(thread.GetID());
736c16f5dcaSChaoren Lin }
737c16f5dcaSChaoren Lin 
738b9c1b51eSKate Stone void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) {
739b9c1b51eSKate Stone   Log *log(
740b9c1b51eSKate Stone       GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
741a6321a8eSPavel Labath   LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID());
742c16f5dcaSChaoren Lin 
743c16f5dcaSChaoren Lin   // Mark the thread as stopped at breakpoint.
744b9cc0c75SPavel Labath   thread.SetStoppedByBreakpoint();
745aef7908fSPavel Labath   FixupBreakpointPCAsNeeded(thread);
746d8c338d4STamas Berghammer 
747b9c1b51eSKate Stone   if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
748b9c1b51eSKate Stone       m_threads_stepping_with_breakpoint.end())
749b9cc0c75SPavel Labath     thread.SetStoppedByTrace();
750c16f5dcaSChaoren Lin 
751b9cc0c75SPavel Labath   StopRunningThreads(thread.GetID());
752c16f5dcaSChaoren Lin }
753c16f5dcaSChaoren Lin 
754b9c1b51eSKate Stone void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread,
755b9c1b51eSKate Stone                                            uint32_t wp_index) {
756b9c1b51eSKate Stone   Log *log(
757b9c1b51eSKate Stone       GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS));
758a6321a8eSPavel Labath   LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}",
759a6321a8eSPavel Labath            thread.GetID(), wp_index);
760c16f5dcaSChaoren Lin 
76105097246SAdrian Prantl   // Mark the thread as stopped at watchpoint. The address is at
76205097246SAdrian Prantl   // (lldb::addr_t)info->si_addr if we need it.
763f9077782SPavel Labath   thread.SetStoppedByWatchpoint(wp_index);
764c16f5dcaSChaoren Lin 
765b9c1b51eSKate Stone   // We need to tell all other running threads before we notify the delegate
766b9c1b51eSKate Stone   // about this stop.
767f9077782SPavel Labath   StopRunningThreads(thread.GetID());
768c16f5dcaSChaoren Lin }
769c16f5dcaSChaoren Lin 
770b9c1b51eSKate Stone void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
771b9c1b51eSKate Stone                                        NativeThreadLinux &thread, bool exited) {
772b9cc0c75SPavel Labath   const int signo = info.si_signo;
773b9cc0c75SPavel Labath   const bool is_from_llgs = info.si_pid == getpid();
774af245d11STodd Fiala 
775a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
776af245d11STodd Fiala 
777af245d11STodd Fiala   // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
77805097246SAdrian Prantl   // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
77905097246SAdrian Prantl   // or raise(3).  Similarly for tgkill(2) on Linux.
780af245d11STodd Fiala   //
781af245d11STodd Fiala   // IOW, user generated signals never generate what we consider to be a
782af245d11STodd Fiala   // "crash".
783af245d11STodd Fiala   //
784af245d11STodd Fiala   // Similarly, ACK signals generated by this monitor.
785af245d11STodd Fiala 
786af245d11STodd Fiala   // Handle the signal.
787a6321a8eSPavel Labath   LLDB_LOG(log,
788a6321a8eSPavel Labath            "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, "
789a6321a8eSPavel Labath            "waitpid pid = {4})",
790a6321a8eSPavel Labath            Host::GetSignalAsCString(signo), signo, info.si_code,
791b9cc0c75SPavel Labath            thread.GetID());
79258a2f669STodd Fiala 
79358a2f669STodd Fiala   // Check for thread stop notification.
794b9c1b51eSKate Stone   if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) {
795af245d11STodd Fiala     // This is a tgkill()-based stop.
796a6321a8eSPavel Labath     LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID());
797fa03ad2eSChaoren Lin 
79805097246SAdrian Prantl     // Check that we're not already marked with a stop reason. Note this thread
79905097246SAdrian Prantl     // really shouldn't already be marked as stopped - if we were, that would
80005097246SAdrian Prantl     // imply that the kernel signaled us with the thread stopping which we
80105097246SAdrian Prantl     // handled and marked as stopped, and that, without an intervening resume,
80205097246SAdrian Prantl     // we received another stop.  It is more likely that we are missing the
80305097246SAdrian Prantl     // marking of a run state somewhere if we find that the thread was marked
80405097246SAdrian Prantl     // as stopped.
805b9cc0c75SPavel Labath     const StateType thread_state = thread.GetState();
806b9c1b51eSKate Stone     if (!StateIsStoppedState(thread_state, false)) {
807ed89c7feSPavel Labath       // An inferior thread has stopped because of a SIGSTOP we have sent it.
808b9c1b51eSKate Stone       // Generally, these are not important stops and we don't want to report
809a6321a8eSPavel Labath       // them as they are just used to stop other threads when one thread (the
810a6321a8eSPavel Labath       // one with the *real* stop reason) hits a breakpoint (watchpoint,
81105097246SAdrian Prantl       // etc...). However, in the case of an asynchronous Interrupt(), this
81205097246SAdrian Prantl       // *is* the real stop reason, so we leave the signal intact if this is
81305097246SAdrian Prantl       // the thread that was chosen as the triggering thread.
814b9c1b51eSKate Stone       if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
815b9cc0c75SPavel Labath         if (m_pending_notification_tid == thread.GetID())
816b9cc0c75SPavel Labath           thread.SetStoppedBySignal(SIGSTOP, &info);
817ed89c7feSPavel Labath         else
818b9cc0c75SPavel Labath           thread.SetStoppedWithNoReason();
819ed89c7feSPavel Labath 
820b9cc0c75SPavel Labath         SetCurrentThreadID(thread.GetID());
8210e1d729bSPavel Labath         SignalIfAllThreadsStopped();
822b9c1b51eSKate Stone       } else {
8230e1d729bSPavel Labath         // We can end up here if stop was initiated by LLGS but by this time a
8240e1d729bSPavel Labath         // thread stop has occurred - maybe initiated by another event.
82597206d57SZachary Turner         Status error = ResumeThread(thread, thread.GetState(), 0);
826a6321a8eSPavel Labath         if (error.Fail())
827a6321a8eSPavel Labath           LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(),
828a6321a8eSPavel Labath                    error);
8290e1d729bSPavel Labath       }
830b9c1b51eSKate Stone     } else {
831a6321a8eSPavel Labath       LLDB_LOG(log,
832a6321a8eSPavel Labath                "pid {0} tid {1}, thread was already marked as a stopped "
833a6321a8eSPavel Labath                "state (state={2}), leaving stop signal as is",
8348198db30SPavel Labath                GetID(), thread.GetID(), thread_state);
8350e1d729bSPavel Labath       SignalIfAllThreadsStopped();
836af245d11STodd Fiala     }
837af245d11STodd Fiala 
83858a2f669STodd Fiala     // Done handling.
839af245d11STodd Fiala     return;
840af245d11STodd Fiala   }
841af245d11STodd Fiala 
84205097246SAdrian Prantl   // Check if debugger should stop at this signal or just ignore it and resume
84305097246SAdrian Prantl   // the inferior.
8444a705e7eSPavel Labath   if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) {
8454a705e7eSPavel Labath      ResumeThread(thread, thread.GetState(), signo);
8464a705e7eSPavel Labath      return;
8474a705e7eSPavel Labath   }
8484a705e7eSPavel Labath 
84986fd8e45SChaoren Lin   // This thread is stopped.
850a6321a8eSPavel Labath   LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo));
851b9cc0c75SPavel Labath   thread.SetStoppedBySignal(signo, &info);
85286fd8e45SChaoren Lin 
85386fd8e45SChaoren Lin   // Send a stop to the debugger after we get all other threads to stop.
854b9cc0c75SPavel Labath   StopRunningThreads(thread.GetID());
855511e5cdcSTodd Fiala }
856af245d11STodd Fiala 
857b9c1b51eSKate Stone bool NativeProcessLinux::SupportHardwareSingleStepping() const {
858ddb93b63SFangrui Song   if (m_arch.GetMachine() == llvm::Triple::arm || m_arch.IsMIPS())
859cdc22a88SMohit K. Bhakkad     return false;
860cdc22a88SMohit K. Bhakkad   return true;
861e7708688STamas Berghammer }
862e7708688STamas Berghammer 
86397206d57SZachary Turner Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
864a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
865a6321a8eSPavel Labath   LLDB_LOG(log, "pid {0}", GetID());
866af245d11STodd Fiala 
867e7708688STamas Berghammer   bool software_single_step = !SupportHardwareSingleStepping();
868af245d11STodd Fiala 
869b9c1b51eSKate Stone   if (software_single_step) {
870a5be48b3SPavel Labath     for (const auto &thread : m_threads) {
871a5be48b3SPavel Labath       assert(thread && "thread list should not contain NULL threads");
872e7708688STamas Berghammer 
873b9c1b51eSKate Stone       const ResumeAction *const action =
874a5be48b3SPavel Labath           resume_actions.GetActionForThread(thread->GetID(), true);
875e7708688STamas Berghammer       if (action == nullptr)
876e7708688STamas Berghammer         continue;
877e7708688STamas Berghammer 
878b9c1b51eSKate Stone       if (action->state == eStateStepping) {
87997206d57SZachary Turner         Status error = SetupSoftwareSingleStepping(
880a5be48b3SPavel Labath             static_cast<NativeThreadLinux &>(*thread));
881e7708688STamas Berghammer         if (error.Fail())
882e7708688STamas Berghammer           return error;
883e7708688STamas Berghammer       }
884e7708688STamas Berghammer     }
885e7708688STamas Berghammer   }
886e7708688STamas Berghammer 
887a5be48b3SPavel Labath   for (const auto &thread : m_threads) {
888a5be48b3SPavel Labath     assert(thread && "thread list should not contain NULL threads");
889af245d11STodd Fiala 
890b9c1b51eSKate Stone     const ResumeAction *const action =
891a5be48b3SPavel Labath         resume_actions.GetActionForThread(thread->GetID(), true);
8926a196ce6SChaoren Lin 
893b9c1b51eSKate Stone     if (action == nullptr) {
894a6321a8eSPavel Labath       LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
895a5be48b3SPavel Labath                thread->GetID());
8966a196ce6SChaoren Lin       continue;
8976a196ce6SChaoren Lin     }
898af245d11STodd Fiala 
899a6321a8eSPavel Labath     LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}",
900a5be48b3SPavel Labath              action->state, GetID(), thread->GetID());
901af245d11STodd Fiala 
902b9c1b51eSKate Stone     switch (action->state) {
903af245d11STodd Fiala     case eStateRunning:
904b9c1b51eSKate Stone     case eStateStepping: {
905af245d11STodd Fiala       // Run the thread, possibly feeding it the signal.
906fa03ad2eSChaoren Lin       const int signo = action->signal;
907a5be48b3SPavel Labath       ResumeThread(static_cast<NativeThreadLinux &>(*thread), action->state,
908b9c1b51eSKate Stone                    signo);
909af245d11STodd Fiala       break;
910ae29d395SChaoren Lin     }
911af245d11STodd Fiala 
912af245d11STodd Fiala     case eStateSuspended:
913af245d11STodd Fiala     case eStateStopped:
914a6321a8eSPavel Labath       llvm_unreachable("Unexpected state");
915af245d11STodd Fiala 
916af245d11STodd Fiala     default:
91797206d57SZachary Turner       return Status("NativeProcessLinux::%s (): unexpected state %s specified "
918b9c1b51eSKate Stone                     "for pid %" PRIu64 ", tid %" PRIu64,
919b9c1b51eSKate Stone                     __FUNCTION__, StateAsCString(action->state), GetID(),
920a5be48b3SPavel Labath                     thread->GetID());
921af245d11STodd Fiala     }
922af245d11STodd Fiala   }
923af245d11STodd Fiala 
92497206d57SZachary Turner   return Status();
925af245d11STodd Fiala }
926af245d11STodd Fiala 
92797206d57SZachary Turner Status NativeProcessLinux::Halt() {
92897206d57SZachary Turner   Status error;
929af245d11STodd Fiala 
930af245d11STodd Fiala   if (kill(GetID(), SIGSTOP) != 0)
931af245d11STodd Fiala     error.SetErrorToErrno();
932af245d11STodd Fiala 
933af245d11STodd Fiala   return error;
934af245d11STodd Fiala }
935af245d11STodd Fiala 
93697206d57SZachary Turner Status NativeProcessLinux::Detach() {
93797206d57SZachary Turner   Status error;
938af245d11STodd Fiala 
939af245d11STodd Fiala   // Stop monitoring the inferior.
94019cbe96aSPavel Labath   m_sigchld_handle.reset();
941af245d11STodd Fiala 
9427a9495bcSPavel Labath   // Tell ptrace to detach from the process.
9437a9495bcSPavel Labath   if (GetID() == LLDB_INVALID_PROCESS_ID)
9447a9495bcSPavel Labath     return error;
9457a9495bcSPavel Labath 
946a5be48b3SPavel Labath   for (const auto &thread : m_threads) {
947a5be48b3SPavel Labath     Status e = Detach(thread->GetID());
9487a9495bcSPavel Labath     if (e.Fail())
949b9c1b51eSKate Stone       error =
950b9c1b51eSKate Stone           e; // Save the error, but still attempt to detach from other threads.
9517a9495bcSPavel Labath   }
9527a9495bcSPavel Labath 
953*0b697561SWalter Erquinigo   m_intel_pt_manager.Clear();
95499e37695SRavitheja Addepally 
955af245d11STodd Fiala   return error;
956af245d11STodd Fiala }
957af245d11STodd Fiala 
95897206d57SZachary Turner Status NativeProcessLinux::Signal(int signo) {
95997206d57SZachary Turner   Status error;
960af245d11STodd Fiala 
961a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
962a6321a8eSPavel Labath   LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo,
963a6321a8eSPavel Labath            Host::GetSignalAsCString(signo), GetID());
964af245d11STodd Fiala 
965af245d11STodd Fiala   if (kill(GetID(), signo))
966af245d11STodd Fiala     error.SetErrorToErrno();
967af245d11STodd Fiala 
968af245d11STodd Fiala   return error;
969af245d11STodd Fiala }
970af245d11STodd Fiala 
97197206d57SZachary Turner Status NativeProcessLinux::Interrupt() {
97205097246SAdrian Prantl   // Pick a running thread (or if none, a not-dead stopped thread) as the
97305097246SAdrian Prantl   // chosen thread that will be the stop-reason thread.
974a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
975e9547b80SChaoren Lin 
976a5be48b3SPavel Labath   NativeThreadProtocol *running_thread = nullptr;
977a5be48b3SPavel Labath   NativeThreadProtocol *stopped_thread = nullptr;
978e9547b80SChaoren Lin 
979a6321a8eSPavel Labath   LLDB_LOG(log, "selecting running thread for interrupt target");
980a5be48b3SPavel Labath   for (const auto &thread : m_threads) {
98105097246SAdrian Prantl     // If we have a running or stepping thread, we'll call that the target of
98205097246SAdrian Prantl     // the interrupt.
983a5be48b3SPavel Labath     const auto thread_state = thread->GetState();
984b9c1b51eSKate Stone     if (thread_state == eStateRunning || thread_state == eStateStepping) {
985a5be48b3SPavel Labath       running_thread = thread.get();
986e9547b80SChaoren Lin       break;
987a5be48b3SPavel Labath     } else if (!stopped_thread && StateIsStoppedState(thread_state, true)) {
98805097246SAdrian Prantl       // Remember the first non-dead stopped thread.  We'll use that as a
98905097246SAdrian Prantl       // backup if there are no running threads.
990a5be48b3SPavel Labath       stopped_thread = thread.get();
991e9547b80SChaoren Lin     }
992e9547b80SChaoren Lin   }
993e9547b80SChaoren Lin 
994a5be48b3SPavel Labath   if (!running_thread && !stopped_thread) {
99597206d57SZachary Turner     Status error("found no running/stepping or live stopped threads as target "
996b9c1b51eSKate Stone                  "for interrupt");
997a6321a8eSPavel Labath     LLDB_LOG(log, "skipping due to error: {0}", error);
9985830aa75STamas Berghammer 
999e9547b80SChaoren Lin     return error;
1000e9547b80SChaoren Lin   }
1001e9547b80SChaoren Lin 
1002a5be48b3SPavel Labath   NativeThreadProtocol *deferred_signal_thread =
1003a5be48b3SPavel Labath       running_thread ? running_thread : stopped_thread;
1004e9547b80SChaoren Lin 
1005a6321a8eSPavel Labath   LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(),
1006a5be48b3SPavel Labath            running_thread ? "running" : "stopped",
1007a5be48b3SPavel Labath            deferred_signal_thread->GetID());
1008e9547b80SChaoren Lin 
1009a5be48b3SPavel Labath   StopRunningThreads(deferred_signal_thread->GetID());
101045f5cb31SPavel Labath 
101197206d57SZachary Turner   return Status();
1012e9547b80SChaoren Lin }
1013e9547b80SChaoren Lin 
101497206d57SZachary Turner Status NativeProcessLinux::Kill() {
1015a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1016a6321a8eSPavel Labath   LLDB_LOG(log, "pid {0}", GetID());
1017af245d11STodd Fiala 
101897206d57SZachary Turner   Status error;
1019af245d11STodd Fiala 
1020b9c1b51eSKate Stone   switch (m_state) {
1021af245d11STodd Fiala   case StateType::eStateInvalid:
1022af245d11STodd Fiala   case StateType::eStateExited:
1023af245d11STodd Fiala   case StateType::eStateCrashed:
1024af245d11STodd Fiala   case StateType::eStateDetached:
1025af245d11STodd Fiala   case StateType::eStateUnloaded:
1026af245d11STodd Fiala     // Nothing to do - the process is already dead.
1027a6321a8eSPavel Labath     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
10288198db30SPavel Labath              m_state);
1029af245d11STodd Fiala     return error;
1030af245d11STodd Fiala 
1031af245d11STodd Fiala   case StateType::eStateConnected:
1032af245d11STodd Fiala   case StateType::eStateAttaching:
1033af245d11STodd Fiala   case StateType::eStateLaunching:
1034af245d11STodd Fiala   case StateType::eStateStopped:
1035af245d11STodd Fiala   case StateType::eStateRunning:
1036af245d11STodd Fiala   case StateType::eStateStepping:
1037af245d11STodd Fiala   case StateType::eStateSuspended:
1038af245d11STodd Fiala     // We can try to kill a process in these states.
1039af245d11STodd Fiala     break;
1040af245d11STodd Fiala   }
1041af245d11STodd Fiala 
1042b9c1b51eSKate Stone   if (kill(GetID(), SIGKILL) != 0) {
1043af245d11STodd Fiala     error.SetErrorToErrno();
1044af245d11STodd Fiala     return error;
1045af245d11STodd Fiala   }
1046af245d11STodd Fiala 
1047af245d11STodd Fiala   return error;
1048af245d11STodd Fiala }
1049af245d11STodd Fiala 
105097206d57SZachary Turner Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
1051b9c1b51eSKate Stone                                                MemoryRegionInfo &range_info) {
1052b9c1b51eSKate Stone   // FIXME review that the final memory region returned extends to the end of
1053b9c1b51eSKate Stone   // the virtual address space,
1054af245d11STodd Fiala   // with no perms if it is not mapped.
1055af245d11STodd Fiala 
105605097246SAdrian Prantl   // Use an approach that reads memory regions from /proc/{pid}/maps. Assume
105705097246SAdrian Prantl   // proc maps entries are in ascending order.
1058af245d11STodd Fiala   // FIXME assert if we find differently.
1059af245d11STodd Fiala 
1060b9c1b51eSKate Stone   if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
1061af245d11STodd Fiala     // We're done.
106297206d57SZachary Turner     return Status("unsupported");
1063af245d11STodd Fiala   }
1064af245d11STodd Fiala 
106597206d57SZachary Turner   Status error = PopulateMemoryRegionCache();
1066b9c1b51eSKate Stone   if (error.Fail()) {
1067af245d11STodd Fiala     return error;
1068af245d11STodd Fiala   }
1069af245d11STodd Fiala 
1070af245d11STodd Fiala   lldb::addr_t prev_base_address = 0;
1071af245d11STodd Fiala 
1072b9c1b51eSKate Stone   // FIXME start by finding the last region that is <= target address using
1073b9c1b51eSKate Stone   // binary search.  Data is sorted.
1074af245d11STodd Fiala   // There can be a ton of regions on pthreads apps with lots of threads.
1075b9c1b51eSKate Stone   for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
1076b9c1b51eSKate Stone        ++it) {
1077a6f5795aSTamas Berghammer     MemoryRegionInfo &proc_entry_info = it->first;
1078af245d11STodd Fiala 
1079af245d11STodd Fiala     // Sanity check assumption that /proc/{pid}/maps entries are ascending.
1080b9c1b51eSKate Stone     assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
1081b9c1b51eSKate Stone            "descending /proc/pid/maps entries detected, unexpected");
1082af245d11STodd Fiala     prev_base_address = proc_entry_info.GetRange().GetRangeBase();
1083b1554311SHafiz Abid Qadeer     UNUSED_IF_ASSERT_DISABLED(prev_base_address);
1084af245d11STodd Fiala 
1085b9c1b51eSKate Stone     // If the target address comes before this entry, indicate distance to next
1086b9c1b51eSKate Stone     // region.
1087b9c1b51eSKate Stone     if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
1088af245d11STodd Fiala       range_info.GetRange().SetRangeBase(load_addr);
1089b9c1b51eSKate Stone       range_info.GetRange().SetByteSize(
1090b9c1b51eSKate Stone           proc_entry_info.GetRange().GetRangeBase() - load_addr);
1091af245d11STodd Fiala       range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
1092af245d11STodd Fiala       range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
1093af245d11STodd Fiala       range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
1094ad007563SHoward Hellyer       range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
1095af245d11STodd Fiala 
1096af245d11STodd Fiala       return error;
1097b9c1b51eSKate Stone     } else if (proc_entry_info.GetRange().Contains(load_addr)) {
1098af245d11STodd Fiala       // The target address is within the memory region we're processing here.
1099af245d11STodd Fiala       range_info = proc_entry_info;
1100af245d11STodd Fiala       return error;
1101af245d11STodd Fiala     }
1102af245d11STodd Fiala 
1103b9c1b51eSKate Stone     // The target memory address comes somewhere after the region we just
1104b9c1b51eSKate Stone     // parsed.
1105af245d11STodd Fiala   }
1106af245d11STodd Fiala 
1107b9c1b51eSKate Stone   // If we made it here, we didn't find an entry that contained the given
110805097246SAdrian Prantl   // address. Return the load_addr as start and the amount of bytes betwwen
110905097246SAdrian Prantl   // load address and the end of the memory as size.
111009839c33STamas Berghammer   range_info.GetRange().SetRangeBase(load_addr);
1111ad007563SHoward Hellyer   range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
111209839c33STamas Berghammer   range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
111309839c33STamas Berghammer   range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
111409839c33STamas Berghammer   range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
1115ad007563SHoward Hellyer   range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
1116af245d11STodd Fiala   return error;
1117af245d11STodd Fiala }
1118af245d11STodd Fiala 
111997206d57SZachary Turner Status NativeProcessLinux::PopulateMemoryRegionCache() {
1120a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1121a6f5795aSTamas Berghammer 
1122a6f5795aSTamas Berghammer   // If our cache is empty, pull the latest.  There should always be at least
1123a6f5795aSTamas Berghammer   // one memory region if memory region handling is supported.
1124a6f5795aSTamas Berghammer   if (!m_mem_region_cache.empty()) {
1125a6321a8eSPavel Labath     LLDB_LOG(log, "reusing {0} cached memory region entries",
1126a6321a8eSPavel Labath              m_mem_region_cache.size());
112797206d57SZachary Turner     return Status();
1128a6f5795aSTamas Berghammer   }
1129a6f5795aSTamas Berghammer 
113032541685SDavid Spickett   Status Result;
113132541685SDavid Spickett   LinuxMapCallback callback = [&](llvm::Expected<MemoryRegionInfo> Info) {
113232541685SDavid Spickett     if (Info) {
113332541685SDavid Spickett       FileSpec file_spec(Info->GetName().GetCString());
113432541685SDavid Spickett       FileSystem::Instance().Resolve(file_spec);
113532541685SDavid Spickett       m_mem_region_cache.emplace_back(*Info, file_spec);
113632541685SDavid Spickett       return true;
113732541685SDavid Spickett     }
113832541685SDavid Spickett 
113932541685SDavid Spickett     Result = Info.takeError();
114032541685SDavid Spickett     m_supports_mem_region = LazyBool::eLazyBoolNo;
114132541685SDavid Spickett     LLDB_LOG(log, "failed to parse proc maps: {0}", Result);
114232541685SDavid Spickett     return false;
114332541685SDavid Spickett   };
114432541685SDavid Spickett 
114532541685SDavid Spickett   // Linux kernel since 2.6.14 has /proc/{pid}/smaps
114632541685SDavid Spickett   // if CONFIG_PROC_PAGE_MONITOR is enabled
114732541685SDavid Spickett   auto BufferOrError = getProcFile(GetID(), "smaps");
114832541685SDavid Spickett   if (BufferOrError)
114932541685SDavid Spickett     ParseLinuxSMapRegions(BufferOrError.get()->getBuffer(), callback);
115032541685SDavid Spickett   else {
115132541685SDavid Spickett     BufferOrError = getProcFile(GetID(), "maps");
115215930862SPavel Labath     if (!BufferOrError) {
115315930862SPavel Labath       m_supports_mem_region = LazyBool::eLazyBoolNo;
115415930862SPavel Labath       return BufferOrError.getError();
115515930862SPavel Labath     }
115632541685SDavid Spickett 
115732541685SDavid Spickett     ParseLinuxMapRegions(BufferOrError.get()->getBuffer(), callback);
1158a6f5795aSTamas Berghammer   }
115932541685SDavid Spickett 
1160c8e364e8SPavel Labath   if (Result.Fail())
1161c8e364e8SPavel Labath     return Result;
1162a6f5795aSTamas Berghammer 
116315930862SPavel Labath   if (m_mem_region_cache.empty()) {
1164a6f5795aSTamas Berghammer     // No entries after attempting to read them.  This shouldn't happen if
116505097246SAdrian Prantl     // /proc/{pid}/maps is supported. Assume we don't support map entries via
116605097246SAdrian Prantl     // procfs.
116715930862SPavel Labath     m_supports_mem_region = LazyBool::eLazyBoolNo;
1168a6321a8eSPavel Labath     LLDB_LOG(log,
1169a6321a8eSPavel Labath              "failed to find any procfs maps entries, assuming no support "
1170a6321a8eSPavel Labath              "for memory region metadata retrieval");
117197206d57SZachary Turner     return Status("not supported");
1172a6f5795aSTamas Berghammer   }
1173a6f5795aSTamas Berghammer 
1174a6321a8eSPavel Labath   LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps",
1175a6321a8eSPavel Labath            m_mem_region_cache.size(), GetID());
1176a6f5795aSTamas Berghammer 
1177a6f5795aSTamas Berghammer   // We support memory retrieval, remember that.
1178a6f5795aSTamas Berghammer   m_supports_mem_region = LazyBool::eLazyBoolYes;
117997206d57SZachary Turner   return Status();
1180a6f5795aSTamas Berghammer }
1181a6f5795aSTamas Berghammer 
1182b9c1b51eSKate Stone void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) {
1183a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1184a6321a8eSPavel Labath   LLDB_LOG(log, "newBumpId={0}", newBumpId);
1185a6321a8eSPavel Labath   LLDB_LOG(log, "clearing {0} entries from memory region cache",
1186a6321a8eSPavel Labath            m_mem_region_cache.size());
1187af245d11STodd Fiala   m_mem_region_cache.clear();
1188af245d11STodd Fiala }
1189af245d11STodd Fiala 
11902c4226f8SPavel Labath llvm::Expected<uint64_t>
11912c4226f8SPavel Labath NativeProcessLinux::Syscall(llvm::ArrayRef<uint64_t> args) {
11922c4226f8SPavel Labath   PopulateMemoryRegionCache();
11932c4226f8SPavel Labath   auto region_it = llvm::find_if(m_mem_region_cache, [](const auto &pair) {
11942c4226f8SPavel Labath     return pair.first.GetExecutable() == MemoryRegionInfo::eYes;
11952c4226f8SPavel Labath   });
11962c4226f8SPavel Labath   if (region_it == m_mem_region_cache.end())
11972c4226f8SPavel Labath     return llvm::createStringError(llvm::inconvertibleErrorCode(),
11982c4226f8SPavel Labath                                    "No executable memory region found!");
1199af245d11STodd Fiala 
12002c4226f8SPavel Labath   addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
1201af245d11STodd Fiala 
12022c4226f8SPavel Labath   NativeThreadLinux &thread = *GetThreadByID(GetID());
12032c4226f8SPavel Labath   assert(thread.GetState() == eStateStopped);
12042c4226f8SPavel Labath   NativeRegisterContextLinux &reg_ctx = thread.GetRegisterContext();
12052c4226f8SPavel Labath 
12062c4226f8SPavel Labath   NativeRegisterContextLinux::SyscallData syscall_data =
12072c4226f8SPavel Labath       *reg_ctx.GetSyscallData();
12082c4226f8SPavel Labath 
12092c4226f8SPavel Labath   DataBufferSP registers_sp;
12102c4226f8SPavel Labath   if (llvm::Error Err = reg_ctx.ReadAllRegisterValues(registers_sp).ToError())
12112c4226f8SPavel Labath     return std::move(Err);
12122c4226f8SPavel Labath   auto restore_regs = llvm::make_scope_exit(
12132c4226f8SPavel Labath       [&] { reg_ctx.WriteAllRegisterValues(registers_sp); });
12142c4226f8SPavel Labath 
12152c4226f8SPavel Labath   llvm::SmallVector<uint8_t, 8> memory(syscall_data.Insn.size());
12162c4226f8SPavel Labath   size_t bytes_read;
12172c4226f8SPavel Labath   if (llvm::Error Err =
12182c4226f8SPavel Labath           ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read)
12192c4226f8SPavel Labath               .ToError()) {
12202c4226f8SPavel Labath     return std::move(Err);
1221af245d11STodd Fiala   }
1222af245d11STodd Fiala 
12232c4226f8SPavel Labath   auto restore_mem = llvm::make_scope_exit(
12242c4226f8SPavel Labath       [&] { WriteMemory(exe_addr, memory.data(), memory.size(), bytes_read); });
12252c4226f8SPavel Labath 
12262c4226f8SPavel Labath   if (llvm::Error Err = reg_ctx.SetPC(exe_addr).ToError())
12272c4226f8SPavel Labath     return std::move(Err);
12282c4226f8SPavel Labath 
12292c4226f8SPavel Labath   for (const auto &zip : llvm::zip_first(args, syscall_data.Args)) {
12302c4226f8SPavel Labath     if (llvm::Error Err =
12312c4226f8SPavel Labath             reg_ctx
12322c4226f8SPavel Labath                 .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip))
12332c4226f8SPavel Labath                 .ToError()) {
12342c4226f8SPavel Labath       return std::move(Err);
12352c4226f8SPavel Labath     }
12362c4226f8SPavel Labath   }
12372c4226f8SPavel Labath   if (llvm::Error Err = WriteMemory(exe_addr, syscall_data.Insn.data(),
12382c4226f8SPavel Labath                                     syscall_data.Insn.size(), bytes_read)
12392c4226f8SPavel Labath                             .ToError())
12402c4226f8SPavel Labath     return std::move(Err);
12412c4226f8SPavel Labath 
12422c4226f8SPavel Labath   m_mem_region_cache.clear();
12432c4226f8SPavel Labath 
12442c4226f8SPavel Labath   // With software single stepping the syscall insn buffer must also include a
12452c4226f8SPavel Labath   // trap instruction to stop the process.
12462c4226f8SPavel Labath   int req = SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP : PTRACE_CONT;
12472c4226f8SPavel Labath   if (llvm::Error Err =
12482c4226f8SPavel Labath           PtraceWrapper(req, thread.GetID(), nullptr, nullptr).ToError())
12492c4226f8SPavel Labath     return std::move(Err);
12502c4226f8SPavel Labath 
12512c4226f8SPavel Labath   int status;
12522c4226f8SPavel Labath   ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(),
12532c4226f8SPavel Labath                                                  &status, __WALL);
12542c4226f8SPavel Labath   if (wait_pid == -1) {
12552c4226f8SPavel Labath     return llvm::errorCodeToError(
12562c4226f8SPavel Labath         std::error_code(errno, std::generic_category()));
12572c4226f8SPavel Labath   }
12582c4226f8SPavel Labath   assert((unsigned)wait_pid == thread.GetID());
12592c4226f8SPavel Labath 
12602c4226f8SPavel Labath   uint64_t result = reg_ctx.ReadRegisterAsUnsigned(syscall_data.Result, -ESRCH);
12612c4226f8SPavel Labath 
12622c4226f8SPavel Labath   // Values larger than this are actually negative errno numbers.
12632c4226f8SPavel Labath   uint64_t errno_threshold =
12642c4226f8SPavel Labath       (uint64_t(-1) >> (64 - 8 * m_arch.GetAddressByteSize())) - 0x1000;
12652c4226f8SPavel Labath   if (result > errno_threshold) {
12662c4226f8SPavel Labath     return llvm::errorCodeToError(
12672c4226f8SPavel Labath         std::error_code(-result & 0xfff, std::generic_category()));
12682c4226f8SPavel Labath   }
12692c4226f8SPavel Labath 
12702c4226f8SPavel Labath   return result;
12712c4226f8SPavel Labath }
12722c4226f8SPavel Labath 
12732c4226f8SPavel Labath llvm::Expected<addr_t>
12742c4226f8SPavel Labath NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions) {
12752c4226f8SPavel Labath 
12762c4226f8SPavel Labath   llvm::Optional<NativeRegisterContextLinux::MmapData> mmap_data =
12772c4226f8SPavel Labath       GetCurrentThread()->GetRegisterContext().GetMmapData();
12782c4226f8SPavel Labath   if (!mmap_data)
12792c4226f8SPavel Labath     return llvm::make_error<UnimplementedError>();
12802c4226f8SPavel Labath 
12812c4226f8SPavel Labath   unsigned prot = PROT_NONE;
12822c4226f8SPavel Labath   assert((permissions & (ePermissionsReadable | ePermissionsWritable |
12832c4226f8SPavel Labath                          ePermissionsExecutable)) == permissions &&
12842c4226f8SPavel Labath          "Unknown permission!");
12852c4226f8SPavel Labath   if (permissions & ePermissionsReadable)
12862c4226f8SPavel Labath     prot |= PROT_READ;
12872c4226f8SPavel Labath   if (permissions & ePermissionsWritable)
12882c4226f8SPavel Labath     prot |= PROT_WRITE;
12892c4226f8SPavel Labath   if (permissions & ePermissionsExecutable)
12902c4226f8SPavel Labath     prot |= PROT_EXEC;
12912c4226f8SPavel Labath 
12922c4226f8SPavel Labath   llvm::Expected<uint64_t> Result =
12932c4226f8SPavel Labath       Syscall({mmap_data->SysMmap, 0, size, prot, MAP_ANONYMOUS | MAP_PRIVATE,
12942c4226f8SPavel Labath                uint64_t(-1), 0});
12952c4226f8SPavel Labath   if (Result)
12962c4226f8SPavel Labath     m_allocated_memory.try_emplace(*Result, size);
12972c4226f8SPavel Labath   return Result;
12982c4226f8SPavel Labath }
12992c4226f8SPavel Labath 
13002c4226f8SPavel Labath llvm::Error NativeProcessLinux::DeallocateMemory(lldb::addr_t addr) {
13012c4226f8SPavel Labath   llvm::Optional<NativeRegisterContextLinux::MmapData> mmap_data =
13022c4226f8SPavel Labath       GetCurrentThread()->GetRegisterContext().GetMmapData();
13032c4226f8SPavel Labath   if (!mmap_data)
13042c4226f8SPavel Labath     return llvm::make_error<UnimplementedError>();
13052c4226f8SPavel Labath 
13062c4226f8SPavel Labath   auto it = m_allocated_memory.find(addr);
13072c4226f8SPavel Labath   if (it == m_allocated_memory.end())
13082c4226f8SPavel Labath     return llvm::createStringError(llvm::errc::invalid_argument,
13092c4226f8SPavel Labath                                    "Memory not allocated by the debugger.");
13102c4226f8SPavel Labath 
13112c4226f8SPavel Labath   llvm::Expected<uint64_t> Result =
13122c4226f8SPavel Labath       Syscall({mmap_data->SysMunmap, addr, it->second});
13132c4226f8SPavel Labath   if (!Result)
13142c4226f8SPavel Labath     return Result.takeError();
13152c4226f8SPavel Labath 
13162c4226f8SPavel Labath   m_allocated_memory.erase(it);
13172c4226f8SPavel Labath   return llvm::Error::success();
1318af245d11STodd Fiala }
1319af245d11STodd Fiala 
1320b9c1b51eSKate Stone size_t NativeProcessLinux::UpdateThreads() {
132105097246SAdrian Prantl   // The NativeProcessLinux monitoring threads are always up to date with
132205097246SAdrian Prantl   // respect to thread state and they keep the thread list populated properly.
132305097246SAdrian Prantl   // All this method needs to do is return the thread count.
1324af245d11STodd Fiala   return m_threads.size();
1325af245d11STodd Fiala }
1326af245d11STodd Fiala 
132797206d57SZachary Turner Status NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size,
1328b9c1b51eSKate Stone                                          bool hardware) {
1329af245d11STodd Fiala   if (hardware)
1330d5ffbad2SOmair Javaid     return SetHardwareBreakpoint(addr, size);
1331af245d11STodd Fiala   else
1332af245d11STodd Fiala     return SetSoftwareBreakpoint(addr, size);
1333af245d11STodd Fiala }
1334af245d11STodd Fiala 
133597206d57SZachary Turner Status NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {
1336d5ffbad2SOmair Javaid   if (hardware)
1337d5ffbad2SOmair Javaid     return RemoveHardwareBreakpoint(addr);
1338d5ffbad2SOmair Javaid   else
1339d5ffbad2SOmair Javaid     return NativeProcessProtocol::RemoveBreakpoint(addr);
1340d5ffbad2SOmair Javaid }
1341d5ffbad2SOmair Javaid 
1342f8b825f6SPavel Labath llvm::Expected<llvm::ArrayRef<uint8_t>>
1343f8b825f6SPavel Labath NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
1344be379e15STamas Berghammer   // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
1345be379e15STamas Berghammer   // linux kernel does otherwise.
1346f8b825f6SPavel Labath   static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
1347f8b825f6SPavel Labath   static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
134812286a27SPavel Labath 
1349f8b825f6SPavel Labath   switch (GetArchitecture().GetMachine()) {
135012286a27SPavel Labath   case llvm::Triple::arm:
1351f8b825f6SPavel Labath     switch (size_hint) {
135263c8be95STamas Berghammer     case 2:
13534f545074SPavel Labath       return llvm::makeArrayRef(g_thumb_opcode);
135463c8be95STamas Berghammer     case 4:
13554f545074SPavel Labath       return llvm::makeArrayRef(g_arm_opcode);
135663c8be95STamas Berghammer     default:
1357f8b825f6SPavel Labath       return llvm::createStringError(llvm::inconvertibleErrorCode(),
1358f8b825f6SPavel Labath                                      "Unrecognised trap opcode size hint!");
135963c8be95STamas Berghammer     }
1360af245d11STodd Fiala   default:
1361f8b825f6SPavel Labath     return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
1362af245d11STodd Fiala   }
1363af245d11STodd Fiala }
1364af245d11STodd Fiala 
136597206d57SZachary Turner Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
1366b9c1b51eSKate Stone                                       size_t &bytes_read) {
1367df7c6995SPavel Labath   if (ProcessVmReadvSupported()) {
1368b9c1b51eSKate Stone     // The process_vm_readv path is about 50 times faster than ptrace api. We
136905097246SAdrian Prantl     // want to use this syscall if it is supported.
1370df7c6995SPavel Labath 
1371df7c6995SPavel Labath     const ::pid_t pid = GetID();
1372df7c6995SPavel Labath 
1373df7c6995SPavel Labath     struct iovec local_iov, remote_iov;
1374df7c6995SPavel Labath     local_iov.iov_base = buf;
1375df7c6995SPavel Labath     local_iov.iov_len = size;
1376df7c6995SPavel Labath     remote_iov.iov_base = reinterpret_cast<void *>(addr);
1377df7c6995SPavel Labath     remote_iov.iov_len = size;
1378df7c6995SPavel Labath 
1379df7c6995SPavel Labath     bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
1380df7c6995SPavel Labath     const bool success = bytes_read == size;
1381df7c6995SPavel Labath 
1382a6321a8eSPavel Labath     Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1383a6321a8eSPavel Labath     LLDB_LOG(log,
1384a6321a8eSPavel Labath              "using process_vm_readv to read {0} bytes from inferior "
1385a6321a8eSPavel Labath              "address {1:x}: {2}",
138610c41f37SPavel Labath              size, addr, success ? "Success" : llvm::sys::StrError(errno));
1387df7c6995SPavel Labath 
1388df7c6995SPavel Labath     if (success)
138997206d57SZachary Turner       return Status();
1390a6321a8eSPavel Labath     // else the call failed for some reason, let's retry the read using ptrace
1391b9c1b51eSKate Stone     // api.
1392df7c6995SPavel Labath   }
1393df7c6995SPavel Labath 
139419cbe96aSPavel Labath   unsigned char *dst = static_cast<unsigned char *>(buf);
139519cbe96aSPavel Labath   size_t remainder;
139619cbe96aSPavel Labath   long data;
139719cbe96aSPavel Labath 
1398a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
1399a6321a8eSPavel Labath   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
140019cbe96aSPavel Labath 
1401b9c1b51eSKate Stone   for (bytes_read = 0; bytes_read < size; bytes_read += remainder) {
140297206d57SZachary Turner     Status error = NativeProcessLinux::PtraceWrapper(
1403b9c1b51eSKate Stone         PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data);
1404a6321a8eSPavel Labath     if (error.Fail())
140519cbe96aSPavel Labath       return error;
140619cbe96aSPavel Labath 
140719cbe96aSPavel Labath     remainder = size - bytes_read;
140819cbe96aSPavel Labath     remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
140919cbe96aSPavel Labath 
141019cbe96aSPavel Labath     // Copy the data into our buffer
1411f6ef187bSMohit K. Bhakkad     memcpy(dst, &data, remainder);
141219cbe96aSPavel Labath 
1413a6321a8eSPavel Labath     LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
141419cbe96aSPavel Labath     addr += k_ptrace_word_size;
141519cbe96aSPavel Labath     dst += k_ptrace_word_size;
141619cbe96aSPavel Labath   }
141797206d57SZachary Turner   return Status();
1418af245d11STodd Fiala }
1419af245d11STodd Fiala 
142097206d57SZachary Turner Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
1421b9c1b51eSKate Stone                                        size_t size, size_t &bytes_written) {
142219cbe96aSPavel Labath   const unsigned char *src = static_cast<const unsigned char *>(buf);
142319cbe96aSPavel Labath   size_t remainder;
142497206d57SZachary Turner   Status error;
142519cbe96aSPavel Labath 
1426a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
1427a6321a8eSPavel Labath   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
142819cbe96aSPavel Labath 
1429b9c1b51eSKate Stone   for (bytes_written = 0; bytes_written < size; bytes_written += remainder) {
143019cbe96aSPavel Labath     remainder = size - bytes_written;
143119cbe96aSPavel Labath     remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder;
143219cbe96aSPavel Labath 
1433b9c1b51eSKate Stone     if (remainder == k_ptrace_word_size) {
143419cbe96aSPavel Labath       unsigned long data = 0;
1435f6ef187bSMohit K. Bhakkad       memcpy(&data, src, k_ptrace_word_size);
143619cbe96aSPavel Labath 
1437a6321a8eSPavel Labath       LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
1438b9c1b51eSKate Stone       error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(),
1439b9c1b51eSKate Stone                                                 (void *)addr, (void *)data);
1440a6321a8eSPavel Labath       if (error.Fail())
144119cbe96aSPavel Labath         return error;
1442b9c1b51eSKate Stone     } else {
144319cbe96aSPavel Labath       unsigned char buff[8];
144419cbe96aSPavel Labath       size_t bytes_read;
144519cbe96aSPavel Labath       error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read);
1446a6321a8eSPavel Labath       if (error.Fail())
144719cbe96aSPavel Labath         return error;
144819cbe96aSPavel Labath 
144919cbe96aSPavel Labath       memcpy(buff, src, remainder);
145019cbe96aSPavel Labath 
145119cbe96aSPavel Labath       size_t bytes_written_rec;
145219cbe96aSPavel Labath       error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec);
1453a6321a8eSPavel Labath       if (error.Fail())
145419cbe96aSPavel Labath         return error;
145519cbe96aSPavel Labath 
1456a6321a8eSPavel Labath       LLDB_LOG(log, "[{0:x}]:{1:x} ({2:x})", addr, *(const unsigned long *)src,
1457b9c1b51eSKate Stone                *(unsigned long *)buff);
145819cbe96aSPavel Labath     }
145919cbe96aSPavel Labath 
146019cbe96aSPavel Labath     addr += k_ptrace_word_size;
146119cbe96aSPavel Labath     src += k_ptrace_word_size;
146219cbe96aSPavel Labath   }
146319cbe96aSPavel Labath   return error;
1464af245d11STodd Fiala }
1465af245d11STodd Fiala 
146697206d57SZachary Turner Status NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) {
146719cbe96aSPavel Labath   return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo);
1468af245d11STodd Fiala }
1469af245d11STodd Fiala 
147097206d57SZachary Turner Status NativeProcessLinux::GetEventMessage(lldb::tid_t tid,
1471b9c1b51eSKate Stone                                            unsigned long *message) {
147219cbe96aSPavel Labath   return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message);
1473af245d11STodd Fiala }
1474af245d11STodd Fiala 
147597206d57SZachary Turner Status NativeProcessLinux::Detach(lldb::tid_t tid) {
147697ccc294SChaoren Lin   if (tid == LLDB_INVALID_THREAD_ID)
147797206d57SZachary Turner     return Status();
147897ccc294SChaoren Lin 
147919cbe96aSPavel Labath   return PtraceWrapper(PTRACE_DETACH, tid);
1480af245d11STodd Fiala }
1481af245d11STodd Fiala 
1482b9c1b51eSKate Stone bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) {
1483a5be48b3SPavel Labath   for (const auto &thread : m_threads) {
1484a5be48b3SPavel Labath     assert(thread && "thread list should not contain NULL threads");
1485a5be48b3SPavel Labath     if (thread->GetID() == thread_id) {
1486af245d11STodd Fiala       // We have this thread.
1487af245d11STodd Fiala       return true;
1488af245d11STodd Fiala     }
1489af245d11STodd Fiala   }
1490af245d11STodd Fiala 
1491af245d11STodd Fiala   // We don't have this thread.
1492af245d11STodd Fiala   return false;
1493af245d11STodd Fiala }
1494af245d11STodd Fiala 
1495b9c1b51eSKate Stone bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) {
1496a6321a8eSPavel Labath   Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
1497a6321a8eSPavel Labath   LLDB_LOG(log, "tid: {0})", thread_id);
14981dbc6c9cSPavel Labath 
14991dbc6c9cSPavel Labath   bool found = false;
1500b9c1b51eSKate Stone   for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
1501b9c1b51eSKate Stone     if (*it && ((*it)->GetID() == thread_id)) {
1502af245d11STodd Fiala       m_threads.erase(it);
15031dbc6c9cSPavel Labath       found = true;
15041dbc6c9cSPavel Labath       break;
1505af245d11STodd Fiala     }
1506af245d11STodd Fiala   }
1507af245d11STodd Fiala 
150899e37695SRavitheja Addepally   if (found)
1509*0b697561SWalter Erquinigo     NotifyTracersOfThreadDestroyed(thread_id);
1510*0b697561SWalter Erquinigo 
15119eb1ecb9SPavel Labath   SignalIfAllThreadsStopped();
15121dbc6c9cSPavel Labath   return found;
1513af245d11STodd Fiala }
1514af245d11STodd Fiala 
1515*0b697561SWalter Erquinigo Status NativeProcessLinux::NotifyTracersOfNewThread(lldb::tid_t tid) {
1516*0b697561SWalter Erquinigo   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
1517*0b697561SWalter Erquinigo   Status error(m_intel_pt_manager.OnThreadCreated(tid));
1518*0b697561SWalter Erquinigo   if (error.Fail())
1519*0b697561SWalter Erquinigo     LLDB_LOG(log, "Failed to trace a new thread with intel-pt, tid = {0}. {1}",
1520*0b697561SWalter Erquinigo              tid, error.AsCString());
1521*0b697561SWalter Erquinigo   return error;
1522*0b697561SWalter Erquinigo }
1523*0b697561SWalter Erquinigo 
1524*0b697561SWalter Erquinigo Status NativeProcessLinux::NotifyTracersOfThreadDestroyed(lldb::tid_t tid) {
1525*0b697561SWalter Erquinigo   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
1526*0b697561SWalter Erquinigo   Status error(m_intel_pt_manager.OnThreadDestroyed(tid));
1527*0b697561SWalter Erquinigo   if (error.Fail())
1528*0b697561SWalter Erquinigo     LLDB_LOG(log,
1529*0b697561SWalter Erquinigo              "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
1530*0b697561SWalter Erquinigo              tid, error.AsCString());
1531*0b697561SWalter Erquinigo   return error;
1532*0b697561SWalter Erquinigo }
1533*0b697561SWalter Erquinigo 
1534*0b697561SWalter Erquinigo NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id,
1535*0b697561SWalter Erquinigo                                                  bool resume) {
1536a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
1537a6321a8eSPavel Labath   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
1538af245d11STodd Fiala 
1539b9c1b51eSKate Stone   assert(!HasThreadNoLock(thread_id) &&
1540b9c1b51eSKate Stone          "attempted to add a thread by id that already exists");
1541af245d11STodd Fiala 
1542af245d11STodd Fiala   // If this is the first thread, save it as the current thread
1543af245d11STodd Fiala   if (m_threads.empty())
1544af245d11STodd Fiala     SetCurrentThreadID(thread_id);
1545af245d11STodd Fiala 
1546a8f3ae7cSJonas Devlieghere   m_threads.push_back(std::make_unique<NativeThreadLinux>(*this, thread_id));
1547*0b697561SWalter Erquinigo   NativeThreadLinux &thread =
1548*0b697561SWalter Erquinigo       static_cast<NativeThreadLinux &>(*m_threads.back());
154999e37695SRavitheja Addepally 
1550*0b697561SWalter Erquinigo   Status tracing_error = NotifyTracersOfNewThread(thread.GetID());
1551*0b697561SWalter Erquinigo   if (tracing_error.Fail()) {
1552*0b697561SWalter Erquinigo     thread.SetStoppedByProcessorTrace(tracing_error.AsCString());
1553*0b697561SWalter Erquinigo     StopRunningThreads(thread.GetID());
1554*0b697561SWalter Erquinigo   } else if (resume)
1555*0b697561SWalter Erquinigo     ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
1556*0b697561SWalter Erquinigo   else
1557*0b697561SWalter Erquinigo     thread.SetStoppedBySignal(SIGSTOP);
155899e37695SRavitheja Addepally 
1559*0b697561SWalter Erquinigo   return thread;
1560af245d11STodd Fiala }
1561af245d11STodd Fiala 
156297206d57SZachary Turner Status NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path,
1563b9c1b51eSKate Stone                                                    FileSpec &file_spec) {
156497206d57SZachary Turner   Status error = PopulateMemoryRegionCache();
1565a6f5795aSTamas Berghammer   if (error.Fail())
1566a6f5795aSTamas Berghammer     return error;
1567a6f5795aSTamas Berghammer 
15688f3be7a3SJonas Devlieghere   FileSpec module_file_spec(module_path);
15698f3be7a3SJonas Devlieghere   FileSystem::Instance().Resolve(module_file_spec);
15707cb18bf5STamas Berghammer 
15717cb18bf5STamas Berghammer   file_spec.Clear();
1572a6f5795aSTamas Berghammer   for (const auto &it : m_mem_region_cache) {
1573a6f5795aSTamas Berghammer     if (it.second.GetFilename() == module_file_spec.GetFilename()) {
1574a6f5795aSTamas Berghammer       file_spec = it.second;
157597206d57SZachary Turner       return Status();
1576a6f5795aSTamas Berghammer     }
1577a6f5795aSTamas Berghammer   }
157897206d57SZachary Turner   return Status("Module file (%s) not found in /proc/%" PRIu64 "/maps file!",
15797cb18bf5STamas Berghammer                 module_file_spec.GetFilename().AsCString(), GetID());
15807cb18bf5STamas Berghammer }
1581c076559aSPavel Labath 
158297206d57SZachary Turner Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name,
1583b9c1b51eSKate Stone                                               lldb::addr_t &load_addr) {
1584783bfc8cSTamas Berghammer   load_addr = LLDB_INVALID_ADDRESS;
158597206d57SZachary Turner   Status error = PopulateMemoryRegionCache();
1586a6f5795aSTamas Berghammer   if (error.Fail())
1587783bfc8cSTamas Berghammer     return error;
1588a6f5795aSTamas Berghammer 
15898f3be7a3SJonas Devlieghere   FileSpec file(file_name);
1590a6f5795aSTamas Berghammer   for (const auto &it : m_mem_region_cache) {
1591a6f5795aSTamas Berghammer     if (it.second == file) {
1592a6f5795aSTamas Berghammer       load_addr = it.first.GetRange().GetRangeBase();
159397206d57SZachary Turner       return Status();
1594a6f5795aSTamas Berghammer     }
1595a6f5795aSTamas Berghammer   }
159697206d57SZachary Turner   return Status("No load address found for specified file.");
1597783bfc8cSTamas Berghammer }
1598783bfc8cSTamas Berghammer 
1599a5be48b3SPavel Labath NativeThreadLinux *NativeProcessLinux::GetThreadByID(lldb::tid_t tid) {
1600a5be48b3SPavel Labath   return static_cast<NativeThreadLinux *>(
1601b9c1b51eSKate Stone       NativeProcessProtocol::GetThreadByID(tid));
1602f9077782SPavel Labath }
1603f9077782SPavel Labath 
16042c4226f8SPavel Labath NativeThreadLinux *NativeProcessLinux::GetCurrentThread() {
16052c4226f8SPavel Labath   return static_cast<NativeThreadLinux *>(
16062c4226f8SPavel Labath       NativeProcessProtocol::GetCurrentThread());
16072c4226f8SPavel Labath }
16082c4226f8SPavel Labath 
160997206d57SZachary Turner Status NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
1610b9c1b51eSKate Stone                                         lldb::StateType state, int signo) {
1611a6321a8eSPavel Labath   Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
1612a6321a8eSPavel Labath   LLDB_LOG(log, "tid: {0}", thread.GetID());
1613c076559aSPavel Labath 
161405097246SAdrian Prantl   // Before we do the resume below, first check if we have a pending stop
161505097246SAdrian Prantl   // notification that is currently waiting for all threads to stop.  This is
161605097246SAdrian Prantl   // potentially a buggy situation since we're ostensibly waiting for threads
161705097246SAdrian Prantl   // to stop before we send out the pending notification, and here we are
161805097246SAdrian Prantl   // resuming one before we send out the pending stop notification.
1619a6321a8eSPavel Labath   if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
1620a6321a8eSPavel Labath     LLDB_LOG(log,
1621a6321a8eSPavel Labath              "about to resume tid {0} per explicit request but we have a "
1622a6321a8eSPavel Labath              "pending stop notification (tid {1}) that is actively "
1623a6321a8eSPavel Labath              "waiting for this thread to stop. Valid sequence of events?",
1624a6321a8eSPavel Labath              thread.GetID(), m_pending_notification_tid);
1625c076559aSPavel Labath   }
1626c076559aSPavel Labath 
162705097246SAdrian Prantl   // Request a resume.  We expect this to be synchronous and the system to
162805097246SAdrian Prantl   // reflect it is running after this completes.
1629b9c1b51eSKate Stone   switch (state) {
1630b9c1b51eSKate Stone   case eStateRunning: {
1631605b51b8SPavel Labath     const auto resume_result = thread.Resume(signo);
16320e1d729bSPavel Labath     if (resume_result.Success())
16330e1d729bSPavel Labath       SetState(eStateRunning, true);
16340e1d729bSPavel Labath     return resume_result;
1635c076559aSPavel Labath   }
1636b9c1b51eSKate Stone   case eStateStepping: {
1637605b51b8SPavel Labath     const auto step_result = thread.SingleStep(signo);
16380e1d729bSPavel Labath     if (step_result.Success())
16390e1d729bSPavel Labath       SetState(eStateRunning, true);
16400e1d729bSPavel Labath     return step_result;
16410e1d729bSPavel Labath   }
16420e1d729bSPavel Labath   default:
16438198db30SPavel Labath     LLDB_LOG(log, "Unhandled state {0}.", state);
16440e1d729bSPavel Labath     llvm_unreachable("Unhandled state for resume");
16450e1d729bSPavel Labath   }
1646c076559aSPavel Labath }
1647c076559aSPavel Labath 
1648c076559aSPavel Labath //===----------------------------------------------------------------------===//
1649c076559aSPavel Labath 
1650b9c1b51eSKate Stone void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) {
1651a6321a8eSPavel Labath   Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
1652a6321a8eSPavel Labath   LLDB_LOG(log, "about to process event: (triggering_tid: {0})",
1653a6321a8eSPavel Labath            triggering_tid);
1654c076559aSPavel Labath 
16550e1d729bSPavel Labath   m_pending_notification_tid = triggering_tid;
16560e1d729bSPavel Labath 
165705097246SAdrian Prantl   // Request a stop for all the thread stops that need to be stopped and are
165805097246SAdrian Prantl   // not already known to be stopped.
1659a5be48b3SPavel Labath   for (const auto &thread : m_threads) {
1660a5be48b3SPavel Labath     if (StateIsRunningState(thread->GetState()))
1661a5be48b3SPavel Labath       static_cast<NativeThreadLinux *>(thread.get())->RequestStop();
16620e1d729bSPavel Labath   }
16630e1d729bSPavel Labath 
16640e1d729bSPavel Labath   SignalIfAllThreadsStopped();
1665a6321a8eSPavel Labath   LLDB_LOG(log, "event processing done");
1666c076559aSPavel Labath }
1667c076559aSPavel Labath 
1668b9c1b51eSKate Stone void NativeProcessLinux::SignalIfAllThreadsStopped() {
16690e1d729bSPavel Labath   if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID)
16700e1d729bSPavel Labath     return; // No pending notification. Nothing to do.
16710e1d729bSPavel Labath 
1672b9c1b51eSKate Stone   for (const auto &thread_sp : m_threads) {
16730e1d729bSPavel Labath     if (StateIsRunningState(thread_sp->GetState()))
16740e1d729bSPavel Labath       return; // Some threads are still running. Don't signal yet.
16750e1d729bSPavel Labath   }
16760e1d729bSPavel Labath 
16770e1d729bSPavel Labath   // We have a pending notification and all threads have stopped.
1678b9c1b51eSKate Stone   Log *log(
1679b9c1b51eSKate Stone       GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS));
16809eb1ecb9SPavel Labath 
1681b9c1b51eSKate Stone   // Clear any temporary breakpoints we used to implement software single
1682b9c1b51eSKate Stone   // stepping.
1683b9c1b51eSKate Stone   for (const auto &thread_info : m_threads_stepping_with_breakpoint) {
168497206d57SZachary Turner     Status error = RemoveBreakpoint(thread_info.second);
16859eb1ecb9SPavel Labath     if (error.Fail())
1686a6321a8eSPavel Labath       LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}",
1687a6321a8eSPavel Labath                thread_info.first, error);
16889eb1ecb9SPavel Labath   }
16899eb1ecb9SPavel Labath   m_threads_stepping_with_breakpoint.clear();
16909eb1ecb9SPavel Labath 
16919eb1ecb9SPavel Labath   // Notify the delegate about the stop
16920e1d729bSPavel Labath   SetCurrentThreadID(m_pending_notification_tid);
1693ed89c7feSPavel Labath   SetState(StateType::eStateStopped, true);
16940e1d729bSPavel Labath   m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
1695c076559aSPavel Labath }
1696c076559aSPavel Labath 
1697b9c1b51eSKate Stone void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
1698a6321a8eSPavel Labath   Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
1699a6321a8eSPavel Labath   LLDB_LOG(log, "tid: {0}", thread.GetID());
17001dbc6c9cSPavel Labath 
1701b9c1b51eSKate Stone   if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID &&
1702b9c1b51eSKate Stone       StateIsRunningState(thread.GetState())) {
1703b9c1b51eSKate Stone     // We will need to wait for this new thread to stop as well before firing
170405097246SAdrian Prantl     // the notification.
1705f9077782SPavel Labath     thread.RequestStop();
1706c076559aSPavel Labath   }
1707c076559aSPavel Labath }
1708068f8a7eSTamas Berghammer 
1709b9c1b51eSKate Stone void NativeProcessLinux::SigchldHandler() {
1710a6321a8eSPavel Labath   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
171119cbe96aSPavel Labath   // Process all pending waitpid notifications.
1712b9c1b51eSKate Stone   while (true) {
171319cbe96aSPavel Labath     int status = -1;
1714c1a6b128SPavel Labath     ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status,
1715c1a6b128SPavel Labath                                           __WALL | __WNOTHREAD | WNOHANG);
171619cbe96aSPavel Labath 
171719cbe96aSPavel Labath     if (wait_pid == 0)
171819cbe96aSPavel Labath       break; // We are done.
171919cbe96aSPavel Labath 
1720b9c1b51eSKate Stone     if (wait_pid == -1) {
172197206d57SZachary Turner       Status error(errno, eErrorTypePOSIX);
1722a6321a8eSPavel Labath       LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error);
172319cbe96aSPavel Labath       break;
172419cbe96aSPavel Labath     }
172519cbe96aSPavel Labath 
17263508fc8cSPavel Labath     WaitStatus wait_status = WaitStatus::Decode(status);
17273508fc8cSPavel Labath     bool exited = wait_status.type == WaitStatus::Exit ||
17283508fc8cSPavel Labath                   (wait_status.type == WaitStatus::Signal &&
17293508fc8cSPavel Labath                    wait_pid == static_cast<::pid_t>(GetID()));
173019cbe96aSPavel Labath 
17313508fc8cSPavel Labath     LLDB_LOG(
17323508fc8cSPavel Labath         log,
17333508fc8cSPavel Labath         "waitpid (-1, &status, _) => pid = {0}, status = {1}, exited = {2}",
17343508fc8cSPavel Labath         wait_pid, wait_status, exited);
173519cbe96aSPavel Labath 
17363508fc8cSPavel Labath     MonitorCallback(wait_pid, exited, wait_status);
173719cbe96aSPavel Labath   }
1738068f8a7eSTamas Berghammer }
1739068f8a7eSTamas Berghammer 
174005097246SAdrian Prantl // Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
174105097246SAdrian Prantl // errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
174297206d57SZachary Turner Status NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
1743b9c1b51eSKate Stone                                          void *data, size_t data_size,
1744b9c1b51eSKate Stone                                          long *result) {
174597206d57SZachary Turner   Status error;
17464a9babb2SPavel Labath   long int ret;
1747068f8a7eSTamas Berghammer 
1748068f8a7eSTamas Berghammer   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
1749068f8a7eSTamas Berghammer 
1750068f8a7eSTamas Berghammer   PtraceDisplayBytes(req, data, data_size);
1751068f8a7eSTamas Berghammer 
1752068f8a7eSTamas Berghammer   errno = 0;
1753068f8a7eSTamas Berghammer   if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET)
1754b9c1b51eSKate Stone     ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid),
1755b9c1b51eSKate Stone                  *(unsigned int *)addr, data);
1756068f8a7eSTamas Berghammer   else
1757b9c1b51eSKate Stone     ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid),
1758b9c1b51eSKate Stone                  addr, data);
1759068f8a7eSTamas Berghammer 
17604a9babb2SPavel Labath   if (ret == -1)
1761068f8a7eSTamas Berghammer     error.SetErrorToErrno();
1762068f8a7eSTamas Berghammer 
17634a9babb2SPavel Labath   if (result)
17644a9babb2SPavel Labath     *result = ret;
17654a9babb2SPavel Labath 
176628096200SPavel Labath   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
176728096200SPavel Labath            data_size, ret);
1768068f8a7eSTamas Berghammer 
1769068f8a7eSTamas Berghammer   PtraceDisplayBytes(req, data, data_size);
1770068f8a7eSTamas Berghammer 
1771a6321a8eSPavel Labath   if (error.Fail())
1772a6321a8eSPavel Labath     LLDB_LOG(log, "ptrace() failed: {0}", error);
1773068f8a7eSTamas Berghammer 
17744a9babb2SPavel Labath   return error;
1775068f8a7eSTamas Berghammer }
177699e37695SRavitheja Addepally 
1777*0b697561SWalter Erquinigo llvm::Expected<TraceSupportedResponse> NativeProcessLinux::TraceSupported() {
1778*0b697561SWalter Erquinigo   if (IntelPTManager::IsSupported())
1779*0b697561SWalter Erquinigo     return TraceSupportedResponse{"intel-pt", "Intel Processor Trace"};
1780*0b697561SWalter Erquinigo   return NativeProcessProtocol::TraceSupported();
178199e37695SRavitheja Addepally }
178299e37695SRavitheja Addepally 
1783*0b697561SWalter Erquinigo Error NativeProcessLinux::TraceStart(StringRef json_request, StringRef type) {
1784*0b697561SWalter Erquinigo   if (type == "intel-pt") {
1785*0b697561SWalter Erquinigo     if (Expected<TraceIntelPTStartRequest> request =
1786*0b697561SWalter Erquinigo             json::parse<TraceIntelPTStartRequest>(json_request,
1787*0b697561SWalter Erquinigo                                                   "TraceIntelPTStartRequest")) {
1788*0b697561SWalter Erquinigo       std::vector<lldb::tid_t> process_threads;
1789*0b697561SWalter Erquinigo       for (auto &thread : m_threads)
1790*0b697561SWalter Erquinigo         process_threads.push_back(thread->GetID());
1791*0b697561SWalter Erquinigo       return m_intel_pt_manager.TraceStart(*request, process_threads);
1792*0b697561SWalter Erquinigo     } else
1793*0b697561SWalter Erquinigo       return request.takeError();
179499e37695SRavitheja Addepally   }
179599e37695SRavitheja Addepally 
1796*0b697561SWalter Erquinigo   return NativeProcessProtocol::TraceStart(json_request, type);
179799e37695SRavitheja Addepally }
179899e37695SRavitheja Addepally 
1799*0b697561SWalter Erquinigo Error NativeProcessLinux::TraceStop(const TraceStopRequest &request) {
1800*0b697561SWalter Erquinigo   if (request.type == "intel-pt")
1801*0b697561SWalter Erquinigo     return m_intel_pt_manager.TraceStop(request);
1802*0b697561SWalter Erquinigo   return NativeProcessProtocol::TraceStop(request);
180399e37695SRavitheja Addepally }
180499e37695SRavitheja Addepally 
1805*0b697561SWalter Erquinigo Expected<json::Value> NativeProcessLinux::TraceGetState(StringRef type) {
1806*0b697561SWalter Erquinigo   if (type == "intel-pt")
1807*0b697561SWalter Erquinigo     return m_intel_pt_manager.GetState();
1808*0b697561SWalter Erquinigo   return NativeProcessProtocol::TraceGetState(type);
180999e37695SRavitheja Addepally }
181099e37695SRavitheja Addepally 
1811*0b697561SWalter Erquinigo Expected<std::vector<uint8_t>> NativeProcessLinux::TraceGetBinaryData(
1812*0b697561SWalter Erquinigo     const TraceGetBinaryDataRequest &request) {
1813*0b697561SWalter Erquinigo   if (request.type == "intel-pt")
1814*0b697561SWalter Erquinigo     return m_intel_pt_manager.GetBinaryData(request);
1815*0b697561SWalter Erquinigo   return NativeProcessProtocol::TraceGetBinaryData(request);
181699e37695SRavitheja Addepally }
1817