diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index b00319cb..cd1931d1 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -16550,6 +16550,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } else if (methodDef->mMethodType == BfMethodType_CtorClear) { + SetIllegalSrcPos(); mBfIRBuilder->ClearDebugLocation(); PopulateType(mCurTypeInstance, BfPopulateType_Data); auto thisVal = GetThis(); diff --git a/IDEHelper/DebugTarget.cpp b/IDEHelper/DebugTarget.cpp index 4db8a8d6..5e8b6410 100644 --- a/IDEHelper/DebugTarget.cpp +++ b/IDEHelper/DebugTarget.cpp @@ -2024,6 +2024,19 @@ bool DebugTarget::RollBackStackFrame_COFFFrameDescriptor(CPURegisters* registers return false; } +bool DebugTarget::RollBackStackFrame_SimpleRet(CPURegisters* registers) +{ + int regSize = sizeof(addr_target); + addr_target* regPC = registers->GetPCRegisterRef(); + addr_target* regSP = registers->GetSPRegisterRef(); + + addr_target newPC = 0; + gDebugger->ReadMemory(*regSP, sizeof(addr_target), &newPC); + *regSP += regSize; + *regPC = newPC; + return true; +} + bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outReturnAddressLoc, bool isStackStart) { if (outReturnAddressLoc != NULL) @@ -2036,16 +2049,7 @@ bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outRe { // If we are literally just a return then often the frame descriptor is wrong, // but we know this is ACTUALLY just a simple rollback - - int regSize = sizeof(addr_target); - addr_target* regPC = registers->GetPCRegisterRef(); - addr_target* regSP = registers->GetSPRegisterRef(); - - addr_target newPC = 0; - gDebugger->ReadMemory(*regSP, sizeof(addr_target), &newPC); - *regSP += regSize; - *regPC = newPC; - return true; + return RollBackStackFrame_SimpleRet(registers); } } @@ -2058,6 +2062,9 @@ bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outRe DbgSubprogram* dbgSubprogram = FindSubProgram(pc); if (dbgSubprogram != NULL) { + if (pc == dbgSubprogram->mBlock.mLowPC) + return RollBackStackFrame_SimpleRet(registers); + auto dbgModule = dbgSubprogram->mCompileUnit->mDbgModule; if ((dbgModule != NULL) && (!dbgModule->mParsedFrameDescriptors)) { @@ -2066,6 +2073,10 @@ bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outRe return true; } } + else + { + return RollBackStackFrame_SimpleRet(registers); + } #endif // Fall through after this, we need to process a 'return' @@ -2081,7 +2092,7 @@ bool DebugTarget::RollBackStackFrame(CPURegisters* registers, addr_target* outRe if (alreadyRolledBackPC) return true; -#ifdef BF_DBG_32 +#ifdef BF_DBG_32 // Try rollback assuming a frame pointer addr_target newPC = 0; addr_target stackFrame = registers->GetBP(); diff --git a/IDEHelper/DebugTarget.h b/IDEHelper/DebugTarget.h index 5fb20f03..7831579c 100644 --- a/IDEHelper/DebugTarget.h +++ b/IDEHelper/DebugTarget.h @@ -65,6 +65,7 @@ protected: bool RollBackStackFrame_ExceptionDirectory(CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC); bool RollBackStackFrame_DwFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc); bool RollBackStackFrame_COFFFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc, bool isStackStart); + bool RollBackStackFrame_SimpleRet(CPURegisters* registers); bool PropogateRegisterUpCallStack_ExceptionDirectory(addr_target findPC, CPURegisters* callerRegisters, CPURegisters* calleeRegisters, void* regPtr, bool& wasSaved); void RemoveTargetData(); bool GetValueByNameInBlock_Helper(DbgSubprogram* dwSubprogram, DbgBlock* dwBlock, String& name, WdStackFrame* stackFrame, intptr* outAddr, DbgType** outType, DbgAddrType* outAddrType); diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index a1d19629..26361ac8 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -4276,42 +4276,51 @@ bool WinDebugger::SetupStep(StepType stepType) if ((mStepType != StepType_StepOut_NoFrame) && (RollBackStackFrame(®isters, true))) { + bool isStackAdjust = false; + DbgSubprogram* dwSubprogram = mDebugTarget->FindSubProgram(pcAddress); + if (dwSubprogram != NULL) + { + if ((strcmp(dwSubprogram->mName, "_chkstk") == 0) || + (strcmp(dwSubprogram->mName, "__chkstk") == 0) || + (strcmp(dwSubprogram->mName, "_alloca_probe") == 0)) + isStackAdjust = true; + } + pcAddress = registers.GetPC(); - - addr_target oldAddress = pcAddress; - - CPUInst inst; - while (true) + if (isStackAdjust) { - if (!mDebugTarget->DecodeInstruction(pcAddress, &inst)) - break; - if ((inst.IsBranch()) || (inst.IsCall()) || (inst.IsReturn())) - break; - DbgSubprogram* checkSubprogram = NULL; - auto checkLineData = FindLineDataAtAddress(pcAddress, &checkSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly); - if (checkLineData == NULL) - break; - if (checkSubprogram->GetLineAddr(*checkLineData) == pcAddress) - break; - pcAddress += inst.GetLength(); + // We set it to zero so we never detect an "isDeeper" condition which would skip over the return-location breakpoint + mStepSP = 0; } + else + { + addr_target oldAddress = pcAddress; - if (pcAddress != oldAddress) - { - BfLogDbg("Adjusting stepout address from %p to %p\n", oldAddress, pcAddress); - } - -#ifdef BF_DBG_32 -// if (mDebugTarget->DecodeInstruction(pcAddress, &inst)) -// { -// if (inst.IsStackAdjust()) -// { -// auto oldAddress = pcAddress; -// pcAddress += inst.GetLength(); -// BfLogDbg("Adjusting stepout address from %p to %p\n", oldAddress, pcAddress); -// } -// } + CPUInst inst; + while (true) + { + if (!mDebugTarget->DecodeInstruction(pcAddress, &inst)) + break; + if ((inst.IsBranch()) || (inst.IsCall()) || (inst.IsReturn())) + break; +#ifdef BF_DBG_32 + if (!inst.StackAdjust(mStepSP)) + break; #endif + DbgSubprogram* checkSubprogram = NULL; + auto checkLineData = FindLineDataAtAddress(pcAddress, &checkSubprogram, NULL, NULL, DbgOnDemandKind_LocalOnly); + if (checkLineData == NULL) + break; + if (checkSubprogram->GetLineAddr(*checkLineData) == pcAddress) + break; + pcAddress += inst.GetLength(); + } + + if (pcAddress != oldAddress) + { + BfLogDbg("Adjusting stepout address from %p to %p\n", oldAddress, pcAddress); + } + } BfLogDbg("SetupStep Stepout SetTempBreakpoint %p\n", pcAddress); SetTempBreakpoint(pcAddress); @@ -4416,7 +4425,10 @@ bool WinDebugger::SetupStep(StepType stepType) if ((inst.IsReturn()) && (instIdx == 0) && (!mStepInAssembly)) { // Do actual STEP OUT so we set up proper "stepping over unimportant post-return instructions" - return SetupStep(StepType_StepOut); + if (stepType == StepType_StepInto) + return SetupStep(StepType_StepOut_ThenInto); + else + return SetupStep(StepType_StepOut); } if ((breakOnNext) || (mStepInAssembly) || (isAtLine) || (inst.IsBranch()) || (inst.IsCall()) || (inst.IsReturn())) diff --git a/IDEHelper/X86.cpp b/IDEHelper/X86.cpp index bbb668d8..f40847d6 100644 --- a/IDEHelper/X86.cpp +++ b/IDEHelper/X86.cpp @@ -151,9 +151,24 @@ int X86Instr::GetLength() return mSize; } -bool X86Instr::IsStackAdjust() +bool X86Instr::StackAdjust(uint32& adjust) { - return mMCInst.getOpcode() == X86::SUB32ri8; + if (adjust == 0) + return true; + + if (mMCInst.getOpcode() != X86::SUB32ri8) + return true; + + auto operand0 = mMCInst.getOperand(0); + if (operand0.getReg() != llvm::X86::ESP) + return true; + auto operand2 = mMCInst.getOperand(2); + if (!operand2.isImm()) + return false; + + adjust -= (uint32)operand2.getImm(); + + return true; } bool X86Instr::IsBranch() diff --git a/IDEHelper/X86.h b/IDEHelper/X86.h index f0e2ea90..0538eb7b 100644 --- a/IDEHelper/X86.h +++ b/IDEHelper/X86.h @@ -292,7 +292,7 @@ public: } int GetLength(); - bool IsStackAdjust(); + bool StackAdjust(uint32& adjust); bool IsBranch(); bool IsCall(); bool IsRep(bool& isPrefixOnly);