use std::path::{Path, PathBuf};
use std::process::exit;
use coreminer::addr::Addr;
use coreminer::debugger::Debugger;
use coreminer::errors::DebuggerError;
use coreminer::feedback::Feedback;
use coreminer::ui::json::{Input, JsonUI};
use clap::Parser;
use coreminer::feedback::Status;
use coreminer::Word;
use serde::de::Error;
use steckrs::PluginIDOwned;
use tracing::trace;
#[derive(Parser, Debug)]
#[command(
author,
version,
about,
long_about,
help_template = r#"{about-section}
{usage-heading} {usage}
{all-args}{tab}
{name}: v{version}
Authors: {author-with-newline}
"#
)]
struct Args {
#[arg(long)]
example_statuses: bool,
#[arg(long)]
example_feedbacks: bool,
#[arg(short, long)]
quiet: bool,
#[arg(long)]
logfile: Option<PathBuf>,
}
fn main() -> Result<(), DebuggerError> {
let args = Args::parse();
if !args.quiet {
setup(args.logfile);
}
if args.example_statuses {
example_statuses();
}
if args.example_feedbacks {
example_feedbacks();
}
if args.example_feedbacks || args.example_statuses {
exit(0);
}
let ui = JsonUI::build()?;
let mut debug: Debugger<_> = Debugger::build(ui)?;
debug.run_debugger()?;
debug.cleanup()?;
Ok(())
}
fn example_statuses() {
let statuses: &[Status] = &[
Status::StepOut,
Status::DebuggerQuit,
Status::Continue,
Status::ProcMap,
#[cfg(feature = "plugins")]
Status::PluginSetEnable(PluginIDOwned::from("foobar"), true),
#[cfg(feature = "plugins")]
Status::PluginGetStatus(PluginIDOwned::from("foobar")),
Status::SetBreakpoint(Addr::from(21958295usize)),
Status::SetRegister(coreminer::Register::r9, 133719),
Status::DumpRegisters,
Status::Backtrace,
Status::WriteMem(Addr::from(9218098521usize), 0xff),
Status::ReadMem(Addr::from(9218098521usize)),
Status::Run(
Path::new("/bin/ls").into(),
vec![c"/etc".into(), c"-la".into()],
),
Status::GetSymbolsByName("main".to_string()),
Status::DisassembleAt(Addr::from(1337139usize), 50, false),
];
for s in statuses {
println!(
"{}",
serde_json::to_string(&Input { status: s.clone() }).unwrap()
)
}
}
fn example_feedbacks() {
let feedbacks: &[Feedback] = &[
Feedback::Ok,
Feedback::Word(921589215 as Word),
Feedback::Word(Word::MAX),
Feedback::Word(Word::MIN),
Feedback::Variable(coreminer::variable::VariableValue::Bytes(vec![
19, 13, 13, 13, 17,
])),
Feedback::Error(DebuggerError::BreakpointIsAlreadyEnabled),
Feedback::Error(DebuggerError::UnimplementedRegister(1337)),
Feedback::Error(DebuggerError::Json(serde_json::Error::custom("test err"))),
#[cfg(feature = "plugins")]
Feedback::PluginStatus(Some(false)),
];
for f in feedbacks {
println!(
"{}",
serde_json::to_string(&JsonUI::format_feedback(f).unwrap()).unwrap()
)
}
}
fn setup(logfile: Option<PathBuf>) {
human_panic::setup_panic!();
if let Some(lf) = logfile {
let file = match std::fs::File::options().create(true).append(true).open(lf) {
Ok(f) => f,
Err(e) => {
eprintln!("could not setup logfile: {e}");
std::process::exit(1);
}
};
let subscriber = tracing_subscriber::fmt()
.with_max_level(
#[cfg(debug_assertions)]
tracing::Level::TRACE,
#[cfg(not(debug_assertions))]
tracing::Level::INFO,
)
.without_time()
.with_file(false)
.with_target(false)
.with_writer(file)
.finish();
tracing::subscriber::set_global_default(subscriber).expect("could not setup logger");
} else {
let subscriber = tracing_subscriber::fmt()
.with_max_level(
#[cfg(debug_assertions)]
tracing::Level::TRACE,
#[cfg(not(debug_assertions))]
tracing::Level::INFO,
)
.without_time()
.with_file(false)
.with_target(false)
.with_writer(std::io::stderr)
.finish();
tracing::subscriber::set_global_default(subscriber).expect("could not setup logger");
}
trace!("set up the logger");
}