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:
Rene Gollent
2013-03-27 23:27:49 -04:00
parent 3fa429781c
commit 76ed6d72a5
12 changed files with 167 additions and 140 deletions
+36 -12
View File
@@ -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;