hrev50181 adds 4 changesets to branch 'master'
old head: 7c6b944cea08924674b1d0d87f506b57b4f73d81
new head: c6897b2871afdbddc7df045d80e9fb0dd1eeabe3
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=c6897b2871af+%5E7c6b944cea08
----------------------------------------------------------------------------
5632edebb402: Debugger: Resolve minor TODO.
6bef41c6a90d: Debugger: Minor refactor.
TeamDebugger:
- Rather than instantiating the DebuggerInterface directly, we now
expect it to be given to us externally. This allows TeamDebugger
to be agnostic of where the team actually resides.
Debugger:
- Create and initialize DebuggerInterface before passing it on to
TeamDebugger.
No functional change.
2e7058114c6e: Debugger: DebuggerInterface refactor.
DebuggerInterface:
- Refactor into abstract base class.
- Introduce interface configuration abstract base class.
- Move existing implementation into LocalDebuggerInterface and add
corresponding configuration class.
Debugger:
- Adjust to instantiate LocalDebuggerInterface.
In and of itself no functional change, but paves the way for further
refactoring to make the debugger fully interface-agnostic (this isn't yet
the case for retrieving target system information such as the team listing,
and creating/attaching to teams).
c6897b2871af: 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.
[ Rene Gollent <rene@xxxxxxxxxxx> ]
----------------------------------------------------------------------------
16 files changed, 1715 insertions(+), 1020 deletions(-)
src/apps/debugger/Debugger.cpp | 17 +-
src/apps/debugger/Jamfile | 13 +
src/apps/debugger/controllers/TeamDebugger.cpp | 16 +-
src/apps/debugger/controllers/TeamDebugger.h | 6 +-
.../debugger_interface/DebuggerInterface.cpp | 949 +-----------------
.../debugger_interface/DebuggerInterface.h | 92 +-
.../interfaces/LocalDebuggerInterface.cpp | 985 +++++++++++++++++++
.../interfaces/LocalDebuggerInterface.h | 97 ++
src/apps/debugger/model/TargetHost.cpp | 182 ++++
src/apps/debugger/model/TargetHost.h | 74 ++
.../TargetHostInterface.cpp | 20 +
.../target_host_interface/TargetHostInterface.h | 44 +
.../TargetHostInterfaceRoster.cpp | 0
.../TargetHostInterfaceRoster.h | 0
.../interfaces/LocalTargetHostInterface.cpp | 199 ++++
.../interfaces/LocalTargetHostInterface.h | 41 +
############################################################################
Commit: 5632edebb4022a1fba58be2a43b9ac00683db495
URL: http://cgit.haiku-os.org/haiku/commit/?id=5632edebb402
Author: Rene Gollent <rene@xxxxxxxxxxx>
Date: Wed Mar 23 21:18:28 2016 UTC
Debugger: Resolve minor TODO.
----------------------------------------------------------------------------
diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
index 8e03267..3f462da 100644
--- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
+++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2010-2015, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2010-2016, Rene Gollent, rene@xxxxxxxxxxx.
* Distributed under the terms of the MIT License.
*/
@@ -292,7 +292,6 @@ DebuggerInterface::Init()
fDebuggerPort, 0);
if (error != B_OK)
return error;
-// TODO: Stop watching in Close()!
// create debug context pool
fDebugContextPool = new(std::nothrow) DebugContextPool(fTeamID,
fNubPort);
@@ -315,8 +314,11 @@ DebuggerInterface::Close(bool killTeam)
else if (fNubPort >= 0)
remove_team_debugger(fTeamID);
- if (fDebuggerPort >= 0)
+ if (fDebuggerPort >= 0) {
+ __stop_watching_system(fTeamID,
B_WATCH_SYSTEM_THREAD_PROPERTIES,
+ fDebuggerPort, 0);
delete_port(fDebuggerPort);
+ }
fNubPort = -1;
fDebuggerPort = -1;
############################################################################
Commit: 6bef41c6a90dea8758295f485c7eba91154d8052
URL: http://cgit.haiku-os.org/haiku/commit/?id=6bef41c6a90d
Author: Rene Gollent <rene@xxxxxxxxxxx>
Date: Tue Mar 29 21:44:18 2016 UTC
Debugger: Minor refactor.
TeamDebugger:
- Rather than instantiating the DebuggerInterface directly, we now
expect it to be given to us externally. This allows TeamDebugger
to be agnostic of where the team actually resides.
Debugger:
- Create and initialize DebuggerInterface before passing it on to
TeamDebugger.
No functional change.
----------------------------------------------------------------------------
diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp
index 603a212..775fd40 100644
--- a/src/apps/debugger/Debugger.cpp
+++ b/src/apps/debugger/Debugger.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2011-2015, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2011-2016, Rene Gollent, rene@xxxxxxxxxxx.
* Distributed under the terms of the MIT License.
*/
@@ -23,6 +23,7 @@
#include "debug_utils.h"
#include "CommandLineUserInterface.h"
+#include "DebuggerInterface.h"
#include "GraphicalUserInterface.h"
#include "ImageDebugLoadingStateHandlerRoster.h"
#include "MessageCodes.h"
@@ -310,12 +311,22 @@ start_team_debugger(team_id teamID, SettingsManager*
settingsManager,
userInterfaceReference.SetTo(userInterface, true);
}
+ BReference<DebuggerInterface> interfaceReference;
+ DebuggerInterface* debuggerInterface
+ = new(std::nothrow) DebuggerInterface(teamID);
+ if (debuggerInterface == NULL)
+ return NULL;
+ interfaceReference.SetTo(debuggerInterface, true);
+
+ if (debuggerInterface->Init() != B_OK)
+ return NULL;
+
status_t error = B_NO_MEMORY;
TeamDebugger* debugger = new(std::nothrow) TeamDebugger(listener,
userInterface, settingsManager);
- if (debugger) {
- error = debugger->Init(teamID, threadID, commandLineArgc,
+ if (debugger != NULL) {
+ error = debugger->Init(debuggerInterface, threadID,
commandLineArgc,
commandLineArgv, stopInMain);
}
diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp
b/src/apps/debugger/controllers/TeamDebugger.cpp
index e86bfb9..9d6e5f9 100644
--- a/src/apps/debugger/controllers/TeamDebugger.cpp
+++ b/src/apps/debugger/controllers/TeamDebugger.cpp
@@ -1,6 +1,6 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2010-2015, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2010-2016, Rene Gollent, rene@xxxxxxxxxxx.
* Distributed under the terms of the MIT License.
*/
@@ -321,7 +321,7 @@ TeamDebugger::~TeamDebugger()
status_t
-TeamDebugger::Init(team_id teamID, thread_id threadID, int argc,
+TeamDebugger::Init(DebuggerInterface* interface, thread_id threadID, int argc,
const char* const* argv, bool stopInMain)
{
bool targetIsLocal = true;
@@ -330,20 +330,14 @@ TeamDebugger::Init(team_id teamID, thread_id threadID,
int argc,
// the first thing we want to do when running
PostMessage(MSG_LOAD_SETTINGS);
- fTeamID = teamID;
-
status_t error = _HandleSetArguments(argc, argv);
if (error != B_OK)
return error;
- // create debugger interface
- fDebuggerInterface = new(std::nothrow) DebuggerInterface(fTeamID);
- if (fDebuggerInterface == NULL)
- return B_NO_MEMORY;
+ fDebuggerInterface = interface;
+ fDebuggerInterface->AcquireReference();
+ fTeamID = interface->TeamID();
- error = fDebuggerInterface->Init();
- if (error != B_OK)
- return error;
// create file manager
fFileManager = new(std::nothrow) FileManager;
diff --git a/src/apps/debugger/controllers/TeamDebugger.h
b/src/apps/debugger/controllers/TeamDebugger.h
index 7e64586..7cce854 100644
--- a/src/apps/debugger/controllers/TeamDebugger.h
+++ b/src/apps/debugger/controllers/TeamDebugger.h
@@ -1,6 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
- * Copyright 2013-2015, Rene Gollent, rene@xxxxxxxxxxx.
+ * Copyright 2013-2016, Rene Gollent, rene@xxxxxxxxxxx.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_DEBUGGER_H
@@ -42,8 +42,8 @@ public:
SettingsManager* settingsManager);
~TeamDebugger();
- status_t Init(team_id teamID,
thread_id threadID,
- int
argc,
+ status_t Init(DebuggerInterface*
interface,
+
thread_id threadID, int argc,
const
char* const* argv,
bool
stopInMain);
diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.h
b/src/apps/debugger/debugger_interface/DebuggerInterface.h
index 6465acc..386730a 100644
--- a/src/apps/debugger/debugger_interface/DebuggerInterface.h
+++ b/src/apps/debugger/debugger_interface/DebuggerInterface.h
@@ -41,6 +41,9 @@ public:
bool Connected() const
{
return fNubPort >= 0; }
+ team_id TeamID() const
+ {
return fTeamID; }
+
Architecture* GetArchitecture() const
{
return fArchitecture; }
############################################################################
Commit: 2e7058114c6e20b2ce9f03187f59d1f73bce49d7
URL: http://cgit.haiku-os.org/haiku/commit/?id=2e7058114c6e
Author: Rene Gollent <rene@xxxxxxxxxxx>
Date: Tue Mar 29 21:49:32 2016 UTC
Debugger: DebuggerInterface refactor.
DebuggerInterface:
- Refactor into abstract base class.
- Introduce interface configuration abstract base class.
- Move existing implementation into LocalDebuggerInterface and add
corresponding configuration class.
Debugger:
- Adjust to instantiate LocalDebuggerInterface.
In and of itself no functional change, but paves the way for further
refactoring to make the debugger fully interface-agnostic (this isn't yet
the case for retrieving target system information such as the team listing,
and creating/attaching to teams).
----------------------------------------------------------------------------
diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp
index 775fd40..5d2773e 100644
--- a/src/apps/debugger/Debugger.cpp
+++ b/src/apps/debugger/Debugger.cpp
@@ -23,7 +23,7 @@
#include "debug_utils.h"
#include "CommandLineUserInterface.h"
-#include "DebuggerInterface.h"
+#include "LocalDebuggerInterface.h"
#include "GraphicalUserInterface.h"
#include "ImageDebugLoadingStateHandlerRoster.h"
#include "MessageCodes.h"
@@ -313,7 +313,7 @@ start_team_debugger(team_id teamID, SettingsManager*
settingsManager,
BReference<DebuggerInterface> interfaceReference;
DebuggerInterface* debuggerInterface
- = new(std::nothrow) DebuggerInterface(teamID);
+ = new(std::nothrow) LocalDebuggerInterface(teamID);
if (debuggerInterface == NULL)
return NULL;
interfaceReference.SetTo(debuggerInterface, true);
diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index cc075c3..be5e74e 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -23,6 +23,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info loading_state_handlers ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_managers ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
+SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface interfaces ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
@@ -137,6 +138,9 @@ local sources =
DebugEvent.cpp
DebuggerInterface.cpp
+ # debugger_interface/interfaces
+ LocalDebuggerInterface.cpp
+
# elf
ElfFile.cpp
diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
index 3f462da..61e6388 100644
--- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
+++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp
@@ -6,958 +6,9 @@
#include "DebuggerInterface.h"
-#include <new>
-
-#include <stdio.h>
-
-#include <Locker.h>
-
-#include <AutoLocker.h>
-#include <memory_private.h>
-#include <OS.h>
-#include <system_info.h>
-#include <util/DoublyLinkedList.h>
-#include <util/KMessage.h>
-
-#include "debug_utils.h"
-
-#include "ArchitectureX86.h"
-#include "ArchitectureX8664.h"
-#include "AreaInfo.h"
-#include "AutoDeleter.h"
-#include "CpuState.h"
-#include "DebugEvent.h"
-#include "ImageInfo.h"
-#include "SemaphoreInfo.h"
-#include "SymbolInfo.h"
-#include "SystemInfo.h"
-#include "TeamInfo.h"
-#include "ThreadInfo.h"
-
-
-// number of debug contexts the pool does initially create
-static const int kInitialDebugContextCount = 3;
-
-// maximum number of debug contexts in the pool
-static const int kMaxDebugContextCount = 10;
-
-
-struct DebuggerInterface::DebugContext : debug_context,
- DoublyLinkedListLinkImpl<DebugContext> {
- DebugContext()
- {
- team = -1;
- nub_port = -1;
- reply_port = -1;
- }
-
- ~DebugContext()
- {
- if (reply_port >= 0)
- destroy_debug_context(this);
- }
-
- status_t Init(team_id team, port_id nubPort)
- {
- return init_debug_context(this, team, nubPort);
- }
-
- void Close()
- {
- if (reply_port >= 0) {
- destroy_debug_context(this);
- team = -1;
- nub_port = -1;
- reply_port = -1;
- }
- }
-};
-
-
-struct DebuggerInterface::DebugContextPool {
- DebugContextPool(team_id team, port_id nubPort)
- :
- fLock("debug context pool"),
- fTeam(team),
- fNubPort(nubPort),
- fBlockSem(-1),
- fContextCount(0),
- fWaiterCount(0),
- fClosed(false)
- {
- }
-
- ~DebugContextPool()
- {
- AutoLocker<BLocker> locker(fLock);
-
- while (DebugContext* context = fFreeContexts.RemoveHead())
- delete context;
-
- if (fBlockSem >= 0)
- delete_sem(fBlockSem);
- }
-
- status_t Init()
- {
- status_t error = fLock.InitCheck();
- if (error != B_OK)
- return error;
-
- fBlockSem = create_sem(0, "debug context pool block");
- if (fBlockSem < 0)
- return fBlockSem;
-
- for (int i = 0; i < kInitialDebugContextCount; i++) {
- DebugContext* context;
- error = _CreateDebugContext(context);
- if (error != B_OK)
- return error;
-
- fFreeContexts.Add(context);
- }
-
- return B_OK;
- }
-
- void Close()
- {
- AutoLocker<BLocker> locker(fLock);
- fClosed = true;
-
- for (DebugContextList::Iterator it =
fFreeContexts.GetIterator();
- DebugContext* context = it.Next();) {
- context->Close();
- }
-
- for (DebugContextList::Iterator it =
fUsedContexts.GetIterator();
- DebugContext* context = it.Next();) {
- context->Close();
- }
- }
-
- DebugContext* GetContext()
- {
- AutoLocker<BLocker> locker(fLock);
- DebugContext* context = fFreeContexts.RemoveHead();
-
- if (context == NULL) {
- if (fContextCount >= kMaxDebugContextCount
- || _CreateDebugContext(context) != B_OK) {
- // wait for a free context
- while (context == NULL) {
- fWaiterCount++;
- locker.Unlock();
- while (acquire_sem(fBlockSem) != B_OK);
- locker.Lock();
- context = fFreeContexts.RemoveHead();
- }
- }
- }
-
- fUsedContexts.Add(context);
-
- return context;
- }
-
- void PutContext(DebugContext* context)
- {
- AutoLocker<BLocker> locker(fLock);
- fUsedContexts.Remove(context);
- fFreeContexts.Add(context);
-
- if (fWaiterCount > 0)
- release_sem(fBlockSem);
- }
-
-private:
- typedef DoublyLinkedList<DebugContext> DebugContextList;
-
-private:
- status_t _CreateDebugContext(DebugContext*& _context)
- {
- DebugContext* context = new(std::nothrow) DebugContext;
- if (context == NULL)
- return B_NO_MEMORY;
-
- if (!fClosed) {
- status_t error = context->Init(fTeam, fNubPort);
- if (error != B_OK) {
- delete context;
- return error;
- }
- }
-
- fContextCount++;
-
- _context = context;
- return B_OK;
- }
-
-private:
- BLocker fLock;
- team_id fTeam;
- port_id fNubPort;
- sem_id fBlockSem;
- int32 fContextCount;
- int32 fWaiterCount;
- DebugContextList fFreeContexts;
- DebugContextList fUsedContexts;
- bool fClosed;
-};
-
-
-struct DebuggerInterface::DebugContextGetter {
- DebugContextGetter(DebugContextPool* pool)
- :
- fPool(pool),
- fContext(pool->GetContext())
- {
- }
-
- ~DebugContextGetter()
- {
- fPool->PutContext(fContext);
- }
-
- DebugContext* Context() const
- {
- return fContext;
- }
-
-private:
- DebugContextPool* fPool;
- DebugContext* fContext;
-};
// #pragma mark - DebuggerInterface
-DebuggerInterface::DebuggerInterface(team_id teamID)
- :
- fTeamID(teamID),
- fDebuggerPort(-1),
- fNubPort(-1),
- fDebugContextPool(NULL),
- fArchitecture(NULL)
-{
-}
-
-
DebuggerInterface::~DebuggerInterface()
{
- if (fArchitecture != NULL)
- fArchitecture->ReleaseReference();
-
- Close(false);
-
- delete fDebugContextPool;
-}
-
-
-status_t
-DebuggerInterface::Init()
-{
- // create the architecture
- // TODO: this probably needs to be rethought a bit,
- // since especially when we eventually support remote debugging,
- // the architecture will depend on the target machine, not the host
-#if defined(ARCH_x86)
- fArchitecture = new(std::nothrow) ArchitectureX86(this);
-#elif defined(ARCH_x86_64)
- fArchitecture = new(std::nothrow) ArchitectureX8664(this);
-#else
- return B_UNSUPPORTED;
-#endif
-
- if (fArchitecture == NULL)
- return B_NO_MEMORY;
-
- status_t error = fArchitecture->Init();
- if (error != B_OK)
- return error;
-
- // create debugger port
- char buffer[128];
- snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debugger",
fTeamID);
- fDebuggerPort = create_port(100, buffer);
- if (fDebuggerPort < 0)
- return fDebuggerPort;
-
- // install as team debugger
- fNubPort = install_team_debugger(fTeamID, fDebuggerPort);
- if (fNubPort < 0)
- return fNubPort;
-
- error = __start_watching_system(fTeamID,
B_WATCH_SYSTEM_THREAD_PROPERTIES,
- fDebuggerPort, 0);
- if (error != B_OK)
- return error;
-
- // create debug context pool
- fDebugContextPool = new(std::nothrow) DebugContextPool(fTeamID,
fNubPort);
- if (fDebugContextPool == NULL)
- return B_NO_MEMORY;
-
- error = fDebugContextPool->Init();
- if (error != B_OK)
- return error;
-
- return B_OK;
-}
-
-
-void
-DebuggerInterface::Close(bool killTeam)
-{
- if (killTeam)
- kill_team(fTeamID);
- else if (fNubPort >= 0)
- remove_team_debugger(fTeamID);
-
- if (fDebuggerPort >= 0) {
- __stop_watching_system(fTeamID,
B_WATCH_SYSTEM_THREAD_PROPERTIES,
- fDebuggerPort, 0);
- delete_port(fDebuggerPort);
- }
-
- fNubPort = -1;
- fDebuggerPort = -1;
-}
-
-
-status_t
-DebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
-{
- while (true) {
- char buffer[2048];
- int32 messageCode;
- ssize_t size = read_port(fDebuggerPort, &messageCode, buffer,
- sizeof(buffer));
- if (size < 0) {
- if (size == B_INTERRUPTED)
- continue;
-
- return size;
- }
-
- if (messageCode <= B_DEBUGGER_MESSAGE_HANDED_OVER) {
- debug_debugger_message_data message;
- memcpy(&message, buffer, size);
- if (message.origin.team != fTeamID)
- continue;
-
- bool ignore = false;
- status_t error = _CreateDebugEvent(messageCode,
message, ignore,
- _event);
- if (error != B_OK)
- return error;
-
- if (ignore) {
- if (message.origin.thread >= 0 &&
message.origin.nub_port >= 0)
- error =
continue_thread(message.origin.nub_port,
- message.origin.thread);
- if (error != B_OK)
- return error;
- continue;
- }
-
- return B_OK;
- }
-
- KMessage message;
- size = message.SetTo(buffer);
- if (size != B_OK)
- return size;
- return _GetNextSystemWatchEvent(_event, message);
- }
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
-{
- return set_team_debugging_flags(fNubPort, flags);
-}
-
-
-status_t
-DebuggerInterface::ContinueThread(thread_id thread)
-{
- return continue_thread(fNubPort, thread);
-}
-
-
-status_t
-DebuggerInterface::StopThread(thread_id thread)
-{
- return debug_thread(thread);
-}
-
-
-status_t
-DebuggerInterface::SingleStepThread(thread_id thread)
-{
- debug_nub_continue_thread continueMessage;
- continueMessage.thread = thread;
- continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
- continueMessage.single_step = true;
-
- return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD,
- &continueMessage, sizeof(continueMessage));
-}
-
-
-status_t
-DebuggerInterface::InstallBreakpoint(target_addr_t address)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- debug_nub_set_breakpoint message;
- message.reply_port = contextGetter.Context()->reply_port;
- message.address = (void*)(addr_t)address;
-
- debug_nub_set_breakpoint_reply reply;
-
- status_t error = send_debug_message(contextGetter.Context(),
- B_DEBUG_MESSAGE_SET_BREAKPOINT, &message, sizeof(message),
&reply,
- sizeof(reply));
- return error == B_OK ? reply.error : error;
-}
-
-
-status_t
-DebuggerInterface::UninstallBreakpoint(target_addr_t address)
-{
- debug_nub_clear_breakpoint message;
- message.address = (void*)(addr_t)address;
-
- return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_BREAKPOINT,
- &message, sizeof(message));
-}
-
-
-status_t
-DebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type,
- int32 length)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- debug_nub_set_watchpoint message;
- message.reply_port = contextGetter.Context()->reply_port;
- message.address = (void*)(addr_t)address;
- message.type = type;
- message.length = length;
-
- debug_nub_set_watchpoint_reply reply;
-
- status_t error = send_debug_message(contextGetter.Context(),
- B_DEBUG_MESSAGE_SET_WATCHPOINT, &message, sizeof(message),
&reply,
- sizeof(reply));
- return error == B_OK ? reply.error : error;
-}
-
-
-status_t
-DebuggerInterface::UninstallWatchpoint(target_addr_t address)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- debug_nub_clear_watchpoint message;
- message.address = (void*)(addr_t)address;
-
- return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_WATCHPOINT,
- &message, sizeof(message));
-}
-
-
-status_t
-DebuggerInterface::GetSystemInfo(SystemInfo& info)
-{
- system_info sysInfo;
- status_t result = get_system_info(&sysInfo);
- if (result != B_OK)
- return result;
-
- utsname name;
- result = uname(&name);
- if (result != B_OK)
- return result;
-
- info.SetTo(fTeamID, sysInfo, name);
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetTeamInfo(TeamInfo& info)
-{
- team_info teamInfo;
- status_t result = get_team_info(fTeamID, &teamInfo);
- if (result != B_OK)
- return result;
-
- info.SetTo(fTeamID, teamInfo);
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos)
-{
- thread_info threadInfo;
- int32 cookie = 0;
- while (get_next_thread_info(fTeamID, &cookie, &threadInfo) == B_OK) {
- ThreadInfo* info = new(std::nothrow) ThreadInfo(threadInfo.team,
- threadInfo.thread, threadInfo.name);
- if (info == NULL || !infos.AddItem(info)) {
- delete info;
- return B_NO_MEMORY;
- }
- }
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
-{
- // get the team's images
- image_info imageInfo;
- int32 cookie = 0;
- while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
- ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID,
imageInfo.id,
- imageInfo.name, imageInfo.type, (addr_t)imageInfo.text,
- imageInfo.text_size, (addr_t)imageInfo.data,
imageInfo.data_size);
- if (info == NULL || !infos.AddItem(info)) {
- delete info;
- return B_NO_MEMORY;
- }
- }
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos)
-{
- // get the team's areas
- area_info areaInfo;
- ssize_t cookie = 0;
- while (get_next_area_info(fTeamID, &cookie, &areaInfo) == B_OK) {
- AreaInfo* info = new(std::nothrow) AreaInfo(fTeamID,
areaInfo.area,
- areaInfo.name, (addr_t)areaInfo.address, areaInfo.size,
- areaInfo.ram_size, areaInfo.lock, areaInfo.protection);
- if (info == NULL || !infos.AddItem(info)) {
- delete info;
- return B_NO_MEMORY;
- }
- }
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos)
-{
- // get the team's semaphores
- sem_info semInfo;
- int32 cookie = 0;
- while (get_next_sem_info(fTeamID, &cookie, &semInfo) == B_OK) {
- SemaphoreInfo* info = new(std::nothrow) SemaphoreInfo(fTeamID,
- semInfo.sem, semInfo.name, semInfo.count,
semInfo.latest_holder);
- if (info == NULL || !infos.AddItem(info)) {
- delete info;
- return B_NO_MEMORY;
- }
- }
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetSymbolInfos(team_id team, image_id image,
- BObjectList<SymbolInfo>& infos)
-{
- // create a lookup context
- debug_symbol_lookup_context* lookupContext;
- status_t error = debug_create_symbol_lookup_context(team, image,
- &lookupContext);
- if (error != B_OK)
- return error;
-
- // create a symbol iterator
- debug_symbol_iterator* iterator;
- error = debug_create_image_symbol_iterator(
- lookupContext, image, &iterator);
- if (error != B_OK) {
- debug_delete_symbol_lookup_context(lookupContext);
- return error;
- }
-
- // get the symbols
- char name[1024];
- int32 type;
- void* address;
- size_t size;
- while (debug_next_image_symbol(iterator, name, sizeof(name), &type,
- &address, &size) == B_OK) {
- SymbolInfo* info = new(std::nothrow) SymbolInfo(
- (target_addr_t)(addr_t)address, size, type, name);
- if (info == NULL)
- break;
- if (!infos.AddItem(info)) {
- delete info;
- break;
- }
- }
-
- // delete the symbol iterator and lookup context
- debug_delete_symbol_iterator(iterator);
- debug_delete_symbol_lookup_context(lookupContext);
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetSymbolInfo(team_id team, image_id image, const char*
name,
- int32 symbolType, SymbolInfo& info)
-{
- // create a lookup context
- debug_symbol_lookup_context* lookupContext;
- status_t error = debug_create_symbol_lookup_context(team, image,
- &lookupContext);
- if (error != B_OK)
- return error;
-
- // try to get the symbol
- void* foundAddress;
- size_t foundSize;
- int32 foundType;
- error = debug_get_symbol(lookupContext, image, name, symbolType,
- &foundAddress, &foundSize, &foundType);
- if (error == B_OK) {
- info.SetTo((target_addr_t)(addr_t)foundAddress, foundSize,
foundType,
- name);
- }
-
- // delete the lookup context
- debug_delete_symbol_lookup_context(lookupContext);
-
- return error;
-}
-
-
-status_t
-DebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
-{
- thread_info threadInfo;
- status_t error = get_thread_info(thread, &threadInfo);
- if (error != B_OK)
- return error;
-
- info.SetTo(threadInfo.team, threadInfo.thread, threadInfo.name);
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
-{
- debug_cpu_state debugState;
- status_t error = _GetDebugCpuState(thread, debugState);
- if (error != B_OK)
- return error;
- return fArchitecture->CreateCpuState(&debugState,
sizeof(debug_cpu_state),
- _state);
-}
-
-
-status_t
-DebuggerInterface::SetCpuState(thread_id thread, const CpuState* state)
-{
- debug_cpu_state debugState;
- status_t error = _GetDebugCpuState(thread, debugState);
- if (error != B_OK)
- return error;
-
- DebugContextGetter contextGetter(fDebugContextPool);
-
- error = state->UpdateDebugState(&debugState, sizeof(debugState));
- if (error != B_OK)
- return error;
-
- debug_nub_set_cpu_state message;
- message.thread = thread;
-
- memcpy(&message.cpu_state, &debugState, sizeof(debugState));
-
- return send_debug_message(contextGetter.Context(),
- B_DEBUG_MESSAGE_SET_CPU_STATE, &message, sizeof(message), NULL,
- 0);
-}
-
-
-status_t
-DebuggerInterface::GetCpuFeatures(uint32& flags)
-{
- return fArchitecture->GetCpuFeatures(flags);
-}
-
-
-status_t
-DebuggerInterface::GetMemoryProperties(target_addr_t address,
- uint32& protection, uint32& locking)
-{
- return get_memory_properties(fTeamID, (const void *)address,
- &protection, &locking);
-}
-
-
-ssize_t
-DebuggerInterface::ReadMemory(target_addr_t address, void* buffer, size_t size)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- return debug_read_memory(contextGetter.Context(),
- (const void*)(addr_t)address, buffer, size);
-}
-
-
-ssize_t
-DebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
- size_t size)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- return debug_write_memory(contextGetter.Context(),
- (const void*)address, buffer, size);
-}
-
-
-status_t
-DebuggerInterface::_CreateDebugEvent(int32 messageCode,
- const debug_debugger_message_data& message, bool& _ignore,
- DebugEvent*& _event)
-{
- DebugEvent* event = NULL;
-
- switch (messageCode) {
- case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
- event = new(std::nothrow)
ThreadDebuggedEvent(message.origin.team,
- message.origin.thread);
- break;
- case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
- event = new(std::nothrow)
DebuggerCallEvent(message.origin.team,
- message.origin.thread,
- (target_addr_t)message.debugger_call.message);
- break;
- case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
- {
- CpuState* state = NULL;
- status_t error = fArchitecture->CreateCpuState(
- &message.breakpoint_hit.cpu_state,
- sizeof(debug_cpu_state), state);
- if (error != B_OK)
- return error;
-
- event = new(std::nothrow)
BreakpointHitEvent(message.origin.team,
- message.origin.thread, state);
- state->ReleaseReference();
- break;
- }
- case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
- {
- CpuState* state = NULL;
- status_t error = fArchitecture->CreateCpuState(
- &message.watchpoint_hit.cpu_state,
- sizeof(debug_cpu_state), state);
- if (error != B_OK)
- return error;
-
- event = new(std::nothrow)
WatchpointHitEvent(message.origin.team,
- message.origin.thread, state);
- state->ReleaseReference();
- break;
- }
- case B_DEBUGGER_MESSAGE_SINGLE_STEP:
- {
- CpuState* state = NULL;
- status_t error = fArchitecture->CreateCpuState(
- &message.single_step.cpu_state,
- sizeof(debug_cpu_state), state);
- if (error != B_OK)
- return error;
-
- event = new(std::nothrow)
SingleStepEvent(message.origin.team,
- message.origin.thread, state);
- state->ReleaseReference();
- break;
- }
- case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
- event = new(std::nothrow) ExceptionOccurredEvent(
- message.origin.team, message.origin.thread,
- message.exception_occurred.exception);
- break;
- case B_DEBUGGER_MESSAGE_TEAM_DELETED:
- if (message.origin.team != fTeamID) {
- _ignore = true;
- return B_OK;
- }
- event = new(std::nothrow)
TeamDeletedEvent(message.origin.team,
- message.origin.thread);
- break;
- case B_DEBUGGER_MESSAGE_TEAM_EXEC:
- if (message.origin.team != fTeamID) {
- _ignore = true;
- return B_OK;
- }
- event = new(std::nothrow)
TeamExecEvent(message.origin.team,
- message.origin.thread);
- break;
- case B_DEBUGGER_MESSAGE_THREAD_CREATED:
- event = new(std::nothrow)
ThreadCreatedEvent(message.origin.team,
- message.origin.thread,
message.thread_created.new_thread);
- break;
- case B_DEBUGGER_MESSAGE_THREAD_DELETED:
- event = new(std::nothrow)
ThreadDeletedEvent(message.origin.team,
- message.origin.thread);
- break;
- case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
- {
- const image_info& info = message.image_created.info;
- event = new(std::nothrow)
ImageCreatedEvent(message.origin.team,
- message.origin.thread,
- ImageInfo(fTeamID, info.id, info.name,
info.type,
- (addr_t)info.text, info.text_size,
(addr_t)info.data,
- info.data_size));
- break;
- }
- case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
- {
- const image_info& info = message.image_deleted.info;
- event = new(std::nothrow)
ImageDeletedEvent(message.origin.team,
- message.origin.thread,
- ImageInfo(fTeamID, info.id, info.name,
info.type,
- (addr_t)info.text, info.text_size,
(addr_t)info.data,
- info.data_size));
- break;
- }
- case B_DEBUGGER_MESSAGE_POST_SYSCALL:
- {
- event = new(std::nothrow)
PostSyscallEvent(message.origin.team,
- message.origin.thread,
- SyscallInfo(message.post_syscall.start_time,
- message.post_syscall.end_time,
- message.post_syscall.return_value,
- message.post_syscall.syscall,
message.post_syscall.args));
- break;
- }
- case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
- {
- event = new(std::nothrow)
SignalReceivedEvent(message.origin.team,
- message.origin.thread,
- SignalInfo(message.signal_received.signal,
- message.signal_received.handler,
- message.signal_received.deadly));
- break;
- }
- default:
- printf("DebuggerInterface for team %" B_PRId32 ":
unknown message "
- "from kernel: %" B_PRId32 "\n", fTeamID,
messageCode);
- // fall through...
- case B_DEBUGGER_MESSAGE_TEAM_CREATED:
- case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
- case B_DEBUGGER_MESSAGE_PROFILER_UPDATE:
- case B_DEBUGGER_MESSAGE_HANDED_OVER:
- _ignore = true;
- return B_OK;
- }
-
- if (event == NULL)
- return B_NO_MEMORY;
-
- if (message.origin.thread >= 0 && message.origin.nub_port >= 0)
- event->SetThreadStopped(true);
-
- _ignore = false;
- _event = event;
-
- return B_OK;
-}
-
-
-status_t
-DebuggerInterface::_GetNextSystemWatchEvent(DebugEvent*& _event,
- KMessage& message)
-{
- status_t error = B_OK;
- if (message.What() != B_SYSTEM_OBJECT_UPDATE)
- return B_BAD_DATA;
-
- int32 opcode = 0;
- if (message.FindInt32("opcode", &opcode) != B_OK)
- return B_BAD_DATA;
-
- DebugEvent* event = NULL;
- switch (opcode)
- {
- case B_THREAD_NAME_CHANGED:
- {
- int32 threadID = -1;
- if (message.FindInt32("thread", &threadID) != B_OK)
- break;
-
- thread_info info;
- error = get_thread_info(threadID, &info);
- if (error != B_OK)
- break;
-
- event = new(std::nothrow) ThreadRenamedEvent(fTeamID,
- threadID, threadID, info.name);
- break;
- }
-
- default:
- {
- error = B_BAD_DATA;
- break;
- }
- }
-
- if (event != NULL)
- _event = event;
-
- return error;
-}
-
-
-status_t
-DebuggerInterface::_GetDebugCpuState(thread_id thread, debug_cpu_state& _state)
-{
- DebugContextGetter contextGetter(fDebugContextPool);
-
- debug_nub_get_cpu_state message;
- message.reply_port = contextGetter.Context()->reply_port;
- message.thread = thread;
-
- debug_nub_get_cpu_state_reply reply;
-
- status_t error = send_debug_message(contextGetter.Context(),
- B_DEBUG_MESSAGE_GET_CPU_STATE, &message, sizeof(message),
&reply,
- sizeof(reply));
- if (error != B_OK)
- return error;
- if (reply.error != B_OK)
- return reply.error;
-
- memcpy(&_state, &reply.cpu_state, sizeof(debug_cpu_state));
-
- return B_OK;
}
diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.h
b/src/apps/debugger/debugger_interface/DebuggerInterface.h
index 386730a..0211f51 100644
--- a/src/apps/debugger/debugger_interface/DebuggerInterface.h
+++ b/src/apps/debugger/debugger_interface/DebuggerInterface.h
@@ -32,90 +32,69 @@ class KMessage;
class DebuggerInterface : public TeamMemory {
public:
-
DebuggerInterface(team_id teamID);
virtual ~DebuggerInterface();
- status_t Init();
- void Close(bool killTeam);
+ virtual status_t Init()
+ = 0;
+ virtual void Close(bool killTeam) = 0;
- bool Connected() const
- {
return fNubPort >= 0; }
+ virtual bool Connected() const = 0;
- team_id TeamID() const
- {
return fTeamID; }
+ virtual team_id TeamID() const = 0;
- Architecture* GetArchitecture() const
- {
return fArchitecture; }
+ virtual Architecture* GetArchitecture() const = 0;
- virtual status_t GetNextDebugEvent(DebugEvent*&
_event);
+ virtual status_t GetNextDebugEvent(DebugEvent*&
_event) = 0;
- virtual status_t SetTeamDebuggingFlags(uint32
flags);
+ virtual status_t SetTeamDebuggingFlags(uint32
flags) = 0;
- virtual status_t ContinueThread(thread_id
thread);
- virtual status_t StopThread(thread_id thread);
- virtual status_t SingleStepThread(thread_id
thread);
+ virtual status_t ContinueThread(thread_id
thread) = 0;
+ virtual status_t StopThread(thread_id thread) =
0;
+ virtual status_t SingleStepThread(thread_id
thread) = 0;
- virtual status_t InstallBreakpoint(target_addr_t
address);
- virtual status_t
UninstallBreakpoint(target_addr_t address);
+ virtual status_t InstallBreakpoint(target_addr_t
address) = 0;
+ virtual status_t
UninstallBreakpoint(target_addr_t address) = 0;
virtual status_t InstallWatchpoint(target_addr_t
address,
- uint32
type, int32 length);
- virtual status_t
UninstallWatchpoint(target_addr_t address);
-
- virtual status_t GetSystemInfo(SystemInfo& info);
- virtual status_t GetTeamInfo(TeamInfo& info);
- virtual status_t
GetThreadInfos(BObjectList<ThreadInfo>& infos);
- virtual status_t
GetImageInfos(BObjectList<ImageInfo>& infos);
- virtual status_t
GetAreaInfos(BObjectList<AreaInfo>& infos);
+ uint32
type, int32 length) = 0;
+ virtual status_t
UninstallWatchpoint(target_addr_t address) = 0;
+
+ virtual status_t GetSystemInfo(SystemInfo& info)
= 0;
+ virtual status_t GetTeamInfo(TeamInfo& info) = 0;
+ virtual status_t
GetThreadInfos(BObjectList<ThreadInfo>& infos)
+ = 0;
+ virtual status_t
GetImageInfos(BObjectList<ImageInfo>& infos)
+ = 0;
+ virtual status_t
GetAreaInfos(BObjectList<AreaInfo>& infos)
+ = 0;
virtual status_t GetSemaphoreInfos(
-
BObjectList<SemaphoreInfo>& infos);
+
BObjectList<SemaphoreInfo>& infos)
+ = 0;
+
virtual status_t GetSymbolInfos(team_id team,
image_id image,
-
BObjectList<SymbolInfo>& infos);
+
BObjectList<SymbolInfo>& infos) = 0;
virtual status_t GetSymbolInfo(team_id team,
image_id image,
const
char* name, int32 symbolType,
-
SymbolInfo& info);
+
SymbolInfo& info) = 0;
virtual status_t GetThreadInfo(thread_id thread,
-
ThreadInfo& info);
+
ThreadInfo& info) = 0;
virtual status_t GetCpuState(thread_id thread,
-
CpuState*& _state);
+
CpuState*& _state) = 0;
// returns a reference to the caller
virtual status_t SetCpuState(thread_id thread,
- const
CpuState* state);
+ const
CpuState* state) = 0;
- virtual status_t GetCpuFeatures(uint32& flags);
+ virtual status_t GetCpuFeatures(uint32& flags) =
0;
// TeamMemory
virtual status_t
GetMemoryProperties(target_addr_t address,
- uint32&
protection, uint32& locking);
+ uint32&
protection, uint32& locking) = 0;
virtual ssize_t ReadMemory(target_addr_t
address, void* buffer,
- size_t
size);
+ size_t
size) = 0;
virtual ssize_t WriteMemory(target_addr_t
address,
- void*
buffer, size_t size);
-
-private:
- struct DebugContext;
- struct DebugContextPool;
- struct DebugContextGetter;
-
-private:
- status_t _CreateDebugEvent(int32
messageCode,
- const
debug_debugger_message_data& message,
- bool&
_ignore, DebugEvent*& _event);
-
- status_t
_GetNextSystemWatchEvent(DebugEvent*& _event,
-
BPrivate::KMessage& message);
-
- status_t
_GetDebugCpuState(thread_id thread,
-
debug_cpu_state& _state);
-
-private:
- team_id fTeamID;
- port_id fDebuggerPort;
- port_id fNubPort;
- DebugContextPool* fDebugContextPool;
- Architecture* fArchitecture;
+ void*
buffer, size_t size) = 0;
};
#endif // DEBUGGER_INTERFACE_H
diff --git
a/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.cpp
b/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.cpp
new file mode 100644
index 0000000..c90b950
--- /dev/null
+++ b/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.cpp
@@ -0,0 +1,985 @@
+/*
+ * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2010-2016, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "LocalDebuggerInterface.h"
+
+#include <new>
+
+#include <stdio.h>
+
+#include <Locker.h>
+
+#include <AutoLocker.h>
+#include <memory_private.h>
+#include <OS.h>
+#include <system_info.h>
+#include <util/DoublyLinkedList.h>
+#include <util/KMessage.h>
+
+#include "debug_utils.h"
+
+#include "ArchitectureX86.h"
+#include "ArchitectureX8664.h"
+#include "AreaInfo.h"
+#include "AutoDeleter.h"
+#include "CpuState.h"
+#include "DebugEvent.h"
+#include "ImageInfo.h"
+#include "SemaphoreInfo.h"
+#include "SymbolInfo.h"
+#include "SystemInfo.h"
+#include "TeamInfo.h"
+#include "ThreadInfo.h"
+
+
+// number of debug contexts the pool does initially create
+static const int kInitialDebugContextCount = 3;
+
+// maximum number of debug contexts in the pool
+static const int kMaxDebugContextCount = 10;
+
+
+// #pragma mark - LocalDebuggerInterface::DebugContext
+
+struct LocalDebuggerInterface::DebugContext : debug_context,
+ DoublyLinkedListLinkImpl<DebugContext> {
+ DebugContext()
+ {
+ team = -1;
+ nub_port = -1;
+ reply_port = -1;
+ }
+
+ ~DebugContext()
+ {
+ if (reply_port >= 0)
+ destroy_debug_context(this);
+ }
+
+ status_t Init(team_id team, port_id nubPort)
+ {
+ return init_debug_context(this, team, nubPort);
+ }
+
+ void Close()
+ {
+ if (reply_port >= 0) {
+ destroy_debug_context(this);
+ team = -1;
+ nub_port = -1;
+ reply_port = -1;
+ }
+ }
+};
+
+// #pragma mark - LocalDebuggerInterface::DebugContextPool
+
+struct LocalDebuggerInterface::DebugContextPool {
+ DebugContextPool(team_id team, port_id nubPort)
+ :
+ fLock("debug context pool"),
+ fTeam(team),
+ fNubPort(nubPort),
+ fBlockSem(-1),
+ fContextCount(0),
+ fWaiterCount(0),
+ fClosed(false)
+ {
+ }
+
+ ~DebugContextPool()
+ {
+ AutoLocker<BLocker> locker(fLock);
+
+ while (DebugContext* context = fFreeContexts.RemoveHead())
+ delete context;
+
+ if (fBlockSem >= 0)
+ delete_sem(fBlockSem);
+ }
+
+ status_t Init()
+ {
+ status_t error = fLock.InitCheck();
+ if (error != B_OK)
+ return error;
+
+ fBlockSem = create_sem(0, "debug context pool block");
+ if (fBlockSem < 0)
+ return fBlockSem;
+
+ for (int i = 0; i < kInitialDebugContextCount; i++) {
+ DebugContext* context;
+ error = _CreateDebugContext(context);
+ if (error != B_OK)
+ return error;
+
+ fFreeContexts.Add(context);
+ }
+
+ return B_OK;
+ }
+
+ void Close()
+ {
+ AutoLocker<BLocker> locker(fLock);
+ fClosed = true;
+
+ for (DebugContextList::Iterator it =
fFreeContexts.GetIterator();
+ DebugContext* context = it.Next();) {
+ context->Close();
+ }
+
+ for (DebugContextList::Iterator it =
fUsedContexts.GetIterator();
+ DebugContext* context = it.Next();) {
+ context->Close();
+ }
+ }
+
+ DebugContext* GetContext()
+ {
+ AutoLocker<BLocker> locker(fLock);
+ DebugContext* context = fFreeContexts.RemoveHead();
+
+ if (context == NULL) {
+ if (fContextCount >= kMaxDebugContextCount
+ || _CreateDebugContext(context) != B_OK) {
+ // wait for a free context
+ while (context == NULL) {
+ fWaiterCount++;
+ locker.Unlock();
+ while (acquire_sem(fBlockSem) != B_OK);
+ locker.Lock();
+ context = fFreeContexts.RemoveHead();
+ }
+ }
+ }
+
+ fUsedContexts.Add(context);
+
+ return context;
+ }
+
+ void PutContext(DebugContext* context)
+ {
+ AutoLocker<BLocker> locker(fLock);
+ fUsedContexts.Remove(context);
+ fFreeContexts.Add(context);
+
+ if (fWaiterCount > 0)
+ release_sem(fBlockSem);
+ }
+
+private:
+ typedef DoublyLinkedList<DebugContext> DebugContextList;
+
+private:
+ status_t _CreateDebugContext(DebugContext*& _context)
+ {
+ DebugContext* context = new(std::nothrow) DebugContext;
+ if (context == NULL)
+ return B_NO_MEMORY;
+
+ if (!fClosed) {
+ status_t error = context->Init(fTeam, fNubPort);
+ if (error != B_OK) {
+ delete context;
+ return error;
+ }
+ }
+
+ fContextCount++;
+
+ _context = context;
+ return B_OK;
+ }
+
+private:
+ BLocker fLock;
+ team_id fTeam;
+ port_id fNubPort;
+ sem_id fBlockSem;
+ int32 fContextCount;
+ int32 fWaiterCount;
+ DebugContextList fFreeContexts;
+ DebugContextList fUsedContexts;
+ bool fClosed;
+};
+
+
+struct LocalDebuggerInterface::DebugContextGetter {
+ DebugContextGetter(DebugContextPool* pool)
+ :
+ fPool(pool),
+ fContext(pool->GetContext())
+ {
+ }
+
+ ~DebugContextGetter()
+ {
+ fPool->PutContext(fContext);
+ }
+
+ DebugContext* Context() const
+ {
+ return fContext;
+ }
+
+private:
+ DebugContextPool* fPool;
+ DebugContext* fContext;
+};
+
+// #pragma mark - LocalDebuggerInterface
+
+LocalDebuggerInterface::LocalDebuggerInterface(team_id team)
+ :
+ DebuggerInterface(),
+ fTeamID(team),
+ fDebuggerPort(-1),
+ fNubPort(-1),
+ fDebugContextPool(NULL),
+ fArchitecture(NULL)
+{
+}
+
+
+LocalDebuggerInterface::~LocalDebuggerInterface()
+{
+ if (fArchitecture != NULL)
+ fArchitecture->ReleaseReference();
+
+ Close(false);
+
+ delete fDebugContextPool;
+}
+
+
+status_t
+LocalDebuggerInterface::Init()
+{
+ // create the architecture
+#if defined(ARCH_x86)
+ fArchitecture = new(std::nothrow) ArchitectureX86(this);
+#elif defined(ARCH_x86_64)
+ fArchitecture = new(std::nothrow) ArchitectureX8664(this);
+#else
+ return B_UNSUPPORTED;
+#endif
+
+ if (fArchitecture == NULL)
+ return B_NO_MEMORY;
+
+ status_t error = fArchitecture->Init();
+ if (error != B_OK)
+ return error;
+
+ // create debugger port
+ char buffer[128];
+ snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debugger",
fTeamID);
+ fDebuggerPort = create_port(100, buffer);
+ if (fDebuggerPort < 0)
+ return fDebuggerPort;
+
+ // install as team debugger
+ fNubPort = install_team_debugger(fTeamID, fDebuggerPort);
+ if (fNubPort < 0)
+ return fNubPort;
+
+ error = __start_watching_system(fTeamID,
B_WATCH_SYSTEM_THREAD_PROPERTIES,
+ fDebuggerPort, 0);
+ if (error != B_OK)
+ return error;
+
+ // create debug context pool
+ fDebugContextPool = new(std::nothrow) DebugContextPool(fTeamID,
fNubPort);
+ if (fDebugContextPool == NULL)
+ return B_NO_MEMORY;
+
+ error = fDebugContextPool->Init();
+ if (error != B_OK)
+ return error;
+
+ return B_OK;
+}
+
+
+void
+LocalDebuggerInterface::Close(bool killTeam)
+{
+ if (killTeam)
+ kill_team(fTeamID);
+ else if (fNubPort >= 0)
+ remove_team_debugger(fTeamID);
+
+ if (fDebuggerPort >= 0) {
+ __stop_watching_system(fTeamID,
B_WATCH_SYSTEM_THREAD_PROPERTIES,
+ fDebuggerPort, 0);
+ delete_port(fDebuggerPort);
+ }
+
+ fNubPort = -1;
+ fDebuggerPort = -1;
+}
+
+
+bool
+LocalDebuggerInterface::Connected() const
+{
+ return fNubPort >= 0;
+}
+
+
+team_id
+LocalDebuggerInterface::TeamID() const
+{
+ return fTeamID;
+}
+
+
+Architecture*
+LocalDebuggerInterface::GetArchitecture() const
+{
+ return fArchitecture;
+}
+
+
+status_t
+LocalDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
+{
+ while (true) {
+ char buffer[2048];
+ int32 messageCode;
+ ssize_t size = read_port(fDebuggerPort, &messageCode, buffer,
+ sizeof(buffer));
+ if (size < 0) {
+ if (size == B_INTERRUPTED)
+ continue;
+
+ return size;
+ }
+
+ if (messageCode <= B_DEBUGGER_MESSAGE_HANDED_OVER) {
+ debug_debugger_message_data message;
+ memcpy(&message, buffer, size);
+ if (message.origin.team != fTeamID)
+ continue;
+
+ bool ignore = false;
+ status_t error = _CreateDebugEvent(messageCode,
message, ignore,
+ _event);
+ if (error != B_OK)
+ return error;
+
+ if (ignore) {
+ if (message.origin.thread >= 0 &&
message.origin.nub_port >= 0)
+ error =
continue_thread(message.origin.nub_port,
+ message.origin.thread);
+ if (error != B_OK)
+ return error;
+ continue;
+ }
+
+ return B_OK;
+ }
+
+ KMessage message;
+ size = message.SetTo(buffer);
+ if (size != B_OK)
+ return size;
+ return _GetNextSystemWatchEvent(_event, message);
+ }
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
+{
+ return set_team_debugging_flags(fNubPort, flags);
+}
+
+
+status_t
+LocalDebuggerInterface::ContinueThread(thread_id thread)
+{
+ return continue_thread(fNubPort, thread);
+}
+
+
+status_t
+LocalDebuggerInterface::StopThread(thread_id thread)
+{
+ return debug_thread(thread);
+}
+
+
+status_t
+LocalDebuggerInterface::SingleStepThread(thread_id thread)
+{
+ debug_nub_continue_thread continueMessage;
+ continueMessage.thread = thread;
+ continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
+ continueMessage.single_step = true;
+
+ return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD,
+ &continueMessage, sizeof(continueMessage));
+}
+
+
+status_t
+LocalDebuggerInterface::InstallBreakpoint(target_addr_t address)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ debug_nub_set_breakpoint message;
+ message.reply_port = contextGetter.Context()->reply_port;
+ message.address = (void*)(addr_t)address;
+
+ debug_nub_set_breakpoint_reply reply;
+
+ status_t error = send_debug_message(contextGetter.Context(),
+ B_DEBUG_MESSAGE_SET_BREAKPOINT, &message, sizeof(message),
&reply,
+ sizeof(reply));
+ return error == B_OK ? reply.error : error;
+}
+
+
+status_t
+LocalDebuggerInterface::UninstallBreakpoint(target_addr_t address)
+{
+ debug_nub_clear_breakpoint message;
+ message.address = (void*)(addr_t)address;
+
+ return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_BREAKPOINT,
+ &message, sizeof(message));
+}
+
+
+status_t
+LocalDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type,
+ int32 length)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ debug_nub_set_watchpoint message;
+ message.reply_port = contextGetter.Context()->reply_port;
+ message.address = (void*)(addr_t)address;
+ message.type = type;
+ message.length = length;
+
+ debug_nub_set_watchpoint_reply reply;
+
+ status_t error = send_debug_message(contextGetter.Context(),
+ B_DEBUG_MESSAGE_SET_WATCHPOINT, &message, sizeof(message),
&reply,
+ sizeof(reply));
+ return error == B_OK ? reply.error : error;
+}
+
+
+status_t
+LocalDebuggerInterface::UninstallWatchpoint(target_addr_t address)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ debug_nub_clear_watchpoint message;
+ message.address = (void*)(addr_t)address;
+
+ return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_WATCHPOINT,
+ &message, sizeof(message));
+}
+
+
+status_t
+LocalDebuggerInterface::GetSystemInfo(SystemInfo& info)
+{
+ system_info sysInfo;
+ status_t result = get_system_info(&sysInfo);
+ if (result != B_OK)
+ return result;
+
+ utsname name;
+ result = uname(&name);
+ if (result != B_OK)
+ return result;
+
+ info.SetTo(fTeamID, sysInfo, name);
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetTeamInfo(TeamInfo& info)
+{
+ team_info teamInfo;
+ status_t result = get_team_info(fTeamID, &teamInfo);
+ if (result != B_OK)
+ return result;
+
+ info.SetTo(fTeamID, teamInfo);
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos)
+{
+ thread_info threadInfo;
+ int32 cookie = 0;
+ while (get_next_thread_info(fTeamID, &cookie, &threadInfo) == B_OK) {
+ ThreadInfo* info = new(std::nothrow) ThreadInfo(threadInfo.team,
+ threadInfo.thread, threadInfo.name);
+ if (info == NULL || !infos.AddItem(info)) {
+ delete info;
+ return B_NO_MEMORY;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
+{
+ // get the team's images
+ image_info imageInfo;
+ int32 cookie = 0;
+ while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
+ ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID,
imageInfo.id,
+ imageInfo.name, imageInfo.type, (addr_t)imageInfo.text,
+ imageInfo.text_size, (addr_t)imageInfo.data,
imageInfo.data_size);
+ if (info == NULL || !infos.AddItem(info)) {
+ delete info;
+ return B_NO_MEMORY;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos)
+{
+ // get the team's areas
+ area_info areaInfo;
+ ssize_t cookie = 0;
+ while (get_next_area_info(fTeamID, &cookie, &areaInfo) == B_OK) {
+ AreaInfo* info = new(std::nothrow) AreaInfo(fTeamID,
areaInfo.area,
+ areaInfo.name, (addr_t)areaInfo.address, areaInfo.size,
+ areaInfo.ram_size, areaInfo.lock, areaInfo.protection);
+ if (info == NULL || !infos.AddItem(info)) {
+ delete info;
+ return B_NO_MEMORY;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos)
+{
+ // get the team's semaphores
+ sem_info semInfo;
+ int32 cookie = 0;
+ while (get_next_sem_info(fTeamID, &cookie, &semInfo) == B_OK) {
+ SemaphoreInfo* info = new(std::nothrow) SemaphoreInfo(fTeamID,
+ semInfo.sem, semInfo.name, semInfo.count,
semInfo.latest_holder);
+ if (info == NULL || !infos.AddItem(info)) {
+ delete info;
+ return B_NO_MEMORY;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetSymbolInfos(team_id team, image_id image,
+ BObjectList<SymbolInfo>& infos)
+{
+ // create a lookup context
+ debug_symbol_lookup_context* lookupContext;
+ status_t error = debug_create_symbol_lookup_context(team, image,
+ &lookupContext);
+ if (error != B_OK)
+ return error;
+
+ // create a symbol iterator
+ debug_symbol_iterator* iterator;
+ error = debug_create_image_symbol_iterator(
+ lookupContext, image, &iterator);
+ if (error != B_OK) {
+ debug_delete_symbol_lookup_context(lookupContext);
+ return error;
+ }
+
+ // get the symbols
+ char name[1024];
+ int32 type;
+ void* address;
+ size_t size;
+ while (debug_next_image_symbol(iterator, name, sizeof(name), &type,
+ &address, &size) == B_OK) {
+ SymbolInfo* info = new(std::nothrow) SymbolInfo(
+ (target_addr_t)(addr_t)address, size, type, name);
+ if (info == NULL)
+ break;
+ if (!infos.AddItem(info)) {
+ delete info;
+ break;
+ }
+ }
+
+ // delete the symbol iterator and lookup context
+ debug_delete_symbol_iterator(iterator);
+ debug_delete_symbol_lookup_context(lookupContext);
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetSymbolInfo(team_id team, image_id image, const
char* name,
+ int32 symbolType, SymbolInfo& info)
+{
+ // create a lookup context
+ debug_symbol_lookup_context* lookupContext;
+ status_t error = debug_create_symbol_lookup_context(team, image,
+ &lookupContext);
+ if (error != B_OK)
+ return error;
+
+ // try to get the symbol
+ void* foundAddress;
+ size_t foundSize;
+ int32 foundType;
+ error = debug_get_symbol(lookupContext, image, name, symbolType,
+ &foundAddress, &foundSize, &foundType);
+ if (error == B_OK) {
+ info.SetTo((target_addr_t)(addr_t)foundAddress, foundSize,
foundType,
+ name);
+ }
+
+ // delete the lookup context
+ debug_delete_symbol_lookup_context(lookupContext);
+
+ return error;
+}
+
+
+status_t
+LocalDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
+{
+ thread_info threadInfo;
+ status_t error = get_thread_info(thread, &threadInfo);
+ if (error != B_OK)
+ return error;
+
+ info.SetTo(threadInfo.team, threadInfo.thread, threadInfo.name);
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
+{
+ debug_cpu_state debugState;
+ status_t error = _GetDebugCpuState(thread, debugState);
+ if (error != B_OK)
+ return error;
+ return fArchitecture->CreateCpuState(&debugState,
sizeof(debug_cpu_state),
+ _state);
+}
+
+
+status_t
+LocalDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state)
+{
+ debug_cpu_state debugState;
+ status_t error = _GetDebugCpuState(thread, debugState);
+ if (error != B_OK)
+ return error;
+
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ error = state->UpdateDebugState(&debugState, sizeof(debugState));
+ if (error != B_OK)
+ return error;
+
+ debug_nub_set_cpu_state message;
+ message.thread = thread;
+
+ memcpy(&message.cpu_state, &debugState, sizeof(debugState));
+
+ return send_debug_message(contextGetter.Context(),
+ B_DEBUG_MESSAGE_SET_CPU_STATE, &message, sizeof(message), NULL,
+ 0);
+}
+
+
+status_t
+LocalDebuggerInterface::GetCpuFeatures(uint32& flags)
+{
+ return fArchitecture->GetCpuFeatures(flags);
+}
+
+
+status_t
+LocalDebuggerInterface::GetMemoryProperties(target_addr_t address,
+ uint32& protection, uint32& locking)
+{
+ return get_memory_properties(fTeamID, (const void *)address,
+ &protection, &locking);
+}
+
+
+ssize_t
+LocalDebuggerInterface::ReadMemory(target_addr_t address, void* buffer, size_t
size)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ return debug_read_memory(contextGetter.Context(),
+ (const void*)(addr_t)address, buffer, size);
+}
+
+
+ssize_t
+LocalDebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
+ size_t size)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ return debug_write_memory(contextGetter.Context(),
+ (const void*)address, buffer, size);
+}
+
+
+status_t
+LocalDebuggerInterface::_CreateDebugEvent(int32 messageCode,
+ const debug_debugger_message_data& message, bool& _ignore,
+ DebugEvent*& _event)
+{
+ DebugEvent* event = NULL;
+
+ switch (messageCode) {
+ case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
+ event = new(std::nothrow)
ThreadDebuggedEvent(message.origin.team,
+ message.origin.thread);
+ break;
+ case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
+ event = new(std::nothrow)
DebuggerCallEvent(message.origin.team,
+ message.origin.thread,
+ (target_addr_t)message.debugger_call.message);
+ break;
+ case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
+ {
+ CpuState* state = NULL;
+ status_t error = fArchitecture->CreateCpuState(
+ &message.breakpoint_hit.cpu_state,
+ sizeof(debug_cpu_state), state);
+ if (error != B_OK)
+ return error;
+
+ event = new(std::nothrow)
BreakpointHitEvent(message.origin.team,
+ message.origin.thread, state);
+ state->ReleaseReference();
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
+ {
+ CpuState* state = NULL;
+ status_t error = fArchitecture->CreateCpuState(
+ &message.watchpoint_hit.cpu_state,
+ sizeof(debug_cpu_state), state);
+ if (error != B_OK)
+ return error;
+
+ event = new(std::nothrow)
WatchpointHitEvent(message.origin.team,
+ message.origin.thread, state);
+ state->ReleaseReference();
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_SINGLE_STEP:
+ {
+ CpuState* state = NULL;
+ status_t error = fArchitecture->CreateCpuState(
+ &message.single_step.cpu_state,
+ sizeof(debug_cpu_state), state);
+ if (error != B_OK)
+ return error;
+
+ event = new(std::nothrow)
SingleStepEvent(message.origin.team,
+ message.origin.thread, state);
+ state->ReleaseReference();
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
+ event = new(std::nothrow) ExceptionOccurredEvent(
+ message.origin.team, message.origin.thread,
+ message.exception_occurred.exception);
+ break;
+ case B_DEBUGGER_MESSAGE_TEAM_DELETED:
+ if (message.origin.team != fTeamID) {
+ _ignore = true;
+ return B_OK;
+ }
+ event = new(std::nothrow)
TeamDeletedEvent(message.origin.team,
+ message.origin.thread);
+ break;
+ case B_DEBUGGER_MESSAGE_TEAM_EXEC:
+ if (message.origin.team != fTeamID) {
+ _ignore = true;
+ return B_OK;
+ }
+ event = new(std::nothrow)
TeamExecEvent(message.origin.team,
+ message.origin.thread);
+ break;
+ case B_DEBUGGER_MESSAGE_THREAD_CREATED:
+ event = new(std::nothrow)
ThreadCreatedEvent(message.origin.team,
+ message.origin.thread,
message.thread_created.new_thread);
+ break;
+ case B_DEBUGGER_MESSAGE_THREAD_DELETED:
+ event = new(std::nothrow)
ThreadDeletedEvent(message.origin.team,
+ message.origin.thread);
+ break;
+ case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
+ {
+ const image_info& info = message.image_created.info;
+ event = new(std::nothrow)
ImageCreatedEvent(message.origin.team,
+ message.origin.thread,
+ ImageInfo(fTeamID, info.id, info.name,
info.type,
+ (addr_t)info.text, info.text_size,
(addr_t)info.data,
+ info.data_size));
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
+ {
+ const image_info& info = message.image_deleted.info;
+ event = new(std::nothrow)
ImageDeletedEvent(message.origin.team,
+ message.origin.thread,
+ ImageInfo(fTeamID, info.id, info.name,
info.type,
+ (addr_t)info.text, info.text_size,
(addr_t)info.data,
+ info.data_size));
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_POST_SYSCALL:
+ {
+ event = new(std::nothrow)
PostSyscallEvent(message.origin.team,
+ message.origin.thread,
+ SyscallInfo(message.post_syscall.start_time,
+ message.post_syscall.end_time,
+ message.post_syscall.return_value,
+ message.post_syscall.syscall,
message.post_syscall.args));
+ break;
+ }
+ case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
+ {
+ event = new(std::nothrow)
SignalReceivedEvent(message.origin.team,
+ message.origin.thread,
+ SignalInfo(message.signal_received.signal,
+ message.signal_received.handler,
+ message.signal_received.deadly));
+ break;
+ }
+ default:
+ printf("DebuggerInterface for team %" B_PRId32 ":
unknown message "
+ "from kernel: %" B_PRId32 "\n", fTeamID,
messageCode);
+ // fall through...
+ case B_DEBUGGER_MESSAGE_TEAM_CREATED:
+ case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
+ case B_DEBUGGER_MESSAGE_PROFILER_UPDATE:
+ case B_DEBUGGER_MESSAGE_HANDED_OVER:
+ _ignore = true;
+ return B_OK;
+ }
+
+ if (event == NULL)
+ return B_NO_MEMORY;
+
+ if (message.origin.thread >= 0 && message.origin.nub_port >= 0)
+ event->SetThreadStopped(true);
+
+ _ignore = false;
+ _event = event;
+
+ return B_OK;
+}
+
+
+status_t
+LocalDebuggerInterface::_GetNextSystemWatchEvent(DebugEvent*& _event,
+ KMessage& message)
+{
+ status_t error = B_OK;
+ if (message.What() != B_SYSTEM_OBJECT_UPDATE)
+ return B_BAD_DATA;
+
+ int32 opcode = 0;
+ if (message.FindInt32("opcode", &opcode) != B_OK)
+ return B_BAD_DATA;
+
+ DebugEvent* event = NULL;
+ switch (opcode)
+ {
+ case B_THREAD_NAME_CHANGED:
+ {
+ int32 threadID = -1;
+ if (message.FindInt32("thread", &threadID) != B_OK)
+ break;
+
+ thread_info info;
+ error = get_thread_info(threadID, &info);
+ if (error != B_OK)
+ break;
+
+ event = new(std::nothrow) ThreadRenamedEvent(fTeamID,
+ threadID, threadID, info.name);
+ break;
+ }
+
+ default:
+ {
+ error = B_BAD_DATA;
+ break;
+ }
+ }
+
+ if (event != NULL)
+ _event = event;
+
+ return error;
+}
+
+
+status_t
+LocalDebuggerInterface::_GetDebugCpuState(thread_id thread, debug_cpu_state&
_state)
+{
+ DebugContextGetter contextGetter(fDebugContextPool);
+
+ debug_nub_get_cpu_state message;
+ message.reply_port = contextGetter.Context()->reply_port;
+ message.thread = thread;
+
+ debug_nub_get_cpu_state_reply reply;
+
+ status_t error = send_debug_message(contextGetter.Context(),
+ B_DEBUG_MESSAGE_GET_CPU_STATE, &message, sizeof(message),
&reply,
+ sizeof(reply));
+ if (error != B_OK)
+ return error;
+ if (reply.error != B_OK)
+ return reply.error;
+
+ memcpy(&_state, &reply.cpu_state, sizeof(debug_cpu_state));
+
+ return B_OK;
+}
diff --git
a/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.h
b/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.h
new file mode 100644
index 0000000..6e44bc7
--- /dev/null
+++ b/src/apps/debugger/debugger_interface/interfaces/LocalDebuggerInterface.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 2010-2016, Rene Gollent, rene@xxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef LOCAL_DEBUGGER_INTERFACE_H
+#define LOCAL_DEBUGGER_INTERFACE_H
+
+#include "DebuggerInterface.h"
+
+
+class LocalDebuggerInterface : public DebuggerInterface {
+public:
+
LocalDebuggerInterface(team_id team);
+ virtual
~LocalDebuggerInterface();
+
+ virtual status_t Init();
+ virtual void Close(bool killTeam);
+
+ virtual bool Connected() const;
+
+ virtual team_id TeamID() const;
+
+ virtual Architecture* GetArchitecture() const;
+
+ virtual status_t GetNextDebugEvent(DebugEvent*&
_event);
+
+ virtual status_t SetTeamDebuggingFlags(uint32
flags);
+
+ virtual status_t ContinueThread(thread_id
thread);
+ virtual status_t StopThread(thread_id thread);
+ virtual status_t SingleStepThread(thread_id
thread);
+
+ virtual status_t InstallBreakpoint(target_addr_t
address);
+ virtual status_t
UninstallBreakpoint(target_addr_t address);
+
+ virtual status_t InstallWatchpoint(target_addr_t
address,
+ uint32
type, int32 length);
+ virtual status_t
UninstallWatchpoint(target_addr_t address);
+
+ virtual status_t GetSystemInfo(SystemInfo& info);
+ virtual status_t GetTeamInfo(TeamInfo& info);
+ virtual status_t
GetThreadInfos(BObjectList<ThreadInfo>& infos);
+ virtual status_t
GetImageInfos(BObjectList<ImageInfo>& infos);
+ virtual status_t
GetAreaInfos(BObjectList<AreaInfo>& infos);
+ virtual status_t GetSemaphoreInfos(
+
BObjectList<SemaphoreInfo>& infos);
+ virtual status_t GetSymbolInfos(team_id team,
image_id image,
+
BObjectList<SymbolInfo>& infos);
+ virtual status_t GetSymbolInfo(team_id team,
image_id image,
+ const
char* name, int32 symbolType,
+
SymbolInfo& info);
+
+ virtual status_t GetThreadInfo(thread_id thread,
+
ThreadInfo& info);
+ virtual status_t GetCpuState(thread_id thread,
+
CpuState*& _state);
+
// returns a reference to the caller
+ virtual status_t SetCpuState(thread_id thread,
+ const
CpuState* state);
+
+ virtual status_t GetCpuFeatures(uint32& flags);
+
+ // TeamMemory
+ virtual status_t
GetMemoryProperties(target_addr_t address,
+ uint32&
protection, uint32& locking);
+
+ virtual ssize_t ReadMemory(target_addr_t
address, void* buffer,
+ size_t
size);
+ virtual ssize_t WriteMemory(target_addr_t
address,
+ void*
buffer, size_t size);
+
+private:
+ struct DebugContext;
+ struct DebugContextPool;
+ struct DebugContextGetter;
+
+private:
+ status_t _CreateDebugEvent(int32
messageCode,
+ const
debug_debugger_message_data& message,
+ bool&
_ignore, DebugEvent*& _event);
+
+ status_t
_GetNextSystemWatchEvent(DebugEvent*& _event,
+
BPrivate::KMessage& message);
+
+ status_t
_GetDebugCpuState(thread_id thread,
+
debug_cpu_state& _state);
+
+private:
+ team_id fTeamID;
+ port_id fDebuggerPort;
+ port_id fNubPort;
+ DebugContextPool* fDebugContextPool;
+ Architecture* fArchitecture;
+};
+
+#endif // DEBUGGER_INTERFACE_H
############################################################################
Revision: hrev50181
Commit: c6897b2871afdbddc7df045d80e9fb0dd1eeabe3
URL: http://cgit.haiku-os.org/haiku/commit/?id=c6897b2871af
Author: Rene Gollent <rene@xxxxxxxxxxx>
Date: Sat Apr 2 21:14:49 2016 UTC
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.
----------------------------------------------------------------------------
diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile
index be5e74e..7b49c77 100644
--- a/src/apps/debugger/Jamfile
+++ b/src/apps/debugger/Jamfile
@@ -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
diff --git a/src/apps/debugger/model/TargetHost.cpp
b/src/apps/debugger/model/TargetHost.cpp
new file mode 100644
index 0000000..42c90ed
--- /dev/null
+++ b/src/apps/debugger/model/TargetHost.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2016, Rene Gollent, rene@xxxxxxxxxxx.
+ * 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;
+}
+
+
[ *** diff truncated: 528 lines dropped *** ]