More improvements to return value handling.
- Thread now has a data member indicating if a subroutine was executed during the last set of steps. - ThreadHandler now sets the aforementioned state appropriate during Step Over/Step Out. - Architecture::CreateStackTrace() now takes a parameter indicating whether return value retrieval is desired (based on aforementioned thread value). Adjust callers accordingly. - DwarfImageDebugInfo: If return value retrieval is requested, loop backwards from the current IP to find the call instruction.
This commit is contained in:
@@ -94,8 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const
|
|||||||
status_t
|
status_t
|
||||||
Architecture::CreateStackTrace(Team* team,
|
Architecture::CreateStackTrace(Team* team,
|
||||||
ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
|
ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
|
||||||
StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace,
|
StackTrace*& _stackTrace, bool getReturnValue, int32 maxStackDepth,
|
||||||
bool getFullFrameInfo)
|
bool useExistingTrace, bool getFullFrameInfo)
|
||||||
{
|
{
|
||||||
BReference<CpuState> cpuStateReference(cpuState);
|
BReference<CpuState> cpuStateReference(cpuState);
|
||||||
|
|
||||||
@@ -163,7 +163,8 @@ Architecture::CreateStackTrace(Team* team,
|
|||||||
if (function != NULL) {
|
if (function != NULL) {
|
||||||
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
||||||
->CreateFrame(image, function, cpuState, getFullFrameInfo,
|
->CreateFrame(image, function, cpuState, getFullFrameInfo,
|
||||||
frame, previousCpuState);
|
nextFrame == NULL ? getReturnValue : false, frame,
|
||||||
|
previousCpuState);
|
||||||
if (error != B_OK && error != B_UNSUPPORTED)
|
if (error != B_OK && error != B_UNSUPPORTED)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ public:
|
|||||||
ImageDebugInfoProvider* imageInfoProvider,
|
ImageDebugInfoProvider* imageInfoProvider,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
StackTrace*& _stackTrace,
|
StackTrace*& _stackTrace,
|
||||||
|
bool getReturnValue,
|
||||||
int32 maxStackDepth = -1,
|
int32 maxStackDepth = -1,
|
||||||
bool useExistingTrace = false,
|
bool useExistingTrace = false,
|
||||||
bool getFullFrameInfo = true);
|
bool getFullFrameInfo = true);
|
||||||
|
|||||||
@@ -253,8 +253,8 @@ ThreadHandler::HandleThreadAction(uint32 action)
|
|||||||
|
|
||||||
if (stackTrace == NULL && cpuState != NULL) {
|
if (stackTrace == NULL && cpuState != NULL) {
|
||||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||||
fThread->GetTeam(), this, cpuState, stackTrace, 1, false,
|
fThread->GetTeam(), this, cpuState, stackTrace, false, 1,
|
||||||
false) == B_OK) {
|
false, false) == B_OK) {
|
||||||
stackTraceReference.SetTo(stackTrace, true);
|
stackTraceReference.SetTo(stackTrace, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -484,6 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
|
|||||||
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
|
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
|
||||||
"%#" B_PRIx64 "\n", info.Address() + info.Size());
|
"%#" B_PRIx64 "\n", info.Address() + info.Size());
|
||||||
|
|
||||||
|
fThread->SetExecutedSubroutine();
|
||||||
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -565,9 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||||||
|
|
||||||
if (stackTrace == NULL && cpuState != NULL) {
|
if (stackTrace == NULL && cpuState != NULL) {
|
||||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||||
fThread->GetTeam(), this, cpuState, stackTrace, 1,
|
fThread->GetTeam(), this, cpuState, stackTrace, false,
|
||||||
false, false)
|
1, false, false) == B_OK) {
|
||||||
== B_OK) {
|
|
||||||
stackTraceReference.SetTo(stackTrace, true);
|
stackTraceReference.SetTo(stackTrace, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,7 +576,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||||||
// If we're not in the same frame we started in,
|
// If we're not in the same frame we started in,
|
||||||
// keep executing.
|
// keep executing.
|
||||||
if (frame != NULL && fPreviousFrameAddress
|
if (frame != NULL && fPreviousFrameAddress
|
||||||
!= stackTrace->FrameAt(0)->FrameAddress()) {
|
!= frame->FrameAddress()) {
|
||||||
status_t error = _InstallTemporaryBreakpoint(
|
status_t error = _InstallTemporaryBreakpoint(
|
||||||
cpuState->InstructionPointer());
|
cpuState->InstructionPointer());
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -608,6 +608,7 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||||||
// That's the return address, so we're done in theory,
|
// That's the return address, so we're done in theory,
|
||||||
// unless we're a recursive function. Check if we've actually
|
// unless we're a recursive function. Check if we've actually
|
||||||
// exited the previous stack frame or not.
|
// exited the previous stack frame or not.
|
||||||
|
fThread->SetExecutedSubroutine();
|
||||||
target_addr_t framePointer = cpuState->StackFramePointer();
|
target_addr_t framePointer = cpuState->StackFramePointer();
|
||||||
bool hasExitedFrame = fDebuggerInterface->GetArchitecture()
|
bool hasExitedFrame = fDebuggerInterface->GetArchitecture()
|
||||||
->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE
|
->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE
|
||||||
@@ -652,9 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
|||||||
|
|
||||||
if (stackTrace == NULL && cpuState != NULL) {
|
if (stackTrace == NULL && cpuState != NULL) {
|
||||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||||
fThread->GetTeam(), this, cpuState, stackTrace, 1,
|
fThread->GetTeam(), this, cpuState, stackTrace, false,
|
||||||
false, false)
|
1, false, false) == B_OK) {
|
||||||
== B_OK) {
|
|
||||||
stackTraceReference.SetTo(stackTrace, true);
|
stackTraceReference.SetTo(stackTrace, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -680,8 +680,24 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
|||||||
case STEP_OVER:
|
case STEP_OVER:
|
||||||
{
|
{
|
||||||
// If we have stepped out of the statement, we're done.
|
// If we have stepped out of the statement, we're done.
|
||||||
if (!fStepStatement->ContainsAddress(cpuState->InstructionPointer()))
|
if (!fStepStatement->ContainsAddress(cpuState->InstructionPointer())) {
|
||||||
|
StackTrace* stackTrace = fThread->GetStackTrace();
|
||||||
|
BReference<StackTrace> stackTraceReference(stackTrace);
|
||||||
|
if (stackTrace == NULL && cpuState != NULL) {
|
||||||
|
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||||
|
fThread->GetTeam(), this, cpuState, stackTrace, false,
|
||||||
|
1, false, false) == B_OK) {
|
||||||
|
stackTraceReference.SetTo(stackTrace, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stackTrace != NULL && stackTrace->FrameAt(0)
|
||||||
|
->FrameAddress() != fPreviousFrameAddress) {
|
||||||
|
fThread->SetExecutedSubroutine();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return _DoStepOver(cpuState);
|
return _DoStepOver(cpuState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t address)
|
|||||||
status_t
|
status_t
|
||||||
DebuggerImageDebugInfo::CreateFrame(Image* image,
|
DebuggerImageDebugInfo::CreateFrame(Image* image,
|
||||||
FunctionInstance* functionInstance, CpuState* cpuState,
|
FunctionInstance* functionInstance, CpuState* cpuState,
|
||||||
bool getFullFrameInfo, StackFrame*& _previousFrame,
|
bool getFullFrameInfo, bool getReturnValue, StackFrame*& _previousFrame,
|
||||||
CpuState*& _previousCpuState)
|
CpuState*& _previousCpuState)
|
||||||
{
|
{
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
FunctionInstance* functionInstance,
|
FunctionInstance* functionInstance,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
bool getFullFrameInfo,
|
bool getFullFrameInfo,
|
||||||
|
bool getReturnValue,
|
||||||
StackFrame*& _previousFrame,
|
StackFrame*& _previousFrame,
|
||||||
CpuState*& _previousCpuState);
|
CpuState*& _previousCpuState);
|
||||||
virtual status_t GetStatement(FunctionDebugInfo* function,
|
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
#include "SymbolInfo.h"
|
#include "SymbolInfo.h"
|
||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
|
#include "Team.h"
|
||||||
#include "TeamMemory.h"
|
#include "TeamMemory.h"
|
||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
#include "TypeLookupConstraints.h"
|
#include "TypeLookupConstraints.h"
|
||||||
@@ -521,7 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address)
|
|||||||
status_t
|
status_t
|
||||||
DwarfImageDebugInfo::CreateFrame(Image* image,
|
DwarfImageDebugInfo::CreateFrame(Image* image,
|
||||||
FunctionInstance* functionInstance, CpuState* cpuState,
|
FunctionInstance* functionInstance, CpuState* cpuState,
|
||||||
bool getFullFrameInfo, StackFrame*& _frame, CpuState*& _previousCpuState)
|
bool getFullFrameInfo, bool getReturnValue, StackFrame*& _frame,
|
||||||
|
CpuState*& _previousCpuState)
|
||||||
{
|
{
|
||||||
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
|
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
|
||||||
functionInstance->GetFunctionDebugInfo());
|
functionInstance->GetFunctionDebugInfo());
|
||||||
@@ -671,10 +673,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
|
|||||||
instructionPointer, functionInstance->Address() - fRelocationDelta,
|
instructionPointer, functionInstance->Address() - fRelocationDelta,
|
||||||
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
||||||
|
|
||||||
// determine if the previously executed instruction was a function
|
if (getReturnValue) {
|
||||||
// call to see if we need to potentially retrieve a return value
|
|
||||||
// as well
|
|
||||||
if (instructionPointer > functionInstance->Address() - fRelocationDelta) {
|
|
||||||
_CreateReturnValue(functionInstance, image, function, frame,
|
_CreateReturnValue(functionInstance, image, function, frame,
|
||||||
*stackFrameDebugInfo, instructionPointer);
|
*stackFrameDebugInfo, instructionPointer);
|
||||||
}
|
}
|
||||||
@@ -1091,6 +1090,8 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
|
|||||||
Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
|
Image* image, DwarfFunctionDebugInfo* function, StackFrame* frame,
|
||||||
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
|
DwarfStackFrameDebugInfo& factory, target_addr_t instructionPointer)
|
||||||
{
|
{
|
||||||
|
// the thread just executed a subroutine, look for the last call
|
||||||
|
// instruction.
|
||||||
DisassembledCode* sourceCode = NULL;
|
DisassembledCode* sourceCode = NULL;
|
||||||
target_size_t bufferSize = std::min(functionInstance->Size(),
|
target_size_t bufferSize = std::min(functionInstance->Size(),
|
||||||
(target_size_t)64 * 1024);
|
(target_size_t)64 * 1024);
|
||||||
@@ -1114,59 +1115,74 @@ DwarfImageDebugInfo::_CreateReturnValue(FunctionInstance* functionInstance,
|
|||||||
previousStatementAddress);
|
previousStatementAddress);
|
||||||
if (statement == NULL)
|
if (statement == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
previousStatementAddress = statement->CoveringAddressRange().Start() - 1;
|
|
||||||
statement = sourceCode->StatementAtAddress(
|
InstructionInfo info;
|
||||||
previousStatementAddress);
|
do {
|
||||||
if (statement == NULL)
|
TargetAddressRange range = statement->CoveringAddressRange();
|
||||||
|
result = fArchitecture->GetInstructionInfo(range.Start(), info);
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
previousStatementAddress = statement->CoveringAddressRange().Start() - 1;
|
||||||
|
statement = sourceCode->StatementAtAddress(
|
||||||
|
previousStatementAddress);
|
||||||
|
} while (statement != NULL);
|
||||||
|
|
||||||
|
// we weren't able to find a subroutine call by stepping back
|
||||||
|
// so we can't retrieve a return value
|
||||||
|
if (info.Type() != INSTRUCTION_TYPE_SUBROUTINE_CALL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
target_addr_t targetAddress = info.TargetAddress();
|
||||||
|
if (targetAddress == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
TargetAddressRange range = statement->CoveringAddressRange();
|
if (!image->ContainsAddress(targetAddress)) {
|
||||||
InstructionInfo info;
|
// our current image doesn't contain the target function,
|
||||||
if (fArchitecture->GetInstructionInfo(range.Start(), info) == B_OK
|
// locate the one which does.
|
||||||
&& info.Type() == INSTRUCTION_TYPE_SUBROUTINE_CALL) {
|
image = image->GetTeam()->ImageByAddress(targetAddress);
|
||||||
target_addr_t targetAddress = info.TargetAddress();
|
if (image == NULL)
|
||||||
if (targetAddress == 0)
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (image->ContainsAddress(targetAddress)) {
|
FunctionInstance* targetFunction;
|
||||||
FunctionInstance* targetFunction;
|
if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) {
|
||||||
if (targetAddress >= fPLTSectionStart && targetAddress < fPLTSectionEnd) {
|
// TODO: resolve actual target address in the PIC case
|
||||||
// TODO: resolve actual target address in the PIC case
|
// and adjust targetAddress accordingly
|
||||||
// and adjust targetAddress accordingly
|
}
|
||||||
|
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
|
||||||
|
targetFunction = imageInfo->FunctionAtAddress(targetAddress);
|
||||||
|
if (targetFunction != NULL) {
|
||||||
|
DwarfFunctionDebugInfo* targetInfo =
|
||||||
|
dynamic_cast<DwarfFunctionDebugInfo*>(
|
||||||
|
targetFunction->GetFunctionDebugInfo());
|
||||||
|
if (targetInfo != NULL) {
|
||||||
|
DIESubprogram* subProgram = targetInfo->SubprogramEntry();
|
||||||
|
DIEType* returnType = subProgram->ReturnType();
|
||||||
|
if (returnType == NULL) {
|
||||||
|
// function doesn't return a value, we're done.
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
|
|
||||||
targetFunction = imageInfo->FunctionAtAddress(targetAddress);
|
|
||||||
if (targetFunction != NULL) {
|
|
||||||
DwarfFunctionDebugInfo* targetInfo =
|
|
||||||
dynamic_cast<DwarfFunctionDebugInfo*>(
|
|
||||||
targetFunction->GetFunctionDebugInfo());
|
|
||||||
if (targetInfo != NULL) {
|
|
||||||
DIESubprogram* subProgram = targetInfo->SubprogramEntry();
|
|
||||||
DIEType* returnType = subProgram->ReturnType();
|
|
||||||
if (returnType == NULL) {
|
|
||||||
// function doesn't return a value, we're done.
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueLocation* location;
|
ValueLocation* location;
|
||||||
result = fArchitecture->GetReturnAddressLocation(frame,
|
result = fArchitecture->GetReturnAddressLocation(frame,
|
||||||
returnType->ByteSize()->constant, location);
|
returnType->ByteSize()->constant, location);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
return result;
|
return result;
|
||||||
BReference<ValueLocation> locationReference(location,
|
BReference<ValueLocation> locationReference(location, true);
|
||||||
true);
|
Variable* variable = NULL;
|
||||||
Variable* variable = NULL;
|
BReference<FunctionID> idReference(
|
||||||
BReference<FunctionID> idReference(
|
targetFunction->GetFunctionID(), true);
|
||||||
targetFunction->GetFunctionID(), true);
|
result = factory.CreateReturnValue(idReference, returnType,
|
||||||
result = factory.CreateReturnValue(idReference,
|
location, variable);
|
||||||
returnType, location, variable);
|
if (result != B_OK)
|
||||||
if (result != B_OK)
|
return result;
|
||||||
return result;
|
BReference<Variable> variableReference(variable, true);
|
||||||
BReference<Variable> variableReference(variable, true);
|
if (!frame->AddLocalVariable(variable))
|
||||||
if (!frame->AddLocalVariable(variable))
|
return B_NO_MEMORY;
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
FunctionInstance* functionInstance,
|
FunctionInstance* functionInstance,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
bool getFullFrameInfo,
|
bool getFullFrameInfo,
|
||||||
|
bool getReturnValue,
|
||||||
StackFrame*& _frame,
|
StackFrame*& _frame,
|
||||||
CpuState*& _previousCpuState);
|
CpuState*& _previousCpuState);
|
||||||
virtual status_t GetStatement(FunctionDebugInfo* function,
|
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ public:
|
|||||||
FunctionInstance* functionInstance,
|
FunctionInstance* functionInstance,
|
||||||
CpuState* cpuState,
|
CpuState* cpuState,
|
||||||
bool getFullFrameInfo,
|
bool getFullFrameInfo,
|
||||||
|
bool getReturnValue,
|
||||||
StackFrame*& _Frame,
|
StackFrame*& _Frame,
|
||||||
CpuState*& _previousCpuState) = 0;
|
CpuState*& _previousCpuState) = 0;
|
||||||
// returns reference to previous frame
|
// returns reference to previous frame
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ GetStackTraceJob::Do()
|
|||||||
// get the stack trace
|
// get the stack trace
|
||||||
StackTrace* stackTrace;
|
StackTrace* stackTrace;
|
||||||
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
||||||
fCpuState, stackTrace);
|
fCpuState, stackTrace, fThread->ExecutedSubroutine());
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
BReference<StackTrace> stackTraceReference(stackTrace, true);
|
BReference<StackTrace> stackTraceReference(stackTrace, true);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Thread::Thread(Team* team, thread_id threadID)
|
|||||||
fTeam(team),
|
fTeam(team),
|
||||||
fID(threadID),
|
fID(threadID),
|
||||||
fState(THREAD_STATE_UNKNOWN),
|
fState(THREAD_STATE_UNKNOWN),
|
||||||
|
fExecutedSubroutine(false),
|
||||||
fStoppedReason(THREAD_STOPPED_UNKNOWN),
|
fStoppedReason(THREAD_STOPPED_UNKNOWN),
|
||||||
fCpuState(NULL),
|
fCpuState(NULL),
|
||||||
fStackTrace(NULL)
|
fStackTrace(NULL)
|
||||||
@@ -68,6 +69,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& info)
|
|||||||
if (fState != THREAD_STATE_STOPPED) {
|
if (fState != THREAD_STATE_STOPPED) {
|
||||||
SetCpuState(NULL);
|
SetCpuState(NULL);
|
||||||
SetStackTrace(NULL);
|
SetStackTrace(NULL);
|
||||||
|
fExecutedSubroutine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fTeam->NotifyThreadStateChanged(this);
|
fTeam->NotifyThreadStateChanged(this);
|
||||||
@@ -108,3 +110,11 @@ Thread::SetStackTrace(StackTrace* trace)
|
|||||||
|
|
||||||
fTeam->NotifyThreadStackTraceChanged(this);
|
fTeam->NotifyThreadStackTraceChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread::SetExecutedSubroutine()
|
||||||
|
{
|
||||||
|
fExecutedSubroutine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,11 +67,16 @@ public:
|
|||||||
StackTrace* GetStackTrace() const { return fStackTrace; }
|
StackTrace* GetStackTrace() const { return fStackTrace; }
|
||||||
void SetStackTrace(StackTrace* trace);
|
void SetStackTrace(StackTrace* trace);
|
||||||
|
|
||||||
|
bool ExecutedSubroutine() const
|
||||||
|
{ return fExecutedSubroutine; }
|
||||||
|
void SetExecutedSubroutine();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Team* fTeam;
|
Team* fTeam;
|
||||||
thread_id fID;
|
thread_id fID;
|
||||||
BString fName;
|
BString fName;
|
||||||
uint32 fState;
|
uint32 fState;
|
||||||
|
bool fExecutedSubroutine;
|
||||||
uint32 fStoppedReason;
|
uint32 fStoppedReason;
|
||||||
BString fStoppedReasonInfo;
|
BString fStoppedReasonInfo;
|
||||||
CpuState* fCpuState;
|
CpuState* fCpuState;
|
||||||
|
|||||||
Reference in New Issue
Block a user