【问题标题】:After attaching to process, how to check whether the tracee is in a syscall?附加到进程后,如何检查tracee是否在系统调用中?
【发布时间】:2019-02-02 23:59:31
【问题描述】:

根据the ptrace manual page

Syscall-enter-stop 和 syscall-exit-stop 无法区分 彼此由示踪剂。跟踪器需要跟踪 ptrace-stops 序列,以免误解 syscall-enter- stop 作为 syscall-exit-stop 或反之亦然。

当我使用PTRACE_ATTACH 附加到一个进程时,我如何知道被跟踪者当前是否在系统调用中?换句话说,如果我使用PTRACE_SYSCALL 重新启动tracee,我怎么知道下一个syscall-stop 是syscall-enter-stop 还是syscall-exit-stop

【问题讨论】:

  • 这是个好问题。我一直认为,当跟踪的进程处于系统调用中时,附件不会成功,但我没有任何证据支持这一假设。
  • 我想系统调用进入/退出的报告只会在当前系统调用返回后开始(在附加之后)(如果它是可中断的,很可能会用 EINTR 中断它),所以你总是可以假设第一个系统调用停止是输入。没有验证自己,但很容易检查。

标签: c linux ptrace


【解决方案1】:

当跟踪的进程在系统调用 ENTRY 上停止时,EAX 寄存器将包含 -ENOSYS 并且 orig_rax 具有该系统调用的编号。

以下代码示例演示了一个示例。

if (registers.rax == -ENOSYS)
                { switch (registers.orig_rax)
                        {
                          case _NR_open: //Example
                          break;
                          default:
                    // to get the arguments

                        fprintf(stderr, "%#08x, %#08x, %#08x",
                                registers.rbx, registers.rcx, 
                                                registers.rdx);
                     break;
                     }
              }
              else
              {
                if (registers.rax < 0)
                {
                        // error condition
                        fprintf(stderr, "#Err: %s\n", 
                 errors[abs(registers.rax)]);
                }
                else
                {
                        // return code
                        fprintf(stderr, "%#08x\n", registers.rax);
                }
        }

【讨论】:

    【解决方案2】:

    当我使用 PTRACE_ATTACH 附加到进程时,我如何知道被跟踪者当前是否处于系统调用中?

    当您使用 PTRACE_ATTACH 附加到进程时,会向被跟踪者发送一个 STOP 信号。

    STOP 信号可以在执行用户空间代码时、进入系统调用时、在内核中阻塞“慢”系统调用时以及从系统调用返回用户空间时生效。

    通过检查指令指针和指令指针周围的指令,通常可以确定进程是否正在执行用户空间代码,仅此而已。

    但是,由于停止点本质上是随机的,您可以等待进程停止,然后使用 PTRACE_SINGLESTEP 单步执行每个线程,直到指令指针发生变化。然后你就知道线程正在执行用户空间代码。

    或者,如果单步导致线程长时间阻塞,则意味着线程正在执行一个阻塞的慢系统调用。

    换句话说,如果我使用 PTRACE_SYSCALL 重新启动 tracee,我如何知道下一个 syscall-stop 是 syscall-enter-stop 还是 syscall-exit-stop?

    你不知道,除非你知道被跟踪者停止的状态。正如我上面提到的,您可以通过单步执行代码来做到这一点,直到指令指针发生变化。

    【讨论】:

    【解决方案3】:

    我不相信你可以用ptrace 做到这一点。 ptracetraces,毕竟是显示事件,没办法查看历史(没有被跟踪进程栈的概念)。

    但是,您可以使用 gdb 以相同的方式附加到正在运行的进程。

    $ gdb -p 20334
    ...
    Attaching to process 20334
    ...
    > bt
    

    这将为您提供进程的堆栈跟踪。只要您安装了内核的调试符号,您就可以看到内核函数列表(而不仅仅是“???”)。

    【讨论】:

    • gdb(或一般使用 ptrace 机制的任何东西)不可能知道进程当前在内核中的哪个位置执行 - 它不会通过该机制公开。
    猜你喜欢
    • 1970-01-01
    • 2020-11-04
    • 2010-10-26
    • 2021-09-06
    • 2011-04-19
    • 1970-01-01
    • 2020-01-04
    • 2012-03-28
    • 1970-01-01
    相关资源
    最近更新 更多