* 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:
Ingo Weinhold
2009-06-26 15:11:56 +00:00
parent 66ae5b2d99
commit 6fb6551c97
14 changed files with 228 additions and 161 deletions
+9 -11
View File
@@ -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;
}
+3 -2
View File
@@ -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;
};
+1 -1
View File
@@ -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',
+6 -6
View File
@@ -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();
}
}
+2 -2
View File
@@ -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,
+10 -9
View File
@@ -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();
+11 -6
View File
@@ -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,
+1 -53
View File
@@ -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)
{
}
-39
View File
@@ -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
};