pub fn event_loop(reason: KCoreStopReason) -> Result<(), KError> {
    if GDB_STUB.is_locked() {
        panic!("re-entrant into event_loop!");
    }

    let mut gdb_stm = GDB_STUB.lock().take().unwrap();
    let target = super::kcb::get_kcb()
        .arch
        .kdebug
        .as_mut()
        .expect("Need a target");

    let mut stop_reason = target.determine_stop_reason(reason);
    debug!("event_loop stop_reason {:?}", stop_reason);
    loop {
        gdb_stm = match gdb_stm {
            GdbStubStateMachine::Idle(mut gdb_stm_inner) => {
                //trace!("GdbStubStateMachine::Idle");

                // This means we expect stuff on the serial line (from GDB)
                // Let's read and react to it:
                let conn = gdb_stm_inner.borrow_conn();
                conn.disable_irq();
                let byte = conn.read()?;

                match gdb_stm_inner.incoming_data(target, byte) {
                    Ok(gdb) => gdb,
                    Err(GdbStubError::TargetError(e)) => {
                        error!("Debugger raised a fatal error {:?}", e);
                        break;
                    }
                    Err(e) => {
                        error!("gdbstub internal error {:?}", e);
                        break;
                    }
                }
            }
            GdbStubStateMachine::CtrlCInterrupt(gdb_stm_inner) => {
                match gdb_stm_inner.interrupt_handled(target, Some(ThreadStopReason::DoneStep)) {
                    Ok(gdb) => gdb,
                    Err(e) => {
                        error!("gdbstub error {:?}", e);
                        break;
                    }
                }
            }
            GdbStubStateMachine::Disconnected(_gdb_stm_inner) => {
                error!("GdbStubStateMachine::Disconnected byebye");
                break;
            }
            GdbStubStateMachine::Running(mut gdb_stm_inner) => {
                //trace!("GdbStubStateMachine::DeferredStopReason");

                // If we're here we were running but have stopped now (either
                // because we hit Ctrl+c in gdb and hence got a serial interrupt
                // or we hit a breakpoint).
                let conn = gdb_stm_inner.borrow_conn();
                conn.disable_irq();
                let data_to_read = conn.peek().unwrap().is_some();

                if data_to_read {
                    let byte = gdb_stm_inner.borrow_conn().read().unwrap();
                    match gdb_stm_inner.incoming_data(target, byte) {
                        Ok(pumped_stm) => pumped_stm,
                        Err(GdbStubError::TargetError(e)) => {
                            error!("Target raised a fatal error: {:?}", e);
                            break;
                        }
                        Err(e) => {
                            error!("gdbstub error in DeferredStopReason.pump: {:?}", e);
                            break;
                        }
                    }
                } else if let Some(reason) = stop_reason.take() {
                    match gdb_stm_inner.report_stop(target, reason) {
                        Ok(gdb_stm_new) => gdb_stm_new,
                        Err(GdbStubError::TargetError(e)) => {
                            error!("Target raised a fatal error {:?}", e);
                            break;
                        }
                        Err(e) => {
                            error!("gdbstub internal error {:?}", e);
                            break;
                        }
                    }
                } else if target.resume_with.is_some() {
                    // We don't have a `stop_reason` and we don't have something
                    // to read on the line. This probably means we're done and
                    // we should run again.
                    conn.enable_irq();
                    let r = GDB_STUB
                        .lock()
                        .replace(GdbStubStateMachine::Running(gdb_stm_inner));
                    assert!(
                        r.is_none(),
                        "Put something in GDB_STUB which we shouldn't have..."
                    );
                    break;
                } else {
                    unreachable!("Can't happen?");
                }
            }
        }
    }

    match target.resume_with.take() {
        Some(ExecMode::Continue) => {
            //trace!("Resume execution.");
            let kcb = super::kcb::get_kcb();
            // If we were stepping, we need to remove the TF bit again for resuming
            if let Some(saved) = &mut kcb.arch.save_area {
                let mut rflags = RFlags::from_bits_truncate(saved.rflags);
                rflags.remove(x86::bits64::rflags::RFlags::FLAGS_TF);
                saved.rflags = rflags.bits();
            }
        }
        Some(ExecMode::SingleStep) => {
            trace!("Step execution, set TF flag.");
            let kcb = super::kcb::get_kcb();
            if let Some(saved) = &mut kcb.arch.save_area {
                saved.rflags |= RFlags::FLAGS_TF.bits();
            }
        }
        _ => {
            unimplemented!("Resume strategy not handled...");
        }
    }

    Ok(())
}
/// Resume the gdb client connection by passing an optional event for the
/// interruption.
///
/// # Arguments
/// - `resume_with`: Should probably always be Some(reason) except the first
///   time after connecting.
Resume the gdb client connection by passing an optional event for the
interruption.
Resume the gdb client connection by passing an optional event for the interruption .
pub fn event_loop(reason: KCoreStopReason) -> Result<(), KError> {
    if GDB_STUB.is_locked() {
        panic!("re-entrant into event_loop!");
    }
    let mut gdb_stm = GDB_STUB.lock().take().unwrap();
    let target = super::kcb::get_kcb()
        .arch
        .kdebug
        .as_mut()
        .expect("Need a target");
    let mut stop_reason = target.determine_stop_reason(reason);
    debug!("event_loop stop_reason {:?}", stop_reason);
    loop {
        gdb_stm = match gdb_stm {
            GdbStubStateMachine::Idle(mut gdb_stm_inner) => {
                //trace!("GdbStubStateMachine::Idle");
                // This means we expect stuff on the serial line (from GDB)
                // Let's read and react to it:
                let conn = gdb_stm_inner.borrow_conn();
                conn.disable_irq();
                let byte = conn.read()?;
                match gdb_stm_inner.incoming_data(target, byte) {
                    Ok(gdb) => gdb,
                    Err(GdbStubError::TargetError(e)) => {
                        error!("Debugger raised a fatal error {:?}", e);
                        break;
                    }
                    Err(e) => {
                        error!("gdbstub internal error {:?}", e);
                        break;
                    }
                }
            }
            GdbStubStateMachine::CtrlCInterrupt(gdb_stm_inner) => {
                match gdb_stm_inner.interrupt_handled(target, Some(ThreadStopReason::DoneStep)) {
                    Ok(gdb) => gdb,
                    Err(e) => {
                        error!("gdbstub error {:?}", e);
                        break;
                    }
                }
            }
            GdbStubStateMachine::Disconnected(_gdb_stm_inner) => {
                error!("GdbStubStateMachine::Disconnected byebye");
                break;
            }
            GdbStubStateMachine::Running(mut gdb_stm_inner) => {
                //trace!("GdbStubStateMachine::DeferredStopReason");
                // If we're here we were running but have stopped now (either
                // because we hit Ctrl+c in gdb and hence got a serial interrupt
                // or we hit a breakpoint).
                let conn = gdb_stm_inner.borrow_conn();
                conn.disable_irq();
                let data_to_read = conn.peek().unwrap().is_some();
                if data_to_read {
                    let byte = gdb_stm_inner.borrow_conn().read().unwrap();
                    match gdb_stm_inner.incoming_data(target, byte) {
                        Ok(pumped_stm) => pumped_stm,
                        Err(GdbStubError::TargetError(e)) => {
                            error!("Target raised a fatal error: {:?}", e);
                            break;
                        }
                        Err(e) => {
                            error!("gdbstub error in DeferredStopReason.pump: {:?}", e);
                            break;
                        }
                    }
                } else if let Some(reason) = stop_reason.take() {
                    match gdb_stm_inner.report_stop(target, reason) {
                        Ok(gdb_stm_new) => gdb_stm_new,
                        Err(GdbStubError::TargetError(e)) => {
                            error!("Target raised a fatal error {:?}", e);
                            break;
                        }
                        Err(e) => {
                            error!("gdbstub internal error {:?}", e);
                            break;
                        }
                    }
                } else if target.resume_with.is_some() {
                    // We don't have a `stop_reason` and we don't have something
                    // to read on the line. This probably means we're done and
                    // we should run again.
                    conn.enable_irq();
                    let r = GDB_STUB
                        .lock()
                        .replace(GdbStubStateMachine::Running(gdb_stm_inner));
                    assert!(
                        r.is_none(),
                        "Put something in GDB_STUB which we shouldn't have..."
                    );
                    break;
                } else {
                    unreachable!("Can't happen?");
                }
            }
        }
    }
    match target.resume_with.take() {
        Some(ExecMode::Continue) => {
            //trace!("Resume execution.");
            let kcb = super::kcb::get_kcb();
            // If we were stepping, we need to remove the TF bit again for resuming
            if let Some(saved) = &mut kcb.arch.save_area {
                let mut rflags = RFlags::from_bits_truncate(saved.rflags);
                rflags.remove(x86::bits64::rflags::RFlags::FLAGS_TF);
                saved.rflags = rflags.bits();
            }
        }
        Some(ExecMode::SingleStep) => {
            trace!("Step execution, set TF flag.");
            let kcb = super::kcb::get_kcb();
            if let Some(saved) = &mut kcb.arch.save_area {
                saved.rflags |= RFlags::FLAGS_TF.bits();
            }
        }
        _ => {
            unimplemented!("Resume strategy not handled...");
        }
    }
    Ok(())
}
pub fn event_loop ( reason : KCoreStopReason ) -> Result < ( ) , KError > { if GDB_STUB . is_locked ( ) { panic ! ( " " ) ; } let mut gdb_stm = GDB_STUB . lock ( ) . take ( ) . unwrap ( ) ; let target = super :: kcb :: get_kcb ( ) . arch . kdebug . as_mut ( ) . expect ( " " ) ; let mut stop_reason = target . determine_stop_reason ( reason ) ; debug ! ( " " stop_reason ) ; loop { gdb_stm = match gdb_stm { GdbStubStateMachine :: Idle ( mut gdb_stm_inner ) => { //trace!("GdbStubStateMachine::Idle"); // This means we expect stuff on the serial line (from GDB) // Let's read and react to it: let conn = gdb_stm_inner . borrow_conn ( ) ; conn . disable_irq ( ) ; let byte = conn . read ( ) ? ; match gdb_stm_inner . incoming_data ( target , byte ) { Ok ( gdb ) => gdb , Err ( GdbStubError :: TargetError ( e ) ) => { error ! ( " " e ) ; break ; } Err ( e ) => { error ! ( " " e ) ; break ; } } } GdbStubStateMachine :: CtrlCInterrupt ( gdb_stm_inner ) => { match gdb_stm_inner . interrupt_handled ( target , Some ( ThreadStopReason :: DoneStep ) ) { Ok ( gdb ) => gdb , Err ( e ) => { error ! ( " " e ) ; break ; } } } GdbStubStateMachine :: Disconnected ( _gdb_stm_inner ) => { error ! ( " " ) ; break ; } GdbStubStateMachine :: Running ( mut gdb_stm_inner ) => { //trace!("GdbStubStateMachine::DeferredStopReason"); // If we're here we were running but have stopped now (either // because we hit Ctrl+c in gdb and hence got a serial interrupt // or we hit a breakpoint). let conn = gdb_stm_inner . borrow_conn ( ) ; conn . disable_irq ( ) ; let data_to_read = conn . peek ( ) . unwrap ( ) . is_some ( ) ; if data_to_read { let byte = gdb_stm_inner . borrow_conn ( ) . read ( ) . unwrap ( ) ; match gdb_stm_inner . incoming_data ( target , byte ) { Ok ( pumped_stm ) => pumped_stm , Err ( GdbStubError :: TargetError ( e ) ) => { error ! ( " " e ) ; break ; } Err ( e ) => { error ! ( " " e ) ; break ; } } } else if let Some ( reason ) = stop_reason . take ( ) { match gdb_stm_inner . report_stop ( target , reason ) { Ok ( gdb_stm_new ) => gdb_stm_new , Err ( GdbStubError :: TargetError ( e ) ) => { error ! ( " " e ) ; break ; } Err ( e ) => { error ! ( " " e ) ; break ; } } } else if target . resume_with . is_some ( ) { // We don't have a `stop_reason` and we don't have something // to read on the line. This probably means we're done and // we should run again. conn . enable_irq ( ) ; let r = GDB_STUB . lock ( ) . replace ( GdbStubStateMachine :: Running ( gdb_stm_inner ) ) ; assert ! ( r is_none ( ) " " ) ; break ; } else { unreachable ! ( " " ) ; } } } } match target . resume_with . take ( ) { Some ( ExecMode :: Continue ) => { //trace!("Resume execution."); let kcb = super :: kcb :: get_kcb ( ) ; // If we were stepping, we need to remove the TF bit again for resuming if let Some ( saved ) = & mut kcb . arch . save_area { let mut rflags = RFlags :: from_bits_truncate ( saved . rflags ) ; rflags . remove ( x86 :: bits64 :: rflags :: RFlags :: FLAGS_TF ) ; saved . rflags = rflags . bits ( ) ; } } Some ( ExecMode :: SingleStep ) => { trace ! ( " " ) ; let kcb = super :: kcb :: get_kcb ( ) ; if let Some ( saved ) = & mut kcb . arch . save_area { saved . rflags |= RFlags :: FLAGS_TF . bits ( ) ; } } _ => { unimplemented ! ( " " ) ; } } Ok ( ( ) ) }
Resume the gdb client connection by passing an optional event for the
interruption.
Resume the gdb client connection by passing an optional event for the interruption .
reason
KCoreStopReason
reason
KCoreStopReason
resume_with
Should probably always be Some(reason) except the first
time after connecting.
Should probably always be Some ( reason ) except the first time after connecting .