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:
Rene Gollent
2016-04-02 22:48:58 -04:00
parent 2e7058114c
commit c6897b2871
9 changed files with 569 additions and 0 deletions
+9
View File
@@ -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
+182
View File
@@ -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)
{
}
+74
View File
@@ -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