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:
parent
99a8d30156
commit
f208695cc1
|
@ -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()
|
||||
{
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -50,12 +50,13 @@ Team::AddThread(Thread* thread)
|
|||
fThreads.Add(thread);
|
||||
_NotifyThreadAdded(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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
::Thread* thread;
|
||||
error = fTeam->AddThread(threadInfo, &thread);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
{
|
||||
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(*info, &thread);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
_UpdateThreadState(thread);
|
||||
_UpdateThreadState(thread);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
{
|
||||
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;
|
||||
// TODO: Error handling!
|
||||
// get the next event
|
||||
DebugEvent* event;
|
||||
status_t error = fDebuggerInterface->GetNextDebugEvent(event);
|
||||
if (error != B_OK)
|
||||
break;
|
||||
}
|
||||
// TODO: Error handling!
|
||||
|
||||
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)
|
||||
newState = THREAD_STATE_RUNNING;
|
||||
}
|
||||
newState = THREAD_STATE_STOPPED;
|
||||
state->RemoveReference();
|
||||
} else if (error == B_BAD_THREAD_STATE)
|
||||
newState = THREAD_STATE_RUNNING;
|
||||
|
||||
thread->SetState(newState);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue