hrev45412 adds 3 changesets to branch 'master' old head: 469f13fdfe886f0eca9cc9204ad2e3da7377f7ba new head: 1efa0a42f6a490bfb88cfd928c53d17c3dd62907 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=1efa0a4+%5E469f13f ---------------------------------------------------------------------------- 04c919f: Fix incorrect target address calculation for memory operands. 029fcc4: Add CPU state at time of function call to Thread. - When we detect that we're stepping over a function call, also store the CPU state at the time it occurred. This information is needed in order to correctly reconstruct target addresses later since some operands may be register-based. - Add the aforementioned CPU state to CreateFrame()'s arguments and adjust implementations and callers accordingly. 1efa0a4: Fix return value handling. - In the case of position independent code, the initial call isn't to the function we want, but rather to a PLT slot which resolves the function's location. As such, find that slot and use it to determine the corresponding GOT offset for the function's real location. Still need some further refactoring of return value handling to properly handle the case of stepping over a single line that makes multiple calls, but this fixes the basic case at least. [ Rene Gollent <anevilyak@xxxxxxxxx> ] ---------------------------------------------------------------------------- 12 files changed, 64 insertions(+), 22 deletions(-) src/apps/debugger/arch/Architecture.cpp | 6 ++-- src/apps/debugger/arch/Architecture.h | 1 + .../debugger/arch/x86/disasm/DisassemblerX86.cpp | 2 ++ src/apps/debugger/controllers/ThreadHandler.cpp | 13 +++---- .../debug_info/DebuggerImageDebugInfo.cpp | 3 +- .../debugger/debug_info/DebuggerImageDebugInfo.h | 1 + .../debugger/debug_info/DwarfImageDebugInfo.cpp | 37 +++++++++++++------- .../debugger/debug_info/DwarfImageDebugInfo.h | 2 ++ .../debugger/debug_info/SpecificImageDebugInfo.h | 1 + src/apps/debugger/jobs/GetStackTraceJob.cpp | 3 +- src/apps/debugger/model/Thread.cpp | 13 +++++++ src/apps/debugger/model/Thread.h | 4 +++ ############################################################################ Commit: 04c919f9d6a8d94b05b0aa91fa529c1e5ba5475e URL: http://cgit.haiku-os.org/haiku/commit/?id=04c919f Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Tue Mar 26 22:42:14 2013 UTC Fix incorrect target address calculation for memory operands. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp index e686d7e..a681f23 100644 --- a/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp +++ b/src/apps/debugger/arch/x86/disasm/DisassemblerX86.cpp @@ -198,6 +198,8 @@ DisassemblerX86::GetInstructionTargetAddress(CpuState* state) const targetAddress += x86State->IntRegisterValue( RegisterNumberFromUdisIndex(fUdisData->operand[0].index)) * fUdisData->operand[0].scale; + if (fUdisData->operand[0].offset != 0) + targetAddress += fUdisData->operand[0].lval.sdword; } break; case UD_OP_JIMM: ############################################################################ Commit: 029fcc4ad65d306eadd3ce77b9ea30bec93ba3fe URL: http://cgit.haiku-os.org/haiku/commit/?id=029fcc4 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Tue Mar 26 22:44:54 2013 UTC Add CPU state at time of function call to Thread. - When we detect that we're stepping over a function call, also store the CPU state at the time it occurred. This information is needed in order to correctly reconstruct target addresses later since some operands may be register-based. - Add the aforementioned CPU state to CreateFrame()'s arguments and adjust implementations and callers accordingly. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/arch/Architecture.cpp b/src/apps/debugger/arch/Architecture.cpp index 42fd88e..ecae506 100644 --- a/src/apps/debugger/arch/Architecture.cpp +++ b/src/apps/debugger/arch/Architecture.cpp @@ -95,7 +95,8 @@ status_t Architecture::CreateStackTrace(Team* team, ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState, StackTrace*& _stackTrace, target_addr_t returnFunctionAddress, - int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo) + CpuState* returnFunctionState, int32 maxStackDepth, bool useExistingTrace, + bool getFullFrameInfo) { BReference<CpuState> cpuStateReference(cpuState); @@ -163,7 +164,8 @@ Architecture::CreateStackTrace(Team* team, if (function != NULL) { status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->CreateFrame(image, function, cpuState, getFullFrameInfo, - nextFrame == NULL ? returnFunctionAddress : 0, frame, + nextFrame == NULL ? returnFunctionAddress : 0, + nextFrame == NULL ? returnFunctionState : 0, frame, previousCpuState); if (error != B_OK && error != B_UNSUPPORTED) break; diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index d9610ba..e390774 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -111,6 +111,7 @@ public: CpuState* cpuState, StackTrace*& _stackTrace, target_addr_t returnFunctionAddress, + CpuState* returnFunctionState, 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 6a2fe94..af647cb 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, 1, + fThread->GetTeam(), this, cpuState, stackTrace, 0, NULL, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } @@ -485,6 +485,7 @@ ThreadHandler::_DoStepOver(CpuState* cpuState) "%#" B_PRIx64 "\n", info.Address() + info.Size()); fThread->SetExecutedSubroutine(info.TargetAddress()); + fThread->SetSubroutineCpuState(cpuState); if (_InstallTemporaryBreakpoint(info.Address() + info.Size()) != B_OK) return false; @@ -566,8 +567,8 @@ ThreadHandler::_HandleBreakpointHitStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, - false, false) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 0, + NULL, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -653,8 +654,8 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( - fThread->GetTeam(), this, cpuState, stackTrace, 0, 1, - false, false) == B_OK) { + fThread->GetTeam(), this, cpuState, stackTrace, 0, + NULL, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } @@ -686,7 +687,7 @@ ThreadHandler::_HandleSingleStepStep(CpuState* cpuState) if (stackTrace == NULL && cpuState != NULL) { if (fDebuggerInterface->GetArchitecture()->CreateStackTrace( fThread->GetTeam(), this, cpuState, stackTrace, 0, - 1, false, false) == B_OK) { + NULL, 1, false, false) == B_OK) { stackTraceReference.SetTo(stackTrace, true); } } diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index b40e08c..c7a77e1 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -69,7 +69,8 @@ status_t DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, target_addr_t returnFunctionAddress, - StackFrame*& _previousFrame, CpuState*& _previousCpuState) + CpuState* returnFunctionState, 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 bcafebc..91d0c1b 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -37,6 +37,7 @@ public: CpuState* cpuState, bool getFullFrameInfo, target_addr_t returnFunctionAddress, + CpuState* returnFunctionState, 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 b96814d..4c0247f 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -523,7 +523,8 @@ status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, target_addr_t returnFunctionAddress, - StackFrame*& _frame, CpuState*& _previousCpuState) + CpuState* returnFunctionState, StackFrame*& _frame, + CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); @@ -1091,7 +1092,8 @@ DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit, status_t DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress, - Image* image, StackFrame* frame, DwarfStackFrameDebugInfo& factory) + CpuState* returnFunctionState, Image* image, StackFrame* frame, + DwarfStackFrameDebugInfo& factory) { if (!image->ContainsAddress(returnFunctionAddress)) { // our current image doesn't contain the target function, diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index 203920b..7dab0fb 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -65,6 +65,7 @@ public: CpuState* cpuState, bool getFullFrameInfo, target_addr_t returnFunctionAddress, + CpuState* returnFunctionState, StackFrame*& _frame, CpuState*& _previousCpuState); virtual status_t GetStatement(FunctionDebugInfo* function, @@ -106,6 +107,7 @@ private: status_t _CreateReturnValue( target_addr_t returnFunctionAddress, + CpuState* returnFunctionState, 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 ac655cd..595d238 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -57,6 +57,7 @@ public: CpuState* cpuState, bool getFullFrameInfo, target_addr_t returnFunctionAddress, + CpuState* returnFunctionState, 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 23ce2fc..c3a2316 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -59,7 +59,8 @@ GetStackTraceJob::Do() StackTrace* stackTrace; status_t error = fArchitecture->CreateStackTrace(fThread->GetTeam(), this, fCpuState, stackTrace, fThread->ExecutedSubroutine() - ? fThread->SubroutineAddress() : 0); + ? fThread->SubroutineAddress() : 0, fThread->ExecutedSubroutine() + ? fThread->SubroutineCpuState() : NULL); if (error != B_OK) return error; BReference<StackTrace> stackTraceReference(stackTrace, true); diff --git a/src/apps/debugger/model/Thread.cpp b/src/apps/debugger/model/Thread.cpp index 63d21e0..e32424c 100644 --- a/src/apps/debugger/model/Thread.cpp +++ b/src/apps/debugger/model/Thread.cpp @@ -19,6 +19,7 @@ Thread::Thread(Team* team, thread_id threadID) fState(THREAD_STATE_UNKNOWN), fExecutedSubroutine(false), fSubroutineAddress(0), + fSubroutineState(NULL), fStoppedReason(THREAD_STOPPED_UNKNOWN), fCpuState(NULL), fStackTrace(NULL) @@ -32,6 +33,8 @@ Thread::~Thread() fCpuState->ReleaseReference(); if (fStackTrace != NULL) fStackTrace->ReleaseReference(); + if (fSubroutineState != NULL) + fSubroutineState->ReleaseReference(); } @@ -121,3 +124,13 @@ Thread::SetExecutedSubroutine(target_addr_t address) fSubroutineAddress = address; } + +void +Thread::SetSubroutineCpuState(CpuState* state) +{ + if (fSubroutineState != NULL) + fSubroutineState->ReleaseReference(); + + fSubroutineState = state; + fSubroutineState->AcquireReference(); +} diff --git a/src/apps/debugger/model/Thread.h b/src/apps/debugger/model/Thread.h index 1cba07f..17aa330 100644 --- a/src/apps/debugger/model/Thread.h +++ b/src/apps/debugger/model/Thread.h @@ -74,6 +74,9 @@ public: target_addr_t SubroutineAddress() const { return fSubroutineAddress; } void SetExecutedSubroutine(target_addr_t address); + CpuState* SubroutineCpuState() const + { return fSubroutineState; } + void SetSubroutineCpuState(CpuState* state); private: Team* fTeam; @@ -82,6 +85,7 @@ private: uint32 fState; bool fExecutedSubroutine; target_addr_t fSubroutineAddress; + CpuState* fSubroutineState; uint32 fStoppedReason; BString fStoppedReasonInfo; CpuState* fCpuState; ############################################################################ Revision: hrev45412 Commit: 1efa0a42f6a490bfb88cfd928c53d17c3dd62907 URL: http://cgit.haiku-os.org/haiku/commit/?id=1efa0a4 Author: Rene Gollent <anevilyak@xxxxxxxxx> Date: Tue Mar 26 22:48:22 2013 UTC Fix return value handling. - In the case of position independent code, the initial call isn't to the function we want, but rather to a PLT slot which resolves the function's location. As such, find that slot and use it to determine the corresponding GOT offset for the function's real location. Still need some further refactoring of return value handling to properly handle the case of stepping over a single line that makes multiple calls, but this fixes the basic case at least. ---------------------------------------------------------------------------- diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 4c0247f..0195ecc 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -674,14 +674,10 @@ DwarfImageDebugInfo::CreateFrame(Image* image, instructionPointer, functionInstance->Address() - fRelocationDelta, subprogramEntry->Variables(), subprogramEntry->Blocks()); - // TODO: re-enable once PIC and false positive issues - // are properly dealt with -#if 0 if (returnFunctionAddress != 0) { - _CreateReturnValue(returnFunctionAddress, image, frame, - *stackFrameDebugInfo); + _CreateReturnValue(returnFunctionAddress, returnFunctionState, + image, frame, *stackFrameDebugInfo); } -#endif } _frame = frameReference.Detach(); @@ -1104,15 +1100,30 @@ DwarfImageDebugInfo::_CreateReturnValue(target_addr_t returnFunctionAddress, } status_t result = B_OK; + ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); FunctionInstance* targetFunction; if (returnFunctionAddress >= fPLTSectionStart && returnFunctionAddress < fPLTSectionEnd) { - // TODO: handle resolving PLT entries - // to their target function - return B_UNSUPPORTED; + // 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; + } + + target_size_t addressSize = fDebuggerInterface->GetArchitecture() + ->AddressSize(); + ssize_t bytesRead = fDebuggerInterface->ReadMemory(info.TargetAddress(), + &returnFunctionAddress, addressSize); + + if (bytesRead != addressSize) + return B_BAD_VALUE; } - ImageDebugInfo* imageInfo = image->GetImageDebugInfo(); + targetFunction = imageInfo->FunctionAtAddress(returnFunctionAddress); if (targetFunction != NULL) { DwarfFunctionDebugInfo* targetInfo =