Refactoring to handle multiple return values.
- Replace use of address + CpuState pair in Thread, SpecificImageDebugInfo::CreateStackTrace() with a ReturnValueInfoList. Adjust all implementing subclasses and callers accordingly. - DwarfImageDebugInfo::CreateReturnValue() -> CreateReturnValues(). Now processes a list of return value information structures rather than just a single one. This means we can now handle multiple return values in a single statement. This still isn't entirely correct though, since, e.g. for functions whose return types fit in a register we need to either retrieve them immediately after function return, or store the CPU state at that point in time for later use in value retrieval, otherwise the return values will all be those of the last called function.
This commit is contained in:
parent
3fa429781c
commit
76ed6d72a5
|
@ -144,6 +144,7 @@ Application Debugger :
|
|||
FileSourceCode.cpp
|
||||
Image.cpp
|
||||
ImageInfo.cpp
|
||||
ReturnValueInfo.cpp
|
||||
SourceCode.cpp
|
||||
StackFrame.cpp
|
||||
StackFrameValues.cpp
|
||||
|
@ -151,7 +152,6 @@ Application Debugger :
|
|||
StackTrace.cpp
|
||||
Statement.cpp
|
||||
SymbolInfo.cpp
|
||||
UserBreakpoint.cpp
|
||||
Team.cpp
|
||||
TeamMemory.cpp
|
||||
TeamMemoryBlock.cpp
|
||||
|
@ -161,6 +161,7 @@ Application Debugger :
|
|||
Type.cpp
|
||||
TypeComponentPath.cpp
|
||||
TypeLookupConstraints.cpp
|
||||
UserBreakpoint.cpp
|
||||
Variable.cpp
|
||||
Watchpoint.cpp
|
||||
|
||||
|
|
|
@ -94,9 +94,8 @@ Architecture::InitRegisterRules(CfaContext& context) const
|
|||
status_t
|
||||
Architecture::CreateStackTrace(Team* team,
|
||||
ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
|
||||
StackTrace*& _stackTrace, target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState, int32 maxStackDepth, bool useExistingTrace,
|
||||
bool getFullFrameInfo)
|
||||
StackTrace*& _stackTrace, ReturnValueInfoList* returnValueInfos,
|
||||
int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo)
|
||||
{
|
||||
BReference<CpuState> cpuStateReference(cpuState);
|
||||
|
||||
|
@ -164,8 +163,8 @@ Architecture::CreateStackTrace(Team* team,
|
|||
if (function != NULL) {
|
||||
status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
|
||||
->CreateFrame(image, function, cpuState, getFullFrameInfo,
|
||||
nextFrame == NULL ? returnFunctionAddress : 0,
|
||||
nextFrame == NULL ? returnFunctionState : 0, frame,
|
||||
nextFrame == NULL
|
||||
? returnValueInfos : NULL, frame,
|
||||
previousCpuState);
|
||||
if (error != B_OK && error != B_UNSUPPORTED)
|
||||
break;
|
||||
|
@ -174,8 +173,7 @@ Architecture::CreateStackTrace(Team* team,
|
|||
// If we have no frame yet, let the architecture create it.
|
||||
if (frame == NULL) {
|
||||
status_t error = CreateStackFrame(image, functionDebugInfo,
|
||||
cpuState, nextFrame == NULL, frame,
|
||||
previousCpuState);
|
||||
cpuState, nextFrame == NULL, frame, previousCpuState);
|
||||
if (error != B_OK)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <Referenceable.h>
|
||||
#include <Variant.h>
|
||||
|
||||
#include "ReturnValueInfo.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
|
@ -110,8 +111,7 @@ public:
|
|||
ImageDebugInfoProvider* imageInfoProvider,
|
||||
CpuState* cpuState,
|
||||
StackTrace*& _stackTrace,
|
||||
target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState,
|
||||
ReturnValueInfoList* returnValueInfos,
|
||||
int32 maxStackDepth = -1,
|
||||
bool useExistingTrace = false,
|
||||
bool getFullFrameInfo = true);
|
||||
|
|
|
@ -253,7 +253,7 @@ ThreadHandler::HandleThreadAction(uint32 action)
|
|||
|
||||
if (stackTrace == NULL && cpuState != NULL) {
|
||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, 0, NULL, 1,
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, NULL, 1,
|
||||
false, false) == B_OK) {
|
||||
stackTraceReference.SetTo(stackTrace, true);
|
||||
}
|
||||
|
@ -484,11 +484,20 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
|
|||
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
|
||||
"%#" B_PRIx64 "\n", info.Address() + info.Size());
|
||||
|
||||
fThread->SetExecutedSubroutine(info.TargetAddress());
|
||||
fThread->SetSubroutineCpuState(cpuState);
|
||||
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
|
||||
return false;
|
||||
|
||||
ReturnValueInfo* returnInfo = new(std::nothrow) ReturnValueInfo(
|
||||
info.TargetAddress(), cpuState);
|
||||
if (returnInfo == NULL)
|
||||
return false;
|
||||
|
||||
BReference<ReturnValueInfo> returnInfoReference(returnInfo, true);
|
||||
|
||||
if (fThread->AddReturnValueInfo(returnInfo) != B_OK)
|
||||
return false;
|
||||
|
||||
returnInfoReference.Detach();
|
||||
_RunThread(cpuState->InstructionPointer());
|
||||
return true;
|
||||
}
|
||||
|
@ -567,8 +576,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||
|
||||
if (stackTrace == NULL && cpuState != NULL) {
|
||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, 0,
|
||||
NULL, 1, false, false) == B_OK) {
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, NULL,
|
||||
1, false, false) == B_OK) {
|
||||
stackTraceReference.SetTo(stackTrace, true);
|
||||
}
|
||||
}
|
||||
|
@ -608,8 +617,16 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
|
|||
{
|
||||
// That's the return address, so we're done in theory,
|
||||
// unless we're a recursive function. Check if we've actually
|
||||
// exited the previous stack frame or not.
|
||||
fThread->SetExecutedSubroutine(cpuState->InstructionPointer());
|
||||
// exited the previous stack frame or not
|
||||
ReturnValueInfo* info = new(std::nothrow) ReturnValueInfo(
|
||||
cpuState->InstructionPointer(), cpuState);
|
||||
if (info == NULL)
|
||||
return false;
|
||||
BReference<ReturnValueInfo> infoReference(info, true);
|
||||
if (fThread->AddReturnValueInfo(info) != B_OK)
|
||||
return false;
|
||||
|
||||
infoReference.Detach();
|
||||
target_addr_t framePointer = cpuState->StackFramePointer();
|
||||
bool hasExitedFrame = fDebuggerInterface->GetArchitecture()
|
||||
->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE
|
||||
|
@ -654,8 +671,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
|||
|
||||
if (stackTrace == NULL && cpuState != NULL) {
|
||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, 0,
|
||||
NULL, 1, false, false) == B_OK) {
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, NULL,
|
||||
1, false, false) == B_OK) {
|
||||
stackTraceReference.SetTo(stackTrace, true);
|
||||
}
|
||||
}
|
||||
|
@ -686,7 +703,7 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
|||
BReference<StackTrace> stackTraceReference(stackTrace);
|
||||
if (stackTrace == NULL && cpuState != NULL) {
|
||||
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
|
||||
fThread->GetTeam(), this, cpuState, stackTrace, 0,
|
||||
fThread->GetTeam(), this, cpuState, stackTrace,
|
||||
NULL, 1, false, false) == B_OK) {
|
||||
stackTraceReference.SetTo(stackTrace, true);
|
||||
}
|
||||
|
@ -694,8 +711,15 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
|
|||
|
||||
if (stackTrace != NULL && stackTrace->FrameAt(0)
|
||||
->FrameAddress() != fPreviousFrameAddress) {
|
||||
fThread->SetExecutedSubroutine(
|
||||
cpuState->InstructionPointer());
|
||||
ReturnValueInfo* info = new(std::nothrow) ReturnValueInfo(
|
||||
cpuState->InstructionPointer(), cpuState);
|
||||
if (info == NULL)
|
||||
return false;
|
||||
BReference<ReturnValueInfo> infoReference(info, true);
|
||||
if (fThread->AddReturnValueInfo(info) != B_OK)
|
||||
return false;
|
||||
|
||||
infoReference.Detach();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -68,9 +68,8 @@ DebuggerImageDebugInfo::GetAddressSectionType(target_addr_t address)
|
|||
status_t
|
||||
DebuggerImageDebugInfo::CreateFrame(Image* image,
|
||||
FunctionInstance* functionInstance, CpuState* cpuState,
|
||||
bool getFullFrameInfo, target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState, StackFrame*& _previousFrame,
|
||||
CpuState*& _previousCpuState)
|
||||
bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos,
|
||||
StackFrame*& _previousFrame, CpuState*& _previousCpuState)
|
||||
{
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
|
|
@ -36,8 +36,7 @@ public:
|
|||
FunctionInstance* functionInstance,
|
||||
CpuState* cpuState,
|
||||
bool getFullFrameInfo,
|
||||
target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState,
|
||||
ReturnValueInfoList* returnValueInfos,
|
||||
StackFrame*& _previousFrame,
|
||||
CpuState*& _previousCpuState);
|
||||
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||
|
|
|
@ -522,9 +522,8 @@ DwarfImageDebugInfo::GetAddressSectionType(target_addr_t address)
|
|||
status_t
|
||||
DwarfImageDebugInfo::CreateFrame(Image* image,
|
||||
FunctionInstance* functionInstance, CpuState* cpuState,
|
||||
bool getFullFrameInfo, target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState, StackFrame*& _frame,
|
||||
CpuState*& _previousCpuState)
|
||||
bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos,
|
||||
StackFrame*& _frame, CpuState*& _previousCpuState)
|
||||
{
|
||||
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
|
||||
functionInstance->GetFunctionDebugInfo());
|
||||
|
@ -674,9 +673,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
|
|||
instructionPointer, functionInstance->Address() - fRelocationDelta,
|
||||
subprogramEntry->Variables(), subprogramEntry->Blocks());
|
||||
|
||||
if (returnFunctionAddress != 0) {
|
||||
_CreateReturnValue(returnFunctionAddress, returnFunctionState,
|
||||
image, frame, *stackFrameDebugInfo);
|
||||
if (!returnValueInfos->IsEmpty()) {
|
||||
_CreateReturnValues(returnValueInfos, image, frame,
|
||||
*stackFrameDebugInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,88 +1086,94 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
|
|||
|
||||
|
||||
status_t
|
||||
DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState, Image* image, StackFrame* frame,
|
||||
DwarfStackFrameDebugInfo& factory)
|
||||
DwarfImageDebugInfo::_CreateReturnValues(ReturnValueInfoList* returnValueInfos,
|
||||
Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory)
|
||||
{
|
||||
if (!image->ContainsAddress(returnFunctionAddress)) {
|
||||
// our current image doesn't contain the target function,
|
||||
// locate the one which does.
|
||||
image = image->GetTeam()->ImageByAddress(returnFunctionAddress);
|
||||
if (image == NULL)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
status_t result = B_OK;
|
||||
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
|
||||
FunctionInstance* targetFunction;
|
||||
if (returnFunctionAddress >= fPLTSectionStart
|
||||
&& returnFunctionAddress < fPLTSectionEnd) {
|
||||
// if the function in question is position-independent, the call
|
||||
// will actually have taken us to its corresponding PLT slot.
|
||||
// in such a case, look at the disassembled jump to determine
|
||||
// where to find the actual function address.
|
||||
InstructionInfo info;
|
||||
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
|
||||
returnFunctionAddress, info, returnFunctionState) != B_OK) {
|
||||
return B_BAD_VALUE;
|
||||
for (int32 i = 0; i < returnValueInfos->CountItems(); i++) {
|
||||
ReturnValueInfo* valueInfo = returnValueInfos->ItemAt(i);
|
||||
target_addr_t subroutineAddress = valueInfo->SubroutineAddress();
|
||||
CpuState* subroutineState = valueInfo->State();
|
||||
if (!image->ContainsAddress(subroutineAddress)) {
|
||||
// our current image doesn't contain the target function,
|
||||
// locate the one which does.
|
||||
image = image->GetTeam()->ImageByAddress(subroutineAddress);
|
||||
if (image == NULL) {
|
||||
// nothing we can do, try the next entry (if any)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
target_size_t addressSize = fDebuggerInterface->GetArchitecture()
|
||||
->AddressSize();
|
||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(info.TargetAddress(),
|
||||
&returnFunctionAddress, addressSize);
|
||||
|
||||
if (bytesRead != (ssize_t)addressSize)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
targetFunction = imageInfo->FunctionAtAddress(returnFunctionAddress);
|
||||
if (targetFunction != NULL) {
|
||||
DwarfFunctionDebugInfo* targetInfo =
|
||||
dynamic_cast<DwarfFunctionDebugInfo*>(
|
||||
targetFunction->GetFunctionDebugInfo());
|
||||
if (targetInfo != NULL) {
|
||||
DIESubprogram* subProgram = targetInfo->SubprogramEntry();
|
||||
DIEType* returnType = subProgram->ReturnType();
|
||||
if (returnType == NULL) {
|
||||
// check if we have a specification, and if so, if that has
|
||||
// a return type
|
||||
subProgram = dynamic_cast<DIESubprogram*>(subProgram->Specification());
|
||||
if (subProgram != NULL)
|
||||
returnType = subProgram->ReturnType();
|
||||
|
||||
// function doesn't return a value, we're done.
|
||||
if (returnType == NULL)
|
||||
return B_OK;
|
||||
status_t result = B_OK;
|
||||
ImageDebugInfo* imageInfo = image->GetImageDebugInfo();
|
||||
FunctionInstance* targetFunction;
|
||||
if (subroutineAddress >= fPLTSectionStart
|
||||
&& subroutineAddress < fPLTSectionEnd) {
|
||||
// if the function in question is position-independent, the call
|
||||
// will actually have taken us to its corresponding PLT slot.
|
||||
// in such a case, look at the disassembled jump to determine
|
||||
// where to find the actual function address.
|
||||
InstructionInfo info;
|
||||
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
|
||||
subroutineAddress, info, subroutineState) != B_OK) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
uint32 byteSize = 0;
|
||||
if (returnType->ByteSize() == NULL) {
|
||||
if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
|
||||
byteSize = fArchitecture->AddressSize();
|
||||
} else
|
||||
byteSize = returnType->ByteSize()->constant;
|
||||
target_size_t addressSize = fDebuggerInterface->GetArchitecture()
|
||||
->AddressSize();
|
||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(
|
||||
info.TargetAddress(), &subroutineAddress, addressSize);
|
||||
|
||||
ValueLocation* location;
|
||||
result = fArchitecture->GetReturnAddressLocation(frame,
|
||||
byteSize, location);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
if (bytesRead != (ssize_t)addressSize)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
BReference<ValueLocation> locationReference(location, true);
|
||||
Variable* variable = NULL;
|
||||
BReference<FunctionID> idReference(
|
||||
targetFunction->GetFunctionID(), true);
|
||||
result = factory.CreateReturnValue(idReference, returnType,
|
||||
location, variable);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
targetFunction = imageInfo->FunctionAtAddress(subroutineAddress);
|
||||
if (targetFunction != NULL) {
|
||||
DwarfFunctionDebugInfo* targetInfo =
|
||||
dynamic_cast<DwarfFunctionDebugInfo*>(
|
||||
targetFunction->GetFunctionDebugInfo());
|
||||
if (targetInfo != NULL) {
|
||||
DIESubprogram* subProgram = targetInfo->SubprogramEntry();
|
||||
DIEType* returnType = subProgram->ReturnType();
|
||||
if (returnType == NULL) {
|
||||
// check if we have a specification, and if so, if that has
|
||||
// a return type
|
||||
subProgram = dynamic_cast<DIESubprogram*>(
|
||||
subProgram->Specification());
|
||||
if (subProgram != NULL)
|
||||
returnType = subProgram->ReturnType();
|
||||
|
||||
BReference<Variable> variableReference(variable, true);
|
||||
if (!frame->AddLocalVariable(variable))
|
||||
return B_NO_MEMORY;
|
||||
// function doesn't return a value, we're done.
|
||||
if (returnType == NULL)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
uint32 byteSize = 0;
|
||||
if (returnType->ByteSize() == NULL) {
|
||||
if (dynamic_cast<DIEAddressingType*>(returnType) != NULL)
|
||||
byteSize = fArchitecture->AddressSize();
|
||||
} else
|
||||
byteSize = returnType->ByteSize()->constant;
|
||||
|
||||
ValueLocation* location;
|
||||
result = fArchitecture->GetReturnAddressLocation(frame,
|
||||
byteSize, location);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
BReference<ValueLocation> locationReference(location, true);
|
||||
Variable* variable = NULL;
|
||||
BReference<FunctionID> idReference(
|
||||
targetFunction->GetFunctionID(), true);
|
||||
result = factory.CreateReturnValue(idReference, returnType,
|
||||
location, variable);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
BReference<Variable> variableReference(variable, true);
|
||||
if (!frame->AddLocalVariable(variable))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,7 @@ public:
|
|||
FunctionInstance* functionInstance,
|
||||
CpuState* cpuState,
|
||||
bool getFullFrameInfo,
|
||||
target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState,
|
||||
ReturnValueInfoList* returnValueInfos,
|
||||
StackFrame*& _frame,
|
||||
CpuState*& _previousCpuState);
|
||||
virtual status_t GetStatement(FunctionDebugInfo* function,
|
||||
|
@ -105,9 +104,8 @@ private:
|
|||
const EntryListWrapper& variableEntries,
|
||||
const EntryListWrapper& blockEntries);
|
||||
|
||||
status_t _CreateReturnValue(
|
||||
target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState,
|
||||
status_t _CreateReturnValues(
|
||||
ReturnValueInfoList* returnValueInfos,
|
||||
Image* image,
|
||||
StackFrame* frame,
|
||||
DwarfStackFrameDebugInfo& factory);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <Referenceable.h>
|
||||
|
||||
#include "AddressSectionTypes.h"
|
||||
#include "ReturnValueInfo.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
|
@ -56,8 +57,7 @@ public:
|
|||
FunctionInstance* functionInstance,
|
||||
CpuState* cpuState,
|
||||
bool getFullFrameInfo,
|
||||
target_addr_t returnFunctionAddress,
|
||||
CpuState* returnFunctionState,
|
||||
ReturnValueInfoList* returnValueInfos,
|
||||
StackFrame*& _Frame,
|
||||
CpuState*& _previousCpuState) = 0;
|
||||
// returns reference to previous frame
|
||||
|
|
|
@ -58,9 +58,7 @@ GetStackTraceJob::Do()
|
|||
// get the stack trace
|
||||
StackTrace* stackTrace;
|
||||
status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this,
|
||||
fCpuState, stackTrace, fThread->ExecutedSubroutine()
|
||||
? fThread->SubroutineAddress() : 0, fThread->ExecutedSubroutine()
|
||||
? fThread->SubroutineCpuState() : NULL);
|
||||
fCpuState, stackTrace, fThread->ReturnValueInfos());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
BReference<StackTrace> stackTraceReference(stackTrace, true);
|
||||
|
|
|
@ -18,8 +18,7 @@ Thread::Thread(Team* team, thread_id threadID)
|
|||
fID(threadID),
|
||||
fState(THREAD_STATE_UNKNOWN),
|
||||
fExecutedSubroutine(false),
|
||||
fSubroutineAddress(0),
|
||||
fSubroutineState(NULL),
|
||||
fReturnValueInfos(NULL),
|
||||
fStoppedReason(THREAD_STOPPED_UNKNOWN),
|
||||
fCpuState(NULL),
|
||||
fStackTrace(NULL)
|
||||
|
@ -33,14 +32,19 @@ Thread::~Thread()
|
|||
fCpuState->ReleaseReference();
|
||||
if (fStackTrace != NULL)
|
||||
fStackTrace->ReleaseReference();
|
||||
if (fSubroutineState != NULL)
|
||||
fSubroutineState->ReleaseReference();
|
||||
|
||||
ClearReturnValueInfos();
|
||||
delete fReturnValueInfos;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Thread::Init()
|
||||
{
|
||||
fReturnValueInfos = new(std::nothrow) ReturnValueInfoList;
|
||||
if (fReturnValueInfos == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -74,7 +78,7 @@ Thread::SetState(uint32 state, uint32 reason, const BString& info)
|
|||
SetCpuState(NULL);
|
||||
SetStackTrace(NULL);
|
||||
fExecutedSubroutine = false;
|
||||
fSubroutineAddress = 0;
|
||||
ClearReturnValueInfos();
|
||||
}
|
||||
|
||||
fTeam->NotifyThreadStateChanged(this);
|
||||
|
@ -117,20 +121,23 @@ Thread::SetStackTrace(StackTrace* trace)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::SetExecutedSubroutine(target_addr_t address)
|
||||
status_t
|
||||
Thread::AddReturnValueInfo(ReturnValueInfo* info)
|
||||
{
|
||||
if (!fReturnValueInfos->AddItem(info))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
info->AcquireReference();
|
||||
fExecutedSubroutine = true;
|
||||
fSubroutineAddress = address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Thread::SetSubroutineCpuState(CpuState* state)
|
||||
Thread::ClearReturnValueInfos()
|
||||
{
|
||||
if (fSubroutineState != NULL)
|
||||
fSubroutineState->ReleaseReference();
|
||||
for (int32 i = 0; i < fReturnValueInfos->CountItems(); i++)
|
||||
fReturnValueInfos->ItemAt(i)->ReleaseReference();
|
||||
|
||||
fSubroutineState = state;
|
||||
fSubroutineState->AcquireReference();
|
||||
fReturnValueInfos->MakeEmpty();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <Referenceable.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "ReturnValueInfo.h"
|
||||
#include "types/Types.h"
|
||||
|
||||
|
||||
|
@ -69,14 +70,11 @@ public:
|
|||
StackTrace* GetStackTrace() const { return fStackTrace; }
|
||||
void SetStackTrace(StackTrace* trace);
|
||||
|
||||
bool ExecutedSubroutine() const
|
||||
{ return fExecutedSubroutine; }
|
||||
target_addr_t SubroutineAddress() const
|
||||
{ return fSubroutineAddress; }
|
||||
void SetExecutedSubroutine(target_addr_t address);
|
||||
CpuState* SubroutineCpuState() const
|
||||
{ return fSubroutineState; }
|
||||
void SetSubroutineCpuState(CpuState* state);
|
||||
ReturnValueInfoList*
|
||||
ReturnValueInfos() const
|
||||
{ return fReturnValueInfos; }
|
||||
status_t AddReturnValueInfo(ReturnValueInfo* info);
|
||||
void ClearReturnValueInfos();
|
||||
|
||||
private:
|
||||
Team* fTeam;
|
||||
|
@ -84,8 +82,8 @@ private:
|
|||
BString fName;
|
||||
uint32 fState;
|
||||
bool fExecutedSubroutine;
|
||||
target_addr_t fSubroutineAddress;
|
||||
CpuState* fSubroutineState;
|
||||
ReturnValueInfoList*
|
||||
fReturnValueInfos;
|
||||
uint32 fStoppedReason;
|
||||
BString fStoppedReasonInfo;
|
||||
CpuState* fCpuState;
|
||||
|
|
Loading…
Reference in New Issue