Moved all interaction with the kernel/debugger interface into new class

DebuggerInterface. This will simplify adding support for remote debugging
eventually.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31100 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-06-18 17:57:37 +00:00
parent 99a8d30156
commit f208695cc1
17 changed files with 1033 additions and 135 deletions

View File

@ -0,0 +1,11 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "CpuState.h"
CpuState::~CpuState()
{
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef CPU_STATE_H
#define CPU_STATE_H
#include <OS.h>
#include <Referenceable.h>
class CpuState : public Referenceable {
public:
virtual ~CpuState();
};
#endif // CPU_STATE_H

View File

@ -6,7 +6,7 @@
#include "Image.h"
Image::Image(Team* team,const image_info& imageInfo)
Image::Image(Team* team,const ImageInfo& imageInfo)
:
fTeam(team),
fInfo(imageInfo)

View File

@ -10,26 +10,28 @@
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include "ImageInfo.h"
class Team;
class Image : public Referenceable, public DoublyLinkedListLinkImpl<Image> {
public:
Image(Team* team, const image_info& imageInfo);
Image(Team* team, const ImageInfo& imageInfo);
~Image();
status_t Init();
Team* GetTeam() const { return fTeam; }
image_id ID() const { return fInfo.id; }
const char* Name() const { return fInfo.name; }
const image_info& Info() const { return fInfo; }
image_id ID() const { return fInfo.ImageID(); }
const char* Name() const { return fInfo.Name(); }
const ImageInfo& Info() const { return fInfo; }
private:
Team* fTeam;
image_info fInfo;
ImageInfo fInfo;
};

View File

@ -0,0 +1,41 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ImageInfo.h"
ImageInfo::ImageInfo()
:
fTeam(-1),
fImage(-1),
fName()
{
}
ImageInfo::ImageInfo(const ImageInfo& other)
:
fTeam(other.fTeam),
fImage(other.fImage),
fName(other.fName)
{
}
ImageInfo::ImageInfo(team_id team, image_id image, const BString& name)
:
fTeam(team),
fImage(image),
fName(name)
{
}
void
ImageInfo::SetTo(team_id team, image_id image, const BString& name)
{
fTeam = team;
fImage = image;
fName = name;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef IMAGE_INFO_H
#define IMAGE_INFO_H
#include <image.h>
#include <String.h>
class ImageInfo {
public:
ImageInfo();
ImageInfo(const ImageInfo& other);
ImageInfo(team_id team, image_id image,
const BString& name);
void SetTo(team_id team, image_id image,
const BString& name);
team_id TeamID() const { return fTeam; }
image_id ImageID() const { return fImage; }
const char* Name() const { return fName.String(); }
private:
thread_id fTeam;
image_id fImage;
BString fName;
};
#endif // IMAGE_INFO_H

View File

@ -6,6 +6,7 @@ C++FLAGS += -Werror ;
UsePrivateHeaders debug interface kernel shared ;
UsePrivateSystemHeaders ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ;
local debugAnalyzerSources
@ -16,14 +17,16 @@ SubDirHdrs [ FDirName $(debugAnalyzerSources) gui ] ;
SubDirHdrs [ FDirName $(debugAnalyzerSources) util ] ;
Application Debugger :
CpuState.cpp
Debugger.cpp
ElfFile.cpp
# ElfFile.cpp
Image.cpp
ImageInfo.cpp
Team.cpp
TeamDebugger.cpp
TeamDebugModel.cpp
Thread.cpp
ThreadInfo.cpp
# DebugAnalyzer:util
Variant.cpp
@ -33,6 +36,10 @@ Application Debugger :
TeamWindow.cpp
ThreadListView.cpp
# debugger_interface
DebugEvent.cpp
DebuggerInterface.cpp
# DWARF
# attribute_classes.cpp
# AttributeValue.cpp

View File

@ -52,10 +52,11 @@ Team::AddThread(Thread* thread)
}
status_t
Team::AddThread(const thread_info& threadInfo, Thread** _thread)
Team::AddThread(const ThreadInfo& threadInfo, Thread** _thread)
{
Thread* thread = new(std::nothrow) Thread(this, threadInfo.thread);
Thread* thread = new(std::nothrow) Thread(this, threadInfo.ThreadID());
if (thread == NULL)
return B_NO_MEMORY;
@ -65,7 +66,7 @@ Team::AddThread(const thread_info& threadInfo, Thread** _thread)
return error;
}
thread->SetName(threadInfo.name);
thread->SetName(threadInfo.Name());
AddThread(thread);
if (_thread != NULL)
@ -75,15 +76,6 @@ Team::AddThread(const thread_info& threadInfo, Thread** _thread)
}
status_t
Team::AddThread(thread_id threadID, Thread** _thread)
{
thread_info threadInfo;
status_t error = get_thread_info(threadID, &threadInfo);
return error == B_OK ? AddThread(threadInfo, _thread) : error;
}
void
Team::RemoveThread(Thread* thread)
{
@ -134,7 +126,7 @@ Team::AddImage(Image* image)
status_t
Team::AddImage(const image_info& imageInfo, Image** _image)
Team::AddImage(const ImageInfo& imageInfo, Image** _image)
{
Image* image = new(std::nothrow) Image(this, imageInfo);
if (image == NULL)

View File

@ -8,7 +8,9 @@
#include <Locker.h>
#include "Image.h"
#include "ImageInfo.h"
#include "Thread.h"
#include "ThreadInfo.h"
// team event types
@ -39,9 +41,7 @@ public:
void SetName(const BString& name);
void AddThread(Thread* thread);
status_t AddThread(const thread_info& threadInfo,
Thread** _thread = NULL);
status_t AddThread(thread_id threadID,
status_t AddThread(const ThreadInfo& threadInfo,
Thread** _thread = NULL);
void RemoveThread(Thread* thread);
bool RemoveThread(thread_id threadID);
@ -49,7 +49,7 @@ public:
const ThreadList& Threads() const;
void AddImage(Image* image);
status_t AddImage(const image_info& imageInfo,
status_t AddImage(const ImageInfo& imageInfo,
Image** _image = NULL);
void RemoveImage(Image* image);
bool RemoveImage(image_id imageID);

View File

@ -15,6 +15,8 @@
#include "debug_utils.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "Team.h"
#include "TeamDebugModel.h"
@ -25,13 +27,11 @@ TeamDebugger::TeamDebugger()
fTeam(NULL),
fDebugModel(NULL),
fTeamID(-1),
fDebuggerPort(-1),
fNubPort(-1),
fDebuggerInterface(NULL),
fDebugEventListener(-1),
fTeamWindow(NULL),
fTerminating(false)
{
fDebugContext.reply_port = -1;
}
@ -41,18 +41,16 @@ TeamDebugger::~TeamDebugger()
fTerminating = true;
if (fDebuggerPort >= 0)
delete_port(fDebuggerPort);
fDebuggerInterface->Close();
locker.Unlock();
if (fDebugEventListener >= 0)
wait_for_thread(fDebugEventListener, NULL);
destroy_debug_context(&fDebugContext);
delete fDebugModel;
delete fTeam;
delete fDebuggerInterface;
}
@ -87,54 +85,52 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
if (error != B_OK)
return error;
// create debugger port
char buffer[128];
snprintf(buffer, sizeof(buffer), "team %ld debugger", fTeamID);
fDebuggerPort = create_port(100, buffer);
if (fDebuggerPort < 0)
return fDebuggerPort;
// create debugger interface
fDebuggerInterface = new(std::nothrow) DebuggerInterface(fTeamID);
if (fDebuggerInterface == NULL)
return B_NO_MEMORY;
// install as team debugger
fNubPort = install_team_debugger(fTeamID, fDebuggerPort);
if (fNubPort < 0)
return fNubPort;
// init debug context
error = init_debug_context(&fDebugContext, fTeamID, fNubPort);
error = fDebuggerInterface->Init();
if (error != B_OK)
return error;
// set team debugging flags
set_team_debugging_flags(fNubPort,
fDebuggerInterface->SetTeamDebuggingFlags(
B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES);
// 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) {
{
BObjectList<ThreadInfo> threadInfos(20, true);
status_t error = fDebuggerInterface->GetThreadInfos(threadInfos);
for (int32 i = 0; ThreadInfo* info = threadInfos.ItemAt(i); i++) {
::Thread* thread;
error = fTeam->AddThread(threadInfo, &thread);
error = fTeam->AddThread(*info, &thread);
if (error != B_OK)
return error;
_UpdateThreadState(thread);
}
}
image_info imageInfo;
cookie = 0;
while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
error = fTeam->AddImage(imageInfo);
{
BObjectList<ImageInfo> imageInfos(20, true);
status_t error = fDebuggerInterface->GetImageInfos(imageInfos);
for (int32 i = 0; ImageInfo* info = imageInfos.ItemAt(i); i++) {
error = fTeam->AddImage(*info);
if (error != B_OK)
return error;
}
}
// create the debug event listener
char buffer[128];
snprintf(buffer, sizeof(buffer), "team %ld debug listener", fTeamID);
fDebugEventListener = spawn_thread(_DebugEventListenerEntry, buffer,
B_NORMAL_PRIORITY, this);
if (fDebugEventListener < 0)
// if (fDebugEventListener < 0)
if (fDebugEventListener < NULL)
return fDebugEventListener;
resume_thread(fDebugEventListener);
@ -191,31 +187,27 @@ 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;
// get the next event
DebugEvent* event;
status_t error = fDebuggerInterface->GetNextDebugEvent(event);
if (error != B_OK)
break;
// TODO: Error handling!
break;
}
if (message.origin.team != fTeamID) {
printf("TeamDebugger for team %ld: received message from team %ld!\n", fTeamID,
message.origin.team);
if (event->Team() != fTeamID) {
printf("TeamDebugger for team %ld: received event from team %ld!\n", fTeamID,
event->Team());
continue;
}
_HandleDebuggerMessage(messageCode, message);
_HandleDebuggerMessage(event);
if (messageCode == B_DEBUGGER_MESSAGE_TEAM_DELETED
|| messageCode == B_DEBUGGER_MESSAGE_TEAM_EXEC) {
// TODO:...
break;
}
// if (event->EventType() == B_DEBUGGER_MESSAGE_TEAM_DELETED
// || event->EventType() == B_DEBUGGER_MESSAGE_TEAM_EXEC) {
// // TODO:...
// break;
// }
}
return B_OK;
@ -223,51 +215,54 @@ message.origin.team);
void
TeamDebugger::_HandleDebuggerMessage(int32 messageCode,
const debug_debugger_message_data& message)
TeamDebugger::_HandleDebuggerMessage(DebugEvent* event)
{
printf("TeamDebugger::_HandleDebuggerMessage(): %ld\n", messageCode);
printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType());
bool handled = false;
switch (messageCode) {
switch (event->EventType()) {
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", message.origin.thread);
printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread());
break;
case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", message.origin.thread);
printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread());
break;
case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", message.origin.thread);
printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread());
break;
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", message.origin.thread);
printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread());
break;
case B_DEBUGGER_MESSAGE_SINGLE_STEP:
printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", message.origin.thread);
printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread());
break;
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", message.origin.thread);
break;
case B_DEBUGGER_MESSAGE_TEAM_CREATED:
printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team);
printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread());
break;
// case B_DEBUGGER_MESSAGE_TEAM_CREATED:
//printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team);
// break;
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", message.origin.team);
printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n", event->Team());
break;
case B_DEBUGGER_MESSAGE_TEAM_EXEC:
printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", message.origin.team);
printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team());
break;
case B_DEBUGGER_MESSAGE_THREAD_CREATED:
handled = _HandleThreadCreated(message.thread_created);
handled = _HandleThreadCreated(
dynamic_cast<ThreadCreatedEvent*>(event));
break;
case B_DEBUGGER_MESSAGE_THREAD_DELETED:
handled = _HandleThreadDeleted(message.thread_deleted);
handled = _HandleThreadDeleted(
dynamic_cast<ThreadDeletedEvent*>(event));
break;
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
handled = _HandleImageCreated(message.image_created);
handled = _HandleImageCreated(
dynamic_cast<ImageCreatedEvent*>(event));
break;
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
handled = _HandleImageDeleted(message.image_deleted);
handled = _HandleImageDeleted(
dynamic_cast<ImageDeletedEvent*>(event));
break;
case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
@ -277,48 +272,54 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", message.origin.team);
// not interested
break;
default:
printf("TeamDebugger for team %ld: unknown message from kernel: "
"%ld\n", fTeamID, messageCode);
printf("TeamDebugger for team %ld: unknown event type: "
"%d\n", fTeamID, event->EventType());
break;
}
if (!handled && message.origin.thread >= 0 && message.origin.nub_port >= 0)
continue_thread(message.origin.nub_port, message.origin.thread);
if (!handled && event->ThreadStopped())
fDebuggerInterface->ContinueThread(event->Thread());
}
bool
TeamDebugger::_HandleThreadCreated(const debug_thread_created& message)
TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event)
{
AutoLocker< ::Team> locker(fTeam);
fTeam->AddThread(message.new_thread);
ThreadInfo info;
status_t error = fDebuggerInterface->GetThreadInfo(event->NewThread(),
info);
if (error == B_OK)
fTeam->AddThread(info);
return false;
}
bool
TeamDebugger::_HandleThreadDeleted(const debug_thread_deleted& message)
TeamDebugger::_HandleThreadDeleted(ThreadDeletedEvent* event)
{
AutoLocker< ::Team> locker(fTeam);
fTeam->RemoveThread(message.origin.thread);
fTeam->RemoveThread(event->Thread());
return false;
}
bool
TeamDebugger::_HandleImageCreated(const debug_image_created& message)
TeamDebugger::_HandleImageCreated(ImageCreatedEvent* event)
{
AutoLocker< ::Team> locker(fTeam);
fTeam->AddImage(message.info);
fTeam->AddImage(event->GetImageInfo());
return false;
}
bool
TeamDebugger::_HandleImageDeleted(const debug_image_deleted& message)
TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event)
{
AutoLocker< ::Team> locker(fTeam);
fTeam->RemoveImage(message.info.id);
fTeam->RemoveImage(event->GetImageInfo().ImageID());
return false;
}
@ -326,23 +327,15 @@ TeamDebugger::_HandleImageDeleted(const debug_image_deleted& message)
void
TeamDebugger::_UpdateThreadState(::Thread* thread)
{
debug_nub_get_cpu_state message;
message.reply_port = fDebugContext.reply_port;
message.thread = thread->ID();
debug_nub_get_cpu_state_reply reply;
status_t error = send_debug_message(&fDebugContext,
B_DEBUG_MESSAGE_GET_CPU_STATE, &message, sizeof(message), &reply,
sizeof(reply));
CpuState* state = NULL;
status_t error = fDebuggerInterface->GetCpuState(thread->ID(), state);
uint32 newState = THREAD_STATE_UNKNOWN;
if (error == B_OK) {
if (reply.error == B_OK)
newState = THREAD_STATE_STOPPED;
else if (reply.error == B_BAD_THREAD_STATE)
state->RemoveReference();
} else if (error == B_BAD_THREAD_STATE)
newState = THREAD_STATE_RUNNING;
}
thread->SetState(newState);
}

