-
-
Android使用perf_event实现硬断点
-
2024-2-15 21:14
3614
-
背景
在Android中,目前有一下几种方式实现硬件断点。
- GDB Server
- rwProcMem33等此类内核模块
但是这些方式都有一些问题,比如GDB Server需要使用ptrace
附加在目标进程,容易被检测。rwProcMem33等内核模块需要内核头文件,不开源内核难以使用,此外触发一次断点后会导致整个线程卡死,直到断点删除。
使用linux perf_event
机制实现硬件断点可以在不附加在目标进程、不安装内核模块的情况下下断,同时也无法被目标进程检测。
该方法支持读、写、执行断点,可以读写断点设置1、4、8字节长度。断点后可以输出此时的寄存器信息。
项目地址: ri-char/pwatch
原理
使用perf_event_open
系统调用,设置断点类型为PERF_TYPE_BREAKPOINT
。sample_type
为PERF_SAMPLE_REGS_USER
,可以采样寄存器信息。
将断点信息填入结构体后使用perf_event_open
创建perf_event
,返回一个fd
。使用mmap
打开该fd可以得到断点出发后的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | let mut attrs = sys::bindings::perf_event_attr:: default ();
attrs.size = std::mem::size_of::<sys::bindings::perf_event_attr>() as u32;
attrs.type_ = sys::bindings::PERF_TYPE_BREAKPOINT;
attrs.__bindgen_anon_1.sample_period = 1;
attrs.__bindgen_anon_2.wakeup_events = 1;
attrs.bp_type = r#type;
attrs.__bindgen_anon_3.bp_addr = addr;
attrs.__bindgen_anon_4.bp_len = len as u64;
attrs.set_precise_ip(2);
attrs.sample_type = sys::bindings::PERF_SAMPLE_REGS_USER | sys::bindings::PERF_SAMPLE_TID;
attrs.sample_regs_user = arch::SAMPLE_REGS_USER;
sys::perf_event_open(
&mut attrs,
pid,
-1,
-1,
(sys::bindings::PERF_FLAG_FD_CLOEXEC) as u64,
)
|
sample_type
还可以加上PERF_SAMPLE_STACK_USER
,获取用户调用栈信息。
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!