diff options
author | emaste <emaste@FreeBSD.org> | 2013-11-12 17:25:33 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2013-11-12 17:25:33 +0000 |
commit | 9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e (patch) | |
tree | b9aa1d1064fb25a0f2313d9a7964c862c0b7b354 /contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD | |
parent | 4372cfee12af5dfa890561beb0fecc90957ba058 (diff) | |
parent | c727fe695d28799acb499e9961f11ec07d4f9fe2 (diff) | |
download | FreeBSD-src-9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e.zip FreeBSD-src-9dd6dd992f8bed9a53bf0653fc1eff3fb4ccd46e.tar.gz |
Update LLDB to upstream r194122 snapshot
ludes minor changes relative to upstream, for compatibility with
FreeBSD's in-tree LLVM 3.3:
- Reverted LLDB r191806, restoring use of previous API.
- Reverted part of LLDB r189317, restoring previous enum names.
- Work around missing LLVM r192504, using previous registerEHFrames API
(limited functionality).
- Removed PlatformWindows header include and init/terminate calls.
Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD')
4 files changed, 122 insertions, 148 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index ea26d97..952ec95 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -122,11 +122,47 @@ ProcessFreeBSD::Terminate() { } +Error +ProcessFreeBSD::DoDetach(bool keep_stopped) +{ + Error error; + if (keep_stopped) + { + error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD."); + return error; + } + + error = m_monitor->Detach(GetID()); + + if (error.Success()) + SetPrivateState(eStateDetached); + + return error; +} + bool ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - // XXX haxx - new_thread_list = old_thread_list; - - return false; + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIu64 ")", __FUNCTION__, GetID()); + + bool has_updated = false; + const lldb::pid_t pid = GetID(); + // Update the process thread list with this new thread. + // FIXME: We should be using tid, not pid. + assert(m_monitor); + ThreadSP thread_sp (old_thread_list.FindThreadByID (pid, false)); + if (!thread_sp) { + ProcessSP me = this->shared_from_this(); + thread_sp.reset(new POSIXThread(*me, pid)); + has_updated = true; + } + + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessFreeBSD::%s() updated tid = %" PRIu64, __FUNCTION__, pid); + + new_thread_list.AddThread(thread_sp); + + return has_updated; // the list has been updated } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h index 5f79b74..fb54974 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -54,6 +54,9 @@ public: ProcessFreeBSD(lldb_private::Target& target, lldb_private::Listener &listener); + virtual lldb_private::Error + DoDetach(bool keep_stopped); + virtual bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 9fd51d2..3833fa6 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -70,12 +70,12 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (log) { - log->Printf("ptrace(%s, %lu, %p, %x) called from file %s line %d", + log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", reqName, pid, addr, data, file, line); if (req == PT_IO) { struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; - log->Printf("PT_IO: op=%s offs=%zx size=%ld", + log->Printf("PT_IO: op=%s offs=%zx size=%zu", Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); } } @@ -704,23 +704,16 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, m_operation_thread(LLDB_INVALID_HOST_THREAD), m_monitor_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), - m_server_mutex(Mutex::eMutexTypeRecursive), m_terminal_fd(-1), - m_client_fd(-1), - m_server_fd(-1) + m_operation(0) { - std::unique_ptr<LaunchArgs> args; - - args.reset(new LaunchArgs(this, module, argv, envp, - stdin_path, stdout_path, stderr_path, working_dir)); + std::unique_ptr<LaunchArgs> args(new LaunchArgs(this, module, argv, envp, + stdin_path, stdout_path, stderr_path, + working_dir)); - // Server/client descriptors. - if (!EnableIPC()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Monitor failed to initialize."); - } + sem_init(&m_operation_pending, 0, 0); + sem_init(&m_operation_done, 0, 0); StartLaunchOpThread(args.get(), error); if (!error.Success()) @@ -765,21 +758,14 @@ ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, m_operation_thread(LLDB_INVALID_HOST_THREAD), m_monitor_thread(LLDB_INVALID_HOST_THREAD), m_pid(pid), - m_server_mutex(Mutex::eMutexTypeRecursive), m_terminal_fd(-1), - m_client_fd(-1), - m_server_fd(-1) + m_operation(0) { - std::unique_ptr<AttachArgs> args; + sem_init(&m_operation_pending, 0, 0); + sem_init(&m_operation_done, 0, 0); - args.reset(new AttachArgs(this, pid)); - // Server/client descriptors. - if (!EnableIPC()) - { - error.SetErrorToGenericError(); - error.SetErrorString("Monitor failed to initialize."); - } + std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid)); StartAttachOpThread(args.get(), error); if (!error.Success()) @@ -855,7 +841,6 @@ ProcessMonitor::Launch(LaunchArgs *args) { ProcessMonitor *monitor = args->m_monitor; ProcessFreeBSD &process = monitor->GetProcess(); - lldb::ProcessSP processSP = process.shared_from_this(); const char **argv = args->m_argv; const char **envp = args->m_envp; const char *stdin_path = args->m_stdin_path; @@ -868,21 +853,10 @@ ProcessMonitor::Launch(LaunchArgs *args) char err_str[err_len]; lldb::pid_t pid; - lldb::ThreadSP inferior; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - // Propagate the environment if one is not supplied. if (envp == NULL || envp[0] == NULL) envp = const_cast<const char **>(environ); - // Pseudo terminal setup. - if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len)) - { - args->m_error.SetErrorToGenericError(); - args->m_error.SetErrorString("Could not open controlling TTY."); - goto FINISH; - } - if ((pid = terminal.Fork(err_str, err_len)) == -1) { args->m_error.SetErrorToGenericError(); @@ -1002,32 +976,12 @@ ProcessMonitor::Launch(LaunchArgs *args) if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) goto FINISH; - // Update the process thread list with this new thread. - inferior.reset(process.CreateNewPOSIXThread(*processSP, pid)); - if (log) - log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid); - process.GetThreadList().AddThread(inferior); - - // Let our process instance know the thread has stopped. - process.SendMessage(ProcessMessage::Trace(pid)); + process.SendMessage(ProcessMessage::Attach(pid)); FINISH: return args->m_error.Success(); } -bool -ProcessMonitor::EnableIPC() -{ - int fd[2]; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) - return false; - - m_client_fd = fd[0]; - m_server_fd = fd[1]; - return true; -} - void ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) { @@ -1059,9 +1013,6 @@ ProcessMonitor::Attach(AttachArgs *args) ProcessMonitor *monitor = args->m_monitor; ProcessFreeBSD &process = monitor->GetProcess(); - lldb::ProcessSP processSP = process.shared_from_this(); - ThreadList &tl = process.GetThreadList(); - lldb::ThreadSP inferior; if (pid <= 1) { @@ -1084,14 +1035,9 @@ ProcessMonitor::Attach(AttachArgs *args) goto FINISH; } - // Update the process thread list with the attached thread. - inferior.reset(process.CreateNewPOSIXThread(*processSP, pid)); - tl.AddThread(inferior); + process.SendMessage(ProcessMessage::Attach(pid)); - // Let our process instance know the thread has stopped. - process.SendMessage(ProcessMessage::Trace(pid)); - - FINISH: +FINISH: return args->m_error.Success(); } @@ -1393,78 +1339,37 @@ void ProcessMonitor::ServeOperation(OperationArgs *args) { int status; - pollfd fdset; ProcessMonitor *monitor = args->m_monitor; - fdset.fd = monitor->m_server_fd; - fdset.events = POLLIN | POLLPRI; - fdset.revents = 0; - // We are finised with the arguments and are ready to go. Sync with the // parent thread and start serving operations on the inferior. sem_post(&args->m_semaphore); for (;;) { - if ((status = poll(&fdset, 1, -1)) < 0) - { - switch (errno) - { - default: - assert(false && "Unexpected poll() failure!"); - continue; + // wait for next pending operation + sem_wait(&monitor->m_operation_pending); - case EINTR: continue; // Just poll again. - case EBADF: return; // Connection terminated. - } - } - - assert(status == 1 && "Too many descriptors!"); + monitor->m_operation->Execute(monitor); - if (fdset.revents & POLLIN) - { - Operation *op = NULL; - - READ_AGAIN: - if ((status = read(fdset.fd, &op, sizeof(op))) < 0) - { - // There is only one acceptable failure. - assert(errno == EINTR); - goto READ_AGAIN; - } - if (status == 0) - continue; // Poll again. The connection probably terminated. - assert(status == sizeof(op)); - op->Execute(monitor); - write(fdset.fd, &op, sizeof(op)); - } + // notify calling thread that operation is complete + sem_post(&monitor->m_operation_done); } } void ProcessMonitor::DoOperation(Operation *op) { - int status; - Operation *ack = NULL; - Mutex::Locker lock(m_server_mutex); + Mutex::Locker lock(m_operation_mutex); - // FIXME: Do proper error checking here. - write(m_client_fd, &op, sizeof(op)); + m_operation = op; -READ_AGAIN: - if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0) - { - // If interrupted by a signal handler try again. Otherwise the monitor - // thread probably died and we have a stale file descriptor -- abort the - // operation. - if (errno == EINTR) - goto READ_AGAIN; - return; - } + // notify operation thread that an operation is ready to be processed + sem_post(&m_operation_pending); - assert(status == sizeof(ack)); - assert(ack == op && "Invalid monitor thread response!"); + // wait for operation to complete + sem_wait(&m_operation_done); } size_t @@ -1556,6 +1461,12 @@ ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, un } bool +ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) +{ + return false; +} + +bool ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) { bool result; @@ -1648,9 +1559,36 @@ ProcessMonitor::StopMonitor() { StopMonitoringChildProcess(); StopOpThread(); - CloseFD(m_terminal_fd); - CloseFD(m_client_fd); - CloseFD(m_server_fd); + sem_destroy(&m_operation_pending); + sem_destroy(&m_operation_done); + + // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to + // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of + // the descriptor to a ConnectionFileDescriptor object. Consequently + // even though still has the file descriptor, we shouldn't close it here. +} + +// FIXME: On Linux, when a new thread is created, we receive to notifications, +// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the +// child thread id as additional information, and (2) a SIGSTOP|SI_USER from +// the new child thread indicating that it has is stopped because we attached. +// We have no guarantee of the order in which these arrive, but we need both +// before we are ready to proceed. We currently keep a list of threads which +// have sent the initial SIGSTOP|SI_USER event. Then when we receive the +// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred +// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it. +// +// Right now, the above logic is in ProcessPOSIX, so we need a definition of +// this function in the FreeBSD ProcessMonitor implementation even if it isn't +// logically needed. +// +// We really should figure out what actually happens on FreeBSD and move the +// Linux-specific logic out of ProcessPOSIX as needed. + +bool +ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) +{ + return true; } void @@ -1665,13 +1603,3 @@ ProcessMonitor::StopOpThread() Host::ThreadJoin(m_operation_thread, &result, NULL); m_operation_thread = LLDB_INVALID_HOST_THREAD; } - -void -ProcessMonitor::CloseFD(int &fd) -{ - if (fd != -1) - { - close(fd); - fd = -1; - } -} diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h index ce66c03..4a9b483 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -160,6 +160,10 @@ public: bool WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset); + /// Reads the value of the thread-specific pointer for a given thread ID. + bool + ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value); + /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID /// to the memory region pointed to by @p lwpinfo. bool @@ -193,6 +197,10 @@ public: void StopMonitor(); + // Waits for the initial stop message from a new thread. + bool + WaitForInitialTIDStop(lldb::tid_t tid); + private: ProcessFreeBSD *m_process; @@ -200,12 +208,17 @@ private: lldb::thread_t m_monitor_thread; lldb::pid_t m_pid; - - lldb_private::Mutex m_server_mutex; int m_terminal_fd; - int m_client_fd; - int m_server_fd; + // current operation which must be executed on the privileged thread + Operation *m_operation; + lldb_private::Mutex m_operation_mutex; + + // semaphores notified when Operation is ready to be processed and when + // the operation is complete. + sem_t m_operation_pending; + sem_t m_operation_done; + struct OperationArgs { OperationArgs(ProcessMonitor *monitor); @@ -252,9 +265,6 @@ private: static bool Launch(LaunchArgs *args); - bool - EnableIPC(); - struct AttachArgs : OperationArgs { AttachArgs(ProcessMonitor *monitor, @@ -314,9 +324,6 @@ private: /// Stops the operation thread used to attach/launch a process. void StopOpThread(); - - void - CloseFD(int &fd); }; #endif // #ifndef liblldb_ProcessMonitor_H_ |