Debugger: Start implementing host interface.
- Add new model class TargetHost for host-specific information such as the running team list. - Add new interface class TargetHostInterface and implementing subclass LocalTargetHostInterface. Not yet complete/usable due to some as of yet unresolved issues with the involved system APIs.
This commit is contained in:
@@ -34,6 +34,8 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language c_family ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language x86 ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) target_host_interface ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) target_host_interface interfaces ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface cli ] ;
|
||||
@@ -193,6 +195,7 @@ local sources =
|
||||
SyntheticPrimitiveType.cpp
|
||||
SyscallInfo.cpp
|
||||
SystemInfo.cpp
|
||||
TargetHost.cpp
|
||||
Team.cpp
|
||||
TeamInfo.cpp
|
||||
TeamMemory.cpp
|
||||
@@ -239,6 +242,12 @@ local sources =
|
||||
# source_language/x86
|
||||
X86AssemblyLanguage.cpp
|
||||
|
||||
# target_host_interface
|
||||
TargetHostInterface.cpp
|
||||
|
||||
# target_host_interface/interfaces
|
||||
LocalTargetHostInterface.cpp
|
||||
|
||||
# types
|
||||
ArrayIndexPath.cpp
|
||||
TargetAddressRangeList.cpp
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "TargetHost.h"
|
||||
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "TeamInfo.h"
|
||||
|
||||
|
||||
TargetHost::TargetHost(const BString& name)
|
||||
:
|
||||
BReferenceable(),
|
||||
fName(name),
|
||||
fLock(),
|
||||
fListeners(),
|
||||
fTeams()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TargetHost::~TargetHost()
|
||||
{
|
||||
while (!fTeams.IsEmpty())
|
||||
delete fTeams.RemoveItemAt((int32)0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::AddListener(Listener* listener)
|
||||
{
|
||||
AutoLocker<TargetHost> hostLocker(this);
|
||||
fListeners.Add(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::RemoveListener(Listener* listener)
|
||||
{
|
||||
AutoLocker<TargetHost> hostLocker(this);
|
||||
fListeners.Remove(listener);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
TargetHost::CountTeams() const
|
||||
{
|
||||
return fTeams.CountItems();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TargetHost::AddTeam(const team_info& info)
|
||||
{
|
||||
TeamInfo* teamInfo = new (std::nothrow) TeamInfo(info.team, info);
|
||||
if (teamInfo == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (!fTeams.BinaryInsert(teamInfo, &_CompareTeams))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_NotifyTeamAdded(teamInfo);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::RemoveTeam(team_id team)
|
||||
{
|
||||
int32 index = fTeams.BinarySearchIndexByKey(team,
|
||||
&_FindTeamByKey);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
_NotifyTeamRemoved(team);
|
||||
TeamInfo* info = fTeams.RemoveItemAt(index);
|
||||
delete info;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::UpdateTeam(const team_info& info)
|
||||
{
|
||||
int32 index = fTeams.BinarySearchIndexByKey(info.team,
|
||||
&_FindTeamByKey);
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
TeamInfo* teamInfo = fTeams.ItemAt(index);
|
||||
teamInfo->SetTo(info.team, info);
|
||||
_NotifyTeamRenamed(teamInfo);
|
||||
}
|
||||
|
||||
|
||||
TeamInfo*
|
||||
TargetHost::TeamInfoAt(int32 index) const
|
||||
{
|
||||
return fTeams.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
TeamInfo*
|
||||
TargetHost::TeamInfoByID(team_id team) const
|
||||
{
|
||||
return fTeams.BinarySearchByKey(team, &_FindTeamByKey);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ int
|
||||
TargetHost::_CompareTeams(const TeamInfo* a, const TeamInfo* b)
|
||||
{
|
||||
return a->TeamID() < b->TeamID() ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ int
|
||||
TargetHost::_FindTeamByKey(const team_id* id, const TeamInfo* info)
|
||||
{
|
||||
if (*id < info->TeamID())
|
||||
return -1;
|
||||
else if (*id > info->TeamID())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::_NotifyTeamAdded(TeamInfo* info)
|
||||
{
|
||||
for (ListenerList::Iterator it = fListeners.GetIterator();
|
||||
Listener* listener = it.Next();) {
|
||||
listener->TeamAdded(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::_NotifyTeamRemoved(team_id team)
|
||||
{
|
||||
for (ListenerList::Iterator it = fListeners.GetIterator();
|
||||
Listener* listener = it.Next();) {
|
||||
listener->TeamRemoved(team);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::_NotifyTeamRenamed(TeamInfo* info)
|
||||
{
|
||||
for (ListenerList::Iterator it = fListeners.GetIterator();
|
||||
Listener* listener = it.Next();) {
|
||||
listener->TeamRenamed(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - TargetHost::Listener
|
||||
|
||||
|
||||
TargetHost::Listener::~Listener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::Listener::TeamAdded(TeamInfo* info)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::Listener::TeamRemoved(team_id team)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHost::Listener::TeamRenamed(TeamInfo* info)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TARGET_HOST_H
|
||||
#define TARGET_HOST_H
|
||||
|
||||
#include <Locker.h>
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
class TeamInfo;
|
||||
|
||||
|
||||
class TargetHost : public BReferenceable {
|
||||
public:
|
||||
class Listener;
|
||||
public:
|
||||
TargetHost(const BString& name);
|
||||
virtual ~TargetHost();
|
||||
|
||||
bool Lock() { return fLock.Lock(); }
|
||||
void Unlock() { fLock.Unlock(); }
|
||||
|
||||
const BString& Name() const { return fName; }
|
||||
|
||||
void AddListener(Listener* listener);
|
||||
void RemoveListener(Listener* listener);
|
||||
|
||||
int32 CountTeams() const;
|
||||
status_t AddTeam(const team_info& info);
|
||||
void RemoveTeam(team_id team);
|
||||
void UpdateTeam(const team_info& info);
|
||||
TeamInfo* TeamInfoAt(int32 index) const;
|
||||
TeamInfo* TeamInfoByID(team_id team) const;
|
||||
|
||||
private:
|
||||
typedef DoublyLinkedList<Listener> ListenerList;
|
||||
typedef BObjectList<TeamInfo> TeamInfoList;
|
||||
|
||||
private:
|
||||
static int _CompareTeams(const TeamInfo* a,
|
||||
const TeamInfo* b);
|
||||
static int _FindTeamByKey(const team_id* id,
|
||||
const TeamInfo* info);
|
||||
|
||||
void _NotifyTeamAdded(TeamInfo* info);
|
||||
void _NotifyTeamRemoved(team_id team);
|
||||
void _NotifyTeamRenamed(TeamInfo* info);
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
BLocker fLock;
|
||||
ListenerList fListeners;
|
||||
TeamInfoList fTeams;
|
||||
};
|
||||
|
||||
|
||||
class TargetHost::Listener
|
||||
: public DoublyLinkedListLinkImpl<TargetHost::Listener> {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void TeamAdded(TeamInfo* info);
|
||||
virtual void TeamRemoved(team_id team);
|
||||
virtual void TeamRenamed(TeamInfo* info);
|
||||
};
|
||||
|
||||
#endif // TARGET_HOST_H
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "TargetHostInterface.h"
|
||||
|
||||
|
||||
// #pragma mark - TargetHostInterface
|
||||
|
||||
TargetHostInterface::~TargetHostInterface()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TargetHostInterface::SetName(const BString& name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TARGET_HOST_INTERFACE_H
|
||||
#define TARGET_HOST_INTERFACE_H
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class DebuggerInterface;
|
||||
class TargetHost;
|
||||
|
||||
|
||||
class TargetHostInterface : public BReferenceable {
|
||||
public:
|
||||
virtual ~TargetHostInterface();
|
||||
|
||||
virtual status_t Init() = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
const BString& Name() const { return fName; }
|
||||
void SetName(const BString& name);
|
||||
|
||||
virtual bool Connected() const = 0;
|
||||
|
||||
virtual TargetHost* GetTargetHost() = 0;
|
||||
|
||||
virtual status_t Attach(team_id id, thread_id threadID,
|
||||
DebuggerInterface*& _interface) = 0;
|
||||
|
||||
virtual status_t CreateTeam(int commandLineArgc,
|
||||
const char* const* arguments,
|
||||
DebuggerInterface*& _interface) = 0;
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
};
|
||||
|
||||
|
||||
#endif // TARGET_HOST_INTERFACE_H
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "LocalTargetHostInterface.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
#include <system_info.h>
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include "TargetHost.h"
|
||||
|
||||
|
||||
LocalTargetHostInterface::LocalTargetHostInterface()
|
||||
:
|
||||
TargetHostInterface(),
|
||||
fTargetHost(NULL),
|
||||
fDataPort(-1)
|
||||
{
|
||||
SetName("Local");
|
||||
}
|
||||
|
||||
|
||||
LocalTargetHostInterface::~LocalTargetHostInterface()
|
||||
{
|
||||
Close();
|
||||
|
||||
if (fTargetHost != NULL)
|
||||
fTargetHost->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LocalTargetHostInterface::Init()
|
||||
{
|
||||
char hostname[HOST_NAME_MAX + 1];
|
||||
status_t error = gethostname(hostname, sizeof(hostname));
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fTargetHost = new(std::nothrow) TargetHost(hostname);
|
||||
if (fTargetHost == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
team_info info;
|
||||
error = get_team_info(B_CURRENT_TEAM, &info);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "LocalTargetHostInterface %" B_PRId32,
|
||||
info.team);
|
||||
|
||||
fDataPort = create_port(100, buffer);
|
||||
if (fDataPort < 0)
|
||||
return fDataPort;
|
||||
|
||||
fPortWorker = spawn_thread(PortLoop, "Local Target Host Loop",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
if (fPortWorker < 0)
|
||||
return fPortWorker;
|
||||
|
||||
resume_thread(fPortWorker);
|
||||
|
||||
AutoLocker<TargetHost> hostLocker(fTargetHost);
|
||||
|
||||
error = __start_watching_system(-1,
|
||||
B_WATCH_SYSTEM_TEAM_CREATION | B_WATCH_SYSTEM_TEAM_DELETION,
|
||||
fDataPort, 0);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
int32 cookie = 0;
|
||||
while (get_next_team_info(&cookie, &info) == B_OK) {
|
||||
error = fTargetHost->AddTeam(info);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LocalTargetHostInterface::Close()
|
||||
{
|
||||
if (fDataPort > 0) {
|
||||
__stop_watching_system(-1,
|
||||
B_WATCH_SYSTEM_TEAM_CREATION | B_WATCH_SYSTEM_TEAM_DELETION,
|
||||
fDataPort, 0);
|
||||
|
||||
delete_port(fDataPort);
|
||||
fDataPort = -1;
|
||||
}
|
||||
|
||||
if (fPortWorker > 0) {
|
||||
wait_for_thread(fPortWorker, NULL);
|
||||
fPortWorker = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LocalTargetHostInterface::Connected() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
TargetHost*
|
||||
LocalTargetHostInterface::GetTargetHost()
|
||||
{
|
||||
return fTargetHost;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LocalTargetHostInterface::Attach(team_id id, thread_id threadID,
|
||||
DebuggerInterface*& _interface)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LocalTargetHostInterface::CreateTeam(int commandLineArgc,
|
||||
const char* const* arguments, DebuggerInterface*& _interface)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LocalTargetHostInterface::PortLoop(void* arg)
|
||||
{
|
||||
LocalTargetHostInterface* interface = (LocalTargetHostInterface*)arg;
|
||||
|
||||
for (;;) {
|
||||
char buffer[2048];
|
||||
int32 messageCode;
|
||||
ssize_t size = read_port(interface->fDataPort, &messageCode, buffer,
|
||||
sizeof(buffer));
|
||||
if (size == B_INTERRUPTED)
|
||||
continue;
|
||||
else if (size < 0)
|
||||
return size;
|
||||
|
||||
KMessage message;
|
||||
size = message.SetTo(buffer);
|
||||
if (size != B_OK)
|
||||
return size;
|
||||
|
||||
if (message.What() != B_SYSTEM_OBJECT_UPDATE)
|
||||
continue;
|
||||
|
||||
int32 opcode = 0;
|
||||
if (message.FindInt32("opcode", &opcode) != B_OK)
|
||||
continue;
|
||||
|
||||
team_id team = -1;
|
||||
if (message.FindInt32("team", &team) != B_OK)
|
||||
continue;
|
||||
|
||||
AutoLocker<TargetHost> locker(interface->fTargetHost);
|
||||
switch (opcode) {
|
||||
case B_TEAM_CREATED:
|
||||
case B_TEAM_EXEC:
|
||||
{
|
||||
team_info info;
|
||||
status_t error = get_team_info(team, &info);
|
||||
if (error != B_OK)
|
||||
continue;
|
||||
|
||||
if (opcode == B_TEAM_CREATED)
|
||||
interface->fTargetHost->AddTeam(info);
|
||||
else
|
||||
interface->fTargetHost->UpdateTeam(info);
|
||||
break;
|
||||
}
|
||||
|
||||
case B_TEAM_DELETED:
|
||||
{
|
||||
interface->fTargetHost->RemoveTeam(team);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2016, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LOCAL_TARGET_HOST_INTERFACE_H
|
||||
#define LOCAL_TARGET_HOST_INTERFACE_H
|
||||
|
||||
#include "TargetHostInterface.h"
|
||||
|
||||
#include <Looper.h>
|
||||
|
||||
|
||||
class LocalTargetHostInterface : public TargetHostInterface {
|
||||
public:
|
||||
LocalTargetHostInterface();
|
||||
virtual ~LocalTargetHostInterface();
|
||||
|
||||
virtual status_t Init();
|
||||
virtual void Close();
|
||||
|
||||
virtual bool Connected() const;
|
||||
|
||||
virtual TargetHost* GetTargetHost();
|
||||
|
||||
virtual status_t Attach(team_id id, thread_id threadID,
|
||||
DebuggerInterface*& _interface);
|
||||
|
||||
virtual status_t CreateTeam(int commandLineArgc,
|
||||
const char* const* arguments,
|
||||
DebuggerInterface*& _interface);
|
||||
|
||||
private:
|
||||
static status_t PortLoop(void* arg);
|
||||
|
||||
private:
|
||||
TargetHost* fTargetHost;
|
||||
port_id fDataPort;
|
||||
thread_id fPortWorker;
|
||||
};
|
||||
|
||||
#endif // LOCAL_TARGET_HOST_INTERFACE_H
|
||||
Reference in New Issue
Block a user