[英]Getting/setting registers for arm32 executable on aarch64
我的目标是使用ptrace
设置在 64 位处理器上运行 32 位 ARM 可执行文件的进程的程序计数器(和其他寄存器)。
如果这是一个 64 位的可执行文件,那么我可以使用struct user_pt_regs
的pc
字段(在 asm/ptrace.h 中定义)。
对于 32 位可执行文件,我将使用哪种结构? 我看到struct user_regs
(在 sys/user.h 中)定义为
struct user_regs {
unsigned long uregs[18];
};
我阅读了这个问题的答案(尽管作者承认这是一个有根据的猜测),这表明使用struct user_regs
中的uregs[15]
。 但是,由于我实际上有一个 64 位系统,这仍然适用于我的情况吗?
即使在 64 位处理器上运行时, ptrace
也会返回有效的 32 位寄存器。 为了确认这一点,请考虑以下两个可执行文件(为简洁起见,我省略了头文件):
测试.c
int main()
{
printf("PID = %li\n", (long)getpid());
pause();
return 0;
}
附件.c
int main(int argc, char **argv)
{
int ret = 1;
unsigned int expected_size;
pid_t pid;
struct {
uint32_t r[18];
} regs;
struct iovec iov;
if ( argc < 2 ) {
return 1;
}
pid = atoi(argv[1]); // Yes, I know I should use strtol. However, this suffices for this example.
if ( ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 ) {
perror("ptrace (ATTACH)");
return 1;
}
iov.iov_base = ®s;
iov.iov_len = expected_size = sizeof(regs);
if ( ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) != 0 ) {
perror("perror (GETREGSET)");
goto done;
}
if ( iov.iov_len != expected_size ) {
fprintf(stderr, "Unexpected size (%zu instead of %u)\n", iov.iov_len, expected_size);
goto done;
}
printf("PC is 0x%x\n", regs.r[15]);
ret = 0;
done:
if ( ptrace(PTRACE_DETACH, pid, NULL, NULL) != 0 ) {
perror("ptrace (DETACH)");
ret = 1;
}
ret = 1;
}
我将第一个编译成 32 位可执行文件,第二个编译成 64 位可执行文件。
从附加程序获取输出,我在/proc/<pid>/maps
中查找地址,发现它位于 libc 的可执行部分(对应于pause
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.