From f5d43e457ed30981de34f9254195873ba7078b05 Mon Sep 17 00:00:00 2001 From: kekeimiku Date: Wed, 5 Jun 2024 13:53:18 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8C=96=E4=B8=80=E7=82=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libptrscan/src/ffi/error.rs | 2 +- libptrscan/src/ffi/ptrscan.rs | 4 +- libptrscan/src/ffi/scan.rs | 463 ++++++++++++++++++---------------- 3 files changed, 242 insertions(+), 227 deletions(-) diff --git a/libptrscan/src/ffi/error.rs b/libptrscan/src/ffi/error.rs index 707718a..a3acd5b 100644 --- a/libptrscan/src/ffi/error.rs +++ b/libptrscan/src/ffi/error.rs @@ -70,7 +70,7 @@ pub unsafe extern "C" fn get_last_error(code: c_int) -> *const c_char { } else if code == CALL_ERROR { // cbindgen 还没支持 c"message" 一类的c字符串... const { - let bytes = concat!("call error", "\0").as_bytes(); + let bytes = concat!("function call error", "\0").as_bytes(); CStr::from_bytes_with_nul_unchecked(bytes).as_ptr() } } else if code == NO_NULL { diff --git a/libptrscan/src/ffi/ptrscan.rs b/libptrscan/src/ffi/ptrscan.rs index e89a7de..d57e7bd 100644 --- a/libptrscan/src/ffi/ptrscan.rs +++ b/libptrscan/src/ffi/ptrscan.rs @@ -200,7 +200,7 @@ pub unsafe extern "C" fn ptrscan_scan_pointer_chain( param: FFIParam, pathname: *const c_char, ) -> c_int { - let FFIParam { addr, depth, srange, lrange, node, last, max, .. } = param; + let FFIParam { addr, depth, srange, lrange, node, last, max, cycle, .. } = param; let range = (srange.left, srange.right); let lrange = lrange.as_ref().copied().map(|r| (r.left, r.right)); @@ -215,7 +215,7 @@ pub unsafe extern "C" fn ptrscan_scan_pointer_chain( #[rustfmt::skip] let param = UserParam { param: Param { depth, addr, srange: range, lrange }, - node, last, max, + node, last, max, cycle }; try_result!(pointer_chain_scan(pointer_map, pathname, param)); diff --git a/libptrscan/src/ffi/scan.rs b/libptrscan/src/ffi/scan.rs index 792e1fe..c3b9dd3 100644 --- a/libptrscan/src/ffi/scan.rs +++ b/libptrscan/src/ffi/scan.rs @@ -15,6 +15,7 @@ pub struct UserParam { pub node: Option, pub last: Option, pub max: Option, + pub cycle: bool, } macro_rules! try_scan { @@ -26,6 +27,32 @@ macro_rules! try_scan { }; } +macro_rules! output_pointer_chain { + ($a:expr, $b:expr, $c:expr, $d:expr $(, $n:expr)?) => {{ + let addr = $a.addr(); + let Some((Range { start, .. }, name)) = $b.get_key_value_by_point(&addr) else { + // 正常永远不会走到这里 + return ControlFlow::Continue(()); + }; + match write!($d, "{name}+{:X}", addr - start) + .and($c.try_for_each(|&o| { + if o >= 0 { + write!($d, ".{o:X}") + } else { + write!($d, ".-{:X}", o.abs()) + } + })) + .and(writeln!($d)) + { + Ok(_) => { + $( $n += 1; )? + ControlFlow::Continue(()) + }, + Err(err) => ControlFlow::Break(Err(err)), + } + }}; +} + pub fn pointer_chain_scan( map: &PointerMap, path: impl AsRef, @@ -35,245 +62,233 @@ pub fn pointer_chain_scan( let mut buffer = BufWriter::with_capacity(0x100000, file); let PointerMap { points, map, modules } = map; - let UserParam { param, node, last, max, .. } = param; - match (node, last, max) { - (None, None, None) => { - let mut f = |chain: Chain| { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); + let UserParam { param, node, last, max, cycle } = param; + if cycle { + match (node, last, max) { + (None, None, None) => { + let mut f = |chain: Chain| match chain.ref_cycle() { + Some(mut iter) => output_pointer_chain!(chain, modules, iter, buffer), + None => output_pointer_chain!(chain, modules, chain.data(), buffer), }; - match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, None, Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + match chain.ref_cycle() { + Some(mut iter) => output_pointer_chain!(chain, modules, iter, buffer, n), + None => output_pointer_chain!(chain, modules, chain.data(), buffer, n), + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, Some(last), None) => { + let mut f = |chain: Chain| { + if chain.last().is_some_and(|o| last.eq(o)) { + match chain.ref_cycle() { + Some(mut iter) => output_pointer_chain!(chain, modules, iter, buffer), + None => output_pointer_chain!(chain, modules, chain.data(), buffer), } - })) - .and(writeln!(buffer)) - { - Ok(_) => ControlFlow::Continue(()), - Err(err) => ControlFlow::Break(Err(err)), - } - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (None, None, Some(max)) => { - let mut n = 0; - let mut f = |chain: Chain| { - if n >= max { - return ControlFlow::Break(Ok(())); - } - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); + } else { + ControlFlow::Continue(()) + } }; - match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, Some(last), Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain.last().is_some_and(|o| last.eq(o)) { + match chain.ref_cycle() { + Some(mut iter) => { + output_pointer_chain!(chain, modules, iter, buffer, n) + } + None => { + output_pointer_chain!(chain, modules, chain.data(), buffer, n) + } } - })) - .and(writeln!(buffer)) - { - Ok(_) => { - n += 1; + } else { ControlFlow::Continue(()) } - Err(err) => ControlFlow::Break(Err(err)), - } - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (None, Some(last), None) => { - let mut f = |chain: Chain| { - if chain.last().is_some_and(|o| last.eq(o)) { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), None, None) => { + let mut f = |chain: Chain| { + if chain.len() >= node { + match chain.ref_cycle() { + Some(mut iter) => output_pointer_chain!(chain, modules, iter, buffer), + None => output_pointer_chain!(chain, modules, chain.data(), buffer), + } + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), None, Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain.len() >= node { + match chain.ref_cycle() { + Some(mut iter) => { + output_pointer_chain!(chain, modules, iter, buffer, n) } - })) - .and(writeln!(buffer)) - { - Ok(_) => ControlFlow::Continue(()), - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (None, Some(last), Some(max)) => { - let mut n = 0; - let mut f = |chain: Chain| { - if n >= max { - return ControlFlow::Break(Ok(())); - } - if chain.last().is_some_and(|o| last.eq(o)) { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) + None => { + output_pointer_chain!(chain, modules, chain.data(), buffer, n) } - })) - .and(writeln!(buffer)) + } + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), Some(last), None) => { + let mut f = |chain: Chain| { + if chain + .last() + .is_some_and(|o| chain.len() >= node && last.eq(o)) { - Ok(_) => { - n += 1; - ControlFlow::Continue(()) + match chain.ref_cycle() { + Some(mut iter) => output_pointer_chain!(chain, modules, iter, buffer), + None => output_pointer_chain!(chain, modules, chain.data(), buffer), } - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (Some(node), None, None) => { - let mut f = |chain: Chain| { - if chain.len() >= node { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) - } - })) - .and(writeln!(buffer)) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), Some(last), Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain + .last() + .is_some_and(|o| chain.len() >= node && last.eq(o)) { - Ok(_) => ControlFlow::Continue(()), - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (Some(node), None, Some(max)) => { - let mut n = 0; - let mut f = |chain: Chain| { - if n >= max { - return ControlFlow::Break(Ok(())); - } - if chain.len() >= node { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) + match chain.ref_cycle() { + Some(mut iter) => { + output_pointer_chain!(chain, modules, iter, buffer, n) + } + None => { + output_pointer_chain!(chain, modules, chain.data(), buffer, n) } - })) - .and(writeln!(buffer)) - { - Ok(_) => { - n += 1; - ControlFlow::Continue(()) } - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } } - (Some(node), Some(last), None) => { - let mut f = |chain: Chain| { - if chain - .last() - .is_some_and(|o| chain.len() >= node && last.eq(o)) - { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) - } - })) - .and(writeln!(buffer)) + } else { + match (node, last, max) { + (None, None, None) => { + let mut f = + |chain: Chain| output_pointer_chain!(chain, modules, chain.data(), buffer); + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, None, Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + output_pointer_chain!(chain, modules, chain.data(), buffer, n) + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, Some(last), None) => { + let mut f = |chain: Chain| { + if chain.last().is_some_and(|o| last.eq(o)) { + output_pointer_chain!(chain, modules, chain.data(), buffer) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (None, Some(last), Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain.last().is_some_and(|o| last.eq(o)) { + output_pointer_chain!(chain, modules, chain.data(), buffer, n) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), None, None) => { + let mut f = |chain: Chain| { + if chain.len() >= node { + output_pointer_chain!(chain, modules, chain.data(), buffer) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), None, Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain.len() >= node { + output_pointer_chain!(chain, modules, chain.data(), buffer, n) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), Some(last), None) => { + let mut f = |chain: Chain| { + if chain + .last() + .is_some_and(|o| chain.len() >= node && last.eq(o)) { - Ok(_) => ControlFlow::Continue(()), - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) - } - (Some(node), Some(last), Some(max)) => { - let mut n = 0; - let mut f = |chain: Chain| { - if n >= max { - return ControlFlow::Break(Ok(())); - } - if chain - .last() - .is_some_and(|o| chain.len() >= node && last.eq(o)) - { - let addr = chain.addr(); - let Some((Range { start, .. }, name)) = modules.get_key_value_by_point(&addr) - else { - return ControlFlow::Continue(()); - }; - return match write!(buffer, "{name}+{:X}", addr - start) - .and(chain.data().try_for_each(|&o| { - if o >= 0 { - write!(buffer, ".{o:X}") - } else { - write!(buffer, ".-{:X}", o.abs()) - } - })) - .and(writeln!(buffer)) + output_pointer_chain!(chain, modules, chain.data(), buffer) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } + (Some(node), Some(last), Some(max)) => { + let mut n = 0; + let mut f = |chain: Chain| { + if n >= max { + return ControlFlow::Break(Ok(())); + } + if chain + .last() + .is_some_and(|o| chain.len() >= node && last.eq(o)) { - Ok(_) => { - n += 1; - ControlFlow::Continue(()) - } - Err(err) => ControlFlow::Break(Err(err)), - }; - } - ControlFlow::Continue(()) - }; - try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + output_pointer_chain!(chain, modules, chain.data(), buffer, n) + } else { + ControlFlow::Continue(()) + } + }; + try_scan!(try_pointer_chain_scan(map, points, param, &mut f)) + } } - }?; - - Ok(()) + } }