From 008dd42650a27f897064eb71f97eedf429fe9f18 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 16 Jun 2009 00:25:36 +0000 Subject: [PATCH] Initial skeletons of the model (Team, Thread, Image) and the controller (TeamDebugger) for debugging a team. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31068 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debugger/Image.cpp | 25 ++++ src/apps/debugger/Image.h | 32 +++++ src/apps/debugger/Jamfile | 8 +- src/apps/debugger/Team.cpp | 164 +++++++++++++++++++++++ src/apps/debugger/Team.h | 47 +++++++ src/apps/debugger/TeamDebugger.cpp | 205 +++++++++++++++++++++++++++++ src/apps/debugger/TeamDebugger.h | 40 ++++++ src/apps/debugger/Thread.cpp | 32 +++++ src/apps/debugger/Thread.h | 36 +++++ src/apps/debugger/debugger.cpp | 9 +- 10 files changed, 593 insertions(+), 5 deletions(-) create mode 100644 src/apps/debugger/Image.cpp create mode 100644 src/apps/debugger/Image.h create mode 100644 src/apps/debugger/Team.cpp create mode 100644 src/apps/debugger/Team.h create mode 100644 src/apps/debugger/TeamDebugger.cpp create mode 100644 src/apps/debugger/TeamDebugger.h create mode 100644 src/apps/debugger/Thread.cpp create mode 100644 src/apps/debugger/Thread.h diff --git a/src/apps/debugger/Image.cpp b/src/apps/debugger/Image.cpp new file mode 100644 index 0000000000..2528212a8b --- /dev/null +++ b/src/apps/debugger/Image.cpp @@ -0,0 +1,25 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Image.h" + + +Image::Image(const image_info& imageInfo) + : + fInfo(imageInfo) +{ +} + + +Image::~Image() +{ +} + + +status_t +Image::Init() +{ + return B_OK; +} diff --git a/src/apps/debugger/Image.h b/src/apps/debugger/Image.h new file mode 100644 index 0000000000..4a01172640 --- /dev/null +++ b/src/apps/debugger/Image.h @@ -0,0 +1,32 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef IMAGE_H +#define IMAGE_H + +#include + +#include + + +class Image : public DoublyLinkedListLinkImpl { +public: + Image(const image_info& imageInfo); + ~Image(); + + status_t Init(); + + image_id ID() const { return fInfo.id; } + const char* Name() const { return fInfo.name; } + const image_info& Info() const { return fInfo; } + +private: + image_info fInfo; +}; + + +typedef DoublyLinkedList ImageList; + + +#endif // IMAGE_H diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 2f10ad5978..57c8a5db36 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -10,6 +10,11 @@ Application Debugger : debugger.cpp ElfFile.cpp + Image.cpp + TeamDebugger.cpp + Team.cpp + Thread.cpp + # DWARF # attribute_classes.cpp # AttributeValue.cpp @@ -19,6 +24,7 @@ Application Debugger : # SourceLanguageInfo.cpp # tag_names.cpp - : $(TARGET_LIBSUPC++) + : $(TARGET_LIBSUPC++) be ; +HaikuSubInclude gui running_teams_window ; diff --git a/src/apps/debugger/Team.cpp b/src/apps/debugger/Team.cpp new file mode 100644 index 0000000000..b4818ee1dd --- /dev/null +++ b/src/apps/debugger/Team.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Team.h" + +#include + + +Team::Team(team_id teamID) + : + fID(teamID) +{ +} + + +Team::~Team() +{ + while (Image* image = fImages.RemoveHead()) + delete image; + + while (Thread* thread = fThreads.RemoveHead()) + delete thread; +} + + +status_t +Team::Init() +{ + return BLocker::InitCheck(); +} + + +void +Team::SetName(const BString& name) +{ + fName = name; +} + + +void +Team::AddThread(Thread* thread) +{ + fThreads.Add(thread); +} + + +status_t +Team::AddThread(const thread_info& threadInfo, Thread** _thread) +{ + Thread* thread = new(std::nothrow) Thread(threadInfo.thread); + if (thread == NULL) + return B_NO_MEMORY; + + status_t error = thread->Init(); + if (error != B_OK) { + delete thread; + return error; + } + + thread->SetName(threadInfo.name); + AddThread(thread); + + if (_thread != NULL) + *_thread = thread; + + return B_OK; +} + + +void +Team::RemoveThread(Thread* thread) +{ + fThreads.Remove(thread); +} + + +bool +Team::RemoveThread(thread_id threadID) +{ + Thread* thread = ThreadByID(threadID); + if (thread == NULL) + return false; + + RemoveThread(thread); + delete thread; + return true; +} + + +Thread* +Team::ThreadByID(thread_id threadID) const +{ + for (ThreadList::ConstIterator it = fThreads.GetIterator(); + Thread* thread = it.Next();) { + if (thread->ID() == threadID) + return thread; + } + + return NULL; +} + + +void +Team::AddImage(Image* image) +{ + fImages.Add(image); +} + + +status_t +Team::AddImage(const image_info& imageInfo, Image** _image) +{ + Image* image = new(std::nothrow) Image(imageInfo); + if (image == NULL) + return B_NO_MEMORY; + + status_t error = image->Init(); + if (error != B_OK) { + delete image; + return error; + } + + AddImage(image); + + if (_image != NULL) + *_image = image; + + return B_OK; +} + + +void +Team::RemoveImage(Image* image) +{ + fImages.Remove(image); +} + + +bool +Team::RemoveImage(image_id imageID) +{ + Image* image = ImageByID(imageID); + if (image == NULL) + return false; + + RemoveImage(image); + delete image; + return true; +} + + +Image* +Team::ImageByID(image_id imageID) const +{ + for (ImageList::ConstIterator it = fImages.GetIterator(); + Image* image = it.Next();) { + if (image->ID() == imageID) + return image; + } + + return NULL; +} diff --git a/src/apps/debugger/Team.h b/src/apps/debugger/Team.h new file mode 100644 index 0000000000..3cabf22ee2 --- /dev/null +++ b/src/apps/debugger/Team.h @@ -0,0 +1,47 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TEAM_H +#define TEAM_H + +#include + +#include "Image.h" +#include "Thread.h" + + +class Team : public BLocker { +public: + Team(team_id teamID); + ~Team(); + + status_t Init(); + + team_id ID() const { return fID; } + + const char* Name() const { return fName.String(); } + void SetName(const BString& name); + + void AddThread(Thread* thread); + status_t AddThread(const thread_info& threadInfo, + Thread** _thread = NULL); + void RemoveThread(Thread* thread); + bool RemoveThread(thread_id threadID); + Thread* ThreadByID(thread_id threadID) const; + + void AddImage(Image* image); + status_t AddImage(const image_info& imageInfo, + Image** _image = NULL); + void RemoveImage(Image* image); + bool RemoveImage(image_id imageID); + Image* ImageByID(image_id imageID) const; + +private: + team_id fID; + BString fName; + ThreadList fThreads; + ImageList fImages; +}; + +#endif // TEAM_H diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp new file mode 100644 index 0000000000..9a1b1cd1fd --- /dev/null +++ b/src/apps/debugger/TeamDebugger.cpp @@ -0,0 +1,205 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "TeamDebugger.h" + +#include + +#include + +#include + +#include "Team.h" + + +TeamDebugger::TeamDebugger() + : + fLock("team debugger"), + fTeam(NULL), + fTeamID(-1), + fDebuggerPort(-1), + fNubPort(-1), + fDebugEventListener(-1), + fTerminating(false) +{ +} + + +TeamDebugger::~TeamDebugger() +{ + AutoLocker locker(fLock); + + fTerminating = true; + + if (fDebuggerPort >= 0) + delete_port(fDebuggerPort); + + locker.Unlock(); + + if (fDebugEventListener >= 0) + wait_for_thread(fDebugEventListener, NULL); + + delete fTeam; +} + + +status_t +TeamDebugger::Init(team_id teamID) +{ + fTeamID = teamID; + + status_t error = fLock.InitCheck(); + if (error != B_OK) + return error; + + // check whether the team exists at all + team_info teamInfo; + error = get_team_info(fTeamID, &teamInfo); + if (error != B_OK) + return error; + + // create a team object + fTeam = new(std::nothrow) Team(fTeamID); + if (fTeam == NULL) + return B_NO_MEMORY; + + error = fTeam->Init(); + if (error != B_OK) + return error; + fTeam->SetName(teamInfo.args); + // TODO: Set a better name! + + // create debugger port + char buffer[128]; + snprintf(buffer, sizeof(buffer), "team %ld 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; + +// TODO: Set the debug event flags! + + // get the initial state of the team + AutoLocker teamLocker(fTeam); + + thread_info threadInfo; + int32 cookie = 0; + while (get_next_thread_info(fTeamID, &cookie, &threadInfo) == B_OK) { + error = fTeam->AddThread(threadInfo); + if (error != B_OK) + return error; + } + + image_info imageInfo; + cookie = 0; + while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) { + error = fTeam->AddImage(imageInfo); + if (error != B_OK) + return error; + } + + // create the debug event listener + snprintf(buffer, sizeof(buffer), "team %ld debug listener", fTeamID); + fDebugEventListener = spawn_thread(_DebugEventListenerEntry, buffer, + B_NORMAL_PRIORITY, this); + if (fDebugEventListener < 0) + return fDebugEventListener; + + resume_thread(fDebugEventListener); + + return B_OK; +} + + +/*static*/ status_t +TeamDebugger::_DebugEventListenerEntry(void* data) +{ + return ((TeamDebugger*)data)->_DebugEventListener(); +} + + +status_t +TeamDebugger::_DebugEventListener() +{ + while (!fTerminating) { + // read the next message + debug_debugger_message_data message; + int32 messageCode; + ssize_t size = read_port(fDebuggerPort, &messageCode, &message, + sizeof(message)); + if (size < 0) { + if (size == B_INTERRUPTED) + continue; +// TODO: Error handling! + break; + } + + if (message.origin.team != fTeamID) { +printf("TeamDebugger for team %ld: received message from team %ld!\n", fTeamID, +message.origin.team); + continue; + } + + _HandleDebuggerMessage(messageCode, message); + + if (messageCode == B_DEBUGGER_MESSAGE_TEAM_DELETED + || messageCode == B_DEBUGGER_MESSAGE_TEAM_EXEC) { + // TODO:... + break; + } + } + + return B_OK; +} + + +void +TeamDebugger::_HandleDebuggerMessage(int32 messageCode, + const debug_debugger_message_data& message) +{ + switch (messageCode) { + case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: + break; + case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: + break; + case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: + break; + case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: + break; + case B_DEBUGGER_MESSAGE_SINGLE_STEP: + break; + case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: + break; + case B_DEBUGGER_MESSAGE_TEAM_CREATED: + break; + case B_DEBUGGER_MESSAGE_TEAM_DELETED: + break; + case B_DEBUGGER_MESSAGE_TEAM_EXEC: + break; + case B_DEBUGGER_MESSAGE_THREAD_CREATED: + break; + case B_DEBUGGER_MESSAGE_THREAD_DELETED: + break; + case B_DEBUGGER_MESSAGE_IMAGE_CREATED: + break; + case B_DEBUGGER_MESSAGE_IMAGE_DELETED: + break; + case B_DEBUGGER_MESSAGE_PRE_SYSCALL: + case B_DEBUGGER_MESSAGE_POST_SYSCALL: + case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: + case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: + case B_DEBUGGER_MESSAGE_HANDED_OVER: + // not interested + break; + default: + printf("TeamDebugger for team %ld: unknown message from kernel: " + "%ld\n", fTeamID, messageCode); + break; + } +} diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h new file mode 100644 index 0000000000..99b9e34822 --- /dev/null +++ b/src/apps/debugger/TeamDebugger.h @@ -0,0 +1,40 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef TEAM_DEBUGGER_H +#define TEAM_DEBUGGER_H + +#include +#include + + +class Team; + + +class TeamDebugger { +public: + TeamDebugger(); + ~TeamDebugger(); + + status_t Init(team_id teamID); + + +private: + static status_t _DebugEventListenerEntry(void* data); + status_t _DebugEventListener(); + + void _HandleDebuggerMessage(int32 messageCode, + const debug_debugger_message_data& message); + +private: + BLocker fLock; + Team* fTeam; + team_id fTeamID; + port_id fDebuggerPort; + port_id fNubPort; + thread_id fDebugEventListener; + volatile bool fTerminating; +}; + +#endif // TEAM_DEBUGGER_H diff --git a/src/apps/debugger/Thread.cpp b/src/apps/debugger/Thread.cpp new file mode 100644 index 0000000000..c1a112ef9e --- /dev/null +++ b/src/apps/debugger/Thread.cpp @@ -0,0 +1,32 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "Thread.h" + + +Thread::Thread(thread_id threadID) + : + fID(threadID) +{ +} + + +Thread::~Thread() +{ +} + + +status_t +Thread::Init() +{ + return B_OK; +} + + +void +Thread::SetName(const BString& name) +{ + fName = name; +} diff --git a/src/apps/debugger/Thread.h b/src/apps/debugger/Thread.h new file mode 100644 index 0000000000..74bf62aa19 --- /dev/null +++ b/src/apps/debugger/Thread.h @@ -0,0 +1,36 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef THREAD_H +#define THREAD_H + +#include +#include + +#include + + +class Thread : public DoublyLinkedListLinkImpl { +public: + Thread(thread_id threadID); + ~Thread(); + + status_t Init(); + + thread_id ID() const { return fID; } + + const char* Name() const { return fName.String(); } + void SetName(const BString& name); + + +private: + thread_id fID; + BString fName; +}; + + +typedef DoublyLinkedList ThreadList; + + +#endif // THREAD_H diff --git a/src/apps/debugger/debugger.cpp b/src/apps/debugger/debugger.cpp index 017ecb3c40..1077519e80 100644 --- a/src/apps/debugger/debugger.cpp +++ b/src/apps/debugger/debugger.cpp @@ -5,7 +5,7 @@ #include -#include "DwarfManager.h" +//#include "DwarfManager.h" int @@ -18,9 +18,10 @@ main(int argc, const char* const* argv) const char* fileName = argv[1]; - DwarfManager manager; - manager.LoadFile(fileName); - manager.FinishLoading(); +// DwarfManager manager; +// manager.LoadFile(fileName); +// manager.FinishLoading(); +(void)fileName; return 0; }