1//===-- NativeThreadLinux.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "NativeThreadLinux.h"
10
11#include <csignal>
12#include <sstream>
13
14#include "NativeProcessLinux.h"
15#include "NativeRegisterContextLinux.h"
16#include "SingleStepCheck.h"
17
18#include "lldb/Host/HostNativeThread.h"
19#include "lldb/Host/linux/Ptrace.h"
20#include "lldb/Host/linux/Support.h"
21#include "lldb/Utility/LLDBAssert.h"
22#include "lldb/Utility/LLDBLog.h"
23#include "lldb/Utility/Log.h"
24#include "lldb/Utility/State.h"
25#include "lldb/lldb-enumerations.h"
26
27#include "llvm/ADT/SmallString.h"
28
29#include "Plugins/Process/POSIX/CrashReason.h"
30#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
31
32#include <sys/syscall.h>
33// Try to define a macro to encapsulate the tgkill syscall
34#define tgkill(pid, tid, sig) \
35 syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \
36 sig)
37
38using namespace lldb;
39using namespace lldb_private;
40using namespace lldb_private::process_linux;
41
42namespace {
43void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info,
44 const char *const header) {
45 switch (stop_info.reason) {
46 case eStopReasonNone:
47 log.Printf(format: "%s: %s no stop reason", __FUNCTION__, header);
48 return;
49 case eStopReasonTrace:
50 log.Printf(format: "%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header,
51 stop_info.signo);
52 return;
53 case eStopReasonBreakpoint:
54 log.Printf(format: "%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
55 header, stop_info.signo);
56 return;
57 case eStopReasonWatchpoint:
58 log.Printf(format: "%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__,
59 header, stop_info.signo);
60 return;
61 case eStopReasonSignal:
62 log.Printf(format: "%s: %s signal 0x%02" PRIx32, __FUNCTION__, header,
63 stop_info.signo);
64 return;
65 case eStopReasonException:
66 log.Printf(format: "%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header,
67 stop_info.details.exception.type);
68 return;
69 case eStopReasonExec:
70 log.Printf(format: "%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header,
71 stop_info.signo);
72 return;
73 case eStopReasonPlanComplete:
74 log.Printf(format: "%s: %s plan complete", __FUNCTION__, header);
75 return;
76 case eStopReasonThreadExiting:
77 log.Printf(format: "%s: %s thread exiting", __FUNCTION__, header);
78 return;
79 case eStopReasonInstrumentation:
80 log.Printf(format: "%s: %s instrumentation", __FUNCTION__, header);
81 return;
82 case eStopReasonProcessorTrace:
83 log.Printf(format: "%s: %s processor trace", __FUNCTION__, header);
84 return;
85 case eStopReasonHistoryBoundary:
86 log.Printf(format: "%s: %s history boundary", __FUNCTION__, header);
87 return;
88 default:
89 log.Printf(format: "%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
90 static_cast<uint32_t>(stop_info.reason));
91 }
92}
93}
94
95NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process,
96 lldb::tid_t tid)
97 : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid),
98 m_stop_info(),
99 m_reg_context_up(
100 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
101 target_arch: process.GetArchitecture(), native_thread&: *this)),
102 m_stop_description() {}
103
104std::string NativeThreadLinux::GetName() {
105 NativeProcessLinux &process = GetProcess();
106
107 auto BufferOrError = getProcFile(pid: process.GetID(), tid: GetID(), file: "comm");
108 if (!BufferOrError)
109 return "";
110 return std::string(BufferOrError.get()->getBuffer().rtrim(Char: '\n'));
111}
112
113lldb::StateType NativeThreadLinux::GetState() { return m_state; }
114
115bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info,
116 std::string &description) {
117 Log *log = GetLog(mask: LLDBLog::Thread);
118
119 description.clear();
120
121 switch (m_state) {
122 case eStateStopped:
123 case eStateCrashed:
124 case eStateExited:
125 case eStateSuspended:
126 case eStateUnloaded:
127 if (log)
128 LogThreadStopInfo(log&: *log, stop_info: m_stop_info, header: "m_stop_info in thread:");
129 stop_info = m_stop_info;
130 description = m_stop_description;
131 if (log)
132 LogThreadStopInfo(log&: *log, stop_info, header: "returned stop_info:");
133
134 return true;
135
136 case eStateInvalid:
137 case eStateConnected:
138 case eStateAttaching:
139 case eStateLaunching:
140 case eStateRunning:
141 case eStateStepping:
142 case eStateDetached:
143 if (log) {
144 LLDB_LOGF(log,
145 "NativeThreadLinux::%s tid %" PRIu64
146 " in state %s cannot answer stop reason",
147 __FUNCTION__, GetID(), StateAsCString(m_state));
148 }
149 return false;
150 }
151 llvm_unreachable("unhandled StateType!");
152}
153
154Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size,
155 uint32_t watch_flags, bool hardware) {
156 if (!hardware)
157 return Status::FromErrorString(str: "not implemented");
158 if (m_state == eStateLaunching)
159 return Status();
160 Status error = RemoveWatchpoint(addr);
161 if (error.Fail())
162 return error;
163 uint32_t wp_index =
164 m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
165 if (wp_index == LLDB_INVALID_INDEX32)
166 return Status::FromErrorString(str: "Setting hardware watchpoint failed.");
167 m_watchpoint_index_map.insert(x: {addr, wp_index});
168 return Status();
169}
170
171Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) {
172 auto wp = m_watchpoint_index_map.find(x: addr);
173 if (wp == m_watchpoint_index_map.end())
174 return Status();
175 uint32_t wp_index = wp->second;
176 m_watchpoint_index_map.erase(position: wp);
177 if (m_reg_context_up->ClearHardwareWatchpoint(hw_index: wp_index))
178 return Status();
179 return Status::FromErrorString(str: "Clearing hardware watchpoint failed.");
180}
181
182Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr,
183 size_t size) {
184 if (m_state == eStateLaunching)
185 return Status();
186
187 Status error = RemoveHardwareBreakpoint(addr);
188 if (error.Fail())
189 return error;
190
191 uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size);
192
193 if (bp_index == LLDB_INVALID_INDEX32)
194 return Status::FromErrorString(str: "Setting hardware breakpoint failed.");
195
196 m_hw_break_index_map.insert(x: {addr, bp_index});
197 return Status();
198}
199
200Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) {
201 auto bp = m_hw_break_index_map.find(x: addr);
202 if (bp == m_hw_break_index_map.end())
203 return Status();
204
205 uint32_t bp_index = bp->second;
206 if (m_reg_context_up->ClearHardwareBreakpoint(hw_idx: bp_index)) {
207 m_hw_break_index_map.erase(position: bp);
208 return Status();
209 }
210
211 return Status::FromErrorString(str: "Clearing hardware breakpoint failed.");
212}
213
214Status NativeThreadLinux::Resume(uint32_t signo) {
215 const StateType new_state = StateType::eStateRunning;
216 MaybeLogStateChange(new_state);
217 m_state = new_state;
218
219 m_stop_info.reason = StopReason::eStopReasonNone;
220 m_stop_description.clear();
221
222 // If watchpoints have been set, but none on this thread, then this is a new
223 // thread. So set all existing watchpoints.
224 if (m_watchpoint_index_map.empty()) {
225 NativeProcessLinux &process = GetProcess();
226
227 const auto &watchpoint_map = process.GetWatchpointMap();
228 m_reg_context_up->ClearAllHardwareWatchpoints();
229 for (const auto &pair : watchpoint_map) {
230 const auto &wp = pair.second;
231 SetWatchpoint(addr: wp.m_addr, size: wp.m_size, watch_flags: wp.m_watch_flags, hardware: wp.m_hardware);
232 }
233 }
234
235 // Set all active hardware breakpoint on all threads.
236 if (m_hw_break_index_map.empty()) {
237 NativeProcessLinux &process = GetProcess();
238
239 const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap();
240 m_reg_context_up->ClearAllHardwareBreakpoints();
241 for (const auto &pair : hw_breakpoint_map) {
242 const auto &bp = pair.second;
243 SetHardwareBreakpoint(addr: bp.m_addr, size: bp.m_size);
244 }
245 }
246
247 intptr_t data = 0;
248
249 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
250 data = signo;
251
252 return NativeProcessLinux::PtraceWrapper(req: PTRACE_CONT, pid: GetID(), addr: nullptr,
253 data: reinterpret_cast<void *>(data));
254}
255
256Status NativeThreadLinux::SingleStep(uint32_t signo) {
257 const StateType new_state = StateType::eStateStepping;
258 MaybeLogStateChange(new_state);
259 m_state = new_state;
260 m_stop_info.reason = StopReason::eStopReasonNone;
261
262 if(!m_step_workaround) {
263 // If we already hava a workaround inplace, don't reset it. Otherwise, the
264 // destructor of the existing instance will run after the new instance has
265 // fetched the cpu mask, and the thread will end up with the wrong mask.
266 m_step_workaround = SingleStepWorkaround::Get(tid: m_tid);
267 }
268
269 intptr_t data = 0;
270 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
271 data = signo;
272
273 // If hardware single-stepping is not supported, we just do a continue. The
274 // breakpoint on the next instruction has been setup in
275 // NativeProcessLinux::Resume.
276 return NativeProcessLinux::PtraceWrapper(
277 req: GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
278 : PTRACE_CONT,
279 pid: m_tid, addr: nullptr, data: reinterpret_cast<void *>(data));
280}
281
282void NativeThreadLinux::SetStoppedBySignal(uint32_t signo,
283 const siginfo_t *info) {
284 Log *log = GetLog(mask: LLDBLog::Thread);
285 LLDB_LOGF(log, "NativeThreadLinux::%s called with signal 0x%02" PRIx32,
286 __FUNCTION__, signo);
287
288 SetStopped();
289
290 m_stop_info.reason = StopReason::eStopReasonSignal;
291 m_stop_info.signo = signo;
292
293 m_stop_description.clear();
294 if (info) {
295 switch (signo) {
296 case SIGSEGV:
297 case SIGBUS:
298 case SIGFPE:
299 case SIGILL:
300 m_stop_description = GetCrashReasonString(info: *info);
301#ifndef SEGV_MTESERR
302#define SEGV_MTESERR 9
303#endif
304 if (info->si_signo == SIGSEGV && info->si_code == SEGV_MTESERR)
305 AnnotateSyncTagCheckFault(
306 fault_addr: reinterpret_cast<lldb::addr_t>(info->si_addr));
307 break;
308 }
309 }
310}
311
312void NativeThreadLinux::AnnotateSyncTagCheckFault(lldb::addr_t fault_addr) {
313 int32_t allocation_tag_type = 0;
314 switch (GetProcess().GetArchitecture().GetMachine()) {
315 // aarch64_32 deliberately not here because there's no 32 bit MTE
316 case llvm::Triple::aarch64:
317 case llvm::Triple::aarch64_be:
318 allocation_tag_type = MemoryTagManagerAArch64MTE::eMTE_allocation;
319 break;
320 default:
321 return;
322 }
323
324 auto details =
325 GetRegisterContext().GetMemoryTaggingDetails(type: allocation_tag_type);
326 if (!details) {
327 llvm::consumeError(Err: details.takeError());
328 return;
329 }
330
331 // We assume that the stop description is currently:
332 // signal SIGSEGV: sync tag check fault (fault address=<addr>)
333 // Remove the closing )
334 m_stop_description.pop_back();
335
336 std::stringstream ss;
337 std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));
338
339 ss << " logical tag=0x" << std::hex << manager->GetLogicalTag(addr: fault_addr);
340
341 std::vector<uint8_t> allocation_tag_data;
342 // The fault address may not be granule aligned. ReadMemoryTags will granule
343 // align any range you give it, potentially making it larger.
344 // To prevent this set len to 1. This always results in a range that is at
345 // most 1 granule in size and includes fault_addr.
346 Status status = GetProcess().ReadMemoryTags(type: allocation_tag_type, addr: fault_addr,
347 len: 1, tags&: allocation_tag_data);
348
349 if (status.Success()) {
350 llvm::Expected<std::vector<lldb::addr_t>> allocation_tag =
351 manager->UnpackTagsData(tags: allocation_tag_data, granules: 1);
352 if (allocation_tag) {
353 ss << " allocation tag=0x" << std::hex << allocation_tag->front() << ")";
354 } else {
355 llvm::consumeError(Err: allocation_tag.takeError());
356 ss << ")";
357 }
358 } else
359 ss << ")";
360
361 m_stop_description += ss.str();
362}
363
364bool NativeThreadLinux::IsStopped(int *signo) {
365 if (!StateIsStoppedState(state: m_state, must_exist: false))
366 return false;
367
368 // If we are stopped by a signal, return the signo.
369 if (signo && m_state == StateType::eStateStopped &&
370 m_stop_info.reason == StopReason::eStopReasonSignal) {
371 *signo = m_stop_info.signo;
372 }
373
374 // Regardless, we are stopped.
375 return true;
376}
377
378void NativeThreadLinux::SetStopped() {
379 if (m_state == StateType::eStateStepping)
380 m_step_workaround.reset();
381
382 // On every stop, clear any cached register data structures
383 GetRegisterContext().InvalidateAllRegisters();
384
385 const StateType new_state = StateType::eStateStopped;
386 MaybeLogStateChange(new_state);
387 m_state = new_state;
388 m_stop_description.clear();
389}
390
391void NativeThreadLinux::SetStoppedByExec() {
392 Log *log = GetLog(mask: LLDBLog::Thread);
393 LLDB_LOGF(log, "NativeThreadLinux::%s()", __FUNCTION__);
394
395 SetStopped();
396
397 m_stop_info.reason = StopReason::eStopReasonExec;
398 m_stop_info.signo = SIGSTOP;
399}
400
401void NativeThreadLinux::SetStoppedByBreakpoint() {
402 SetStopped();
403
404 m_stop_info.reason = StopReason::eStopReasonBreakpoint;
405 m_stop_info.signo = SIGTRAP;
406 m_stop_description.clear();
407}
408
409void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) {
410 SetStopped();
411
412 lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");
413
414 std::ostringstream ostr;
415 ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " ";
416 ostr << wp_index;
417
418 /*
419 * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For
420 * example:
421 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at
422 * 'm', then
423 * watch exception is generated even when 'n' is read/written. To handle this
424 * case,
425 * find the base address of the load/store instruction and append it in the
426 * stop-info
427 * packet.
428 */
429 ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index);
430
431 m_stop_description = ostr.str();
432
433 m_stop_info.reason = StopReason::eStopReasonWatchpoint;
434 m_stop_info.signo = SIGTRAP;
435}
436
437bool NativeThreadLinux::IsStoppedAtBreakpoint() {
438 return GetState() == StateType::eStateStopped &&
439 m_stop_info.reason == StopReason::eStopReasonBreakpoint;
440}
441
442bool NativeThreadLinux::IsStoppedAtWatchpoint() {
443 return GetState() == StateType::eStateStopped &&
444 m_stop_info.reason == StopReason::eStopReasonWatchpoint;
445}
446
447void NativeThreadLinux::SetStoppedByTrace() {
448 SetStopped();
449
450 m_stop_info.reason = StopReason::eStopReasonTrace;
451 m_stop_info.signo = SIGTRAP;
452}
453
454void NativeThreadLinux::SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid) {
455 SetStopped();
456
457 m_stop_info.reason =
458 is_vfork ? StopReason::eStopReasonVFork : StopReason::eStopReasonFork;
459 m_stop_info.signo = SIGTRAP;
460 m_stop_info.details.fork.child_pid = child_pid;
461 m_stop_info.details.fork.child_tid = child_pid;
462 m_stop_description = std::to_string(val: child_pid);
463 m_stop_description += " ";
464 m_stop_description += std::to_string(val: child_pid);
465}
466
467void NativeThreadLinux::SetStoppedByVForkDone() {
468 SetStopped();
469
470 m_stop_info.reason = StopReason::eStopReasonVForkDone;
471 m_stop_info.signo = SIGTRAP;
472}
473
474void NativeThreadLinux::SetStoppedWithNoReason() {
475 SetStopped();
476
477 m_stop_info.reason = StopReason::eStopReasonNone;
478 m_stop_info.signo = 0;
479}
480
481void NativeThreadLinux::SetStoppedByProcessorTrace(
482 llvm::StringRef description) {
483 SetStopped();
484
485 m_stop_info.reason = StopReason::eStopReasonProcessorTrace;
486 m_stop_info.signo = 0;
487 m_stop_description = description.str();
488}
489
490void NativeThreadLinux::SetExited() {
491 const StateType new_state = StateType::eStateExited;
492 MaybeLogStateChange(new_state);
493 m_state = new_state;
494
495 m_stop_info.reason = StopReason::eStopReasonThreadExiting;
496}
497
498Status NativeThreadLinux::RequestStop() {
499 Log *log = GetLog(mask: LLDBLog::Thread);
500
501 NativeProcessLinux &process = GetProcess();
502
503 lldb::pid_t pid = process.GetID();
504 lldb::tid_t tid = GetID();
505
506 LLDB_LOGF(log,
507 "NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64
508 ", tid: %" PRIu64 ")",
509 __FUNCTION__, pid, tid);
510
511 Status err;
512 errno = 0;
513 if (::tgkill(pid, tid, SIGSTOP) != 0) {
514 err = Status::FromErrno();
515 LLDB_LOGF(log,
516 "NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64
517 ", SIGSTOP) failed: %s",
518 __FUNCTION__, pid, tid, err.AsCString());
519 }
520
521 return err;
522}
523
524void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) {
525 Log *log = GetLog(mask: LLDBLog::Thread);
526 // If we're not logging, we're done.
527 if (!log)
528 return;
529
530 // If this is a state change to the same state, we're done.
531 lldb::StateType old_state = m_state;
532 if (new_state == old_state)
533 return;
534
535 LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}",
536 m_process.GetID(), GetID(), old_state, new_state);
537}
538
539NativeProcessLinux &NativeThreadLinux::GetProcess() {
540 return static_cast<NativeProcessLinux &>(m_process);
541}
542
543const NativeProcessLinux &NativeThreadLinux::GetProcess() const {
544 return static_cast<const NativeProcessLinux &>(m_process);
545}
546
547llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
548NativeThreadLinux::GetSiginfo() const {
549 auto siginfo_buf =
550 llvm::WritableMemoryBuffer::getNewUninitMemBuffer(Size: sizeof(siginfo_t));
551 Status error =
552 GetProcess().GetSignalInfo(tid: GetID(), siginfo: siginfo_buf->getBufferStart());
553 if (!error.Success())
554 return error.ToError();
555 return std::move(siginfo_buf);
556}
557

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp