Add #dis, wait-for-configure, other tweaks to Auxtools (#233)

This fulfils some auxtool debugger requests you had.

1) All connection modes except for `BACKGROUND` wait for the DAP client 
   to be configured before continuing.
2) stddef.dm contents are sent to the debug client
3) disassemble eval command works (with the added benefit of being able 
   to disassemble procs that aren't currently running)

The updated auxtools also does some other stuff you wanted:

1) src/usr moved to arguments
2) your PR https://github.com/willox/auxtools/pull/11
3) arguments with no formal parameter in a proc that is being debugged 
   should show up
This commit is contained in:
William Wallace 2020-12-09 06:34:18 +00:00 committed by GitHub
parent 86899bfd54
commit 00edac18cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 6 deletions

View file

@ -146,6 +146,46 @@ impl Auxtools {
self.stream = StreamState::Disconnected;
}
pub fn configured(&mut self) -> Result<(), Box<dyn std::error::Error>> {
debug_output!(in self.seq, "[auxtools] configured");
self.send_or_disconnect(Request::Configured)?;
match self.read_response_or_disconnect()? {
Response::Ack { .. } => Ok(()),
response => Err(Box::new(UnexpectedResponse::new("Ack", response))),
}
}
pub fn get_stddef(&mut self) -> Result<Option<String>, Box<dyn std::error::Error>> {
self.send_or_disconnect(Request::StdDef)?;
match self.read_response_or_disconnect()? {
Response::StdDef(contents) => Ok(contents),
response => Err(Box::new(UnexpectedResponse::new("StdDef", response))),
}
}
pub fn disassemble(&mut self, path: &str, override_id: u32) -> Result<String, Box<dyn std::error::Error>> {
self.send_or_disconnect(Request::Disassemble(ProcRef {
path: path.to_owned(),
override_id,
}))?;
match self.read_response_or_disconnect()? {
Response::Disassemble(res) => Ok(res),
response => Err(Box::new(UnexpectedResponse::new("Disassemble", response))),
}
}
pub fn get_current_proc(&mut self, frame_id: u32) -> Result<Option<(String, u32)>, Box<dyn std::error::Error>> {
self.send_or_disconnect(Request::CurrentInstruction { frame_id })?;
match self.read_response_or_disconnect()? {
Response::CurrentInstruction(ins) => Ok(ins.map(|x| (x.proc.path, x.proc.override_id))),
response => Err(Box::new(UnexpectedResponse::new("CurrentInstruction", response))),
}
}
pub fn get_line_number(&mut self, path: &str, override_id: u32, offset: u32) -> Result<Option<u32>, Box<dyn std::error::Error>> {
self.send_or_disconnect(Request::LineNumber {
proc: ProcRef {

View file

@ -9,6 +9,12 @@ pub const DEFAULT_PORT: u16 = 2448;
#[derive(Serialize, Deserialize, Debug)]
pub enum Request {
Disconnect,
Configured,
StdDef,
Disassemble(ProcRef),
CurrentInstruction {
frame_id: u32,
},
BreakpointSet {
instruction: InstructionRef,
},
@ -48,6 +54,9 @@ pub enum Request {
#[derive(Serialize, Deserialize, Debug)]
pub enum Response {
Ack,
StdDef(Option<String>),
Disassemble(String),
CurrentInstruction(Option<InstructionRef>),
BreakpointSet {
result: BreakpointSetResult,
},

View file

@ -1,23 +1,31 @@
use regex::Regex;
use lazy_static;
use super::dap_types::*;
use super::*;
const EVALUATE_HELP: &str = "
const EXTOOLS_HELP: &str = "
#dis, #disassemble: show disassembly for current stack frame";
const AUXTOOLS_HELP: &str = "
#dis, #disassemble: show disassembly for current stack frame
#dis, #disassemble <proc path> <override id (optional)>: show disassembly for specified proc";
impl Debugger {
pub fn evaluate(
&mut self,
params: EvaluateArguments,
) -> Result<EvaluateResponse, Box<dyn std::error::Error>> {
let input = params.expression.trim_start();
if input.starts_with("#help") {
return Ok(EvaluateResponse::from(EVALUATE_HELP.trim()));
}
match &mut self.client {
DebugClient::Extools(extools) => {
let extools = extools.get()?;
if input.starts_with("#help") {
return Ok(EvaluateResponse::from(EXTOOLS_HELP.trim()));
}
guard!(let Some(frame_id) = params.frameId else {
return Err(Box::new(GenericError("Must select a stack frame to evaluate in")));
});
@ -36,7 +44,37 @@ impl Debugger {
}
}
DebugClient::Auxtools(_) => {}
DebugClient::Auxtools(auxtools) => {
lazy_static! {
static ref DISASSEMBLE_REGEX: Regex = Regex::new(r"^#dis(?:assemble)? (?P<path>[^ ]+) ?(?P<override>[0-9]*)$").unwrap();
}
if input.starts_with("#help") {
return Ok(EvaluateResponse::from(AUXTOOLS_HELP.trim()));
}
if input == "#dis" || input == "#disassemble" {
guard!(let Some(frame_id) = params.frameId else {
return Err(Box::new(GenericError("Must select a stack frame to evaluate in")));
});
let (path, override_id) = auxtools.get_current_proc(frame_id as u32)?.ok_or_else(|| {
Box::new(GenericError("Couldn't find current proc"))
})?;
return Ok(EvaluateResponse::from(auxtools.disassemble(&path, override_id)?));
}
if let Some(captures) = DISASSEMBLE_REGEX.captures(input) {
let path = &captures["path"];
let override_id = match captures.name("override").map(|x| x.as_str()) {
Some(str) => str.parse::<u32>().unwrap_or(0),
_ => 0,
};
return Ok(EvaluateResponse::from(auxtools.disassemble(path, override_id)?));
}
}
}
Err(Box::new(GenericError("Not yet implemented")))

View file

@ -504,7 +504,10 @@ handle_request! {
extools.configuration_done();
}
DebugClient::Auxtools(_) => {}
DebugClient::Auxtools(auxtools) => {
self.stddef_dm_info = auxtools.get_stddef()?.map(|x| StddefDmInfo::new(x));
auxtools.configured()?;
}
}
}