1 use super::prelude::*; 2 use crate::protocol::commands::ext::ExtendedMode; 3 use crate::protocol::SpecificIdKind; 4 use crate::protocol::SpecificThreadId; 5 use crate::target::ext::base::BaseOps; 6 use crate::SINGLE_THREAD_TID; 7 8 impl<T: Target, C: Connection> GdbStubImpl<T, C> { handle_extended_mode( &mut self, res: &mut ResponseWriter<'_, C>, target: &mut T, command: ExtendedMode<'_>, ) -> Result<HandlerStatus, Error<T::Error, C::Error>>9 pub(crate) fn handle_extended_mode( 10 &mut self, 11 res: &mut ResponseWriter<'_, C>, 12 target: &mut T, 13 command: ExtendedMode<'_>, 14 ) -> Result<HandlerStatus, Error<T::Error, C::Error>> { 15 let ops = match target.support_extended_mode() { 16 Some(ops) => ops, 17 None => return Ok(HandlerStatus::Handled), 18 }; 19 20 crate::__dead_code_marker!("extended_mode", "impl"); 21 22 let handler_status = match command { 23 ExtendedMode::ExclamationMark(_cmd) => { 24 ops.on_start().map_err(Error::TargetError)?; 25 HandlerStatus::NeedsOk 26 } 27 ExtendedMode::R(_cmd) => { 28 ops.restart().map_err(Error::TargetError)?; 29 HandlerStatus::Handled 30 } 31 ExtendedMode::vAttach(cmd) => { 32 if ops.support_current_active_pid().is_none() { 33 return Err(Error::MissingCurrentActivePidImpl); 34 } 35 36 ops.attach(cmd.pid).handle_error()?; 37 self.report_reasonable_stop_reason(res, target)? 38 } 39 ExtendedMode::qC(_cmd) if ops.support_current_active_pid().is_some() => { 40 let ops = ops.support_current_active_pid().unwrap(); 41 42 res.write_str("QC")?; 43 let pid = ops.current_active_pid().map_err(Error::TargetError)?; 44 let tid = match target.base_ops() { 45 BaseOps::SingleThread(_) => SINGLE_THREAD_TID, 46 BaseOps::MultiThread(ops) => { 47 // HACK: gdbstub should avoid using a sentinel value here... 48 if self.current_mem_tid == SINGLE_THREAD_TID { 49 let mut err: Result<_, Error<T::Error, C::Error>> = Ok(()); 50 let mut first_tid = None; 51 ops.list_active_threads(&mut |tid| { 52 // TODO: replace this with a try block (once stabilized) 53 let e = (|| { 54 if first_tid.is_some() { 55 return Ok(()); 56 } 57 first_tid = Some(tid); 58 Ok(()) 59 })(); 60 61 if let Err(e) = e { 62 err = Err(e) 63 } 64 }) 65 .map_err(Error::TargetError)?; 66 err?; 67 first_tid.unwrap_or(SINGLE_THREAD_TID) 68 } else { 69 self.current_mem_tid 70 } 71 } 72 }; 73 74 res.write_specific_thread_id(SpecificThreadId { 75 pid: self 76 .features 77 .multiprocess() 78 .then_some(SpecificIdKind::WithId(pid)), 79 tid: SpecificIdKind::WithId(tid), 80 })?; 81 82 HandlerStatus::Handled 83 } 84 ExtendedMode::vRun(cmd) => { 85 use crate::target::ext::extended_mode::Args; 86 87 let _pid = ops 88 .run(cmd.filename, Args::new(&mut cmd.args.into_iter())) 89 .handle_error()?; 90 91 self.report_reasonable_stop_reason(res, target)? 92 } 93 // --------- ASLR --------- // 94 ExtendedMode::QDisableRandomization(cmd) if ops.support_configure_aslr().is_some() => { 95 let ops = ops.support_configure_aslr().unwrap(); 96 ops.cfg_aslr(cmd.value).handle_error()?; 97 HandlerStatus::NeedsOk 98 } 99 // --------- Environment --------- // 100 ExtendedMode::QEnvironmentHexEncoded(cmd) if ops.support_configure_env().is_some() => { 101 let ops = ops.support_configure_env().unwrap(); 102 ops.set_env(cmd.key, cmd.value).handle_error()?; 103 HandlerStatus::NeedsOk 104 } 105 ExtendedMode::QEnvironmentUnset(cmd) if ops.support_configure_env().is_some() => { 106 let ops = ops.support_configure_env().unwrap(); 107 ops.remove_env(cmd.key).handle_error()?; 108 HandlerStatus::NeedsOk 109 } 110 ExtendedMode::QEnvironmentReset(_cmd) if ops.support_configure_env().is_some() => { 111 let ops = ops.support_configure_env().unwrap(); 112 ops.reset_env().handle_error()?; 113 HandlerStatus::NeedsOk 114 } 115 // --------- Working Dir --------- // 116 ExtendedMode::QSetWorkingDir(cmd) if ops.support_configure_working_dir().is_some() => { 117 let ops = ops.support_configure_working_dir().unwrap(); 118 ops.cfg_working_dir(cmd.dir).handle_error()?; 119 HandlerStatus::NeedsOk 120 } 121 // --------- Startup Shell --------- // 122 ExtendedMode::QStartupWithShell(cmd) 123 if ops.support_configure_startup_shell().is_some() => 124 { 125 let ops = ops.support_configure_startup_shell().unwrap(); 126 ops.cfg_startup_with_shell(cmd.value).handle_error()?; 127 HandlerStatus::NeedsOk 128 } 129 130 _ => HandlerStatus::Handled, 131 }; 132 133 Ok(handler_status) 134 } 135 } 136