Linux 在当前进程中添加观察点(不在gdb中,不用于调试)

Linux 在当前进程中添加观察点(不在gdb中,不用于调试),linux,breakpoints,ptrace,watchpoint,Linux,Breakpoints,Ptrace,Watchpoint,我想知道是否可以在当前进程中添加观察点,以便在读取或写入内存(取决于标志)时调用回调 有一些相关的问题,但它们都是关于使用gdb或其他调试器进行调试的。这不是为了调试,也不是为了跟踪另一个进程。我希望进程本身在自己的地址空间中的内存位置设置一个观察点。通常对于这种情况,我会使用ptrace,但据我从手册页了解(“ptrace()系统调用提供了一种方法,通过这种方法,一个进程(“跟踪器”)可以观察和控制另一个进程的执行(“tracee”),…“--我的重点)它不能用于在当前进程中添加观察点 有没有

我想知道是否可以在当前进程中添加观察点,以便在读取或写入内存(取决于标志)时调用回调

有一些相关的问题,但它们都是关于使用gdb或其他调试器进行调试的。这不是为了调试,也不是为了跟踪另一个进程。我希望进程本身在自己的地址空间中的内存位置设置一个观察点。通常对于这种情况,我会使用ptrace,但据我从手册页了解(“ptrace()系统调用提供了一种方法,通过这种方法,一个进程(“跟踪器”)可以观察和控制另一个进程的执行(“tracee”),…“--我的重点)它不能用于在当前进程中添加观察点


有没有一种不使用ptrace的方法可以做到这一点?或者我可以在当前进程中使用ptrace来执行此操作吗?

监视点通常通过配置嵌入CPU本身的调试功能(即硬件监视点)来工作。 实际上,您将要监视的地址范围加载到特殊寄存器中

每个CPU架构都需要专门的代码。 以下是gdbserver在ARM CPU上设置观察点的操作:

注意,调用
update\u registers\u callback()
-gdbserver必须使用
ptrace
功能来更新tracee上下文中的寄存器。如果您想让进程监视自己,它可以直接访问这些寄存器

以下是您的流程如何注意到自己的观察点被击中: 它接收SIGTRAP信号,详细信息指示观察点。 在gdbserver上下文中,必须再次通过
ptrace
传递通知。在您自己的过程中,您可以直接在SIGTRAP的处理程序中检查信号信息。代码摘录(适用于ARM):

进一步阅读后发现,跟踪器通过
ptrace
访问的硬件断点“寄存器”并不是真正的东西,而是在Linux内核中实现的抽象

其中涉及到一个“hw断点”框架,它从CPU细节中抽象出来。找到以下概述:

虽然这给了人们希望,实际上可以使用进程本身应用的
ptrace()
syscall,以一种相当便携的方式安装硬件监视点,但这并不可行——请参见下文

您需要此
ptrace()
请求代码(通常手册页中没有记录):

进一步试验后:

  • 进程不能
    ptrace()
    自身(权限被拒绝)
  • 一个进程可以调用
    clone()
    ,然后一个线程可以成功地
    ptrace(ptrace\u-jack)
    另一个线程
  • 此时,您还可以使用tracer
    exec()
    gdb进行监视
  • x86和x86_64似乎都没有实现PTRACE_SETHBPREGS(从内核4.15开始)
  • aarch64有,但到目前为止,我只设法提出了一些总线错误
因此,我想可以排除使用
ptrace()
作为以任何便携方式设置硬件监视点的选项

  /* This must be a hardware breakpoint.  */
  if (siginfo.si_signo != SIGTRAP
      || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
    return 0;

  /* If we are in a positive slot then we're looking at a breakpoint and not
     a watchpoint.  */
  if (siginfo.si_errno >= 0)
    return 0;

  /* Cache stopped data address for use by arm_stopped_data_address.  */
  lwp->arch_private->stopped_data_address
    = (CORE_ADDR) (uintptr_t) siginfo.si_addr;
PTRACE_SETHBPREGS