* ThreadHandler::_ClearContinuationState(): Forgot to set fStepStatement to
NULL after releasing its reference, so it could be released again later. * No longer attach the source code to StackFrame, but rather to FunctionDebugInfo. Besides being the more obvious place it also prevents un-/reloading the source code when stepping. Only disadvantage is that we never unload the source again yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31256 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -284,27 +284,27 @@ LoadImageDebugInfoJob::Do()
|
|||||||
|
|
||||||
LoadSourceCodeJob::LoadSourceCodeJob(
|
LoadSourceCodeJob::LoadSourceCodeJob(
|
||||||
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
||||||
Team* team, StackFrame* stackFrame)
|
Team* team, FunctionDebugInfo* function)
|
||||||
:
|
:
|
||||||
fDebuggerInterface(debuggerInterface),
|
fDebuggerInterface(debuggerInterface),
|
||||||
fArchitecture(architecture),
|
fArchitecture(architecture),
|
||||||
fTeam(team),
|
fTeam(team),
|
||||||
fStackFrame(stackFrame)
|
fFunction(function)
|
||||||
{
|
{
|
||||||
fStackFrame->AddReference();
|
fFunction->AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LoadSourceCodeJob::~LoadSourceCodeJob()
|
LoadSourceCodeJob::~LoadSourceCodeJob()
|
||||||
{
|
{
|
||||||
fStackFrame->RemoveReference();
|
fFunction->RemoveReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JobKey
|
JobKey
|
||||||
LoadSourceCodeJob::Key() const
|
LoadSourceCodeJob::Key() const
|
||||||
{
|
{
|
||||||
return JobKey(fStackFrame, JOB_TYPE_LOAD_SOURCE_CODE);
|
return JobKey(fFunction, JOB_TYPE_LOAD_SOURCE_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -313,18 +313,16 @@ LoadSourceCodeJob::Do()
|
|||||||
{
|
{
|
||||||
// load the source code, if we can
|
// load the source code, if we can
|
||||||
SourceCode* sourceCode = NULL;
|
SourceCode* sourceCode = NULL;
|
||||||
status_t error = B_BAD_VALUE;
|
status_t error = fFunction->GetDebugInfo()->LoadSourceCode(fFunction,
|
||||||
FunctionDebugInfo* function = fStackFrame->Function();
|
sourceCode);
|
||||||
if (function != NULL)
|
|
||||||
error = function->GetDebugInfo()->LoadSourceCode(function, sourceCode);
|
|
||||||
|
|
||||||
// set the result
|
// set the result
|
||||||
AutoLocker<Team> locker(fTeam);
|
AutoLocker<Team> locker(fTeam);
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
fStackFrame->SetSourceCode(sourceCode, STACK_SOURCE_LOADED);
|
fFunction->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
|
||||||
sourceCode->RemoveReference();
|
sourceCode->RemoveReference();
|
||||||
} else
|
} else
|
||||||
fStackFrame->SetSourceCode(NULL, STACK_SOURCE_UNAVAILABLE);
|
fFunction->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
class Architecture;
|
class Architecture;
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class DebuggerInterface;
|
class DebuggerInterface;
|
||||||
|
class FunctionDebugInfo;
|
||||||
class Image;
|
class Image;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
class Team;
|
class Team;
|
||||||
@@ -106,7 +107,7 @@ public:
|
|||||||
LoadSourceCodeJob(
|
LoadSourceCodeJob(
|
||||||
DebuggerInterface* debuggerInterface,
|
DebuggerInterface* debuggerInterface,
|
||||||
Architecture* architecture,
|
Architecture* architecture,
|
||||||
Team* team, StackFrame* stackFrame);
|
Team* team, FunctionDebugInfo* function);
|
||||||
virtual ~LoadSourceCodeJob();
|
virtual ~LoadSourceCodeJob();
|
||||||
|
|
||||||
virtual JobKey Key() const;
|
virtual JobKey Key() const;
|
||||||
@@ -116,7 +117,7 @@ private:
|
|||||||
DebuggerInterface* fDebuggerInterface;
|
DebuggerInterface* fDebuggerInterface;
|
||||||
Architecture* fArchitecture;
|
Architecture* fArchitecture;
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
StackFrame* fStackFrame;
|
FunctionDebugInfo* fFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ enum {
|
|||||||
MSG_THREAD_STATE_CHANGED = 'tsch',
|
MSG_THREAD_STATE_CHANGED = 'tsch',
|
||||||
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
|
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
|
||||||
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
|
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
|
||||||
MSG_STACK_FRAME_SOURCE_CODE_CHANGED = 'sfsc',
|
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||||
MSG_DEBUGGER_EVENT = 'dbge',
|
MSG_DEBUGGER_EVENT = 'dbge',
|
||||||
|
|
||||||
|
|||||||
@@ -325,24 +325,24 @@ TeamDebugger::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamDebugger::StackFrameSourceCodeRequested(TeamWindow* window,
|
TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
|
||||||
StackFrame* frame)
|
FunctionDebugInfo* function)
|
||||||
{
|
{
|
||||||
// mark loading
|
// mark loading
|
||||||
AutoLocker< ::Team> locker(fTeam);
|
AutoLocker< ::Team> locker(fTeam);
|
||||||
if (frame->SourceCodeState() != STACK_SOURCE_NOT_LOADED)
|
if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
|
||||||
return;
|
return;
|
||||||
frame->SetSourceCode(NULL, STACK_SOURCE_LOADING);
|
function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING);
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// schedule the job
|
// schedule the job
|
||||||
if (fWorker->ScheduleJob(
|
if (fWorker->ScheduleJob(
|
||||||
new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface,
|
new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface,
|
||||||
fDebuggerInterface->GetArchitecture(), fTeam, frame),
|
fDebuggerInterface->GetArchitecture(), fTeam, function),
|
||||||
this) != B_OK) {
|
this) != B_OK) {
|
||||||
// scheduling failed -- mark unavailable
|
// scheduling failed -- mark unavailable
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
frame->SetSourceCode(NULL, STACK_SOURCE_UNAVAILABLE);
|
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// TeamWindow::Listener
|
// TeamWindow::Listener
|
||||||
virtual void StackFrameSourceCodeRequested(
|
virtual void FunctionSourceCodeRequested(TeamWindow* window,
|
||||||
TeamWindow* window, StackFrame* frame);
|
FunctionDebugInfo* function);
|
||||||
virtual void ThreadActionRequested(TeamWindow* window,
|
virtual void ThreadActionRequested(TeamWindow* window,
|
||||||
thread_id threadID, uint32 action);
|
thread_id threadID, uint32 action);
|
||||||
virtual void SetBreakpointRequested(target_addr_t address,
|
virtual void SetBreakpointRequested(target_addr_t address,
|
||||||
|
|||||||
@@ -362,9 +362,13 @@ ThreadHandler::_GetStatementAtInstructionPointer(StackFrame* frame)
|
|||||||
{
|
{
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
|
|
||||||
// If there's source code attached to the stack frame, we can just get the
|
FunctionDebugInfo* function = frame->Function();
|
||||||
|
if (function == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// If there's source code attached to the function, we can just get the
|
||||||
// statement.
|
// statement.
|
||||||
SourceCode* sourceCode = frame->GetSourceCode();
|
SourceCode* sourceCode = function->GetSourceCode();
|
||||||
if (sourceCode != NULL) {
|
if (sourceCode != NULL) {
|
||||||
Statement* statement = sourceCode->StatementAtAddress(
|
Statement* statement = sourceCode->StatementAtAddress(
|
||||||
frame->InstructionPointer());
|
frame->InstructionPointer());
|
||||||
@@ -375,12 +379,7 @@ ThreadHandler::_GetStatementAtInstructionPointer(StackFrame* frame)
|
|||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// We need to get the statement from the debug info of the function (if
|
// We need to get the statement from the debug info of the function.
|
||||||
// any).
|
|
||||||
FunctionDebugInfo* function = frame->Function();
|
|
||||||
if (function == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
Statement* statement;
|
Statement* statement;
|
||||||
if (function->GetDebugInfo()->GetStatement(function,
|
if (function->GetDebugInfo()->GetStatement(function,
|
||||||
frame->InstructionPointer(), statement) != B_OK) {
|
frame->InstructionPointer(), statement) != B_OK) {
|
||||||
@@ -456,8 +455,10 @@ ThreadHandler::_ClearContinuationState()
|
|||||||
{
|
{
|
||||||
_UninstallTemporaryBreakpoint();
|
_UninstallTemporaryBreakpoint();
|
||||||
|
|
||||||
if (fStepStatement != NULL)
|
if (fStepStatement != NULL) {
|
||||||
fStepStatement->RemoveReference();
|
fStepStatement->RemoveReference();
|
||||||
|
fStepStatement = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fStepMode = STEP_NONE;
|
fStepMode = STEP_NONE;
|
||||||
fSingleStepping = false;
|
fSingleStepping = false;
|
||||||
|
|||||||
@@ -61,3 +61,24 @@ BasicFunctionDebugInfo::PrettyName() const
|
|||||||
{
|
{
|
||||||
return fPrettyName.String();
|
return fPrettyName.String();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
BasicFunctionDebugInfo::SourceFileName() const
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SourceLocation
|
||||||
|
BasicFunctionDebugInfo::SourceStartLocation() const
|
||||||
|
{
|
||||||
|
return SourceLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SourceLocation
|
||||||
|
BasicFunctionDebugInfo::SourceEndLocation() const
|
||||||
|
{
|
||||||
|
return SourceLocation();
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ public:
|
|||||||
virtual const char* Name() const;
|
virtual const char* Name() const;
|
||||||
virtual const char* PrettyName() const;
|
virtual const char* PrettyName() const;
|
||||||
|
|
||||||
|
virtual const char* SourceFileName() const;
|
||||||
|
virtual SourceLocation SourceStartLocation() const;
|
||||||
|
virtual SourceLocation SourceEndLocation() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DebugInfo* fDebugInfo;
|
DebugInfo* fDebugInfo;
|
||||||
target_addr_t fAddress;
|
target_addr_t fAddress;
|
||||||
|
|||||||
@@ -5,8 +5,71 @@
|
|||||||
|
|
||||||
#include "FunctionDebugInfo.h"
|
#include "FunctionDebugInfo.h"
|
||||||
|
|
||||||
|
#include "SourceCode.h"
|
||||||
|
|
||||||
FunctionDebugInfo::~FunctionDebugInfo()
|
|
||||||
|
FunctionDebugInfo::FunctionDebugInfo()
|
||||||
|
:
|
||||||
|
fSourceCode(NULL),
|
||||||
|
fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FunctionDebugInfo::~FunctionDebugInfo()
|
||||||
|
{
|
||||||
|
SetSourceCode(NULL, FUNCTION_SOURCE_NOT_LOADED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionDebugInfo::SetSourceCode(SourceCode* source,
|
||||||
|
function_source_state state)
|
||||||
|
{
|
||||||
|
if (source == fSourceCode && state == fSourceCodeState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fSourceCode != NULL)
|
||||||
|
fSourceCode->RemoveReference();
|
||||||
|
|
||||||
|
fSourceCode = source;
|
||||||
|
fSourceCodeState = state;
|
||||||
|
|
||||||
|
if (fSourceCode != NULL)
|
||||||
|
fSourceCode->AddReference();
|
||||||
|
|
||||||
|
// notify listeners
|
||||||
|
for (ListenerList::Iterator it = fListeners.GetIterator();
|
||||||
|
Listener* listener = it.Next();) {
|
||||||
|
listener->FunctionSourceCodeChanged(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionDebugInfo::AddListener(Listener* listener)
|
||||||
|
{
|
||||||
|
fListeners.Add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionDebugInfo::RemoveListener(Listener* listener)
|
||||||
|
{
|
||||||
|
fListeners.Remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Listener
|
||||||
|
|
||||||
|
|
||||||
|
FunctionDebugInfo::Listener::~Listener()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionDebugInfo::Listener::FunctionSourceCodeChanged(
|
||||||
|
FunctionDebugInfo* function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,15 +6,30 @@
|
|||||||
#define FUNCTION_DEBUG_INFO_H
|
#define FUNCTION_DEBUG_INFO_H
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "ArchitectureTypes.h"
|
||||||
|
#include "SourceLocation.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum function_source_state {
|
||||||
|
FUNCTION_SOURCE_NOT_LOADED,
|
||||||
|
FUNCTION_SOURCE_LOADING,
|
||||||
|
FUNCTION_SOURCE_LOADED,
|
||||||
|
FUNCTION_SOURCE_UNAVAILABLE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class DebugInfo;
|
class DebugInfo;
|
||||||
|
class SourceCode;
|
||||||
|
|
||||||
|
|
||||||
class FunctionDebugInfo : public Referenceable {
|
class FunctionDebugInfo : public Referenceable {
|
||||||
public:
|
public:
|
||||||
|
class Listener;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FunctionDebugInfo();
|
||||||
virtual ~FunctionDebugInfo();
|
virtual ~FunctionDebugInfo();
|
||||||
|
|
||||||
virtual DebugInfo* GetDebugInfo() const = 0;
|
virtual DebugInfo* GetDebugInfo() const = 0;
|
||||||
@@ -22,6 +37,39 @@ public:
|
|||||||
virtual target_size_t Size() const = 0;
|
virtual target_size_t Size() const = 0;
|
||||||
virtual const char* Name() const = 0;
|
virtual const char* Name() const = 0;
|
||||||
virtual const char* PrettyName() const = 0;
|
virtual const char* PrettyName() const = 0;
|
||||||
|
|
||||||
|
virtual const char* SourceFileName() const = 0;
|
||||||
|
virtual SourceLocation SourceStartLocation() const = 0;
|
||||||
|
virtual SourceLocation SourceEndLocation() const = 0;
|
||||||
|
|
||||||
|
// mutable attributes follow (locking required)
|
||||||
|
SourceCode* GetSourceCode() const { return fSourceCode; }
|
||||||
|
function_source_state SourceCodeState() const
|
||||||
|
{ return fSourceCodeState; }
|
||||||
|
void SetSourceCode(SourceCode* source,
|
||||||
|
function_source_state state);
|
||||||
|
|
||||||
|
void AddListener(Listener* listener);
|
||||||
|
void RemoveListener(Listener* listener);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef DoublyLinkedList<Listener> ListenerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// mutable
|
||||||
|
SourceCode* fSourceCode;
|
||||||
|
function_source_state fSourceCodeState;
|
||||||
|
ListenerList fListeners;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionDebugInfo::Listener : public DoublyLinkedListLinkImpl<Listener> {
|
||||||
|
public:
|
||||||
|
virtual ~Listener();
|
||||||
|
|
||||||
|
virtual void FunctionSourceCodeChanged(
|
||||||
|
FunctionDebugInfo* function);
|
||||||
|
// called with lock held
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
|
|||||||
fActiveThread(NULL),
|
fActiveThread(NULL),
|
||||||
fActiveStackTrace(NULL),
|
fActiveStackTrace(NULL),
|
||||||
fActiveStackFrame(NULL),
|
fActiveStackFrame(NULL),
|
||||||
|
fActiveFunction(NULL),
|
||||||
fActiveSourceCode(NULL),
|
fActiveSourceCode(NULL),
|
||||||
fListener(listener),
|
fListener(listener),
|
||||||
fTabView(NULL),
|
fTabView(NULL),
|
||||||
@@ -75,6 +76,7 @@ TeamWindow::~TeamWindow()
|
|||||||
fDebugModel->RemoveListener(this);
|
fDebugModel->RemoveListener(this);
|
||||||
|
|
||||||
_SetActiveSourceCode(NULL);
|
_SetActiveSourceCode(NULL);
|
||||||
|
_SetActiveFunction(NULL);
|
||||||
_SetActiveStackFrame(NULL);
|
_SetActiveStackFrame(NULL);
|
||||||
_SetActiveStackTrace(NULL);
|
_SetActiveStackTrace(NULL);
|
||||||
_SetActiveThread(NULL);
|
_SetActiveThread(NULL);
|
||||||
@@ -151,7 +153,7 @@ TeamWindow::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MSG_STACK_FRAME_SOURCE_CODE_CHANGED:
|
case MSG_FUNCTION_SOURCE_CODE_CHANGED:
|
||||||
{
|
{
|
||||||
_HandleSourceCodeChanged();
|
_HandleSourceCodeChanged();
|
||||||
break;
|
break;
|
||||||
@@ -236,11 +238,11 @@ TeamWindow::UserBreakpointChanged(const TeamDebugModel::BreakpointEvent& event)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::StackFrameSourceCodeChanged(StackFrame* frame)
|
TeamWindow::FunctionSourceCodeChanged(FunctionDebugInfo* function)
|
||||||
{
|
{
|
||||||
printf("TeamWindow::StackFrameSourceCodeChanged(%p): source: %p, state: %d\n",
|
printf("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, state: %d\n",
|
||||||
frame, frame->GetSourceCode(), frame->SourceCodeState());
|
function, function->GetSourceCode(), function->SourceCodeState());
|
||||||
PostMessage(MSG_STACK_FRAME_SOURCE_CODE_CHANGED);
|
PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -371,44 +373,59 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
|||||||
if (frame == fActiveStackFrame)
|
if (frame == fActiveStackFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
if (fActiveStackFrame != NULL)
|
||||||
|
|
||||||
if (fActiveStackFrame != NULL) {
|
|
||||||
fActiveStackFrame->RemoveListener(this);
|
|
||||||
fActiveStackFrame->RemoveReference();
|
fActiveStackFrame->RemoveReference();
|
||||||
}
|
|
||||||
|
|
||||||
fActiveStackFrame = frame;
|
fActiveStackFrame = frame;
|
||||||
|
|
||||||
SourceCode* sourceCode = NULL;
|
|
||||||
Reference<SourceCode> sourceCodeReference;
|
|
||||||
bool setSourceCode = false;
|
|
||||||
|
|
||||||
if (fActiveStackFrame != NULL) {
|
if (fActiveStackFrame != NULL) {
|
||||||
fActiveStackFrame->AddReference();
|
fActiveStackFrame->AddReference();
|
||||||
fActiveStackFrame->AddListener(this);
|
_SetActiveFunction(fActiveStackFrame->Function());
|
||||||
|
|
||||||
sourceCode = fActiveStackFrame->GetSourceCode();
|
|
||||||
sourceCodeReference.SetTo(sourceCode);
|
|
||||||
setSourceCode = true;
|
|
||||||
|
|
||||||
// If the source code is not loaded yet, request it.
|
|
||||||
if (fActiveStackFrame->SourceCodeState() == STACK_SOURCE_NOT_LOADED)
|
|
||||||
fListener->StackFrameSourceCodeRequested(this, fActiveStackFrame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_UpdateCpuState();
|
_UpdateCpuState();
|
||||||
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
if (setSourceCode)
|
|
||||||
_SetActiveSourceCode(sourceCode);
|
|
||||||
|
|
||||||
fStackTraceView->SetStackFrame(fActiveStackFrame);
|
fStackTraceView->SetStackFrame(fActiveStackFrame);
|
||||||
fSourceView->SetStackFrame(fActiveStackFrame);
|
fSourceView->SetStackFrame(fActiveStackFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamWindow::_SetActiveFunction(FunctionDebugInfo* function)
|
||||||
|
{
|
||||||
|
if (function == fActiveFunction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
|
|
||||||
|
if (fActiveFunction != NULL) {
|
||||||
|
fActiveFunction->RemoveListener(this);
|
||||||
|
fActiveFunction->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
fActiveFunction = function;
|
||||||
|
|
||||||
|
SourceCode* sourceCode = NULL;
|
||||||
|
Reference<SourceCode> sourceCodeReference;
|
||||||
|
|
||||||
|
if (fActiveFunction != NULL) {
|
||||||
|
fActiveFunction->AddReference();
|
||||||
|
fActiveFunction->AddListener(this);
|
||||||
|
|
||||||
|
sourceCode = fActiveFunction->GetSourceCode();
|
||||||
|
sourceCodeReference.SetTo(sourceCode);
|
||||||
|
|
||||||
|
// If the source code is not loaded yet, request it.
|
||||||
|
if (fActiveFunction->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED)
|
||||||
|
fListener->FunctionSourceCodeRequested(this, fActiveFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
_SetActiveSourceCode(sourceCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
|
TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
|
||||||
{
|
{
|
||||||
@@ -529,14 +546,14 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
|
|||||||
void
|
void
|
||||||
TeamWindow::_HandleSourceCodeChanged()
|
TeamWindow::_HandleSourceCodeChanged()
|
||||||
{
|
{
|
||||||
// If we don't have an active stack frame anymore, the message is obsolete.
|
// If we don't have an active function anymore, the message is obsolete.
|
||||||
if (fActiveStackFrame == NULL)
|
if (fActiveFunction == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// get a reference to the source code
|
// get a reference to the source code
|
||||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||||
|
|
||||||
SourceCode* sourceCode = fActiveStackFrame->GetSourceCode();
|
SourceCode* sourceCode = fActiveFunction->GetSourceCode();
|
||||||
Reference<SourceCode> sourceCodeReference(sourceCode);
|
Reference<SourceCode> sourceCodeReference(sourceCode);
|
||||||
|
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#include "SourceView.h"
|
#include "SourceView.h"
|
||||||
#include "StackFrame.h"
|
#include "FunctionDebugInfo.h"
|
||||||
#include "StackTraceView.h"
|
#include "StackTraceView.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "TeamDebugModel.h"
|
#include "TeamDebugModel.h"
|
||||||
@@ -18,14 +18,16 @@
|
|||||||
|
|
||||||
class BButton;
|
class BButton;
|
||||||
class BTabView;
|
class BTabView;
|
||||||
|
class FunctionDebugInfo;
|
||||||
class ImageListView;
|
class ImageListView;
|
||||||
class RegisterView;
|
class RegisterView;
|
||||||
class SourceCode;
|
class SourceCode;
|
||||||
|
class StackFrame;
|
||||||
|
|
||||||
|
|
||||||
class TeamWindow : public BWindow, private ThreadListView::Listener,
|
class TeamWindow : public BWindow, private ThreadListView::Listener,
|
||||||
StackTraceView::Listener, SourceView::Listener, Team::Listener,
|
StackTraceView::Listener, SourceView::Listener, Team::Listener,
|
||||||
private TeamDebugModel::Listener, StackFrame::Listener {
|
private TeamDebugModel::Listener, FunctionDebugInfo::Listener {
|
||||||
public:
|
public:
|
||||||
class Listener;
|
class Listener;
|
||||||
|
|
||||||
@@ -66,14 +68,16 @@ private:
|
|||||||
const TeamDebugModel::BreakpointEvent&
|
const TeamDebugModel::BreakpointEvent&
|
||||||
event);
|
event);
|
||||||
|
|
||||||
// StackFrame::Listener
|
// FunctionDebugInfo::Listener
|
||||||
virtual void StackFrameSourceCodeChanged(StackFrame* frame);
|
virtual void FunctionSourceCodeChanged(
|
||||||
|
FunctionDebugInfo* function);
|
||||||
|
|
||||||
void _Init();
|
void _Init();
|
||||||
|
|
||||||
void _SetActiveThread(::Thread* thread);
|
void _SetActiveThread(::Thread* thread);
|
||||||
void _SetActiveStackTrace(StackTrace* stackTrace);
|
void _SetActiveStackTrace(StackTrace* stackTrace);
|
||||||
void _SetActiveStackFrame(StackFrame* frame);
|
void _SetActiveStackFrame(StackFrame* frame);
|
||||||
|
void _SetActiveFunction(FunctionDebugInfo* function);
|
||||||
void _SetActiveSourceCode(SourceCode* sourceCode);
|
void _SetActiveSourceCode(SourceCode* sourceCode);
|
||||||
void _UpdateCpuState();
|
void _UpdateCpuState();
|
||||||
void _UpdateRunButtons();
|
void _UpdateRunButtons();
|
||||||
@@ -90,6 +94,7 @@ private:
|
|||||||
::Thread* fActiveThread;
|
::Thread* fActiveThread;
|
||||||
StackTrace* fActiveStackTrace;
|
StackTrace* fActiveStackTrace;
|
||||||
StackFrame* fActiveStackFrame;
|
StackFrame* fActiveStackFrame;
|
||||||
|
FunctionDebugInfo* fActiveFunction;
|
||||||
SourceCode* fActiveSourceCode;
|
SourceCode* fActiveSourceCode;
|
||||||
Listener* fListener;
|
Listener* fListener;
|
||||||
BTabView* fTabView;
|
BTabView* fTabView;
|
||||||
@@ -110,8 +115,8 @@ class TeamWindow::Listener {
|
|||||||
public:
|
public:
|
||||||
virtual ~Listener();
|
virtual ~Listener();
|
||||||
|
|
||||||
virtual void StackFrameSourceCodeRequested(
|
virtual void FunctionSourceCodeRequested(TeamWindow* window,
|
||||||
TeamWindow* window, StackFrame* frame) = 0;
|
FunctionDebugInfo* function) = 0;
|
||||||
virtual void ThreadActionRequested(TeamWindow* window,
|
virtual void ThreadActionRequested(TeamWindow* window,
|
||||||
thread_id threadID, uint32 action) = 0;
|
thread_id threadID, uint32 action) = 0;
|
||||||
virtual void SetBreakpointRequested(target_addr_t address,
|
virtual void SetBreakpointRequested(target_addr_t address,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
#include "FunctionDebugInfo.h"
|
#include "FunctionDebugInfo.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "SourceCode.h"
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - StackFrame
|
// #pragma mark - StackFrame
|
||||||
@@ -23,9 +22,7 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
|||||||
fInstructionPointer(instructionPointer),
|
fInstructionPointer(instructionPointer),
|
||||||
fReturnAddress(0),
|
fReturnAddress(0),
|
||||||
fImage(NULL),
|
fImage(NULL),
|
||||||
fFunction(NULL),
|
fFunction(NULL)
|
||||||
fSourceCode(NULL),
|
|
||||||
fSourceCodeState(STACK_SOURCE_NOT_LOADED)
|
|
||||||
{
|
{
|
||||||
fCpuState->AddReference();
|
fCpuState->AddReference();
|
||||||
}
|
}
|
||||||
@@ -33,7 +30,6 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
|||||||
|
|
||||||
StackFrame::~StackFrame()
|
StackFrame::~StackFrame()
|
||||||
{
|
{
|
||||||
SetSourceCode(NULL, STACK_SOURCE_NOT_LOADED);
|
|
||||||
SetImage(NULL);
|
SetImage(NULL);
|
||||||
SetFunction(NULL);
|
SetFunction(NULL);
|
||||||
fCpuState->RemoveReference();
|
fCpuState->RemoveReference();
|
||||||
@@ -71,51 +67,3 @@ StackFrame::SetFunction(FunctionDebugInfo* function)
|
|||||||
if (fFunction != NULL)
|
if (fFunction != NULL)
|
||||||
fFunction->AddReference();
|
fFunction->AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
StackFrame::SetSourceCode(SourceCode* source, stack_frame_source_state state)
|
|
||||||
{
|
|
||||||
if (fSourceCode != NULL)
|
|
||||||
fSourceCode->RemoveReference();
|
|
||||||
|
|
||||||
fSourceCode = source;
|
|
||||||
fSourceCodeState = state;
|
|
||||||
|
|
||||||
if (fSourceCode != NULL)
|
|
||||||
fSourceCode->AddReference();
|
|
||||||
|
|
||||||
// notify listeners
|
|
||||||
for (ListenerList::Iterator it = fListeners.GetIterator();
|
|
||||||
Listener* listener = it.Next();) {
|
|
||||||
listener->StackFrameSourceCodeChanged(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
StackFrame::AddListener(Listener* listener)
|
|
||||||
{
|
|
||||||
fListeners.Add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
StackFrame::RemoveListener(Listener* listener)
|
|
||||||
{
|
|
||||||
fListeners.Remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Listener
|
|
||||||
|
|
||||||
|
|
||||||
StackFrame::Listener::~Listener()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
StackFrame::Listener::StackFrameSourceCodeChanged(StackFrame* frame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
|
||||||
|
|
||||||
#include "ArchitectureTypes.h"
|
#include "ArchitectureTypes.h"
|
||||||
|
|
||||||
@@ -21,24 +20,12 @@ enum stack_frame_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum stack_frame_source_state {
|
|
||||||
STACK_SOURCE_NOT_LOADED,
|
|
||||||
STACK_SOURCE_LOADING,
|
|
||||||
STACK_SOURCE_LOADED,
|
|
||||||
STACK_SOURCE_UNAVAILABLE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class CpuState;
|
class CpuState;
|
||||||
class Image;
|
class Image;
|
||||||
class FunctionDebugInfo;
|
class FunctionDebugInfo;
|
||||||
class SourceCode;
|
|
||||||
|
|
||||||
|
|
||||||
class StackFrame : public Referenceable {
|
class StackFrame : public Referenceable {
|
||||||
public:
|
|
||||||
class Listener;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StackFrame(stack_frame_type type,
|
StackFrame(stack_frame_type type,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
@@ -62,19 +49,6 @@ public:
|
|||||||
FunctionDebugInfo* Function() const { return fFunction; }
|
FunctionDebugInfo* Function() const { return fFunction; }
|
||||||
void SetFunction(FunctionDebugInfo* function);
|
void SetFunction(FunctionDebugInfo* function);
|
||||||
|
|
||||||
// mutable attributes follow (locking required)
|
|
||||||
SourceCode* GetSourceCode() const { return fSourceCode; }
|
|
||||||
stack_frame_source_state SourceCodeState() const
|
|
||||||
{ return fSourceCodeState; }
|
|
||||||
void SetSourceCode(SourceCode* source,
|
|
||||||
stack_frame_source_state state);
|
|
||||||
|
|
||||||
void AddListener(Listener* listener);
|
|
||||||
void RemoveListener(Listener* listener);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef DoublyLinkedList<Listener> ListenerList;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
stack_frame_type fType;
|
stack_frame_type fType;
|
||||||
CpuState* fCpuState;
|
CpuState* fCpuState;
|
||||||
@@ -83,19 +57,6 @@ private:
|
|||||||
target_addr_t fReturnAddress;
|
target_addr_t fReturnAddress;
|
||||||
Image* fImage;
|
Image* fImage;
|
||||||
FunctionDebugInfo* fFunction;
|
FunctionDebugInfo* fFunction;
|
||||||
// mutable
|
|
||||||
SourceCode* fSourceCode;
|
|
||||||
stack_frame_source_state fSourceCodeState;
|
|
||||||
ListenerList fListeners;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class StackFrame::Listener : public DoublyLinkedListLinkImpl<Listener> {
|
|
||||||
public:
|
|
||||||
virtual ~Listener();
|
|
||||||
|
|
||||||
virtual void StackFrameSourceCodeChanged(StackFrame* frame);
|
|
||||||
// called with lock held
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user