Skip to content

Commit

Permalink
delete watchpoint, redo expr
Browse files Browse the repository at this point in the history
  • Loading branch information
pm100 committed Jan 26, 2024
1 parent adeb274 commit 5afef27
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 125 deletions.
45 changes: 40 additions & 5 deletions src/about.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
=topics

symbols,s - information about symbols, names ,uses..
breakpoint,b - information about break and watch points
traps,t - information about traps (invalid writes, reads..)
watch,w - watchpoints
ccode,c - working with c source code
expressions,ex - expression evaluator
stop - what happens when code execution is interrupted
misc - general points about commands etc

about accepts the long or short topic name ('about s' for symbols)
=symbols,s
Expand Down Expand Up @@ -119,7 +121,14 @@ example
ca65 -g -t sim6502 filetest.s -o filetest.o
ld65 --dbgfile filetest.dbg -t sim6502 filetest.o -o filetest sim6502.lib

then
or

cl65 -t sim6502 -g --ld-args --dbgfile --ld-args argtest.sym argtest.c

note that this does not keep the intermediate .s file. db65 will complain
about that but it does not matter at the moment, no features use the .s files

then

db65 sim6502 debugger 0.2.1 (16024e9)
>> load filetest
Expand Down Expand Up @@ -159,17 +168,31 @@ filetest.c:17 FILE *foo = fopen("foo.txt", "w");
>> p -s buf
yo

Note that globals do not have their names as symbols, they have their
'system' name (toolchain limitation). IE

char buffer[100];

is called '_buffer', not 'buffer'

Static locals are not visible (toolchain limitation)
locals declared within code blocks are not visible (toolchain limitation)

TODO
- no way to use locals in expressions
- no 'nice' change variable command, write byte has to be used
- watch points set on locals will fire when that stack memory is reused

=expression,ex
Expressions can be used anywhere an address is required. Expr command
can be used to test an expression and also to inspect values.
Expressions can be used anywhere an address is required. An expression is
signalled by preceding it with an '=' character.

The 'expr' command can be used to test an expression and also to inspect values.



Examples:
expr =0x20 evaluates to 0x20 (redundant)

expr =.xr the xr register
expr =.xr+1 the xr register plus 1
dis =.pc-6 disassemble from pc-6
Expand All @@ -186,6 +209,7 @@ p -s =@(sreg) print a string pointed to by sreg, sreg+1
Note if there are spaces in the expression, you must quote it:
mem '=@(ptr + 0x20)'
=stop

When execution stops for any reason other than program exit the current
code location is displayed, preceded by the reason for the stop.

Expand All @@ -202,4 +226,15 @@ Commands to resume execution:
TODO
- execute n statments or instructions
- trace, ie execute one line or instruction, report state and then continue
- resume at a different address (doable via changing pc using reg command)
- resume at a different address (doable via changing pc using reg command)

=misc,m
The command line supports command recall using up and down arrows.
Reverse search via ctrl-r

Command history is kept from session to session

When code is running ctrl-c will interrupt it

Hex strings can be entered as 0xff, 0Xff or $ff.

32 changes: 26 additions & 6 deletions src/db/debugdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,41 @@ pub struct SourceFile {
}
pub struct DebugData {
pub conn: Connection,
name: String,
pub cc65_dir: Option<PathBuf>,
}

