Rework how return values are handled.

- ArchitectureX86 now hands off the work for GetInstructionInfo() to
  DisassemblerX86, since the latter has all the information we need
  to properly classify and evaluate instructions. Correspondingly a
  CpuState is passed down to it in order to perform address calculations
  for the instruction if it's a jump or call instruction. The latter's
  targets are then stored on the thread for later retrieval when
  constructing a stack trace. Adjust X86_64 accordingly for the
  signature changes. This also fixes a bug where Step Over would
  sometimes result in a Step Into instead due to the previous
  implementation of GetInstructionInfo() occasionally failing to
  classify call instructions correctly.

- Architecture::CreateStackTrace() now takes an argument specifying
  the address of the last executed function if applicable. This is used
  to decide who/where to decode a return value from. Adjust callers.

- DwarfImageDebugInfo::_CreateReturnValue() uses the above information
  in order to know directly who the caller it needs to look up a return
  value for is, rather than trying to walk backwards to find them.
  Type resolution is now also a bit more sophisticated due to various
  cases where the subprogram entry didn't directly contain the return
  type but referred to another DIE that did. Retrieving return value
  now appears to work properly in all cases except when position
  independent code is involved. The latter however will require
  resolving the appropriate function address in the PLT, which will
  need some additional work.
This commit is contained in:
Rene Gollent
2012-12-31 23:02:24 -05:00
parent bdbbc10b44
commit 5745a40dd1
17 changed files with 197 additions and 131 deletions
+11 -10
View File
@@ -253,7 +253,7 @@ ThreadHandler::HandleThreadAction(uint32 action)
if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, false, 1,
fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true);
}
@@ -469,7 +469,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
// just single-step, otherwise we set a breakpoint after the instruction.
InstructionInfo info;
if (fDebuggerInterface->GetArchitecture()->GetInstructionInfo(
cpuState->InstructionPointer(), info) != B_OK) {
cpuState->InstructionPointer(), info, cpuState) != B_OK) {
TRACE_CONTROL(" failed to get instruction info\n");
return false;
}
@@ -484,7 +484,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState)
TRACE_CONTROL(" subroutine call -- installing breakpoint at address "
"%#" B_PRIx64 "\n", info.Address() + info.Size());
fThread->SetExecutedSubroutine();
fThread->SetExecutedSubroutine(info.TargetAddress());
if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK)
return false;
@@ -566,8 +566,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState)
if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, false,
1, false, false) == B_OK) {
fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true);
}
}
@@ -608,7 +608,7 @@ 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();
fThread->SetExecutedSubroutine(cpuState->InstructionPointer());
target_addr_t framePointer = cpuState->StackFramePointer();
bool hasExitedFrame = fDebuggerInterface->GetArchitecture()
->StackGrowthDirection() == STACK_GROWTH_DIRECTION_POSITIVE
@@ -653,8 +653,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, false,
1, false, false) == B_OK) {
fThread->GetTeam(), this, cpuState, stackTrace, 0, 1,
false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true);
}
}
@@ -685,7 +685,7 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
BReference<StackTrace> stackTraceReference(stackTrace);
if (stackTrace == NULL && cpuState != NULL) {
if (fDebuggerInterface->GetArchitecture()->CreateStackTrace(
fThread->GetTeam(), this, cpuState, stackTrace, false,
fThread->GetTeam(), this, cpuState, stackTrace, 0,
1, false, false) == B_OK) {
stackTraceReference.SetTo(stackTrace, true);
}
@@ -693,7 +693,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState)
if (stackTrace != NULL && stackTrace->FrameAt(0)
->FrameAddress() != fPreviousFrameAddress) {
fThread->SetExecutedSubroutine();
fThread->SetExecutedSubroutine(
cpuState->InstructionPointer());
}
return false;