首页
社区
课程
招聘
[原创]复习arm64指令架构上通过ptrace安装硬件断点的源码流程
发表于: 2025-8-11 11:08 3094

[原创]复习arm64指令架构上通过ptrace安装硬件断点的源码流程

2025-8-11 11:08
3094

前些天有些讨论提到了安装硬件断点的相关操作,会出现用户进程出错退出的情况,所以这里从源码里复习一下怎么在arm64机器上注册硬件断点。

用户态空间安装硬件断点最常使用的是PTRACE_SETREGSET,指定寄存器集合为NT_ARM_HW_BREAK的一系列读写,从源码kernel/ptrace.c中可以观察到,实际PTRACE_SETREGSET时候只是调用到了跨平台写法
ptrace_regset

其中task_user_regset_view会返回架构相关信息。这里内部使用的是arch/arm64/ptrace.c中定义的user_aarch64_view,内含aarch64_regsets

其中对dbg系列寄存器定义了hw_break_get/hw_break_set来注册断点回调,核心调用流程为

ptrace_hbp_set_addr

ptrace_hbp_set_ctrl

那么这样一个硬件断点在ptrace的流程中就安装完成了,实际用户进程触发时便会自动调用ptrace_hbptriggered处理信号,接下来看这个回调怎么触发

ptrace_hbptriggered回调的起始与完结点:

可以看到ptrace这套接口其实很方便地把指令集中的同步异常转化为了被trace进程中的信号,被tracer异步唤醒处理。挺优雅的,具备很强的跨平台通用性,就是整体效率上不算很高。如果直接在处理同步异常时刻不挂起信号,而是直接进入到同线程用户态或内核态的handler处理动作,可以有更好的效率。

目前为了解决这个handler的灵活度可以用内核lua接口绑定常用的寄存器读取与内核读取的c接口来实现,感兴趣的朋友可以关注更新。

const struct user_regset_view *view = task_user_regset_view(task);
const struct user_regset *regset = find_regset(view, type);
const struct user_regset_view *view = task_user_regset_view(task);
const struct user_regset *regset = find_regset(view, type);
1
2
const struct user_regset_view *view = task_user_regset_view(task);
const struct user_regset *regset = find_regset(view, type);
  • ptrace_hbp_get_initialised_bp
    • ptrace_hbp_create
      • ptrace_breakpoint_init新建断点结构体
      • register_user_hw_breakpoint hw_breadkpoint.h 注册断点事件,包含回调ptrace_hbptriggered
      • ptrace_hbp_set_event写入线程的调试寄存器
        • tsk->thread.debug.hbp_break[idx] = bp;
        • tsk->thread.debug.hbp_watch[idx] = bp;
  • modify_user_hw_breakpoint in hw_breadkpoint.h控制修改断点信息
  • ptrace_hbp_create
    • ptrace_breakpoint_init新建断点结构体
    • register_user_hw_breakpoint hw_breadkpoint.h 注册断点事件,包含回调ptrace_hbptriggered
    • ptrace_hbp_set_event写入线程的调试寄存器
      • tsk->thread.debug.hbp_break[idx] = bp;
      • tsk->thread.debug.hbp_watch[idx] = bp;
  • ptrace_breakpoint_init新建断点结构体
  • register_user_hw_breakpoint hw_breadkpoint.h 注册断点事件,包含回调ptrace_hbptriggered
  • ptrace_hbp_set_event写入线程的调试寄存器
    • tsk->thread.debug.hbp_break[idx] = bp;
    • tsk->thread.debug.hbp_watch[idx] = bp;
  • tsk->thread.debug.hbp_break[idx] = bp;
  • tsk->thread.debug.hbp_watch[idx] = bp;
  • 写入dbg控制寄存器
  • 由执行指令(breakpoint)或访问内存(watchpoint)踩到硬件断点异常入口点位于中断处理入口entry.S el0_dbg位置,也即用户态调试异常,调用流程为
    • do_debug_exception,
      • 关键1.fault信息的获取位置const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
      • 关键2.fault回调函数的入口if (!inf->fn(addr_if_watchpoint, esr, regs)) 这个在arch/arm64/hw_breakpoint.c中被hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP,TRAP_HWBKPT, "hw-breakpoint handler");设置为了使用breakpoint_handler处理
        • perf_bp_event(bp, regs)为调用回调的perf事件入口点
          • 兜兜转转会到达__perf_event_overflow(event, throttle, data, regs))核心调用
            • READ_ONCE(event->overflow_handler)(event, data, regs);=(等效于)=>此处调用到了event->overflow_handler即注册的ptrace_hbptriggered函数,其中唯一的关键是:
              • 为用户态进程安装一个trap信号,以供tracer捕获信息 force_sig_info(SIGTRAP, &info, current); info包含了断点踩踏的地址(void __user *)(bkpt->trigger),作为触发参数。
  • do_debug_exception,
    • 关键1.fault信息的获取位置const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
    • 关键2.fault回调函数的入口if (!inf->fn(addr_if_watchpoint, esr, regs)) 这个在arch/arm64/hw_breakpoint.c中被hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP,TRAP_HWBKPT, "hw-breakpoint handler");设置为了使用breakpoint_handler处理
      • perf_bp_event(bp, regs)为调用回调的perf事件入口点
        • 兜兜转转会到达__perf_event_overflow(event, throttle, data, regs))核心调用
          • READ_ONCE(event->overflow_handler)(event, data, regs);=(等效于)=>此处调用到了event->overflow_handler即注册的ptrace_hbptriggered函数,其中唯一的关键是:
            • 为用户态进程安装一个trap信号,以供tracer捕获信息 force_sig_info(SIGTRAP, &info, current); info包含了断点踩踏的地址(void __user *)(bkpt->trigger),作为触发参数。
  • 关键1.fault信息的获取位置const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
  • 关键2.fault回调函数的入口if (!inf->fn(addr_if_watchpoint, esr, regs)) 这个在arch/arm64/hw_breakpoint.c中被hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP,TRAP_HWBKPT, "hw-breakpoint handler");设置为了使用breakpoint_handler处理
    • perf_bp_event(bp, regs)为调用回调的perf事件入口点
      • 兜兜转转会到达__perf_event_overflow(event, throttle, data, regs))核心调用
        • READ_ONCE(event->overflow_handler)(event, data, regs);=(等效于)=>此处调用到了event->overflow_handler即注册的ptrace_hbptriggered函数,其中唯一的关键是:
          • 为用户态进程安装一个trap信号,以供tracer捕获信息 force_sig_info(SIGTRAP, &info, current); info包含了断点踩踏的地址(void __user *)(bkpt->trigger),作为触发参数。
  • perf_bp_event(bp, regs)为调用回调的perf事件入口点
    • 兜兜转转会到达__perf_event_overflow(event, throttle, data, regs))核心调用
      • READ_ONCE(event->overflow_handler)(event, data, regs);=(等效于)=>此处调用到了event->overflow_handler即注册的ptrace_hbptriggered函数,其中唯一的关键是:
        • 为用户态进程安装一个trap信号,以供tracer捕获信息 force_sig_info(SIGTRAP, &info, current); info包含了断点踩踏的地址(void __user *)(bkpt->trigger),作为触发参数。

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 81
支持
分享
最新回复 (35)
雪    币: 204
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
牛逼
2025-8-11 14:29
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2025-8-11 22:01
0
雪    币: 3095
活跃值: (3999)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
过来瞧瞧
2025-8-12 01:21
0
雪    币: 11
活跃值: (720)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享
2025-8-12 08:41
0
雪    币: 2687
活跃值: (5490)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6