impl DebugData {
pub fn new() -> Result<DebugData> {
let dbfile = "dbg.db";
if fs::metadata(dbfile).is_ok() {
std::fs::remove_file("dbg.db")?;
pub fn new(name: &str) -> Result<DebugData> {
if fs::metadata(name).is_ok() {
std::fs::remove_file(name)?;
}
let mut ret = Self {
conn: Connection::open("dbg.db")?,
conn: Connection::open(name)?,
cc65_dir: None,
name: name.to_string(),
};
ret.create_tables()?;
Ok(ret)
}

pub fn clear(&mut self) -> Result<()> {
let tx = self.conn.transaction()?;
tx.execute("delete from symdef", [])?;
tx.execute("delete from symref", [])?;
tx.execute("delete from line", [])?;
tx.execute("delete from file", [])?;
tx.execute("delete from source", [])?;
tx.execute("delete from source_line", [])?;
tx.execute("delete from segment", [])?;
tx.execute("delete from span", [])?;
tx.execute("delete from scope", [])?;
tx.execute("delete from csymbol", [])?;
tx.execute("delete from module", [])?;
tx.commit()?;

Ok(())
}
fn convert_symbol_type(s: &str) -> SymbolType {
match s {
"lab" => SymbolType::Label,
Expand Down Expand Up @@ -224,7 +243,8 @@ impl DebugData {
let full_path = if let Some(p) = self.find_file(file)? {
p
} else {
bail!("can't find file {}", file.display())
say(&format!("can't find file {}", file.display()));
return Ok(());
};

let fd = File::open(full_path)?;
Expand Down
12 changes: 0 additions & 12 deletions src/debugger/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ static mut THECPU: Cpu = Cpu {
memhits: [(false, 0); 8],
memhitcount: 0,
paracall: false,
tainted_ac: false,
tainted_xr: false,
tainted_yr: false,
tainted_zr: false,
tainted_sr: false,
tainted_sp: false,
};

pub enum MemCheck {
Expand All @@ -61,12 +55,6 @@ pub struct Cpu {
memhits: [(bool, u16); 8], // used for data watches
memhitcount: u8, // entry count in hit array for this instruction
pub paracall: bool, // we just did a pv call
tainted_ac: bool, // the ac is tainted
tainted_xr: bool, // the xr is tainted
tainted_yr: bool, // the yr is tainted
tainted_zr: bool, // the zr is tainted
tainted_sr: bool, // the sr is tainted
tainted_sp: bool, // the sp is tainted
}
bitflags! {
#[derive(Copy, Clone, Default, Debug)]
Expand Down
73 changes: 41 additions & 32 deletions src/debugger/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ the same functionality as the cli shell.

use anyhow::{bail, Result};
use evalexpr::Value;

use std::cell::RefCell;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::{
Expand All @@ -22,7 +24,6 @@ use crate::{
debugger::cpu::{Cpu, ShadowFlags},
debugger::execute::StopReason,
debugger::loader,
expr::DB65Context,
log::say,
};

Expand Down Expand Up @@ -72,8 +73,8 @@ pub struct Symbol {
}
type InterceptFunc = fn(&mut Debugger, bool) -> Result<Option<StopReason>>;
pub struct Debugger {
pub break_points: HashMap<u16, BreakPoint>,
pub(crate) watch_points: HashMap<u16, WatchPoint>,
pub(crate) break_points: BTreeMap<u16, BreakPoint>,
pub(crate) watch_points: BTreeMap<u16, WatchPoint>,
pub(crate) source_info: BTreeMap<u16, SourceInfo>,
pub(crate) current_file: Option<i64>,
pub(crate) next_bp: Option<u16>,
Expand All @@ -87,7 +88,6 @@ pub struct Debugger {
pub(crate) enable_mem_check: bool,
load_name: String,
pub(crate) run_done: bool,
pub(crate) expr_context: DB65Context,
pub(crate) dbgdb: DebugData,
pub(crate) seg_list: Vec<Segment>,
pub(crate) heap_blocks: HashMap<u16, HeapBlock>,
Expand All @@ -97,6 +97,7 @@ pub struct Debugger {
pub(crate) regbank_addr: Option<u16>,
pub(crate) regbank_size: Option<u16>,
pub(crate) ctrlc: Arc<AtomicBool>,
pub(crate) expr_value: RefCell<evalexpr::Value>,
}

pub struct HeapBlock {
Expand Down Expand Up @@ -149,7 +150,6 @@ pub struct StackFrame {
pub struct BreakPoint {
pub(crate) addr: u16,
pub(crate) symbol: String,
pub(crate) number: usize,
pub(crate) temp: bool,
}
#[derive(Debug, Clone)]
Expand All @@ -158,17 +158,18 @@ pub enum WatchType {
Write,
ReadWrite,
}
#[derive(Debug, Clone)]
pub struct WatchPoint {
pub(crate) addr: u16,
pub(crate) symbol: String,
pub(crate) number: usize,
pub(crate) watch: WatchType,
}
impl Debugger {
pub fn new() -> Self {
Cpu::reset();
let s = Self {
break_points: HashMap::new(),
watch_points: HashMap::new(),
break_points: BTreeMap::new(),
watch_points: BTreeMap::new(),
source_info: BTreeMap::new(),
current_file: None,
loader_start: 0,
Expand All @@ -180,8 +181,7 @@ impl Debugger {
next_bp: None,
load_name: String::new(),
run_done: false,
expr_context: DB65Context::new(),
dbgdb: DebugData::new().unwrap(),
dbgdb: DebugData::new(".db65.db").unwrap(),
seg_list: Vec::new(),
source_mode: SourceDebugMode::None,
call_intercepts: HashMap::new(),
Expand All @@ -192,6 +192,7 @@ impl Debugger {
regbank_addr: None,
regbank_size: None,
ctrlc: Arc::new(AtomicBool::new(false)),
expr_value: RefCell::new(Value::Int(0)),
};
let ctrlc = s.ctrlc.clone();
ctrlc::set_handler(move || {
Expand All @@ -203,13 +204,7 @@ impl Debugger {
pub fn delete_breakpoint(&mut self, id_opt: Option<&String>) -> Result<()> {
if let Some(id) = id_opt {
if let Ok(num) = id.parse::<usize>() {
if let Some(find) = self.break_points.iter().find_map(|bp| {
if bp.1.number == num {
Some(*bp.0)
} else {
None
}
}) {
if let Some(find) = self.break_points.iter().map(|e| *e.0).nth(num - 1) {
self.break_points.remove(&find);
}
}
Expand All @@ -219,14 +214,26 @@ impl Debugger {
};
Ok(())
}
pub fn delete_watchpoint(&mut self, id_opt: Option<&String>) -> Result<()> {
if let Some(id) = id_opt {
if let Ok(num) = id.parse::<usize>() {
if let Some(find) = self.watch_points.iter().map(|e| *e.0).nth(num - 1) {
self.watch_points.remove(&find);
}
}
// else lookup symbol?
} else {
self.watch_points.clear();
};
Ok(())
}
pub fn set_break(&mut self, addr_str: &str, temp: bool) -> Result<()> {
let (bp_addr, save_sym) = self.convert_addr(addr_str)?;
self.break_points.insert(
bp_addr,
BreakPoint {
addr: bp_addr,
symbol: save_sym,
number: self.break_points.len() + 1,
temp,
},
);
Expand All @@ -245,7 +252,6 @@ impl Debugger {
WatchPoint {
addr: wp_addr,
symbol: save_sym,
number: self.watch_points.len() + 1,
watch: wt,
},
);
Expand Down Expand Up @@ -316,26 +322,18 @@ impl Debugger {
pub fn load_dbg(&mut self, file: &Path) -> Result<()> {
let fd = File::open(file)?;
let mut reader = BufReader::new(fd);
self.dbgdb.clear()?;
self.dbgdb.parse(&mut reader)?;

self.dbgdb.load_seg_list(&mut self.seg_list)?;
self.dbgdb.load_all_cfiles()?;
self.source_info.clear();
self.dbgdb.load_all_source_files(&mut self.source_info)?;
self.dbgdb
.load_expr_symbols(&mut self.expr_context.symbols)?;

self.load_intercepts()?;
self.init_shadow()?;
self.dbgdb.load_files(&mut self.file_table)?;

// load file lines int expr db
for (x, si) in self.source_info.iter() {
if let Some(name) = self.lookup_file_by_id(si.file_id) {
let str = format!("{}:{}", name.short_name, si.line_no);
self.expr_context.symbols.insert(str, Value::Int(*x as i64));
}
}
let regbank = self.dbgdb.get_symbol("zeropage.regbank")?;
if regbank.len() != 0 {
self.regbank_addr = Some(regbank[0].1);
Expand All @@ -359,7 +357,17 @@ impl Debugger {
let s = self.dbgdb.get_symbols(filter)?;
Ok(s)
}
fn reset(&mut self) {
self.stack_frames.clear();
self.heap_blocks.clear();
self.run_done = false;
self.next_bp = None;
self.source_mode = SourceDebugMode::None;
self.ticks = 0;
Cpu::reset();
}
pub fn load_code(&mut self, file: &Path) -> Result<(u16, u16)> {
self.reset();
let (sp65_addr, run, _cpu, size) = loader::load_code(file)?;
// println!("size={:x}, entry={:x}, cpu={}", size, run, cpu);
Cpu::sp65_addr(sp65_addr);
Expand All @@ -380,12 +388,13 @@ impl Debugger {

Ok((size, run))
}
pub fn get_breaks(&self) -> Vec<u16> {
self.break_points.iter().map(|bp| bp.1.addr).collect()
pub fn get_breaks(&self) -> Result<&BTreeMap<u16, BreakPoint>> {
Ok(&self.break_points)
}
pub fn get_watches(&self) -> Vec<u16> {
self.watch_points.iter().map(|wp| wp.1.addr).collect()
pub fn get_watches(&self) -> Result<&BTreeMap<u16, WatchPoint>> {
Ok(&self.watch_points)
}

pub fn go(&mut self) -> Result<StopReason> {
if !self.run_done {
self.run(vec![])
Expand Down
Loading

0 comments on commit 5afef27

Please sign in to comment.