* 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(
|
||||
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
||||
Team* team, StackFrame* stackFrame)
|
||||
Team* team, FunctionDebugInfo* function)
|
||||
:
|
||||
fDebuggerInterface(debuggerInterface),
|
||||
fArchitecture(architecture),
|
||||
fTeam(team),
|
||||
fStackFrame(stackFrame)
|
||||
fFunction(function)
|
||||
{
|
||||
fStackFrame->AddReference();
|
||||
fFunction->AddReference();
|
||||
}
|
||||
|
||||
|
||||
LoadSourceCodeJob::~LoadSourceCodeJob()
|
||||
{
|
||||
fStackFrame->RemoveReference();
|
||||
fFunction->RemoveReference();
|
||||
}
|
||||
|
||||
|
||||
JobKey
|
||||
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
|
||||
SourceCode* sourceCode = NULL;
|
||||
status_t error = B_BAD_VALUE;
|
||||
FunctionDebugInfo* function = fStackFrame->Function();
|
||||
if (function != NULL)
|
||||
error = function->GetDebugInfo()->LoadSourceCode(function, sourceCode);
|
||||
status_t error = fFunction->GetDebugInfo()->LoadSourceCode(fFunction,
|
||||
sourceCode);
|
||||
|
||||
// set the result
|
||||
AutoLocker<Team> locker(fTeam);
|
||||
if (error == B_OK) {
|
||||
fStackFrame->SetSourceCode(sourceCode, STACK_SOURCE_LOADED);
|
||||
fFunction->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED);
|
||||
sourceCode->RemoveReference();
|
||||
} else
|
||||
fStackFrame->SetSourceCode(NULL, STACK_SOURCE_UNAVAILABLE);
|
||||
fFunction->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
class Architecture;
|
||||
class CpuState;
|
||||
class DebuggerInterface;
|
||||
class FunctionDebugInfo;
|
||||
class Image;
|
||||
class StackFrame;
|
||||
class Team;
|
||||
@@ -106,7 +107,7 @@ public:
|
||||
LoadSourceCodeJob(
|
||||
DebuggerInterface* debuggerInterface,
|
||||
Architecture* architecture,
|
||||
Team* team, StackFrame* stackFrame);
|
||||
Team* team, FunctionDebugInfo* function);
|
||||
virtual ~LoadSourceCodeJob();
|
||||
|
||||
virtual JobKey Key() const;
|
||||
@@ -116,7 +117,7 @@ private:
|
||||
DebuggerInterface* fDebuggerInterface;
|
||||
Architecture* fArchitecture;
|
||||
Team* fTeam;
|
||||
StackFrame* fStackFrame;
|
||||
FunctionDebugInfo* fFunction;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ enum {
|
||||
MSG_THREAD_STATE_CHANGED = 'tsch',
|
||||
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
|
||||
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_DEBUGGER_EVENT = 'dbge',
|
||||
|
||||
|
||||
@@ -325,24 +325,24 @@ TeamDebugger::MessageReceived(BMessage* message)
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::StackFrameSourceCodeRequested(TeamWindow* window,
|
||||
StackFrame* frame)
|
||||
TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window,
|
||||
FunctionDebugInfo* function)
|
||||
{
|
||||
// mark loading
|
||||
AutoLocker< ::Team> locker(fTeam);
|
||||
if (frame->SourceCodeState() != STACK_SOURCE_NOT_LOADED)
|
||||
if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED)
|
||||
return;
|
||||
frame->SetSourceCode(NULL, STACK_SOURCE_LOADING);
|
||||
function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING);
|
||||
locker.Unlock();
|
||||
|
||||
// schedule the job
|
||||
if (fWorker->ScheduleJob(
|
||||
new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface,
|
||||
fDebuggerInterface->GetArchitecture(), fTeam, frame),
|
||||
fDebuggerInterface->GetArchitecture(), fTeam, function),
|
||||
this) != B_OK) {
|
||||
// scheduling failed -- mark unavailable
|
||||
locker.Lock();
|
||||
frame->SetSourceCode(NULL, STACK_SOURCE_UNAVAILABLE);
|
||||
function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE);
|
||||
locker.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
|
||||
private:
|
||||
// TeamWindow::Listener
|
||||
virtual void StackFrameSourceCodeRequested(
|
||||
TeamWindow* window, StackFrame* frame);
|
||||
virtual void FunctionSourceCodeRequested(TeamWindow* window,
|
||||
FunctionDebugInfo* function);
|
||||
virtual void ThreadActionRequested(TeamWindow* window,
|
||||
thread_id threadID, uint32 action);
|
||||
virtual void SetBreakpointRequested(target_addr_t address,
|
||||
|
||||
@@ -362,9 +362,13 @@ ThreadHandler::_GetStatementAtInstructionPointer(StackFrame* frame)
|
||||
{
|
||||
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.
|
||||
SourceCode* sourceCode = frame->GetSourceCode();
|
||||
SourceCode* sourceCode = function->GetSourceCode();
|
||||
if (sourceCode != NULL) {
|
||||
Statement* statement = sourceCode->StatementAtAddress(
|
||||
frame->InstructionPointer());
|
||||
@@ -375,12 +379,7 @@ ThreadHandler::_GetStatementAtInstructionPointer(StackFrame* frame)
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
// We need to get the statement from the debug info of the function (if
|
||||
// any).
|
||||
FunctionDebugInfo* function = frame->Function();
|
||||
if (function == NULL)
|
||||
return NULL;
|
||||
|
||||
// We need to get the statement from the debug info of the function.
|
||||
Statement* statement;
|
||||
if (function->GetDebugInfo()->GetStatement(function,
|
||||
frame->InstructionPointer(), statement) != B_OK) {
|
||||
@@ -456,8 +455,10 @@ ThreadHandler::_ClearContinuationState()
|
||||
{
|
||||
_UninstallTemporaryBreakpoint();
|
||||
|
||||
if (fStepStatement != NULL)
|
||||
if (fStepStatement != NULL) {
|
||||
fStepStatement->RemoveReference();
|
||||
fStepStatement = NULL;
|
||||
}
|
||||
|
||||
fStepMode = STEP_NONE;
|
||||
fSingleStepping = false;
|
||||
|
||||
@@ -61,3 +61,24 @@ BasicFunctionDebugInfo::PrettyName() const
|
||||
{
|
||||
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* PrettyName() const;
|
||||
|
||||
virtual const char* SourceFileName() const;
|
||||
virtual SourceLocation SourceStartLocation() const;
|
||||
virtual SourceLocation SourceEndLocation() const;
|
||||
|
||||
private:
|
||||
DebugInfo* fDebugInfo;
|
||||
target_addr_t fAddress;
|
||||
|
||||
@@ -5,8 +5,71 @@
|
||||
|
||||
#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
|
||||
|
||||
#include <Referenceable.h>
|
||||
#include <util/DoublyLinkedList.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 SourceCode;
|
||||
|
||||
|
||||
class FunctionDebugInfo : public Referenceable {
|
||||
public:
|
||||
class Listener;
|
||||
|
||||
public:
|
||||
FunctionDebugInfo();
|
||||
virtual ~FunctionDebugInfo();
|
||||
|
||||
virtual DebugInfo* GetDebugInfo() const = 0;
|
||||
@@ -22,6 +37,39 @@ public:
|
||||
virtual target_size_t Size() const = 0;
|
||||
virtual const char* Name() 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),
|
||||
fActiveStackTrace(NULL),
|
||||
fActiveStackFrame(NULL),
|
||||
fActiveFunction(NULL),
|
||||
fActiveSourceCode(NULL),
|
||||
fListener(listener),
|
||||
fTabView(NULL),
|
||||
@@ -75,6 +76,7 @@ TeamWindow::~TeamWindow()
|
||||
fDebugModel->RemoveListener(this);
|
||||
|
||||
_SetActiveSourceCode(NULL);
|
||||
_SetActiveFunction(NULL);
|
||||
_SetActiveStackFrame(NULL);
|
||||
_SetActiveStackTrace(NULL);
|
||||
_SetActiveThread(NULL);
|
||||
@@ -151,7 +153,7 @@ TeamWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_STACK_FRAME_SOURCE_CODE_CHANGED:
|
||||
case MSG_FUNCTION_SOURCE_CODE_CHANGED:
|
||||
{
|
||||
_HandleSourceCodeChanged();
|
||||
break;
|
||||
@@ -236,11 +238,11 @@ TeamWindow::UserBreakpointChanged(const TeamDebugModel::BreakpointEvent& event)
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::StackFrameSourceCodeChanged(StackFrame* frame)
|
||||
TeamWindow::FunctionSourceCodeChanged(FunctionDebugInfo* function)
|
||||
{
|
||||
printf("TeamWindow::StackFrameSourceCodeChanged(%p): source: %p, state: %d\n",
|
||||
frame, frame->GetSourceCode(), frame->SourceCodeState());
|
||||
PostMessage(MSG_STACK_FRAME_SOURCE_CODE_CHANGED);
|
||||
printf("TeamWindow::FunctionSourceCodeChanged(%p): source: %p, state: %d\n",
|
||||
function, function->GetSourceCode(), function->SourceCodeState());
|
||||
PostMessage(MSG_FUNCTION_SOURCE_CODE_CHANGED);
|
||||
}
|
||||
|
||||
|
||||
@@ -371,44 +373,59 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
||||
if (frame == fActiveStackFrame)
|
||||
return;
|
||||
|
||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||
|
||||
if (fActiveStackFrame != NULL) {
|
||||
fActiveStackFrame->RemoveListener(this);
|
||||
if (fActiveStackFrame != NULL)
|
||||
fActiveStackFrame->RemoveReference();
|
||||
}
|
||||
|
||||
fActiveStackFrame = frame;
|
||||
|
||||
SourceCode* sourceCode = NULL;
|
||||
Reference<SourceCode> sourceCodeReference;
|
||||
bool setSourceCode = false;
|
||||
|
||||
if (fActiveStackFrame != NULL) {
|
||||
fActiveStackFrame->AddReference();
|
||||
fActiveStackFrame->AddListener(this);
|
||||
|
||||
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);
|
||||
_SetActiveFunction(fActiveStackFrame->Function());
|
||||
}
|
||||
|
||||
_UpdateCpuState();
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
if (setSourceCode)
|
||||
_SetActiveSourceCode(sourceCode);
|
||||
|
||||
fStackTraceView->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
|
||||
TeamWindow::_SetActiveSourceCode(SourceCode* sourceCode)
|
||||
{
|
||||
@@ -529,14 +546,14 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
|
||||
void
|
||||
TeamWindow::_HandleSourceCodeChanged()
|
||||
{
|
||||
// If we don't have an active stack frame anymore, the message is obsolete.
|
||||
if (fActiveStackFrame == NULL)
|
||||
// If we don't have an active function anymore, the message is obsolete.
|
||||
if (fActiveFunction == NULL)
|
||||
return;
|
||||
|
||||
// get a reference to the source code
|
||||
AutoLocker<TeamDebugModel> locker(fDebugModel);
|
||||
|
||||
SourceCode* sourceCode = fActiveStackFrame->GetSourceCode();
|
||||
SourceCode* sourceCode = fActiveFunction->GetSourceCode();
|
||||
Reference<SourceCode> sourceCodeReference(sourceCode);
|
||||
|
||||
locker.Unlock();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <Window.h>
|
||||
|
||||
#include "SourceView.h"
|
||||
#include "StackFrame.h"
|
||||
#include "FunctionDebugInfo.h"
|
||||
#include "StackTraceView.h"
|
||||
#include "Team.h"
|
||||
#include "TeamDebugModel.h"
|
||||
@@ -18,14 +18,16 @@
|
||||
|
||||
class BButton;
|
||||
class BTabView;
|
||||
class FunctionDebugInfo;
|
||||
class ImageListView;
|
||||
class RegisterView;
|
||||
class SourceCode;
|
||||
class StackFrame;
|
||||
|
||||
|
||||
class TeamWindow : public BWindow, private ThreadListView::Listener,
|
||||
StackTraceView::Listener, SourceView::Listener, Team::Listener,
|
||||
private TeamDebugModel::Listener, StackFrame::Listener {
|
||||
private TeamDebugModel::Listener, FunctionDebugInfo::Listener {
|
||||
public:
|
||||
class Listener;
|
||||
|
||||
@@ -66,14 +68,16 @@ private:
|
||||
const TeamDebugModel::BreakpointEvent&
|
||||
event);
|
||||
|
||||
// StackFrame::Listener
|
||||
virtual void StackFrameSourceCodeChanged(StackFrame* frame);
|
||||
// FunctionDebugInfo::Listener
|
||||
virtual void FunctionSourceCodeChanged(
|
||||
FunctionDebugInfo* function);
|
||||
|
||||
void _Init();
|
||||
|
||||
void _SetActiveThread(::Thread* thread);
|
||||
void _SetActiveStackTrace(StackTrace* stackTrace);
|
||||
void _SetActiveStackFrame(StackFrame* frame);
|
||||
void _SetActiveFunction(FunctionDebugInfo* function);
|
||||
void _SetActiveSourceCode(SourceCode* sourceCode);
|
||||
void _UpdateCpuState();
|
||||
void _UpdateRunButtons();
|
||||
@@ -90,6 +94,7 @@ private:
|
||||
::Thread* fActiveThread;
|
||||
StackTrace* fActiveStackTrace;
|
||||
StackFrame* fActiveStackFrame;
|
||||
FunctionDebugInfo* fActiveFunction;
|
||||
SourceCode* fActiveSourceCode;
|
||||
Listener* fListener;
|
||||
BTabView* fTabView;
|
||||
@@ -110,8 +115,8 @@ class TeamWindow::Listener {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void StackFrameSourceCodeRequested(
|
||||
TeamWindow* window, StackFrame* frame) = 0;
|
||||
virtual void FunctionSourceCodeRequested(TeamWindow* window,
|
||||
FunctionDebugInfo* function) = 0;
|
||||
virtual void ThreadActionRequested(TeamWindow* window,
|
||||
thread_id threadID, uint32 action) = 0;
|
||||
virtual void SetBreakpointRequested(target_addr_t address,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "CpuState.h"
|
||||
#include "FunctionDebugInfo.h"
|
||||
#include "Image.h"
|
||||
#include "SourceCode.h"
|
||||
|
||||
|
||||
// #pragma mark - StackFrame
|
||||
@@ -23,9 +22,7 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
||||
fInstructionPointer(instructionPointer),
|
||||
fReturnAddress(0),
|
||||
fImage(NULL),
|
||||
fFunction(NULL),
|
||||
fSourceCode(NULL),
|
||||
fSourceCodeState(STACK_SOURCE_NOT_LOADED)
|
||||
fFunction(NULL)
|
||||
{
|
||||
fCpuState->AddReference();
|
||||
}
|
||||
@@ -33,7 +30,6 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
||||
|
||||
StackFrame::~StackFrame()
|
||||
{
|
||||
SetSourceCode(NULL, STACK_SOURCE_NOT_LOADED);
|
||||
SetImage(NULL);
|
||||
SetFunction(NULL);
|
||||
fCpuState->RemoveReference();
|
||||
@@ -71,51 +67,3 @@ StackFrame::SetFunction(FunctionDebugInfo* function)
|
||||
if (fFunction != NULL)
|
||||
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 <Referenceable.h>
|
||||
#include <util/DoublyLinkedList.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 Image;
|
||||
class FunctionDebugInfo;
|
||||
class SourceCode;
|
||||
|
||||
|
||||
class StackFrame : public Referenceable {
|
||||
public:
|
||||
class Listener;
|
||||
|
||||
public:
|
||||
StackFrame(stack_frame_type type,
|
||||
CpuState* cpuState,
|
||||
@@ -62,19 +49,6 @@ public:
|
||||
FunctionDebugInfo* Function() const { return fFunction; }
|
||||
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:
|
||||
stack_frame_type fType;
|
||||
CpuState* fCpuState;
|
||||
@@ -83,19 +57,6 @@ private:
|
||||
target_addr_t fReturnAddress;
|
||||
Image* fImage;
|
||||
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