View File

@ -11,9 +11,11 @@
#include <debug_support.h>
#include <util/DoublyLinkedList.h>
#include "DebugEvent.h"
#include "TeamWindow.h"
class DebuggerInterface;
class Team;
class TeamDebugModel;
@ -36,17 +38,16 @@ private:
static status_t _DebugEventListenerEntry(void* data);
status_t _DebugEventListener();
void _HandleDebuggerMessage(int32 messageCode,
const debug_debugger_message_data& message);
void _HandleDebuggerMessage(DebugEvent* event);
bool _HandleThreadCreated(
const debug_thread_created& message);
ThreadCreatedEvent* event);
bool _HandleThreadDeleted(
const debug_thread_deleted& message);
ThreadDeletedEvent* event);
bool _HandleImageCreated(
const debug_image_created& message);
ImageCreatedEvent* event);
bool _HandleImageDeleted(
const debug_image_deleted& message);
ImageDeletedEvent* event);
void _UpdateThreadState(::Thread* thread);
@ -54,9 +55,8 @@ private:
::Team* fTeam;
TeamDebugModel* fDebugModel;
team_id fTeamID;
port_id fDebuggerPort;
port_id fNubPort;
debug_context fDebugContext;
DebuggerInterface* fDebuggerInterface;
thread_id fDebugEventListener;
TeamWindow* fTeamWindow;
volatile bool fTerminating;

