mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Add scaffolding for multiple threads
This commit is contained in:
parent
cd99c8b665
commit
1da4eb3246
3 changed files with 64 additions and 20 deletions
|
|
@ -13,10 +13,15 @@ impl Debugger {
|
|||
|
||||
let extools = self.extools.get()?;
|
||||
|
||||
guard!(let Some(frame_id) = params.frameId else {
|
||||
return Err(Box::new(GenericError("Must select a stack frame to evaluate in")));
|
||||
});
|
||||
|
||||
let (thread, frame_no) = extools.get_thread_by_frame_id(frame_id)?;
|
||||
|
||||
if input.starts_with('#') {
|
||||
if input == "#dis" || input == "#disassemble" {
|
||||
let thread = extools.get_default_thread()?;
|
||||
guard!(let Some(frame) = thread.call_stack.get(params.frameId.unwrap_or(0) as usize) else {
|
||||
guard!(let Some(frame) = thread.call_stack.get(frame_no) else {
|
||||
return Err(Box::new(GenericError("Stack frame out of range")));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -196,8 +196,8 @@ impl Extools {
|
|||
(extools, thread)
|
||||
}
|
||||
|
||||
pub fn get_default_thread(&self) -> Result<ThreadInfo, Box<dyn Error>> {
|
||||
self.get_thread(0)
|
||||
pub fn get_all_threads(&self) -> std::sync::MutexGuard<HashMap<i64, ThreadInfo>> {
|
||||
self.threads.lock().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_thread(&self, thread_id: i64) -> Result<ThreadInfo, Box<dyn Error>> {
|
||||
|
|
@ -205,6 +205,16 @@ impl Extools {
|
|||
.ok_or_else(|| Box::new(super::GenericError("Getting call stack failed")) as Box<dyn Error>)
|
||||
}
|
||||
|
||||
pub fn get_thread_by_frame_id(&self, frame_id: i64) -> Result<(ThreadInfo, usize), Box<dyn Error>> {
|
||||
let frame_id = frame_id as usize;
|
||||
let threads = self.threads.lock().unwrap();
|
||||
let thread_id = (frame_id % threads.len()) as i64;
|
||||
let frame_no = frame_id / threads.len();
|
||||
let thread = threads.get(&thread_id).cloned()
|
||||
.ok_or_else(|| Box::new(super::GenericError("Getting call stack failed")) as Box<dyn Error>)?;
|
||||
Ok((thread, frame_no))
|
||||
}
|
||||
|
||||
pub fn bytecode(&mut self, proc_ref: &str, override_id: usize) -> &[DisassembledInstruction] {
|
||||
let Extools { bytecode, sender, seq: _seq, bytecode_rx, .. } = self;
|
||||
bytecode.entry((proc_ref.to_owned(), override_id)).or_insert_with(|| {
|
||||
|
|
@ -402,6 +412,22 @@ impl ExtoolsThread {
|
|||
debug_output!(in self.seq, "[extools] Dropping {:?}", _e);
|
||||
}
|
||||
}
|
||||
|
||||
fn stopped(&self, base: dap_types::StoppedEvent) {
|
||||
for &k in self.threads.lock().unwrap().keys() {
|
||||
if k != 0 {
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
reason: "sleep".to_owned(),
|
||||
threadId: Some(k),
|
||||
.. Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
threadId: Some(0),
|
||||
.. base
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handle_extools! {
|
||||
|
|
@ -420,25 +446,22 @@ handle_extools! {
|
|||
on BreakpointHit(&mut self, hit) {
|
||||
match hit.reason {
|
||||
BreakpointHitReason::Step => {
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
self.stopped(dap_types::StoppedEvent {
|
||||
reason: dap_types::StoppedEvent::REASON_STEP.to_owned(),
|
||||
threadId: Some(0),
|
||||
.. Default::default()
|
||||
});
|
||||
}
|
||||
BreakpointHitReason::Pause => {
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
self.stopped(dap_types::StoppedEvent {
|
||||
reason: dap_types::StoppedEvent::REASON_PAUSE.to_owned(),
|
||||
description: Some("Paused by request".to_owned()),
|
||||
threadId: Some(0),
|
||||
.. Default::default()
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
debug_output!(in self.seq, "[extools] {}#{}@{} hit", hit.proc, hit.override_id, hit.offset);
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
self.stopped(dap_types::StoppedEvent {
|
||||
reason: dap_types::StoppedEvent::REASON_BREAKPOINT.to_owned(),
|
||||
threadId: Some(0),
|
||||
.. Default::default()
|
||||
});
|
||||
}
|
||||
|
|
@ -447,10 +470,9 @@ handle_extools! {
|
|||
|
||||
on Runtime(&mut self, runtime) {
|
||||
output!(in self.seq, "[extools] Runtime in {}: {}", runtime.proc, runtime.message);
|
||||
self.seq.issue_event(dap_types::StoppedEvent {
|
||||
self.stopped(dap_types::StoppedEvent {
|
||||
reason: dap_types::StoppedEvent::REASON_EXCEPTION.to_owned(),
|
||||
text: Some(runtime.message.clone()),
|
||||
threadId: Some(0),
|
||||
.. Default::default()
|
||||
});
|
||||
self.queue(&self.runtime_tx, runtime);
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ handle_request! {
|
|||
for (i, ex_frame) in thread.call_stack.into_iter().enumerate() {
|
||||
let mut dap_frame = StackFrame {
|
||||
name: ex_frame.proc.clone(),
|
||||
id: i as i64,
|
||||
id: (i * extools.get_all_threads().len()) as i64 + params.threadId,
|
||||
instructionPointerReference: Some(format!("{}@{}#{}", ex_frame.proc, ex_frame.override_id, ex_frame.offset)),
|
||||
.. Default::default()
|
||||
};
|
||||
|
|
@ -588,9 +588,14 @@ handle_request! {
|
|||
|
||||
on Scopes(&mut self, ScopesArguments { frameId }) {
|
||||
let extools = self.extools.get()?;
|
||||
let thread = extools.get_default_thread()?;
|
||||
guard!(let Some(frame) = thread.call_stack.get(frameId as usize) else {
|
||||
return Err(Box::new(GenericError("Stack frame out of range")));
|
||||
let frame_id = frameId as usize;
|
||||
|
||||
let threads = extools.get_all_threads();
|
||||
let thread_id = (frame_id % threads.len()) as i64;
|
||||
let frame_no = frame_id / threads.len();
|
||||
|
||||
guard!(let Some(frame) = threads[&thread_id].call_stack.get(frame_no) else {
|
||||
return Err(Box::new(GenericError2(format!("Stack frame out of range: {} (thread {}, depth {})", frameId, thread_id, frame_no))));
|
||||
});
|
||||
|
||||
ScopesResponse {
|
||||
|
|
@ -674,12 +679,11 @@ handle_request! {
|
|||
}
|
||||
|
||||
// Stack frame, arguments or locals
|
||||
let frame_idx = (params.variablesReference - 1) / 2;
|
||||
let frame_id = (params.variablesReference - 1) / 2;
|
||||
let mod2 = params.variablesReference % 2;
|
||||
|
||||
// TODO: variablesReference should be different based on thread ID
|
||||
let thread = extools.get_default_thread()?;
|
||||
guard!(let Some(frame) = thread.call_stack.get(frame_idx as usize) else {
|
||||
let (thread, frame_no) = extools.get_thread_by_frame_id(frame_id)?;
|
||||
guard!(let Some(frame) = thread.call_stack.get(frame_no) else {
|
||||
return Err(Box::new(GenericError("Stack frame out of range")));
|
||||
});
|
||||
|
||||
|
|
@ -944,6 +948,19 @@ impl std::fmt::Display for GenericError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GenericError2(String);
|
||||
|
||||
impl Error for GenericError2 {
|
||||
fn description(&self) -> &str { &self.0 }
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GenericError2 {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation-specific DAP extensions.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue