You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

aarch64架构下如何通过ptrace获取/设置程序寄存器

aarch64架构下ptrace操作寄存器的正确方案

你看到的sys/user.h里的注释,是android-ndk-r10e这个老旧版本工具链的头文件遗留说明,不代表aarch64架构不支持ptrace操作寄存器。32位ARM沿用的传统user结构体体系本来就没有在aarch64上保留,不是你漏找了定义,是aarch64的ptrace寄存器接口换了头文件、结构体和调用方式。

核心操作要点

  • 头文件不需要依赖sys/user.h,直接引入<sys/ptrace.h>、<asm/ptrace.h>和<sys/uio.h>即可,所有寄存器相关的结构体和常量定义都在这几个头文件中。
  • aarch64下对应两类常用寄存器结构体:
    • 通用寄存器组:struct user_pt_regs,包含X0~X30共31个通用寄存器,以及SP、PC、PSTATE(程序状态寄存器),普通断点调试、函数调用参数修改操作这个结构体就足够。
    • 浮点/SIMD寄存器组:struct user_fpsimd_state,包含V0~V31共32个128位向量寄存器,以及FPSR、FPCR浮点状态控制寄存器,需要操作浮点/Neon指令场景才用到。
  • ptrace调用不要用老旧的PTRACE_GETREGS/PTRACE_SETREGS(部分内核做了兼容但不保证跨版本可用),统一用标准的PTRACE_GETREGSET/PTRACE_SETREGSET接口:
    • 操作通用寄存器时,regset类型传NT_PRSTATUS
    • 操作浮点寄存器时,regset类型传NT_FPREGSET
    • 参数通过struct iovec传递寄存器结构体的地址和长度。

最简调用示例

#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdint.h>

void read_aarch64_regs(pid_t tracee_pid) {
    struct user_pt_regs regs;
    struct iovec regs_io = {
        .iov_base = &regs,
        .iov_len = sizeof(regs)
    };

    if (ptrace(PTRACE_GETREGSET, tracee_pid, NT_PRSTATUS, &regs_io) == -1) {
        perror("ptrace get regs failed");
        return;
    }

    // 读取寄存器示例:打印X0和PC值
    printf("X0 = 0x%llx, PC = 0x%llx\n", regs.regs[0], regs.pc);

    // 修改寄存器示例:把X0改成0x1234
    regs.regs[0] = 0x1234;
    ptrace(PTRACE_SETREGSET, tracee_pid, NT_PRSTATUS, &regs_io);
}

针对NDK r10e的特殊说明

r10e是2015年发布的极早版本aarch64 NDK,部分版本的头文件确实缺失struct user_pt_regs的定义,如果不想升级NDK,可以手动按照内核固定布局补全结构体:

struct user_pt_regs {
    uint64_t regs[31]; // X0~X30
    uint64_t sp;
    uint64_t pc;
    uint64_t pstate;
};

这个布局是aarch64内核ABI固定的,不会随版本变化,直接定义即可正常使用。不要尝试用PTRACE_PEEKUSER加偏移的方式读寄存器,aarch64的user区布局没有对外做稳定偏移承诺,不同内核版本可能出现偏移不兼容问题。

内容的提问来源于stack exchange,提问作者Daniel Walker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:18:47