2010-06-09 00:52:24 +08:00
|
|
|
//===-- 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"
|
2011-03-09 06:40:15 +08:00
|
|
|
#include "lldb/Target/Platform.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#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),
|
2010-08-27 05:32:51 +08:00
|
|
|
m_selected_target_idx (0)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// Destructor
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
TargetList::~TargetList()
|
|
|
|
{
|
|
|
|
Mutex::Locker locker(m_target_list_mutex);
|
|
|
|
m_target_list.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error
|
|
|
|
TargetList::CreateTarget
|
|
|
|
(
|
2010-06-23 09:19:29 +08:00
|
|
|
Debugger &debugger,
|
2010-06-09 00:52:24 +08:00
|
|
|
const FileSpec& file,
|
|
|
|
const ArchSpec& arch,
|
|
|
|
bool get_dependent_files,
|
|
|
|
TargetSP &target_sp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
Timer scoped_timer (__PRETTY_FUNCTION__,
|
2011-03-09 06:40:15 +08:00
|
|
|
"TargetList::CreateTarget (file = '%s/%s', arch = '%s')",
|
2010-06-09 00:52:24 +08:00
|
|
|
file.GetDirectory().AsCString(),
|
|
|
|
file.GetFilename().AsCString(),
|
2011-03-09 06:40:15 +08:00
|
|
|
arch.GetArchitectureName());
|
2010-08-10 07:31:02 +08:00
|
|
|
Error error;
|
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
if (file)
|
2010-08-10 07:31:02 +08:00
|
|
|
{
|
|
|
|
ModuleSP exe_module_sp;
|
|
|
|
FileSpec resolved_file(file);
|
2011-03-09 06:40:15 +08:00
|
|
|
ArchSpec platform_arch;
|
2010-09-10 12:48:55 +08:00
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
PlatformSP platform_sp (Platform::GetSelectedPlatform ());
|
|
|
|
if (platform_sp)
|
|
|
|
error = platform_sp->ResolveExecutable (file, arch, exe_module_sp);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
if (error.Success() && exe_module_sp)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-08-10 07:31:02 +08:00
|
|
|
if (exe_module_sp->GetObjectFile() == NULL)
|
|
|
|
{
|
2010-12-08 12:55:11 +08:00
|
|
|
if (arch.IsValid())
|
|
|
|
{
|
|
|
|
error.SetErrorStringWithFormat("\"%s%s%s\" doesn't contain architecture %s",
|
|
|
|
file.GetDirectory().AsCString(),
|
|
|
|
file.GetDirectory() ? "/" : "",
|
|
|
|
file.GetFilename().AsCString(),
|
2011-02-23 08:35:02 +08:00
|
|
|
arch.GetArchitectureName());
|
2010-12-08 12:55:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error.SetErrorStringWithFormat("unsupported file type \"%s%s%s\"",
|
|
|
|
file.GetDirectory().AsCString(),
|
|
|
|
file.GetDirectory() ? "/" : "",
|
|
|
|
file.GetFilename().AsCString());
|
|
|
|
}
|
2010-08-10 07:31:02 +08:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
target_sp.reset(new Target(debugger));
|
|
|
|
target_sp->SetExecutableModule (exe_module_sp, get_dependent_files);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2010-08-10 07:31:02 +08:00
|
|
|
}
|
2011-03-09 06:40:15 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// No file was specified, just create an empty target with any arch
|
|
|
|
// if a valid arch was specified
|
|
|
|
target_sp.reset(new Target(debugger));
|
|
|
|
if (arch.IsValid())
|
|
|
|
target_sp->SetArchitecture(arch);
|
|
|
|
}
|
2010-09-27 08:30:10 +08:00
|
|
|
|
2011-03-09 06:40:15 +08:00
|
|
|
if (target_sp)
|
2010-08-10 07:31:02 +08:00
|
|
|
{
|
2011-03-09 06:40:15 +08:00
|
|
|
target_sp->UpdateInstanceName();
|
|
|
|
|
2010-08-10 07:31:02 +08:00
|
|
|
Mutex::Locker locker(m_target_list_mutex);
|
2010-08-27 05:32:51 +08:00
|
|
|
m_selected_target_idx = m_target_list.size();
|
2010-08-10 07:31:02 +08:00
|
|
|
m_target_list.push_back(target_sp);
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
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
|
2010-08-27 05:32:51 +08:00
|
|
|
TargetList::SetSelectedTarget (Target* target)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2010-08-27 05:32:51 +08:00
|
|
|
m_selected_target_idx = std::distance (begin, pos);
|
|
|
|
return m_selected_target_idx;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
}
|
2010-08-27 05:32:51 +08:00
|
|
|
m_selected_target_idx = 0;
|
|
|
|
return m_selected_target_idx;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lldb::TargetSP
|
2010-08-27 05:32:51 +08:00
|
|
|
TargetList::GetSelectedTarget ()
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
|
|
|
Mutex::Locker locker (m_target_list_mutex);
|
2010-08-27 05:32:51 +08:00
|
|
|
if (m_selected_target_idx >= m_target_list.size())
|
|
|
|
m_selected_target_idx = 0;
|
|
|
|
return GetTargetAtIndex (m_selected_target_idx);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|