Add symbol table load command

This commit is contained in:
pjht 2022-10-11 17:26:01 -05:00
parent 7505d172f2
commit 1ecd6083a6
3 changed files with 62 additions and 27 deletions

7
Cargo.lock generated
View File

@ -177,6 +177,12 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "elf"
version = "0.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b9c86cae88373e32c872967c296dcdd3b25771dcc7da1c4ba060b4a68fd8db7"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.2.8" version = "0.2.8"
@ -354,6 +360,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitvec", "bitvec",
"derive-try-from-primitive", "derive-try-from-primitive",
"elf",
"human-repr", "human-repr",
"inventory", "inventory",
"itertools", "itertools",

View File

@ -8,6 +8,7 @@ edition = "2021"
[dependencies] [dependencies]
bitvec = "1.0.0" bitvec = "1.0.0"
derive-try-from-primitive = "1.0.0" derive-try-from-primitive = "1.0.0"
elf = "0.0.12"
human-repr = { version = "1.0.1", features = ["iec", "space"] } human-repr = { version = "1.0.1", features = ["iec", "space"] }
inventory = "0.3.1" inventory = "0.3.1"
itertools = "0.10.5" itertools = "0.10.5"

View File

@ -14,6 +14,7 @@ use crate::{
m68k::{BusError, M68K}, m68k::{BusError, M68K},
}; };
use disas::DisassemblyError; use disas::DisassemblyError;
use elf::types::Symbol;
use itertools::Itertools; use itertools::Itertools;
use parse_int::parse; use parse_int::parse;
use reedline_repl_rs::{ use reedline_repl_rs::{
@ -155,6 +156,11 @@ impl TryFrom<char> for PeekSize {
} }
} }
struct EmuState {
cpu: M68K,
symbols: Vec<Symbol>,
}
fn main() -> Result<(), ReplError> { fn main() -> Result<(), ReplError> {
let config: Mapping = serde_yaml::from_str( let config: Mapping = serde_yaml::from_str(
&fs::read_to_string("config.yaml").expect("Could not read config file"), &fs::read_to_string("config.yaml").expect("Could not read config file"),
@ -178,7 +184,7 @@ fn main() -> Result<(), ReplError> {
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
}; };
} }
Repl::<_, Error>::new(M68K::new(backplane)) Repl::<_, Error>::new(EmuState {cpu: M68K::new(backplane), symbols: Vec::new()})
.with_name("68KEmu") .with_name("68KEmu")
.with_version("0.1.0") .with_version("0.1.0")
.with_banner("68K Backplane Computer Emulator") .with_banner("68K Backplane Computer Emulator")
@ -198,9 +204,9 @@ fn main() -> Result<(), ReplError> {
.takes_value(true), .takes_value(true),
) )
.about("Send a command to a card"), .about("Send a command to a card"),
|args, cpu| { |args, state| {
let num = args.get_one::<String>("num").unwrap().parse::<u8>()?; let num = args.get_one::<String>("num").unwrap().parse::<u8>()?;
cpu.bus_mut() state.cpu.bus_mut()
.cards_mut() .cards_mut()
.get_mut(num as usize) .get_mut(num as usize)
.ok_or(Error::InvalidCard(num))? .ok_or(Error::InvalidCard(num))?
@ -216,10 +222,10 @@ fn main() -> Result<(), ReplError> {
) )
.with_command( .with_command(
Command::new("ls").about("List the cards in the system"), Command::new("ls").about("List the cards in the system"),
|_, cpu| { |_, state| {
#[allow(unstable_name_collisions)] #[allow(unstable_name_collisions)]
Ok(Some( Ok(Some(
cpu.bus_mut() state.cpu.bus_mut()
.cards() .cards()
.iter() .iter()
.enumerate() .enumerate()
@ -231,7 +237,7 @@ fn main() -> Result<(), ReplError> {
) )
.with_command( .with_command(
Command::new("regs").about("Show CPU registers"), Command::new("regs").about("Show CPU registers"),
|_, cpu| Ok(Some(format!("{}", cpu))), |_, state| Ok(Some(format!("{}", state.cpu))),
) )
.with_command( .with_command(
Command::new("step") Command::new("step")
@ -255,22 +261,23 @@ fn main() -> Result<(), ReplError> {
.help("Print ending registers") .help("Print ending registers")
) )
.about("Step the CPU"), .about("Step the CPU"),
|args, cpu| { |args, state| {
let count = let count =
parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?; parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
let mut out = String::new(); let mut out = String::new();
for _ in 0..count { for _ in 0..count {
if cpu.stopped { if state.cpu.stopped {
out += &format!("CPU stopped at PC {:#x}\n", cpu.pc()); out += &format!("CPU stopped at PC {:#x}\n", state.cpu.pc());
break; break;
} }
if args.get_flag("print_ins") { if args.get_flag("print_ins") {
out += &disas_fmt(cpu, cpu.pc()).0; let pc = state.cpu.pc();
out += &disas_fmt(&mut state.cpu, pc).0;
} }
cpu.step(); state.cpu.step();
} }
if args.get_flag("print_regs") { if args.get_flag("print_regs") {
out += &format!("{}\n", cpu); out += &format!("{}\n", state.cpu);
} }
if out.is_empty() { if out.is_empty() {
Ok(None) Ok(None)
@ -295,34 +302,36 @@ fn main() -> Result<(), ReplError> {
.help("Print all executed instructions") .help("Print all executed instructions")
) )
.about("Run the CPU"), .about("Run the CPU"),
|args, cpu| { |args, state| {
let mut out = String::new(); let mut out = String::new();
while !cpu.stopped { while !state.cpu.stopped {
let stop_addr = args let stop_addr = args
.get_one::<String>("stop_addr") .get_one::<String>("stop_addr")
.map(|s| parse::<u32>(s)) .map(|s| parse::<u32>(s))
.transpose()?; .transpose()?;
if stop_addr.map(|a| cpu.pc() == a).unwrap_or(false) { if stop_addr.map(|a| state.cpu.pc() == a).unwrap_or(false) {
break; break;
} }
if args.get_flag("print_ins") { if args.get_flag("print_ins") {
out += &disas_fmt(cpu, cpu.pc()).0; let pc = state.cpu.pc();
out += &disas_fmt(&mut state.cpu, pc).0;
} }
cpu.step(); state.cpu.step();
} }
out += &format!("{}\n", cpu); out += &format!("{}\n", state.cpu);
out += &disas_fmt(cpu, cpu.pc()).0; let pc = state.cpu.pc();
out += &disas_fmt(&mut state.cpu, pc).0;
out.pop(); // Remove trailing newline out.pop(); // Remove trailing newline
Ok(Some(out)) Ok(Some(out))
}, },
) )
.with_command( .with_command(
Command::new("reset").about("Reset the cards and CPU, in that order"), Command::new("reset").about("Reset the cards and CPU, in that order"),
|_, cpu| { |_, state| {
for card in cpu.bus_mut().cards_mut() { for card in state.cpu.bus_mut().cards_mut() {
card.reset(); card.reset();
} }
cpu.reset(); state.cpu.reset();
Ok(None) Ok(None)
}, },
) )
@ -332,7 +341,7 @@ fn main() -> Result<(), ReplError> {
.arg(Arg::new("fmt").short('f').required(true).takes_value(true)) .arg(Arg::new("fmt").short('f').required(true).takes_value(true))
.arg(Arg::new("addr").required(true)) .arg(Arg::new("addr").required(true))
.about("Peek a memory address"), .about("Peek a memory address"),
|args, cpu| { |args, state| {
let fmt_str = args.get_one::<String>("fmt").unwrap(); let fmt_str = args.get_one::<String>("fmt").unwrap();
if fmt_str.len() != 2 { if fmt_str.len() != 2 {
return Err(Error::Misc("Peek format length must be 2")); return Err(Error::Misc("Peek format length must be 2"));
@ -344,7 +353,7 @@ fn main() -> Result<(), ReplError> {
let addr = parse::<u32>(args.get_one::<String>("addr").unwrap())?; let addr = parse::<u32>(args.get_one::<String>("addr").unwrap())?;
let mut data = Vec::new(); let mut data = Vec::new();
let bus = cpu.bus_mut(); let bus = state.cpu.bus_mut();
for i in 0..count { for i in 0..count {
match size { match size {
PeekSize::Byte => data.push(bus.read_byte(addr + i)? as u32), PeekSize::Byte => data.push(bus.read_byte(addr + i)? as u32),
@ -387,15 +396,15 @@ fn main() -> Result<(), ReplError> {
.help("Count of instructions to disassemble. Defaults to 1"), .help("Count of instructions to disassemble. Defaults to 1"),
) )
.about("Disassemble a region of memory"), .about("Disassemble a region of memory"),
|args, cpu| { |args, state| {
let mut addr = args let mut addr = args
.get_one::<String>("addr") .get_one::<String>("addr")
.map_or(Ok(cpu.pc()), |s| parse::<u32>(s))?; .map_or(Ok(state.cpu.pc()), |s| parse::<u32>(s))?;
let count = let count =
parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?; parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
let mut out = String::new(); let mut out = String::new();
for _ in 0..count { for _ in 0..count {
let (fmt, res) = disas_fmt(cpu, addr); let (fmt, res) = disas_fmt(&mut state.cpu, addr);
out += &fmt; out += &fmt;
match res { match res {
Ok(new_addr) => { Ok(new_addr) => {
@ -410,6 +419,24 @@ fn main() -> Result<(), ReplError> {
Ok(Some(out)) Ok(Some(out))
}, },
) )
.with_command(
Command::new("sym")
.arg(
Arg::new("file")
.required(true)
.help("The ELF file to load symbols from"),
)
.about("Load symbols from an ELF file"),
|args, state| {
let file = args
.get_one::<String>("file").unwrap();
let file = elf::File::open_path(file).unwrap();
let symtab = file.get_section(".symtab").ok_or(Error::Misc("Could not find symbol table section"))?;
let symbols = file.get_symbols(symtab).unwrap();
state.symbols = symbols;
Ok(None)
},
)
.with_command(Command::new("quit") .with_command(Command::new("quit")
.visible_alias("q") .visible_alias("q")
.visible_alias("exit") .visible_alias("exit")