Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ NativeProcessLinux::Manager::Attach(
if (!tids_or)
return tids_or.takeError();
ArrayRef<::pid_t> tids = *tids_or;

llvm::Expected<ArchSpec> arch_or =
NativeRegisterContextLinux::DetermineArchitecture(tids[0]);
if (!arch_or)
Expand Down Expand Up @@ -447,6 +448,7 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
Log *log = GetLog(POSIXLog::Process);

uint64_t options = GetDefaultPtraceOpts();
Status status;
// Use a map to keep track of the threads which we have attached/need to
// attach.
Expand All @@ -457,9 +459,12 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
if (it->second == false) {
lldb::tid_t tid = it->first;

// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) {
// Seize and interrupt the requested process.
// This will cause the thread to stop in a TRACE_STOP state.
// Akin to a sigstop but without sending the signal.
if ((status =
PtraceWrapper(PTRACE_SEIZE, tid, nullptr, (void *)options))
.Fail()) {
// No such thread. The thread may have exited. More error handling
// may be needed.
if (status.GetError() == ESRCH) {
Expand All @@ -474,6 +479,24 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
return status.ToError();
}

// Send a sigstop, this makes it so our seize->interrupt is signal wise
// the same as ptrace_attach. We do this so any program/workflow
// depending on the sending of a sigstop will still receive a sigstop.
tgkill(tid, tid, SIGSTOP);

if ((status = PtraceWrapper(PTRACE_INTERRUPT, tid)).Fail()) {
// No such thread, the thread may have exited, this shouldn't
// happen at this stage, but we check regardless
if (status.GetError() == ESRCH) {
it = tids_to_attach.erase(it);
continue;
}

// No check for EPERM because we already checked for it above
// when we seized
return status.ToError();
}

int wpid =
llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
// Need to use __WALL otherwise we receive an error with errno=ECHLD At
Expand All @@ -489,9 +512,6 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
std::error_code(errno, std::generic_category()));
}

if ((status = SetDefaultPtraceOpts(tid)).Fail())
return status.ToError();

LLDB_LOG(log, "adding tid = {0}", tid);
it->second = true;
}
Expand All @@ -513,8 +533,8 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
return std::move(tids);
}

Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
long ptrace_opts = 0;
uint64_t NativeProcessLinux::GetDefaultPtraceOpts() {
uint64_t ptrace_opts = 0;

// Have the child raise an event on exit. This is used to keep the child in
// limbo until it is destroyed.
Expand All @@ -537,6 +557,11 @@ Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
// the child finishes sharing memory.
ptrace_opts |= PTRACE_O_TRACEVFORKDONE;

return ptrace_opts;
}

Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
uint64_t ptrace_opts = GetDefaultPtraceOpts();
return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
}

Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ class NativeProcessLinux : public NativeProcessELF,
private:
Manager &m_manager;
ArchSpec m_arch;

LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;

Expand All @@ -194,6 +193,8 @@ class NativeProcessLinux : public NativeProcessELF,

static Status SetDefaultPtraceOpts(const lldb::pid_t);

static uint64_t GetDefaultPtraceOpts();

bool TryHandleWaitStatus(lldb::pid_t pid, WaitStatus status);

void MonitorCallback(NativeThreadLinux &thread, WaitStatus status);
Expand Down
Loading