| 5415 | } |
| 5416 | |
| 5417 | bool WinDebugger::SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize) |
| 5418 | { |
| 5419 | BfLogDbg("SetHotJump %s %p->%p\n", oldSubprogram->mName, oldSubprogram->mBlock.mLowPC, newTarget); |
| 5420 | |
| 5421 | //AutoCrit autoCrit(mDebugManager->mCritSect); |
| 5422 | BF_ASSERT(mDebugManager->mCritSect.mLockCount == 1); |
| 5423 | |
| 5424 | addr_target jmpInstStart = oldSubprogram->mBlock.mLowPC; |
| 5425 | addr_target jmpInstEnd = jmpInstStart + sizeof(HotJumpOp); |
| 5426 | |
| 5427 | if (jmpInstEnd > oldSubprogram->mBlock.mHighPC) |
| 5428 | { |
| 5429 | if ((oldSubprogram->mBlock.mHighPC - oldSubprogram->mBlock.mLowPC == 1) && |
| 5430 | (newTargetSize == 1)) |
| 5431 | return true; // Special case for just stub 'ret' methods |
| 5432 | String err = StrFormat("Failed to hot replace method, method '%s' too small to insert hot thunk", oldSubprogram->ToString().c_str()); |
| 5433 | Fail(err); |
| 5434 | return false; |
| 5435 | } |
| 5436 | |
| 5437 | if (oldSubprogram->mHotReplaceKind != DbgSubprogram::HotReplaceKind_Replaced) |
| 5438 | { |
| 5439 | for (int hotThreadIdx = 0; hotThreadIdx < (int)mHotThreadStates.size(); hotThreadIdx++) |
| 5440 | { |
| 5441 | auto& hotThreadState = mHotThreadStates[hotThreadIdx]; |
| 5442 | WdThreadInfo* threadInfo = NULL; |
| 5443 | if (!mThreadMap.TryGetValue((uint32)hotThreadState.mThreadId, &threadInfo)) |
| 5444 | continue; |
| 5445 | |
| 5446 | int tryStart = GetTickCount(); |
| 5447 | |
| 5448 | while ((hotThreadState.mRegisters.GetPC() >= jmpInstStart) && (hotThreadState.mRegisters.GetPC() < jmpInstEnd)) |
| 5449 | { |
| 5450 | if (GetTickCount() - tryStart >= 8000) |
| 5451 | { |
| 5452 | Fail("Failed to hot replace method, can't move past prelude"); |
| 5453 | return false; |
| 5454 | } |
| 5455 | |
| 5456 | BfLogDbg("SetHotJump skipping through %p\n", hotThreadState.mRegisters.GetPC()); |
| 5457 | |
| 5458 | bool removedBreakpoint = false; |
| 5459 | |
| 5460 | mActiveThread = threadInfo; |
| 5461 | if ((mActiveThread->mStoppedAtAddress >= jmpInstStart) && (mActiveThread->mStoppedAtAddress < jmpInstEnd)) |
| 5462 | { |
| 5463 | for (addr_target addr = jmpInstStart; addr < jmpInstEnd; addr++) |
| 5464 | { |
| 5465 | if (mPhysBreakpointAddrMap.ContainsKey(addr)) |
| 5466 | { |
| 5467 | removedBreakpoint = true; |
| 5468 | RemoveBreakpoint(addr); |
| 5469 | } |
| 5470 | } |
| 5471 | } |
| 5472 | |
| 5473 | RunState oldRunState = mRunState; |
| 5474 | mRunState = RunState_HotStep; |
no test coverage detected