繁体   English   中英

在 aarch64 上获取/设置 arm32 可执行文件的寄存器

[英]Getting/setting registers for arm32 executable on aarch64

我的目标是使用ptrace设置在 64 位处理器上运行 32 位 ARM 可执行文件的进程的程序计数器(和其他寄存器)。

如果这是一个 64 位的可执行文件,那么我可以使用struct user_pt_regspc字段(在 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 = &regs;
    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM