From 748974ef2c0e969e95cccc9cb061436d5a1d1b35 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Tue, 29 Oct 2024 14:03:04 +1300 Subject: Load and display symbols in debug information The assembler saves out symbols files, which are loaded automatically by the emulator when present. The name and location of the most recent label is displayed with the debug information when symbols are loaded. --- src/bin/br.rs | 85 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 23 deletions(-) (limited to 'src/bin/br.rs') diff --git a/src/bin/br.rs b/src/bin/br.rs index bf3befe..e96df54 100644 --- a/src/bin/br.rs +++ b/src/bin/br.rs @@ -43,13 +43,18 @@ fn main_run(args: Run) { unsafe { VERBOSE = true; } } - let bytecode = load_bytecode(args.program.as_ref().map(|p| p.as_path())); + let program_path = args.program.as_ref().map(|p| p.as_path()); + let Bytecode { bytes: bytecode, path } = load_bytecode(program_path); + let symbols_path = path.as_ref().map(|p| { + let mut path = p.to_path_buf(); + path.set_extension("br.sym"); + path + }); + let metadata = parse_metadata(&bytecode); if metadata.is_none() { verbose!("Could not read program metadata"); } - // TODO: Load and parse symbols file into debug state, use nearest symbol - // path when debugging. let mut config = EmulatorConfig { dimensions: ScreenDimensions::ZERO, @@ -60,6 +65,7 @@ fn main_run(args: Run) { initial_transmission: None, decode_stdin: args.decode_stdin, encode_stdout: args.encode_stdout, + symbols_path, }; let phosphor = Phosphor::new(); @@ -106,14 +112,18 @@ fn main_run(args: Run) { std::process::exit(0); } -fn load_bytecode(path: Option<&Path>) -> Vec { +fn load_bytecode(path: Option<&Path>) -> Bytecode { // TODO: Etch file location into bytecode. if let Some(path) = path { if let Ok(bytecode) = load_bytecode_from_file(path) { - verbose!("Loaded program from {path:?} ({} bytes)", bytecode.len()); + let length = bytecode.bytes.len(); + let path = bytecode.path(); + verbose!("Loaded program from {path:?} ({length} bytes)"); return bytecode; - } else if let Some((bytecode, path)) = load_bytecode_from_bedrock_path(path) { - verbose!("Loaded program from {path:?} ({} bytes)", bytecode.len()); + } else if let Some(bytecode) = load_bytecode_from_bedrock_path(path) { + let length = bytecode.bytes.len(); + let path = bytecode.path(); + verbose!("Loaded program from {path:?} ({length} bytes)"); return bytecode; } else { eprintln!("Could not read program from {path:?}, exiting"); @@ -122,7 +132,8 @@ fn load_bytecode(path: Option<&Path>) -> Vec { } else { verbose!("Reading program from standard input..."); if let Ok(bytecode) = load_bytecode_from_stdin() { - verbose!("Loaded program from standard input ({} bytes)", bytecode.len()); + let length = bytecode.bytes.len(); + verbose!("Loaded program from standard input ({length} bytes)"); return bytecode; } else { eprintln!("Could not read program from standard input, exiting"); @@ -131,13 +142,8 @@ fn load_bytecode(path: Option<&Path>) -> Vec { } } -/// Attempt to load bytecode from a file path. -fn load_bytecode_from_file(path: &Path) -> Result, std::io::Error> { - load_bytecode_from_readable_source(std::fs::File::open(path)?) -} - /// Attempt to load bytecode from a directory in the BEDROCK_PATH environment variable. -fn load_bytecode_from_bedrock_path(path: &Path) -> Option<(Vec, PathBuf)> { +fn load_bytecode_from_bedrock_path(path: &Path) -> Option { if path.is_relative() && path.components().count() == 1 { for base_path in std::env::var("BEDROCK_PATH").ok()?.split(':') { let mut base_path = PathBuf::from(base_path); @@ -145,29 +151,48 @@ fn load_bytecode_from_bedrock_path(path: &Path) -> Option<(Vec, PathBuf)> { base_path.push(path); verbose!("Attempting to load program from {base_path:?}"); if let Ok(bytecode) = load_bytecode_from_file(&base_path) { - return Some((bytecode, base_path)); + return Some(bytecode); } if path.extension().is_some() { continue; } base_path.set_extension("br"); verbose!("Attempting to load program from {base_path:?}"); if let Ok(bytecode) = load_bytecode_from_file(&base_path) { - return Some((bytecode, base_path)); + return Some(bytecode); } } } return None; } +/// Attempt to load bytecode from a file path. +fn load_bytecode_from_file(path: &Path) -> Result { + load_bytecode_from_readable_source(std::fs::File::open(path)?, Some(path)) +} + /// Attempt to load bytecode from standard input. -fn load_bytecode_from_stdin() -> Result, std::io::Error> { - load_bytecode_from_readable_source(std::io::stdin()) +fn load_bytecode_from_stdin() -> Result { + load_bytecode_from_readable_source(std::io::stdin(), None) } /// Attempt to load bytecode from a source that implements std::io::Read. -fn load_bytecode_from_readable_source(source: impl Read) -> Result, std::io::Error> { - let mut bytecode = Vec::::new(); - source.take(65536).read_to_end(&mut bytecode)?; - return Ok(bytecode); +fn load_bytecode_from_readable_source(source: impl Read, path: Option<&Path>) -> Result { + let mut bytes = Vec::::new(); + source.take(65536).read_to_end(&mut bytes)?; + return Ok(Bytecode { bytes, path: path.map(|p| p.to_path_buf()) }); +} + +struct Bytecode { + bytes: Vec, + path: Option, +} + +impl Bytecode { + fn path(&self) -> String { + match &self.path { + Some(path) => path.as_os_str().to_string_lossy().to_string(), + None => String::from(""), + } + } } @@ -248,7 +273,19 @@ fn main_asm(args: Asm) { // ----------------------------------------------------------------------- // GENERATE symbols file and bytecode let bytecode = generate_bytecode(&mut semantic_tokens); - // let symbols = generate_symbols_file(&semantic_tokens); + + if args.symbols && !args.check { + if let Some(path) = &args.output { + let mut symbols_path = path.to_path_buf(); + symbols_path.set_extension("br.sym"); + let symbols = generate_symbols_file(&semantic_tokens); + if let Err(err) = std::fs::write(&symbols_path, symbols) { + verbose!("Could not write to symbols path {symbols_path:?}: ({err:?})."); + } else { + verbose!("Saved debug symbols to {symbols_path:?}"); + } + } + } let length = bytecode.len(); let percentage = (length as f32 / 65536.0 * 100.0).round() as u16; @@ -361,6 +398,8 @@ xflags::xflags! { optional --check /// Only return resolved source code. optional --resolve + /// Generate debug symbols with file extension '.br.sym' + optional --symbols } } } -- cgit v1.2.3-70-g09d2