180814287SRaphael Isemann //===-- NativeThreadLinux.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 "NativeThreadLinux.h"
10af245d11STodd Fiala 
1176e47d48SRaphael Isemann #include <csignal>
1218fe6404SChaoren Lin #include <sstream>
13af245d11STodd Fiala 
14af245d11STodd Fiala #include "NativeProcessLinux.h"
150f4b17d1SPavel Labath #include "NativeRegisterContextLinux.h"
16605b51b8SPavel Labath #include "SingleStepCheck.h"
172850b1beSTodd Fiala 
1839de3110SZachary Turner #include "lldb/Host/HostNativeThread.h"
19605b51b8SPavel Labath #include "lldb/Host/linux/Ptrace.h"
20225b7952SPavel Labath #include "lldb/Host/linux/Support.h"
21c16f5dcaSChaoren Lin #include "lldb/Utility/LLDBAssert.h"
226f9e6901SZachary Turner #include "lldb/Utility/Log.h"
23d821c997SPavel Labath #include "lldb/Utility/State.h"
24af245d11STodd Fiala #include "lldb/lldb-enumerations.h"
2539de3110SZachary Turner 
2639de3110SZachary Turner #include "llvm/ADT/SmallString.h"
2739de3110SZachary Turner 
2828e57429SChaoren Lin #include "Plugins/Process/POSIX/CrashReason.h"
29d510b5f1SDavid Spickett #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
3028e57429SChaoren Lin 
318c8ff7afSPavel Labath #include <sys/syscall.h>
328c8ff7afSPavel Labath // Try to define a macro to encapsulate the tgkill syscall
338c8ff7afSPavel Labath #define tgkill(pid, tid, sig)                                                  \
34b9c1b51eSKate Stone   syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid),   \
35b9c1b51eSKate Stone           sig)
368c8ff7afSPavel Labath 
37af245d11STodd Fiala using namespace lldb;
38af245d11STodd Fiala using namespace lldb_private;
39db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
40af245d11STodd Fiala 
41b9c1b51eSKate Stone namespace {
42b9c1b51eSKate Stone void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
43b9c1b51eSKate Stone                        const char *const header) {
44b9c1b51eSKate Stone   switch (stop_info.reason) {
4512fd3756SPavel Labath   case eStopReasonNone:
4612fd3756SPavel Labath     log.Printf("%s: %s no stop reason", __FUNCTION__, header);
4712fd3756SPavel Labath     return;
4812fd3756SPavel Labath   case eStopReasonTrace:
49b9c1b51eSKate Stone     log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,
50b9c1b51eSKate Stone                stop_info.details.signal.signo);
5112fd3756SPavel Labath     return;
5212fd3756SPavel Labath   case eStopReasonBreakpoint:
53b9c1b51eSKate Stone     log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
54b9c1b51eSKate Stone                header, stop_info.details.signal.signo);
5512fd3756SPavel Labath     return;
5612fd3756SPavel Labath   case eStopReasonWatchpoint:
57b9c1b51eSKate Stone     log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
58b9c1b51eSKate Stone                header, stop_info.details.signal.signo);
5912fd3756SPavel Labath     return;
60af245d11STodd Fiala   case eStopReasonSignal:
61b9c1b51eSKate Stone     log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,
62b9c1b51eSKate Stone                stop_info.details.signal.signo);
63af245d11STodd Fiala     return;
64af245d11STodd Fiala   case eStopReasonException:
65b9c1b51eSKate Stone     log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,
66b9c1b51eSKate Stone                stop_info.details.exception.type);
67a9882ceeSTodd Fiala     return;
68a9882ceeSTodd Fiala   case eStopReasonExec:
69b9c1b51eSKate Stone     log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,
70b9c1b51eSKate Stone                stop_info.details.signal.signo);
71af245d11STodd Fiala     return;
7212fd3756SPavel Labath   case eStopReasonPlanComplete:
7312fd3756SPavel Labath     log.Printf("%s: %s plan complete", __FUNCTION__, header);
7412fd3756SPavel Labath     return;
7512fd3756SPavel Labath   case eStopReasonThreadExiting:
7612fd3756SPavel Labath     log.Printf("%s: %s thread exiting", __FUNCTION__, header);
7712fd3756SPavel Labath     return;
7812fd3756SPavel Labath   case eStopReasonInstrumentation:
7912fd3756SPavel Labath     log.Printf("%s: %s instrumentation", __FUNCTION__, header);
8012fd3756SPavel Labath     return;
810b697561SWalter Erquinigo   case eStopReasonProcessorTrace:
820b697561SWalter Erquinigo     log.Printf("%s: %s processor trace", __FUNCTION__, header);
830b697561SWalter Erquinigo     return;
84af245d11STodd Fiala   default:
85b9c1b51eSKate Stone     log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
86b9c1b51eSKate Stone                static_cast<uint32_t>(stop_info.reason));
87af245d11STodd Fiala   }
88af245d11STodd Fiala }
89af245d11STodd Fiala }
90af245d11STodd Fiala 
9182abefa4SPavel Labath NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process,
92b9c1b51eSKate Stone                                      lldb::tid_t tid)
93b9c1b51eSKate Stone     : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
94d37349f3SPavel Labath       m_stop_info(),
95d37349f3SPavel Labath       m_reg_context_up(
96d37349f3SPavel Labath           NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
97d37349f3SPavel Labath               process.GetArchitecture(), *this)),
98d37349f3SPavel Labath       m_stop_description() {}
99af245d11STodd Fiala 
100b9c1b51eSKate Stone std::string NativeThreadLinux::GetName() {
101225b7952SPavel Labath   NativeProcessLinux &process = GetProcess();
102af245d11STodd Fiala 
103225b7952SPavel Labath   auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");
104225b7952SPavel Labath   if (!BufferOrError)
105225b7952SPavel Labath     return "";
106adcd0268SBenjamin Kramer   return std::string(BufferOrError.get()->getBuffer().rtrim('\n'));
107af245d11STodd Fiala }
108af245d11STodd Fiala 
109b9c1b51eSKate Stone lldb::StateType NativeThreadLinux::GetState() { return m_state; }
110af245d11STodd Fiala 
111b9c1b51eSKate Stone bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,
112b9c1b51eSKate Stone                                       std::string &description) {
113af245d11STodd Fiala   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
11428e57429SChaoren Lin 
11528e57429SChaoren Lin   description.clear();
11628e57429SChaoren Lin 
117b9c1b51eSKate Stone   switch (m_state) {
118af245d11STodd Fiala   case eStateStopped:
119af245d11STodd Fiala   case eStateCrashed:
120af245d11STodd Fiala   case eStateExited:
121af245d11STodd Fiala   case eStateSuspended:
122af245d11STodd Fiala   case eStateUnloaded:
123af245d11STodd Fiala     if (log)
124af245d11STodd Fiala       LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:");
125af245d11STodd Fiala     stop_info = m_stop_info;
12628e57429SChaoren Lin     description = m_stop_description;
127af245d11STodd Fiala     if (log)
128af245d11STodd Fiala       LogThreadStopInfo(*log, stop_info, "returned stop_info:");
12928e57429SChaoren Lin 
130af245d11STodd Fiala     return true;
131af245d11STodd Fiala 
132af245d11STodd Fiala   case eStateInvalid:
133af245d11STodd Fiala   case eStateConnected:
134af245d11STodd Fiala   case eStateAttaching:
135af245d11STodd Fiala   case eStateLaunching:
136af245d11STodd Fiala   case eStateRunning:
137af245d11STodd Fiala   case eStateStepping:
138af245d11STodd Fiala   case eStateDetached:
139b9c1b51eSKate Stone     if (log) {
14063e5fb76SJonas Devlieghere       LLDB_LOGF(log,
14163e5fb76SJonas Devlieghere                 "NativeThreadLinux::%s tid %" PRIu64
142b9c1b51eSKate Stone                 " in state %s cannot answer stop reason",
143af245d11STodd Fiala                 __FUNCTION__, GetID(), StateAsCString(m_state));
144af245d11STodd Fiala     }
145af245d11STodd Fiala     return false;
146af245d11STodd Fiala   }
1478faf9370SDavid Majnemer   llvm_unreachable("unhandled StateType!");
148af245d11STodd Fiala }
149af245d11STodd Fiala 
15097206d57SZachary Turner Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,
151b9c1b51eSKate Stone                                         uint32_t watch_flags, bool hardware) {
15218fe6404SChaoren Lin   if (!hardware)
15397206d57SZachary Turner     return Status("not implemented");
154f591f69fSChaoren Lin   if (m_state == eStateLaunching)
15597206d57SZachary Turner     return Status();
15697206d57SZachary Turner   Status error = RemoveWatchpoint(addr);
157b9c1b51eSKate Stone   if (error.Fail())
158b9c1b51eSKate Stone     return error;
159d37349f3SPavel Labath   uint32_t wp_index =
160d37349f3SPavel Labath       m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
16118fe6404SChaoren Lin   if (wp_index == LLDB_INVALID_INDEX32)
16297206d57SZachary Turner     return Status("Setting hardware watchpoint failed.");
16318fe6404SChaoren Lin   m_watchpoint_index_map.insert({addr, wp_index});
16497206d57SZachary Turner   return Status();
165af245d11STodd Fiala }
166af245d11STodd Fiala 
16797206d57SZachary Turner Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
16818fe6404SChaoren Lin   auto wp = m_watchpoint_index_map.find(addr);
16918fe6404SChaoren Lin   if (wp == m_watchpoint_index_map.end())
17097206d57SZachary Turner     return Status();
17118fe6404SChaoren Lin   uint32_t wp_index = wp->second;
17218fe6404SChaoren Lin   m_watchpoint_index_map.erase(wp);
173d37349f3SPavel Labath   if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))
17497206d57SZachary Turner     return Status();
17597206d57SZachary Turner   return Status("Clearing hardware watchpoint failed.");
176af245d11STodd Fiala }
177af245d11STodd Fiala 
17897206d57SZachary Turner Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr,
17997206d57SZachary Turner                                                 size_t size) {
180d5ffbad2SOmair Javaid   if (m_state == eStateLaunching)
18197206d57SZachary Turner     return Status();
182d5ffbad2SOmair Javaid 
18397206d57SZachary Turner   Status error = RemoveHardwareBreakpoint(addr);
184d5ffbad2SOmair Javaid   if (error.Fail())
185d5ffbad2SOmair Javaid     return error;
186d5ffbad2SOmair Javaid 
187d37349f3SPavel Labath   uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);
188d5ffbad2SOmair Javaid 
189d5ffbad2SOmair Javaid   if (bp_index == LLDB_INVALID_INDEX32)
19097206d57SZachary Turner     return Status("Setting hardware breakpoint failed.");
191d5ffbad2SOmair Javaid 
192d5ffbad2SOmair Javaid   m_hw_break_index_map.insert({addr, bp_index});
19397206d57SZachary Turner   return Status();
194d5ffbad2SOmair Javaid }
195d5ffbad2SOmair Javaid 
19697206d57SZachary Turner Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {
197d5ffbad2SOmair Javaid   auto bp = m_hw_break_index_map.find(addr);
198d5ffbad2SOmair Javaid   if (bp == m_hw_break_index_map.end())
19997206d57SZachary Turner     return Status();
200d5ffbad2SOmair Javaid 
201d5ffbad2SOmair Javaid   uint32_t bp_index = bp->second;
202d37349f3SPavel Labath   if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) {
203d5ffbad2SOmair Javaid     m_hw_break_index_map.erase(bp);
20497206d57SZachary Turner     return Status();
205d5ffbad2SOmair Javaid   }
206d5ffbad2SOmair Javaid 
20797206d57SZachary Turner   return Status("Clearing hardware breakpoint failed.");
208d5ffbad2SOmair Javaid }
209d5ffbad2SOmair Javaid 
21097206d57SZachary Turner Status NativeThreadLinux::Resume(uint32_t signo) {
211af245d11STodd Fiala   const StateType new_state = StateType::eStateRunning;
212af245d11STodd Fiala   MaybeLogStateChange(new_state);
213af245d11STodd Fiala   m_state = new_state;
214af245d11STodd Fiala 
215af245d11STodd Fiala   m_stop_info.reason = StopReason::eStopReasonNone;
21628e57429SChaoren Lin   m_stop_description.clear();
21718fe6404SChaoren Lin 
21805097246SAdrian Prantl   // If watchpoints have been set, but none on this thread, then this is a new
21905097246SAdrian Prantl   // thread. So set all existing watchpoints.
220b9c1b51eSKate Stone   if (m_watchpoint_index_map.empty()) {
221605b51b8SPavel Labath     NativeProcessLinux &process = GetProcess();
222605b51b8SPavel Labath 
223605b51b8SPavel Labath     const auto &watchpoint_map = process.GetWatchpointMap();
224d37349f3SPavel Labath     m_reg_context_up->ClearAllHardwareWatchpoints();
225b9c1b51eSKate Stone     for (const auto &pair : watchpoint_map) {
22618fe6404SChaoren Lin       const auto &wp = pair.second;
22718fe6404SChaoren Lin       SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware);
22818fe6404SChaoren Lin     }
22918fe6404SChaoren Lin   }
230605b51b8SPavel Labath 
231d5ffbad2SOmair Javaid   // Set all active hardware breakpoint on all threads.
232d5ffbad2SOmair Javaid   if (m_hw_break_index_map.empty()) {
233d5ffbad2SOmair Javaid     NativeProcessLinux &process = GetProcess();
234d5ffbad2SOmair Javaid 
235d5ffbad2SOmair Javaid     const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();
236d37349f3SPavel Labath     m_reg_context_up->ClearAllHardwareBreakpoints();
237d5ffbad2SOmair Javaid     for (const auto &pair : hw_breakpoint_map) {
238d5ffbad2SOmair Javaid       const auto &bp = pair.second;
239d5ffbad2SOmair Javaid       SetHardwareBreakpoint(bp.m_addr, bp.m_size);
240d5ffbad2SOmair Javaid     }
241d5ffbad2SOmair Javaid   }
242d5ffbad2SOmair Javaid 
243605b51b8SPavel Labath   intptr_t data = 0;
244605b51b8SPavel Labath 
245605b51b8SPavel Labath   if (signo != LLDB_INVALID_SIGNAL_NUMBER)
246605b51b8SPavel Labath     data = signo;
247605b51b8SPavel Labath 
248b9c1b51eSKate Stone   return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr,
249b9c1b51eSKate Stone                                            reinterpret_cast<void *>(data));
250605b51b8SPavel Labath }
251605b51b8SPavel Labath 
25297206d57SZachary Turner Status NativeThreadLinux::SingleStep(uint32_t signo) {
253af245d11STodd Fiala   const StateType new_state = StateType::eStateStepping;
254af245d11STodd Fiala   MaybeLogStateChange(new_state);
255af245d11STodd Fiala   m_state = new_state;
256af245d11STodd Fiala   m_stop_info.reason = StopReason::eStopReasonNone;
257a37bbbd4SPavel Labath 
258a37bbbd4SPavel Labath   if(!m_step_workaround) {
259a37bbbd4SPavel Labath     // If we already hava a workaround inplace, don't reset it. Otherwise, the
260a37bbbd4SPavel Labath     // destructor of the existing instance will run after the new instance has
261a37bbbd4SPavel Labath     // fetched the cpu mask, and the thread will end up with the wrong mask.
2628abd34f0SPavel Labath     m_step_workaround = SingleStepWorkaround::Get(m_tid);
263a37bbbd4SPavel Labath   }
264605b51b8SPavel Labath 
265605b51b8SPavel Labath   intptr_t data = 0;
266605b51b8SPavel Labath   if (signo != LLDB_INVALID_SIGNAL_NUMBER)
267605b51b8SPavel Labath     data = signo;
268605b51b8SPavel Labath 
269b9c1b51eSKate Stone   // If hardware single-stepping is not supported, we just do a continue. The
27005097246SAdrian Prantl   // breakpoint on the next instruction has been setup in
27105097246SAdrian Prantl   // NativeProcessLinux::Resume.
272b9c1b51eSKate Stone   return NativeProcessLinux::PtraceWrapper(
273b9c1b51eSKate Stone       GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
274605b51b8SPavel Labath                                                    : PTRACE_CONT,
275605b51b8SPavel Labath       m_tid, nullptr, reinterpret_cast<void *>(data));
276af245d11STodd Fiala }
277af245d11STodd Fiala 
278b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,
279b9c1b51eSKate Stone                                            const siginfo_t *info) {
280af245d11STodd Fiala   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
28163e5fb76SJonas Devlieghere   LLDB_LOGF(log, "NativeThreadLinux::%s called with signal 0x%02" PRIx32,
282b9c1b51eSKate Stone             __FUNCTION__, signo);
283af245d11STodd Fiala 
284605b51b8SPavel Labath   SetStopped();
285af245d11STodd Fiala 
286af245d11STodd Fiala   m_stop_info.reason = StopReason::eStopReasonSignal;
287af245d11STodd Fiala   m_stop_info.details.signal.signo = signo;
288c4e25c96SPavel Labath 
289c4e25c96SPavel Labath   m_stop_description.clear();
290b9c1b51eSKate Stone   if (info) {
291b9c1b51eSKate Stone     switch (signo) {
292c4e25c96SPavel Labath     case SIGSEGV:
293c4e25c96SPavel Labath     case SIGBUS:
294c4e25c96SPavel Labath     case SIGFPE:
295c4e25c96SPavel Labath     case SIGILL:
296b9c1b51eSKate Stone       // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit
297b9c1b51eSKate Stone       // address.
298b9c1b51eSKate Stone       const auto reason =
299b9c1b51eSKate Stone           (info->si_signo == SIGBUS && info->si_code == SI_KERNEL)
300b9c1b51eSKate Stone               ? CrashReason::eInvalidAddress
301b9c1b51eSKate Stone               : GetCrashReason(*info);
3026f8c1f8dSValentina Giusti       m_stop_description = GetCrashReasonString(reason, *info);
303d510b5f1SDavid Spickett 
304d510b5f1SDavid Spickett       if (reason == CrashReason::eSyncTagCheckFault) {
305d510b5f1SDavid Spickett         AnnotateSyncTagCheckFault(info);
306d510b5f1SDavid Spickett       }
307d510b5f1SDavid Spickett 
308c4e25c96SPavel Labath       break;
309c4e25c96SPavel Labath     }
310af245d11STodd Fiala   }
3113681c5b8SMohit K. Bhakkad }
312af245d11STodd Fiala 
313d510b5f1SDavid Spickett void NativeThreadLinux::AnnotateSyncTagCheckFault(const siginfo_t *info) {
314d510b5f1SDavid Spickett   int32_t allocation_tag_type = 0;
315d510b5f1SDavid Spickett   switch (GetProcess().GetArchitecture().GetMachine()) {
316d510b5f1SDavid Spickett   // aarch64_32 deliberately not here because there's no 32 bit MTE
317d510b5f1SDavid Spickett   case llvm::Triple::aarch64:
318d510b5f1SDavid Spickett   case llvm::Triple::aarch64_be:
319d510b5f1SDavid Spickett     allocation_tag_type = MemoryTagManagerAArch64MTE::eMTE_allocation;
320d510b5f1SDavid Spickett     break;
321d510b5f1SDavid Spickett   default:
322d510b5f1SDavid Spickett     return;
323d510b5f1SDavid Spickett   }
324d510b5f1SDavid Spickett 
325d510b5f1SDavid Spickett   auto details =
326d510b5f1SDavid Spickett       GetRegisterContext().GetMemoryTaggingDetails(allocation_tag_type);
327d510b5f1SDavid Spickett   if (!details) {
328d510b5f1SDavid Spickett     llvm::consumeError(details.takeError());
329d510b5f1SDavid Spickett     return;
330d510b5f1SDavid Spickett   }
331d510b5f1SDavid Spickett 
332d510b5f1SDavid Spickett   // We assume that the stop description is currently:
333d510b5f1SDavid Spickett   // signal SIGSEGV: sync tag check fault (fault address: <addr>)
334d510b5f1SDavid Spickett   // Remove the closing )
335d510b5f1SDavid Spickett   m_stop_description.pop_back();
336d510b5f1SDavid Spickett 
337d510b5f1SDavid Spickett   std::stringstream ss;
338d510b5f1SDavid Spickett   lldb::addr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
339d510b5f1SDavid Spickett   std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));
340d510b5f1SDavid Spickett 
341d510b5f1SDavid Spickett   ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr);
342d510b5f1SDavid Spickett 
343d510b5f1SDavid Spickett   std::vector<uint8_t> allocation_tag_data;
344d510b5f1SDavid Spickett   // The fault address may not be granule aligned. ReadMemoryTags will granule
345d510b5f1SDavid Spickett   // align any range you give it, potentially making it larger.
346d510b5f1SDavid Spickett   // To prevent this set len to 1. This always results in a range that is at
347d510b5f1SDavid Spickett   // most 1 granule in size and includes fault_addr.
348d510b5f1SDavid Spickett   Status status = GetProcess().ReadMemoryTags(allocation_tag_type, fault_addr,
349d510b5f1SDavid Spickett                                               1, allocation_tag_data);
350d510b5f1SDavid Spickett 
351d510b5f1SDavid Spickett   if (status.Success()) {
352d510b5f1SDavid Spickett     llvm::Expected<std::vector<lldb::addr_t>> allocation_tag =
353d510b5f1SDavid Spickett         manager->UnpackTagsData(allocation_tag_data, 1);
354d510b5f1SDavid Spickett     if (allocation_tag) {
355d510b5f1SDavid Spickett       ss << " allocation tag: 0x" << std::hex << allocation_tag->front() << ")";
356d510b5f1SDavid Spickett     } else {
357d510b5f1SDavid Spickett       llvm::consumeError(allocation_tag.takeError());
358d510b5f1SDavid Spickett       ss << ")";
359d510b5f1SDavid Spickett     }
360d510b5f1SDavid Spickett   } else
361d510b5f1SDavid Spickett     ss << ")";
362d510b5f1SDavid Spickett 
363d510b5f1SDavid Spickett   m_stop_description += ss.str();
364d510b5f1SDavid Spickett }
365d510b5f1SDavid Spickett 
366b9c1b51eSKate Stone bool NativeThreadLinux::IsStopped(int *signo) {
367511e5cdcSTodd Fiala   if (!StateIsStoppedState(m_state, false))
368511e5cdcSTodd Fiala     return false;
369511e5cdcSTodd Fiala 
370511e5cdcSTodd Fiala   // If we are stopped by a signal, return the signo.
371b9c1b51eSKate Stone   if (signo && m_state == StateType::eStateStopped &&
372b9c1b51eSKate Stone       m_stop_info.reason == StopReason::eStopReasonSignal) {
373511e5cdcSTodd Fiala     *signo = m_stop_info.details.signal.signo;
374511e5cdcSTodd Fiala   }
375511e5cdcSTodd Fiala 
376511e5cdcSTodd Fiala   // Regardless, we are stopped.
377511e5cdcSTodd Fiala   return true;
378511e5cdcSTodd Fiala }
379511e5cdcSTodd Fiala 
380b9c1b51eSKate Stone void NativeThreadLinux::SetStopped() {
381605b51b8SPavel Labath   if (m_state == StateType::eStateStepping)
3828abd34f0SPavel Labath     m_step_workaround.reset();
383605b51b8SPavel Labath 
384af4f40c3SMuhammad Omair Javaid   // On every stop, clear any cached register data structures
385af4f40c3SMuhammad Omair Javaid   GetRegisterContext().InvalidateAllRegisters();
386af4f40c3SMuhammad Omair Javaid 
387605b51b8SPavel Labath   const StateType new_state = StateType::eStateStopped;
388605b51b8SPavel Labath   MaybeLogStateChange(new_state);
389605b51b8SPavel Labath   m_state = new_state;
390605b51b8SPavel Labath   m_stop_description.clear();
391605b51b8SPavel Labath }
392511e5cdcSTodd Fiala 
393b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedByExec() {
394a9882ceeSTodd Fiala   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
39563e5fb76SJonas Devlieghere   LLDB_LOGF(log, "NativeThreadLinux::%s()", __FUNCTION__);
396a9882ceeSTodd Fiala 
397605b51b8SPavel Labath   SetStopped();
398a9882ceeSTodd Fiala 
399a9882ceeSTodd Fiala   m_stop_info.reason = StopReason::eStopReasonExec;
400a9882ceeSTodd Fiala   m_stop_info.details.signal.signo = SIGSTOP;
401a9882ceeSTodd Fiala }
402a9882ceeSTodd Fiala 
403b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedByBreakpoint() {
404605b51b8SPavel Labath   SetStopped();
405af245d11STodd Fiala 
40628e57429SChaoren Lin   m_stop_info.reason = StopReason::eStopReasonBreakpoint;
407af245d11STodd Fiala   m_stop_info.details.signal.signo = SIGTRAP;
40818fe6404SChaoren Lin   m_stop_description.clear();
40918fe6404SChaoren Lin }
41018fe6404SChaoren Lin 
411b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {
412605b51b8SPavel Labath   SetStopped();
413c16f5dcaSChaoren Lin 
414b9c1b51eSKate Stone   lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
415eadb2a9eSTamas Berghammer 
41618fe6404SChaoren Lin   std::ostringstream ostr;
417d37349f3SPavel Labath   ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " ";
418c16f5dcaSChaoren Lin   ostr << wp_index;
41983143504SJaydeep Patil 
42083143504SJaydeep Patil   /*
421b9c1b51eSKate Stone    * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For
422b9c1b51eSKate Stone    * example:
423b9c1b51eSKate Stone    * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
424b9c1b51eSKate Stone    * 'm', then
425b9c1b51eSKate Stone    * watch exception is generated even when 'n' is read/written. To handle this
426b9c1b51eSKate Stone    * case,
427b9c1b51eSKate Stone    * find the base address of the load/store instruction and append it in the
428b9c1b51eSKate Stone    * stop-info
42983143504SJaydeep Patil    * packet.
43083143504SJaydeep Patil   */
431d37349f3SPavel Labath   ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index);
43283143504SJaydeep Patil 
43318fe6404SChaoren Lin   m_stop_description = ostr.str();
434eadb2a9eSTamas Berghammer 
435eadb2a9eSTamas Berghammer   m_stop_info.reason = StopReason::eStopReasonWatchpoint;
436eadb2a9eSTamas Berghammer   m_stop_info.details.signal.signo = SIGTRAP;
437af245d11STodd Fiala }
438af245d11STodd Fiala 
439b9c1b51eSKate Stone bool NativeThreadLinux::IsStoppedAtBreakpoint() {
44018fe6404SChaoren Lin   return GetState() == StateType::eStateStopped &&
44118fe6404SChaoren Lin          m_stop_info.reason == StopReason::eStopReasonBreakpoint;
44218fe6404SChaoren Lin }
443af245d11STodd Fiala 
444b9c1b51eSKate Stone bool NativeThreadLinux::IsStoppedAtWatchpoint() {
44518fe6404SChaoren Lin   return GetState() == StateType::eStateStopped &&
44618fe6404SChaoren Lin          m_stop_info.reason == StopReason::eStopReasonWatchpoint;
447af245d11STodd Fiala }
448af245d11STodd Fiala 
449b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedByTrace() {
450605b51b8SPavel Labath   SetStopped();
45128e57429SChaoren Lin 
45228e57429SChaoren Lin   m_stop_info.reason = StopReason::eStopReasonTrace;
45328e57429SChaoren Lin   m_stop_info.details.signal.signo = SIGTRAP;
45428e57429SChaoren Lin }
45528e57429SChaoren Lin 
456fd0af0cfSMichał Górny void NativeThreadLinux::SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid) {
457fd0af0cfSMichał Górny   SetStopped();
458fd0af0cfSMichał Górny 
459fd0af0cfSMichał Górny   m_stop_info.reason =
460fd0af0cfSMichał Górny       is_vfork ? StopReason::eStopReasonVFork : StopReason::eStopReasonFork;
461fd0af0cfSMichał Górny   m_stop_info.details.fork.child_pid = child_pid;
462fd0af0cfSMichał Górny   m_stop_info.details.fork.child_tid = child_pid;
463fd0af0cfSMichał Górny }
464fd0af0cfSMichał Górny 
465fd0af0cfSMichał Górny void NativeThreadLinux::SetStoppedByVForkDone() {
466fd0af0cfSMichał Górny   SetStopped();
467fd0af0cfSMichał Górny 
468fd0af0cfSMichał Górny   m_stop_info.reason = StopReason::eStopReasonVForkDone;
469fd0af0cfSMichał Górny }
470fd0af0cfSMichał Górny 
471b9c1b51eSKate Stone void NativeThreadLinux::SetStoppedWithNoReason() {
472605b51b8SPavel Labath   SetStopped();
473af245d11STodd Fiala 
474af245d11STodd Fiala   m_stop_info.reason = StopReason::eStopReasonNone;
47505569f67SPavel Labath   m_stop_info.details.signal.signo = 0;
476af245d11STodd Fiala }
477af245d11STodd Fiala 
4780b697561SWalter Erquinigo void NativeThreadLinux::SetStoppedByProcessorTrace(
4790b697561SWalter Erquinigo     llvm::StringRef description) {
4800b697561SWalter Erquinigo   SetStopped();
4810b697561SWalter Erquinigo 
4820b697561SWalter Erquinigo   m_stop_info.reason = StopReason::eStopReasonProcessorTrace;
4830b697561SWalter Erquinigo   m_stop_info.details.signal.signo = 0;
4840b697561SWalter Erquinigo   m_stop_description = description.str();
4850b697561SWalter Erquinigo }
4860b697561SWalter Erquinigo 
487b9c1b51eSKate Stone void NativeThreadLinux::SetExited() {
488af245d11STodd Fiala   const StateType new_state = StateType::eStateExited;
489af245d11STodd Fiala   MaybeLogStateChange(new_state);
490af245d11STodd Fiala   m_state = new_state;
491af245d11STodd Fiala 
492af245d11STodd Fiala   m_stop_info.reason = StopReason::eStopReasonThreadExiting;
493af245d11STodd Fiala }
494af245d11STodd Fiala 
49597206d57SZachary Turner Status NativeThreadLinux::RequestStop() {
4968c8ff7afSPavel Labath   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
4978c8ff7afSPavel Labath 
498605b51b8SPavel Labath   NativeProcessLinux &process = GetProcess();
4998c8ff7afSPavel Labath 
500605b51b8SPavel Labath   lldb::pid_t pid = process.GetID();
5018c8ff7afSPavel Labath   lldb::tid_t tid = GetID();
5028c8ff7afSPavel Labath 
50363e5fb76SJonas Devlieghere   LLDB_LOGF(log,
50463e5fb76SJonas Devlieghere             "NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64
505b9c1b51eSKate Stone             ", tid: %" PRIu64 ")",
506b9c1b51eSKate Stone             __FUNCTION__, pid, tid);
5078c8ff7afSPavel Labath 
50897206d57SZachary Turner   Status err;
5098c8ff7afSPavel Labath   errno = 0;
510b9c1b51eSKate Stone   if (::tgkill(pid, tid, SIGSTOP) != 0) {
5118c8ff7afSPavel Labath     err.SetErrorToErrno();
51263e5fb76SJonas Devlieghere     LLDB_LOGF(log,
51363e5fb76SJonas Devlieghere               "NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64
514b9c1b51eSKate Stone               ", SIGSTOP) failed: %s",
515b9c1b51eSKate Stone               __FUNCTION__, pid, tid, err.AsCString());
5168c8ff7afSPavel Labath   }
5178c8ff7afSPavel Labath 
5188c8ff7afSPavel Labath   return err;
5198c8ff7afSPavel Labath }
5208c8ff7afSPavel Labath 
521b9c1b51eSKate Stone void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
522af245d11STodd Fiala   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
523af245d11STodd Fiala   // If we're not logging, we're done.
524af245d11STodd Fiala   if (!log)
525af245d11STodd Fiala     return;
526af245d11STodd Fiala 
527af245d11STodd Fiala   // If this is a state change to the same state, we're done.
528af245d11STodd Fiala   lldb::StateType old_state = m_state;
529af245d11STodd Fiala   if (new_state == old_state)
530af245d11STodd Fiala     return;
531af245d11STodd Fiala 
53282abefa4SPavel Labath   LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}",
53382abefa4SPavel Labath            m_process.GetID(), GetID(), old_state, new_state);
534af245d11STodd Fiala }
535605b51b8SPavel Labath 
536b9c1b51eSKate Stone NativeProcessLinux &NativeThreadLinux::GetProcess() {
53782abefa4SPavel Labath   return static_cast<NativeProcessLinux &>(m_process);
538605b51b8SPavel Labath }
5391e74e5e9SMichał Górny 
5401e74e5e9SMichał Górny const NativeProcessLinux &NativeThreadLinux::GetProcess() const {
5411e74e5e9SMichał Górny   return static_cast<const NativeProcessLinux &>(m_process);
5421e74e5e9SMichał Górny }
5431e74e5e9SMichał Górny 
5441e74e5e9SMichał Górny llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
5451e74e5e9SMichał Górny NativeThreadLinux::GetSiginfo() const {
5461e74e5e9SMichał Górny   auto siginfo_buf =
5471e74e5e9SMichał Górny       llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeof(siginfo_t));
5481e74e5e9SMichał Górny   Status error =
5491e74e5e9SMichał Górny       GetProcess().GetSignalInfo(GetID(), siginfo_buf->getBufferStart());
5501e74e5e9SMichał Górny   if (!error.Success())
5511e74e5e9SMichał Górny     return error.ToError();
552*8bfa7a6dSPavel Labath   return std::move(siginfo_buf);
5531e74e5e9SMichał Górny }
554