【问题标题】:Ptrace read errno value in child processPtrace 在子进程中读取 errno 值
【发布时间】:2020-06-23 22:10:10
【问题描述】:

strace 如何从它所跟踪的进程中的失败系统调用中获取 errno?

例如,如果我执行strace ls,strace 会在调用失败时显示符号 errno 值(例如 ENOENT)。我知道 strace 在后台使用 ptrace。

如果我使用 ptrace 来跟踪一个进程的系统调用,我如何才能在被跟踪的进程中读取 errno 的值?

更具体地说,如何获取子进程中errno的地址,以便使用PTRACE_PEEKDATAprocess_vm_readv读取?

谢谢

【问题讨论】:

  • errno is a C concept (以及每个线程变量),而不是系统概念。 errno 中的值是系统调用返回值的否定。这就是为什么 this 读取 RAX 以及为什么 this 设置 RAX(当覆盖系统调用时)。
  • 我看到了我的错误:strace输出表明系统调用返回-1,但我假设rax中也返回了-1,但事实并非如此。我写的程序也正确地表明raxerrno 的否定。谢谢
  • 随时发布答案。我太累了,你显然有可以分享的工作代码:)

标签: c system-calls errno strace ptrace


【解决方案1】:

在系统调用之后,您需要获取寄存器,特别是rax。如果系统调用失败,则rax 的值将是一个大数字,例如0xFFFFFFFFFFFFFFF4errno 是通过否定这个数字来计算的,如下所示:

-0xFFFFFFFFFFFFFFF4 = 0xFFFFFFFFFFFFFFFF - 0xFFFFFFFFFFFFFFF4 + 1 = 0xC = 12

拥有errno 后,您可以在errno.h 中查找它。不同系统上的位置有点不同;如果你找不到它,你可以运行echo "#include <errno.h>" | gcc -E -,它会打印出位置。在此示例中,错误为 ENOMEM

【讨论】: