Files
haiku-beta6/src/apps/debugger/TeamDebugger.cpp
T

242 lines
5.0 KiB
C++
Raw Normal View History

/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "TeamDebugger.h"
#include <stdio.h>
#include <new>
#include <Message.h>
#include <AutoLocker.h>
#include "Team.h"
TeamDebugger::TeamDebugger()
:
BLooper("team debugger"),
fTeam(NULL),
fTeamID(-1),
fDebuggerPort(-1),
fNubPort(-1),
fDebugEventListener(-1),
fTeamWindow(NULL),
fTerminating(false)
{
}
TeamDebugger::~TeamDebugger()
{
AutoLocker<BLooper> locker(this);
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, thread_id threadID, bool stopInMain)
{
fTeamID = teamID;
// check whether the team exists at all
team_info teamInfo;
status_t 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< ::Team> 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);
// run looper
thread_id looperThread = Run();
if (looperThread < 0)
return looperThread;
// create the team window
try {
fTeamWindow = TeamWindow::Create(fTeam, this);
} catch (...) {
// TODO: Notify the user!
fprintf(stderr, "Error: Failed to create team window!\n");
return B_NO_MEMORY;
}
fTeamWindow->Show();
// if requested, stop the given thread
if (threadID >= 0) {
if (stopInMain) {
// TODO: Set a temporary breakpoint in main and run the thread.
} else {
debug_thread(threadID);
// TODO: Superfluous, if the thread is already stopped.
}
}
return B_OK;
}
void
TeamDebugger::MessageReceived(BMessage* message)
{
switch (message->what) {
default:
BLooper::MessageReceived(message);
break;
}
}
/*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;
}
}