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;