diff options
Diffstat (limited to 'lldb/source/Target/TargetList.cpp')
-rw-r--r-- | lldb/source/Target/TargetList.cpp | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp new file mode 100644 index 00000000000..d92940003d6 --- /dev/null +++ b/lldb/source/Target/TargetList.cpp @@ -0,0 +1,342 @@ +//===-- TargetList.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/State.h" +#include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/TargetList.h" + +using namespace lldb; +using namespace lldb_private; + + +//---------------------------------------------------------------------- +// TargetList constructor +//---------------------------------------------------------------------- +TargetList::TargetList() : + Broadcaster("TargetList"), + m_target_list(), + m_target_list_mutex (Mutex::eMutexTypeRecursive), + m_current_target_idx (0) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +TargetList::~TargetList() +{ + Mutex::Locker locker(m_target_list_mutex); + m_target_list.clear(); +} + +Error +TargetList::CreateTarget +( + const FileSpec& file, + const ArchSpec& arch, + const UUID *uuid_ptr, + bool get_dependent_files, + TargetSP &target_sp +) +{ + Timer scoped_timer (__PRETTY_FUNCTION__, + "TargetList::CreateTarget (file = '%s/%s', arch = '%s', uuid = %p)", + file.GetDirectory().AsCString(), + file.GetFilename().AsCString(), + arch.AsCString(), + uuid_ptr); + ModuleSP exe_module_sp; + FileSpec resolved_file(file); + if (!Host::ResolveExecutableInBundle (&resolved_file)) + resolved_file = file; + + Error error = ModuleList::GetSharedModule(resolved_file, + arch, + uuid_ptr, + NULL, + 0, + exe_module_sp, + NULL, + NULL); + if (exe_module_sp) + { + target_sp.reset(new Target); + target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); + + if (target_sp.get()) + { + Mutex::Locker locker(m_target_list_mutex); + m_current_target_idx = m_target_list.size(); + m_target_list.push_back(target_sp); + } + +// target_sp.reset(new Target); +// // Let the target resolve any funky bundle paths before we try and get +// // the object file... +// target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); +// if (exe_module_sp->GetObjectFile() == NULL) +// { +// error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s", +// file.GetDirectory().AsCString(), +// file.GetDirectory() ? "/" : "", +// file.GetFilename().AsCString(), +// arch.AsCString()); +// } +// else +// { +// if (target_sp.get()) +// { +// error.Clear(); +// Mutex::Locker locker(m_target_list_mutex); +// m_current_target_idx = m_target_list.size(); +// m_target_list.push_back(target_sp); +// } +// } + } + else + { + target_sp.reset(); + } + + return error; +} + +bool +TargetList::DeleteTarget (TargetSP &target_sp) +{ + Mutex::Locker locker(m_target_list_mutex); + collection::iterator pos, end = m_target_list.end(); + + for (pos = m_target_list.begin(); pos != end; ++pos) + { + if (pos->get() == target_sp.get()) + { + m_target_list.erase(pos); + return true; + } + } + return false; +} + + +TargetSP +TargetList::FindTargetWithExecutableAndArchitecture +( + const FileSpec &exe_file_spec, + const ArchSpec *exe_arch_ptr +) const +{ + Mutex::Locker locker (m_target_list_mutex); + TargetSP target_sp; + bool full_match = exe_file_spec.GetDirectory(); + + collection::const_iterator pos, end = m_target_list.end(); + for (pos = m_target_list.begin(); pos != end; ++pos) + { + ModuleSP module_sp ((*pos)->GetExecutableModule()); + + if (module_sp) + { + if (FileSpec::Equal (exe_file_spec, module_sp->GetFileSpec(), full_match)) + { + if (exe_arch_ptr) + { + if (*exe_arch_ptr != module_sp->GetArchitecture()) + continue; + } + target_sp = *pos; + break; + } + } + } + return target_sp; +} + +TargetSP +TargetList::FindTargetWithProcessID (lldb::pid_t pid) const +{ + Mutex::Locker locker(m_target_list_mutex); + TargetSP target_sp; + collection::const_iterator pos, end = m_target_list.end(); + for (pos = m_target_list.begin(); pos != end; ++pos) + { + Process* process = (*pos)->GetProcessSP().get(); + if (process && process->GetID() == pid) + { + target_sp = *pos; + break; + } + } + return target_sp; +} + + +TargetSP +TargetList::FindTargetWithProcess (Process *process) const +{ + TargetSP target_sp; + if (process) + { + Mutex::Locker locker(m_target_list_mutex); + collection::const_iterator pos, end = m_target_list.end(); + for (pos = m_target_list.begin(); pos != end; ++pos) + { + if (process == (*pos)->GetProcessSP().get()) + { + target_sp = *pos; + break; + } + } + } + return target_sp; +} + +TargetSP +TargetList::GetTargetSP (Target *target) const +{ + TargetSP target_sp; + if (target) + { + Mutex::Locker locker(m_target_list_mutex); + collection::const_iterator pos, end = m_target_list.end(); + for (pos = m_target_list.begin(); pos != end; ++pos) + { + if (target == (*pos).get()) + { + target_sp = *pos; + break; + } + } + } + return target_sp; +} + +uint32_t +TargetList::SendAsyncInterrupt (lldb::pid_t pid) +{ + uint32_t num_async_interrupts_sent = 0; + + if (pid != LLDB_INVALID_PROCESS_ID) + { + TargetSP target_sp(FindTargetWithProcessID (pid)); + if (target_sp.get()) + { + Process* process = target_sp->GetProcessSP().get(); + if (process) + { + process->BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); + ++num_async_interrupts_sent; + } + } + } + else + { + // We don't have a valid pid to broadcast to, so broadcast to the target + // list's async broadcaster... + BroadcastEvent (Process::eBroadcastBitInterrupt, NULL); + } + + return num_async_interrupts_sent; +} + +uint32_t +TargetList::SignalIfRunning (lldb::pid_t pid, int signo) +{ + uint32_t num_signals_sent = 0; + Process *process = NULL; + if (pid == LLDB_INVALID_PROCESS_ID) + { + // Signal all processes with signal + Mutex::Locker locker(m_target_list_mutex); + collection::iterator pos, end = m_target_list.end(); + for (pos = m_target_list.begin(); pos != end; ++pos) + { + process = (*pos)->GetProcessSP().get(); + if (process) + { + if (process->IsAlive()) + { + ++num_signals_sent; + process->Signal (signo); + } + } + } + } + else + { + // Signal a specific process with signal + TargetSP target_sp(FindTargetWithProcessID (pid)); + if (target_sp.get()) + { + process = target_sp->GetProcessSP().get(); + if (process) + { + if (process->IsAlive()) + { + ++num_signals_sent; + process->Signal (signo); + } + } + } + } + return num_signals_sent; +} + +int +TargetList::GetNumTargets () const +{ + Mutex::Locker locker (m_target_list_mutex); + return m_target_list.size(); +} + +lldb::TargetSP +TargetList::GetTargetAtIndex (uint32_t idx) const +{ + TargetSP target_sp; + Mutex::Locker locker (m_target_list_mutex); + if (idx < m_target_list.size()) + target_sp = m_target_list[idx]; + return target_sp; +} + +uint32_t +TargetList::SetCurrentTarget (Target* target) +{ + Mutex::Locker locker (m_target_list_mutex); + collection::const_iterator pos, + begin = m_target_list.begin(), + end = m_target_list.end(); + for (pos = begin; pos != end; ++pos) + { + if (pos->get() == target) + { + m_current_target_idx = std::distance (begin, pos); + return m_current_target_idx; + } + } + m_current_target_idx = 0; + return m_current_target_idx; +} + +lldb::TargetSP +TargetList::GetCurrentTarget () +{ + Mutex::Locker locker (m_target_list_mutex); + if (m_current_target_idx >= m_target_list.size()) + m_current_target_idx = 0; + return GetTargetAtIndex (m_current_target_idx); +} |