分享一张很久之前记录硬断调用的流程图

2025-8-12 12:00
0
雪    币: 280
活跃值: (595)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
zhuzhu_biu 分享一张很久之前记录硬断调用的流程图
图好糊。有无高清大图?
2025-8-12 12:04
0
雪    币: 104
活跃值: (665)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
zhuzhu_biu 分享一张很久之前记录硬断调用的流程图
你这个也太糊了不过看几个关键节点应该总结蛮好的
2025-8-12 13:01
0
雪    币: 2687
活跃值: (5490)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
sk97 图好糊。有无高清大图?

看雪压缩了,我没注意

最后于 2025-8-13 12:03 被zhuzhu_biu编辑 ,原因:
上传的附件:
2025-8-13 12:03
1
雪    币: 104
活跃值: (665)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
zhuzhu_biu sk97 图好糊。有无高清大图? 看雪压缩了,我没注意
赞,挺全面了
2025-8-13 14:38
0
雪    币: 18
活跃值: (1372)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习学习
2025-8-14 10:13
0
雪    币: 23
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
1
2025-8-16 20:07
0
雪    币: 153
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
6666
2025-8-16 21:39
0
雪    币: 20
活跃值: (1410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
6666
2025-8-17 03:53
0
雪    币: 29
活跃值: (1729)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
66666666666
2025-8-17 08:55
0
雪    币: 5630
活跃值: (3944)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
666
2025-8-18 09:26
0
雪    币: 3320
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
看看
2025-8-18 10:33
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
6666666666666666666
2025-8-18 14:54
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
666
2025-8-19 17:37
0
雪    币: 764
活跃值: (2967)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
1
2025-8-19 22:16
0
雪    币: 155
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
1
2025-8-20 01:57
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
круто
2025-8-20 19:01
0
雪    币: 1771
活跃值: (1285)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
23
感谢
2025-9-11 10:49
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
6
2025-9-15 15:11
0
雪    币: 527
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25
6
2025-9-18 12:42
0
游客
登录 | 注册 方可回帖
返回