From 76ed6d72a535697c54305bc36c946e13dc5ed28c Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 27 Mar 2013 23:21:42 -0400 Subject: [PATCH] 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. --- src/apps/debugger/Jamfile | 3 +- src/apps/debugger/arch/Architecture.cpp | 12 +- src/apps/debugger/arch/Architecture.h | 4 +- .../debugger/controllers/ThreadHandler.cpp | 48 +++-- .../debug_info/DebuggerImageDebugInfo.cpp | 5 +- .../debug_info/DebuggerImageDebugInfo.h | 3 +- .../debug_info/DwarfImageDebugInfo.cpp | 165 +++++++++--------- .../debugger/debug_info/DwarfImageDebugInfo.h | 8 +- .../debug_info/SpecificImageDebugInfo.h | 4 +- src/apps/debugger/jobs/GetStackTraceJob.cpp | 4 +- src/apps/debugger/model/Thread.cpp | 33 ++-- src/apps/debugger/model/Thread.h | 18 +- 12 files changed, 167 insertions(+), 140 deletions(-) diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index c2aaa66bd9..053121c22a 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -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 diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index ecae506adb..162002466b 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.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 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; } diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index e39077400b..76d553bac4 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -13,6 +13,7 @@ #include #include +#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); diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index af647cb1c5..b40aa35efa 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -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 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 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 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 infoReference(info, true); + if (fThread->AddReturnValueInfo(info) != B_OK) + return false; + + infoReference.Detach(); } return false; diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index c7a77e1603..8aa49b4c48 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -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; } diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index 91d0c1bc63..efe5816b58 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -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, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 5c58ed369c..b467cd1188 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -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( 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( - 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(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(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 locationReference(location, true); - Variable* variable = NULL; - BReference 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( + 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( + subProgram->Specification()); + if (subProgram != NULL) + returnType = subProgram->ReturnType(); - BReference 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(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 locationReference(location, true); + Variable* variable = NULL; + BReference idReference( + targetFunction->GetFunctionID(), true); + result = factory.CreateReturnValue(idReference, returnType, + location, variable); + if (result != B_OK) + return result; + + BReference variableReference(variable, true); + if (!frame->AddLocalVariable(variable)) + return B_NO_MEMORY; + } } } diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 7dab0fbffa..422925a9b9 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -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); diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index 595d2383ab..02a1fa92e6 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -10,6 +10,7 @@ #include #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 diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index c3a2316a76..0bc286ea73 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -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 stackTraceReference(stackTrace, true); diff --git a/src/apps/debugger/model/Thread.cpp b/src/apps/debugger/model/Thread.cpp index e32424c46d..0dc319fb6a 100644 --- a/src/apps/debugger/model/Thread.cpp +++ b/src/apps/debugger/model/Thread.cpp @@ -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(); } diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h index 17aa3307a0..e25a6c78ad 100644 --- a/src/apps/debugger/model/Thread.h +++ b/src/apps/debugger/model/Thread.h @@ -11,6 +11,7 @@ #include #include +#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;