@@ -312,10 +312,26 @@ NativeProcessLinux::Manager::Attach(
312312 Log *log = GetLog (POSIXLog::Process);
313313 LLDB_LOG (log, " pid = {0:x}" , pid);
314314
315- auto tids_or = NativeProcessLinux::Attach (pid);
316- if (!tids_or)
317- return tids_or.takeError ();
318- ArrayRef<::pid_t > tids = *tids_or;
315+ // This safety check lets us decide if we should
316+ // seize or attach.
317+ ProcessInstanceInfo process_info;
318+ if (!Host::GetProcessInfo (pid, process_info))
319+ return llvm::make_error<StringError>(" Unable to read process info" ,
320+ llvm::inconvertibleErrorCode ());
321+
322+ std::vector<::pid_t > tids;
323+ if (process_info.IsCoreDumping ()) {
324+ auto attached_or = NativeProcessLinux::Seize (pid);
325+ if (!attached_or)
326+ return attached_or.takeError ();
327+ tids = std::move (*attached_or);
328+ } else {
329+ auto attached_or = NativeProcessLinux::Attach (pid);
330+ if (!attached_or)
331+ return attached_or.takeError ();
332+ tids = std::move (*attached_or);
333+ }
334+
319335 llvm::Expected<ArchSpec> arch_or =
320336 NativeRegisterContextLinux::DetermineArchitecture (tids[0 ]);
321337 if (!arch_or)
@@ -444,6 +460,88 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
444460 SetState (StateType::eStateStopped, false );
445461}
446462
463+ llvm::Expected<std::vector<::pid_t >> NativeProcessLinux::Seize (::pid_t pid) {
464+ Log *log = GetLog (POSIXLog::Process);
465+
466+ uint64_t options = GetDefaultPtraceOpts ();
467+ Status status;
468+ // Use a map to keep track of the threads which we have attached/need to
469+ // attach.
470+ Host::TidMap tids_to_attach;
471+ while (Host::FindProcessThreads (pid, tids_to_attach)) {
472+ for (Host::TidMap::iterator it = tids_to_attach.begin ();
473+ it != tids_to_attach.end ();) {
474+ if (it->second == true ) {
475+ continue ;
476+ }
477+ lldb::tid_t tid = it->first ;
478+ if ((status = PtraceWrapper (PTRACE_SEIZE, tid, nullptr , (void *)options))
479+ .Fail ()) {
480+ // No such thread. The thread may have exited. More error handling
481+ // may be needed.
482+ if (status.GetError () == ESRCH) {
483+ it = tids_to_attach.erase (it);
484+ continue ;
485+ }
486+ if (status.GetError () == EPERM) {
487+ // Depending on the value of ptrace_scope, we can return a
488+ // different error that suggests how to fix it.
489+ return AddPtraceScopeNote (status.ToError ());
490+ }
491+ return status.ToError ();
492+ }
493+
494+ if ((status = PtraceWrapper (PTRACE_INTERRUPT, tid)).Fail ()) {
495+ // No such thread. The thread may have exited. More error handling
496+ // may be needed.
497+ if (status.GetError () == ESRCH) {
498+ it = tids_to_attach.erase (it);
499+ continue ;
500+ }
501+ if (status.GetError () == EPERM) {
502+ // Depending on the value of ptrace_scope, we can return a
503+ // different error that suggests how to fix it.
504+ return AddPtraceScopeNote (status.ToError ());
505+ }
506+ return status.ToError ();
507+ }
508+
509+ int wpid =
510+ llvm::sys::RetryAfterSignal (-1 , ::waitpid, tid, nullptr , __WALL);
511+ // Need to use __WALL otherwise we receive an error with errno=ECHLD At
512+ // this point we should have a thread stopped if waitpid succeeds.
513+ if (wpid < 0 ) {
514+ // No such thread. The thread may have exited. More error handling
515+ // may be needed.
516+ if (errno == ESRCH) {
517+ it = tids_to_attach.erase (it);
518+ continue ;
519+ }
520+ return llvm::errorCodeToError (
521+ std::error_code (errno, std::generic_category ()));
522+ }
523+
524+ LLDB_LOG (log, " adding tid = {0}" , tid);
525+ it->second = true ;
526+
527+ // move the loop forward
528+ ++it;
529+ }
530+ }
531+
532+ size_t tid_count = tids_to_attach.size ();
533+ if (tid_count == 0 )
534+ return llvm::make_error<StringError>(" No such process" ,
535+ llvm::inconvertibleErrorCode ());
536+
537+ std::vector<::pid_t > tids;
538+ tids.reserve (tid_count);
539+ for (const auto &p : tids_to_attach)
540+ tids.push_back (p.first );
541+
542+ return std::move (tids);
543+ }
544+
447545llvm::Expected<std::vector<::pid_t >> NativeProcessLinux::Attach (::pid_t pid) {
448546 Log *log = GetLog (POSIXLog::Process);
449547
@@ -513,8 +611,8 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
513611 return std::move (tids);
514612}
515613
516- Status NativeProcessLinux::SetDefaultPtraceOpts (lldb:: pid_t pid ) {
517- long ptrace_opts = 0 ;
614+ uint64_t NativeProcessLinux::GetDefaultPtraceOpts ( ) {
615+ uint64_t ptrace_opts = 0 ;
518616
519617 // Have the child raise an event on exit. This is used to keep the child in
520618 // limbo until it is destroyed.
@@ -537,6 +635,11 @@ Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
537635 // the child finishes sharing memory.
538636 ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
539637
638+ return ptrace_opts;
639+ }
640+
641+ Status NativeProcessLinux::SetDefaultPtraceOpts (lldb::pid_t pid) {
642+ uint64_t ptrace_opts = GetDefaultPtraceOpts ();
540643 return PtraceWrapper (PTRACE_SETOPTIONS, pid, nullptr , (void *)ptrace_opts);
541644}
542645
0 commit comments