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