src/developer/debug/zxdb/client/step_thread_controller_unittest.cc
// Software exceptions should always stop execution. These might be from something like a hardcoded
// breakpoint instruction in the code. Doing "step" shouldn't skip over these.
Software exceptions should always stop execution. These might be from something like a hardcoded
breakpoint instruction in the code. Doing "step" shouldn't skip over these.
Software exceptions should always stop execution . These might be from something like a hardcoded breakpoint instruction in the code . Doing " step " shouldn ' t skip over these .
TEST_F(StepThreadControllerTest, SofwareException) {
  constexpr uint64_t kBeginAddr = 0x1000;
  constexpr uint64_t kEndAddr = 0x1010;
  debug_ipc::NotifyException exception;
  exception.type = debug_ipc::ExceptionType::kSingleStep;
  exception.thread.process_koid = process()->GetKoid();
  exception.thread.thread_koid = thread()->GetKoid();
  exception.thread.state = debug_ipc::ThreadRecord::State::kBlocked;
  exception.thread.frames.emplace_back(kBeginAddr, 0x5000);
  InjectException(exception);
  auto step_into =
      std::make_unique<StepThreadController>(AddressRanges(AddressRange(kBeginAddr, kEndAddr)));
  bool continued = false;
  thread()->ContinueWith(std::move(step_into), [&continued](const Err& err) {
    if (!err.has_error())
      continued = true;
  });
  EXPECT_TRUE(continued);
  EXPECT_EQ(1, mock_remote_api()->GetAndResetResumeCount());
  exception.type = debug_ipc::ExceptionType::kSoftwareBreakpoint;
  exception.thread.frames[0].ip += 4;
  InjectException(exception);
  EXPECT_EQ(0, mock_remote_api()->GetAndResetResumeCount());  
  EXPECT_EQ(debug_ipc::ThreadRecord::State::kBlocked, thread()->GetState());
}
TEST_F ( StepThreadControllerTest , SofwareException ) { constexpr uint64_t kBeginAddr = 0x1000 ; constexpr uint64_t kEndAddr = 0x1010 ; debug_ipc :: NotifyException exception ; exception . type = debug_ipc :: ExceptionType :: kSingleStep ; exception . thread . process_koid = process ( ) -> GetKoid ( ) ; exception . thread . thread_koid = thread ( ) -> GetKoid ( ) ; exception . thread . state = debug_ipc :: ThreadRecord :: State :: kBlocked ; exception . thread . frames . emplace_back ( kBeginAddr , 0x5000 ) ; InjectException ( exception ) ; auto step_into = std :: make_unique < StepThreadController > ( AddressRanges ( AddressRange ( kBeginAddr , kEndAddr ) ) ) ; bool continued = false ; thread ( ) -> ContinueWith ( std :: move ( step_into ) , [ & continued ] ( const Err & err ) { if ( ! err . has_error ( ) ) continued = true ; } ) ; EXPECT_TRUE ( continued ) ; EXPECT_EQ ( 1 , mock_remote_api ( ) -> GetAndResetResumeCount ( ) ) ; exception . type = debug_ipc :: ExceptionType :: kSoftwareBreakpoint ; exception . thread . frames [ 0 ] . ip += 4 ; InjectException ( exception ) ; EXPECT_EQ ( 0 , mock_remote_api ( ) -> GetAndResetResumeCount ( ) ) ; EXPECT_EQ ( debug_ipc :: ThreadRecord :: State :: kBlocked , thread ( ) -> GetState ( ) ) ; }
Software exceptions should always stop execution.
Software exceptions should always stop execution .
// Step as long as we're in this range. Using the "code range" for stepping allows us to avoid // dependencies on the symbol subsystem. // Set up the thread to be stopped at the beginning of our range. // Continue the thread with the controller stepping in range. // It should have been able to step without doing any further async work. // Issue a software exception in the range. // It should have stayed stopped despite being in range. // Stopped