C语言中的Ptrace:void*addr指的是什么



我正在使用C语言中的ptrace系统调用:

long ptrace(enum __ptrace_request requête, pid_t pid, void *addr, void *data);

但我不知道void*addr指的是什么…

在这个例子中,我想得到RIP中的当前指令的地址:

unsigned long ip = ptrace(PTRACE_PEEKUSER, child, 8 * RIP, NULL);

child指的是子进程的PID,我不明白为什么我们需要将RIP乘以8,以及为什么RIP被用作整数常数(在<sys/reg.h>中定义为16(

16*8=128是一个整数常数:它是有效的(void*addr(吗?

ptrace()实际上是手册中所述的可变函数:

尽管ptrace((的参数是根据给定原型,glibc当前将ptrace((声明为变量只固定了请求参数的函数。建议使用始终提供四个参数,即使请求的操作不使用它们,将未使用/忽略的参数设置为0L或(无效*(0。

因此,根据请求(第一个参数(,以下参数将被相应地解释为函数实际上应该被视为类似long ptrace(enum __ptrace_request request, ...);的东西。

在GLIBC的源代码中,它在sysdeps/unix/sysv/linux/prace.c:中定义如下

long int
ptrace (enum __ptrace_request request, ...)
{
long int res, ret;
va_list ap;
pid_t pid;
void *addr, *data;
va_start (ap, request);
pid = va_arg (ap, pid_t);
addr = va_arg (ap, void *);
data = va_arg (ap, void *);
va_end (ap);
if (request > 0 && request < 4)
data = &ret;
res = INLINE_SYSCALL (ptrace, 4, request, pid, addr, data);
if (res >= 0 && request > 0 && request < 4)
{
__set_errno (0);
return ret;
}
return res;
}

在前面的文章中,您可以看到它是一个variadic函数,它使用va_arg()来获得一个pid,然后再将两个void*传递给实际的ptrace()系统调用
关于8 * RIP乘法,在头文件(</sys/reg.h>(中说RIP常量是8字节长的数组中的索引。因此乘法:

#ifdef __x86_64__
/* Index into an array of 8 byte longs returned from ptrace for
location of the users' stored general purpose registers.  */
# define R15    0
# define R14    1
# define R13    2
# define R12    3
# define RBP    4
# define RBX    5
# define R11    6
# define R10    7
# define R9 8
# define R8 9
# define RAX    10
# define RCX    11
# define RDX    12
# define RSI    13
# define RDI    14
# define ORIG_RAX 15
# define RIP    16
[...]

最新更新