ptrace 系统调用 returns -1 with errno=0

ptrace system call returns -1 with errno=0

我正在尝试使用 ptrace 做一些非常基本的事情,但我的行为非常奇怪。

unsigned long start=strtoul(start_text,NULL,16);

long start_data; 
 if ((start_data = ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL))<0){
      free_memory(vars,registers,size);
      exit(1);
}
    

start_text是一个字符串到另一个程序中有效的地方,start的值是正确的,child_pid的值也是正确的。

出于某种原因,对于 start 的某些值,调用工作正常,但对于某些值则失败。

我试图了解导致这种情况的原因,所以我写了这篇文章:

ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL);
printf("%d",errno);

errno 每次都是 0。

任何人都可以解释导致问题的原因吗?

来自 Linux 的 ptrace 手册页:

Since the value returned by a successful PTRACE_PEEK* request may be -1, the caller must clear errno before the call, and then check it afterward to determine whether or not an error occurred.

也就是说,您正在读取的值可能恰好是 -1,或者在您的情况下,是其他一些负数(即设置了高位的 64 位值) .

因此,与大多数其他系统调用函数不同,您不能通过测试返回值是否为负来检查是否成功。你应该改为

errno = 0;
start_data = ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL));
if (errno != 0) {
    // handle error
}

请注意首先设置 errno = 0 的重要性。与其他系统调用一样,如果 ptrace 成功,它可能会使 errno 的值保持不变 。因此,除非您首先清除 errno,否则您将无法判断之后的非零值是否表示 ptrace 失败,或者 ptrace 是否成功并且该值是以前的一些遗留的调用失败。

(我的手册页版本表明 ptrace 库包装器实际上可能会在成功时将 errno 设置为零,但没有明确说明具体时间,所以最好不要依赖于这种行为。)