View File

@ -0,0 +1,42 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ThreadInfo.h"
ThreadInfo::ThreadInfo()
:
fTeam(-1),
fThread(-1),
fName()
{
}
ThreadInfo::ThreadInfo(const ThreadInfo& other)
:
fTeam(other.fTeam),
fThread(other.fThread),
fName(other.fName)
{
}
ThreadInfo::ThreadInfo(team_id team, thread_id thread, const BString& name)
:
fTeam(team),
fThread(thread),
fName(name)
{
}
void
ThreadInfo::SetTo(team_id team, thread_id thread, const BString& name)
{
fTeam = team;
fThread = thread;
fName = name;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_INFO_H
#define THREAD_INFO_H
#include <OS.h>
#include <String.h>
class ThreadInfo {
public:
ThreadInfo();
ThreadInfo(const ThreadInfo& other);
ThreadInfo(team_id team, thread_id thread,
const BString& name);
void SetTo(team_id team, thread_id thread,
const BString& name);
team_id TeamID() const { return fTeam; }
thread_id ThreadID() const { return fThread; }
const char* Name() const { return fName.String(); }
private:
team_id fTeam;
thread_id fThread;
BString fName;
};
#endif // THREAD_INFO_H

View File

@ -0,0 +1,201 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DebugEvent.h"
#include "CpuState.h"
// #pragma mark - DebugEvent
DebugEvent::DebugEvent(debug_debugger_message eventType, team_id team,
thread_id thread)
:
fEventType(eventType),
fTeam(team),
fThread(thread),
fThreadStopped(false)
{
}
DebugEvent::~DebugEvent()
{
}
void
DebugEvent::SetThreadStopped(bool stopped)
{
fThreadStopped = stopped;
}
// #pragma mark - CpuStateEvent
CpuStateEvent::CpuStateEvent(debug_debugger_message eventType, team_id team,
thread_id thread, CpuState* state)
:
DebugEvent(eventType, team, thread),
fCpuState(state)
{
if (fCpuState != NULL)
fCpuState->AddReference();
}
CpuStateEvent::~CpuStateEvent()
{
if (fCpuState != NULL)
fCpuState->RemoveReference();
}
// #pragma mark - ThreadDebuggedEvent
ThreadDebuggedEvent::ThreadDebuggedEvent(team_id team, thread_id thread)
:
DebugEvent(B_DEBUGGER_MESSAGE_THREAD_DEBUGGED, team, thread)
{
}
// #pragma mark - DebuggerCallEvent
DebuggerCallEvent::DebuggerCallEvent(team_id team, thread_id thread,
target_addr_t message)
:
DebugEvent(B_DEBUGGER_MESSAGE_DEBUGGER_CALL, team, thread),
fMessage(message)
{
}
// #pragma mark - BreakpointHitEvent
BreakpointHitEvent::BreakpointHitEvent(team_id team, thread_id thread,
CpuState* state)
:
CpuStateEvent(B_DEBUGGER_MESSAGE_BREAKPOINT_HIT, team, thread, state)
{
}
// #pragma mark - WatchpointHitEvent
WatchpointHitEvent::WatchpointHitEvent(team_id team, thread_id thread,
CpuState* state)
:
CpuStateEvent(B_DEBUGGER_MESSAGE_WATCHPOINT_HIT, team, thread, state)
{
}
// #pragma mark - SingleStepEvent
SingleStepEvent::SingleStepEvent(team_id team, thread_id thread,
CpuState* state)
:
CpuStateEvent(B_DEBUGGER_MESSAGE_SINGLE_STEP, team, thread, state)
{
}
// #pragma mark - ExceptionOccurredEvent
ExceptionOccurredEvent::ExceptionOccurredEvent(team_id team, thread_id thread,
uint32 exception)
:
DebugEvent(B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED, team, thread),
fException(exception)
{
}
// #pragma mark - TeamDeletedEvent
TeamDeletedEvent::TeamDeletedEvent(team_id team, thread_id thread)
:
DebugEvent(B_DEBUGGER_MESSAGE_TEAM_DELETED, team, thread)
{
}
// #pragma mark - TeamExecEvent
TeamExecEvent::TeamExecEvent(team_id team, thread_id thread)
:
DebugEvent(B_DEBUGGER_MESSAGE_TEAM_EXEC, team, thread)
{
}
// #pragma mark - ThreadCreatedEvent
ThreadCreatedEvent::ThreadCreatedEvent(team_id team, thread_id thread,
thread_id newThread)
:
DebugEvent(B_DEBUGGER_MESSAGE_THREAD_CREATED, team, thread),
fNewThread(newThread)
{
}
// #pragma mark - ThreadDeletedEvent
ThreadDeletedEvent::ThreadDeletedEvent(team_id team, thread_id thread)
:
DebugEvent(B_DEBUGGER_MESSAGE_THREAD_DELETED, team, thread)
{
}
// #pragma mark - ImageCreatedEvent
ImageCreatedEvent::ImageCreatedEvent(team_id team, thread_id thread,
const ImageInfo& info)
:
DebugEvent(B_DEBUGGER_MESSAGE_IMAGE_CREATED, team, thread),
fInfo(info)
{
}
// #pragma mark - ImageDeletedEvent
ImageDeletedEvent::ImageDeletedEvent(team_id team, thread_id thread,
const ImageInfo& info)
:
DebugEvent(B_DEBUGGER_MESSAGE_IMAGE_DELETED, team, thread),
fInfo(info)
{
}
// #pragma mark - HandedOverEvent
HandedOverEvent::HandedOverEvent(team_id team, thread_id thread,
thread_id causingThread)
:
DebugEvent(B_DEBUGGER_MESSAGE_HANDED_OVER, team, thread),
fCausingThread(causingThread)
{
}

View File

@ -0,0 +1,174 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DEBUG_EVENT_H
#define DEBUG_EVENT_H
#include <debugger.h>
#include "ImageInfo.h"
typedef uint64 target_addr_t;
// TODO: Define elsewhere!
class CpuState;
class DebugEvent {
public:
DebugEvent(debug_debugger_message eventType,
team_id team, thread_id thread);
virtual ~DebugEvent();
debug_debugger_message EventType() const { return fEventType; }
team_id Team() const { return fTeam; }
thread_id Thread() const { return fThread; }
bool ThreadStopped() const { return fThreadStopped; }
void SetThreadStopped(bool stopped);
private:
debug_debugger_message fEventType;
team_id fTeam;
thread_id fThread;
bool fThreadStopped;
};
class CpuStateEvent : public DebugEvent {
public:
CpuStateEvent(debug_debugger_message eventType,
team_id team, thread_id thread,
CpuState* state);
virtual ~CpuStateEvent();
CpuState* GetCpuState() const { return fCpuState; }
private:
CpuState* fCpuState;
};
class ThreadDebuggedEvent : public DebugEvent {
public:
ThreadDebuggedEvent(team_id team,
thread_id thread);
};
class DebuggerCallEvent : public DebugEvent {
public:
DebuggerCallEvent(team_id team,
thread_id thread, target_addr_t message);
target_addr_t Message() const { return fMessage; }
private:
target_addr_t fMessage;
};
class BreakpointHitEvent : public CpuStateEvent {
public:
BreakpointHitEvent(team_id team,
thread_id thread, CpuState* state);
};
class WatchpointHitEvent : public CpuStateEvent {
public:
WatchpointHitEvent(team_id team,
thread_id thread, CpuState* state);
};
class SingleStepEvent : public CpuStateEvent {
public:
SingleStepEvent(team_id team,
thread_id thread, CpuState* state);
};
class ExceptionOccurredEvent : public DebugEvent {
public:
ExceptionOccurredEvent(team_id team,
thread_id thread, uint32 exception);
uint32 Exception() const { return fException; }
private:
uint32 fException;
};
class TeamDeletedEvent : public DebugEvent {
public:
TeamDeletedEvent(team_id team,
thread_id thread);
};
class TeamExecEvent : public DebugEvent {
public:
TeamExecEvent(team_id team, thread_id thread);
};
class ThreadCreatedEvent : public DebugEvent {
public:
ThreadCreatedEvent(team_id team,
thread_id thread, thread_id newThread);
thread_id NewThread() const { return fNewThread; }
private:
thread_id fNewThread;
};
class ThreadDeletedEvent : public DebugEvent {
public:
ThreadDeletedEvent(team_id team,
thread_id thread);
};
class ImageCreatedEvent : public DebugEvent {
public:
ImageCreatedEvent(team_id team,
thread_id thread, const ImageInfo& info);
const ImageInfo& GetImageInfo() const { return fInfo; }
private:
ImageInfo fInfo;
};
class ImageDeletedEvent : public DebugEvent {
public:
ImageDeletedEvent(team_id team,
thread_id thread, const ImageInfo& info);
const ImageInfo& GetImageInfo() const { return fInfo; }
private:
ImageInfo fInfo;
};
class HandedOverEvent : public DebugEvent {
public:
HandedOverEvent(team_id team,
thread_id thread, thread_id causingThread);
thread_id CausingThread() const { return fCausingThread; }
private:
thread_id fCausingThread;
};
#endif // DEBUG_EVENT_H

View File

@ -0,0 +1,295 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "DebuggerInterface.h"
#include <new>
#include <stdio.h>
#include "debug_utils.h"
#include "CpuState.h"
#include "DebugEvent.h"
#include "ImageInfo.h"
#include "ThreadInfo.h"
DebuggerInterface::DebuggerInterface(team_id teamID)
:
fTeamID(teamID),
fDebuggerPort(-1),
fNubPort(-1)
{
fDebugContext.reply_port = -1;
}
DebuggerInterface::~DebuggerInterface()
{
destroy_debug_context(&fDebugContext);
Close();
}
status_t
DebuggerInterface::Init()
{
// 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;
// init debug context
status_t error = init_debug_context(&fDebugContext, fTeamID, fNubPort);
if (error != B_OK)
return error;
return B_OK;
}
void
DebuggerInterface::Close()
{
if (fDebuggerPort >= 0)
delete_port(fDebuggerPort);
}
status_t
DebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
{
while (true) {
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;
return 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)
continue_thread(message.origin.nub_port, message.origin.thread);
continue;
}
return B_OK;
}
}
status_t
DebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
{
set_team_debugging_flags(fNubPort, flags);
return B_OK;
}
status_t
DebuggerInterface::ContinueThread(thread_id thread)
{
continue_thread(fNubPort, thread);
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)
{
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);
if (info == NULL || !infos.AddItem(info)) {
delete info;
return B_NO_MEMORY;
}
}
return B_OK;
}
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_nub_get_cpu_state message;
message.reply_port = fDebugContext.reply_port;
message.thread = thread;
debug_nub_get_cpu_state_reply reply;
status_t error = send_debug_message(&fDebugContext,
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;
// TODO: Correctly create the state...
CpuState* state = new(std::nothrow) CpuState;
if (state == NULL)
return B_NO_MEMORY;
_state = state;
return B_OK;
}
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:
event = new(std::nothrow) BreakpointHitEvent(message.origin.team,
message.origin.thread, NULL);
// TODO: CpuState!
break;
case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
event = new(std::nothrow) WatchpointHitEvent(message.origin.team,
message.origin.thread, NULL);
// TODO: CpuState!
break;
case B_DEBUGGER_MESSAGE_SINGLE_STEP:
event = new(std::nothrow) SingleStepEvent(message.origin.team,
message.origin.thread, NULL);
// TODO: CpuState!
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));
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));
break;
}
default:
printf("DebuggerInterface for team %ld: unknown message from "
"kernel: %ld\n", fTeamID, messageCode);
// fall through...
case B_DEBUGGER_MESSAGE_TEAM_CREATED:
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:
_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;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef DEBUGGER_INTERFACE_H
#define DEBUGGER_INTERFACE_H
#include <debugger.h>
#include <debug_support.h>
#include <ObjectList.h>
class CpuState;
class DebugEvent;
class ImageInfo;
class ThreadInfo;
class DebuggerInterface {
public:
DebuggerInterface(team_id teamID);
~DebuggerInterface();
status_t Init();
void Close();
virtual status_t GetNextDebugEvent(DebugEvent*& _event);
virtual status_t SetTeamDebuggingFlags(uint32 flags);
virtual status_t ContinueThread(thread_id thread);
virtual status_t GetThreadInfos(BObjectList<ThreadInfo>& infos);
virtual status_t GetImageInfos(BObjectList<ImageInfo>& infos);
virtual status_t GetThreadInfo(thread_id thread,
ThreadInfo& info);
virtual status_t GetCpuState(thread_id thread,
CpuState*& _state);
// returns a reference to the caller
private:
status_t _CreateDebugEvent(int32 messageCode,
const debug_debugger_message_data& message,
bool& _ignore, DebugEvent*& _event);
private:
team_id fTeamID;
port_id fDebuggerPort;
port_id fNubPort;
debug_context fDebugContext;
};
#endif // DEBUGGER_INTERFACE_H