ctoolbox/utilities/
debug_tools.rs1use anyhow::{Context, Result};
2use std::io::{self, BufRead, Write};
3
4pub fn generate_gdb_instructions_streaming() -> Result<()> {
6 let stdin = io::stdin();
7 let mut stdout = io::stdout();
8 generate_gdb_instructions_from_data(stdin.lock(), &mut stdout)
9}
10
11pub fn generate_gdb_instructions_from_data<R: BufRead, W: Write>(
13 reader: R,
14 writer: &mut W,
15) -> Result<()> {
16 const CHUNK_SIZE: usize = 1000;
17 let mut symbols = Vec::new();
18
19 for line in reader.lines() {
21 let sym = line.context("Failed to read line")?;
22 symbols.push(sym);
23 }
24
25 for sym in symbols {
26 if sym.len() > 200 {
28 continue;
29 }
30 let esc = sym.replace('\\', r"\\").replace('"', r#"\""#);
32 writeln!(writer, "break {esc}")
33 .context("Failed to write breakpoint")?;
34 writeln!(writer, "commands").context("Failed to write commands")?;
35 writeln!(writer, " silent").context("Failed to write silent")?;
36 writeln!(writer, " bt 1").context("Failed to write bt 1")?;
37 writeln!(writer, " continue").context("Failed to write continue")?;
38 writeln!(writer, "end").context("Failed to write end")?;
39 }
40 writer.flush().context("Failed to flush output")?;
41
42 Ok(())
43}
44
45pub fn generate_gdb_instructions(data: Vec<u8>) -> Result<Vec<u8>> {
46 let mut output = Vec::new();
47 generate_gdb_instructions_from_data(&data[..], &mut output)?;
48 Ok(output)
49}
50
51#[cfg(test)]
52#[allow(clippy::unwrap_in_result, clippy::panic_in_result_fn)]
53mod tests {
54
55 use crate::utilities::assert_vec_u8_ok_eq;
56
57 use super::*;
58
59 #[crate::ctb_test]
60 fn test_generate_gdb_instructions() {
61 let input = "<F as core::future::into_future::IntoFuture>::into_future::h952eb23145f23b7d\ntokio::runtime::scheduler::multi_thread::MultiThread::block_on::h9acd86b63968a313\ntokio::runtime::scheduler::multi_thread::MultiThread::block_on::hd8141c28d0d6be82\nbreak core::ptr::drop_in_place<core::array::drain::Drain<(&str,alloc::boxed::Box<[jaq_core::Bind]>,(fn(&jaq_core::compile::Lut<jaq_core::filter::Native<jaq_json::Val>>,(jaq_core::filter::Ctx<jaq_json::Val>,jaq_json::Val)) .> alloc::boxed::Box<dyn core::iter::traits::iterator::Iterator+Item = core::result::Result<jaq_json::Val,jaq_core::exn::Exn<jaq_json::Val>>>,fn(&jaq_core::compile::Lut<jaq_core::filter::Native<jaq_json::Val>>,(jaq_core::filter::Ctx<jaq_json::Val>,jaq_json::Val),alloc::boxed::Box<dyn jaq_core::filter::Update<jaq_json::Val>+Output = alloc::boxed::Box<dyn core::iter::traits::iterator::Iterator+Item = core::result::Result<jaq_json::Val,jaq_core::exn::Exn<jaq_json::Val>>>>) .> alloc::boxed::Box<dyn core::iter::traits::iterator::Iterator+Item = core::result::Result<jaq_json::Val,jaq_core::exn::Exn<jaq_json::Val>>>))>>::h3979d882214be3bc\n<&mut T as core::ops::deref::DerefMut>::deref_mut::h6564409efaf38817\n";
62 let expected_output = "break <F as core::future::into_future::IntoFuture>::into_future::h952eb23145f23b7d\ncommands\n silent\n bt 1\n continue\nend\nbreak tokio::runtime::scheduler::multi_thread::MultiThread::block_on::h9acd86b63968a313\ncommands\n silent\n bt 1\n continue\nend\nbreak tokio::runtime::scheduler::multi_thread::MultiThread::block_on::hd8141c28d0d6be82\ncommands\n silent\n bt 1\n continue\nend\nbreak <&mut T as core::ops::deref::DerefMut>::deref_mut::h6564409efaf38817\ncommands\n silent\n bt 1\n continue\nend\n";
63
64 let output = generate_gdb_instructions(input.as_bytes().to_vec());
65
66 assert_vec_u8_ok_eq(expected_output.as_bytes(), output);
67 }
68}