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

Intel Pin技术问题:如何获取系统调用的返回地址

获取Intel Pin中系统调用的返回地址

在Intel Pin里,常规函数调用能用IARG_RETURN_IP拿到返回地址,但系统调用的机制不一样——它不是普通的call指令,而是通过syscall(x86-64)或sysenter(32位)这类指令进入内核,返回地址的存储逻辑和普通调用完全不同,所以直接在SyscallExitFunction里读REG_INST_PTR是拿不到用户态的返回地址的(此时这个寄存器指向的是内核态的指令地址,或者已经是返回后的下一条指令,取决于Pin的插桩时机)。

正确的做法是在系统调用入口时保存返回地址,到出口时再取出,具体步骤如下:

1. 准备线程本地存储(TLS)

因为多线程环境下,每个线程的系统调用是独立的,不能用全局变量存返回地址,得用TLS来隔离每个线程的数据:

static TLS_KEY tls_key_return_ip;

在Pin初始化的时候创建这个TLS键:

PIN_InitSymbols();
tls_key_return_ip = PIN_CreateThreadDataKey(NULL);

2. 在系统调用入口保存返回地址

根据不同的CPU架构,系统调用的返回地址存在不同的寄存器里:

  • x86-64(TARGET_IA32E):syscall指令会把当前用户态的RIP存入RCX寄存器
  • 32位(TARGET_IA32):sysenter指令会把返回地址存入EDX寄存器

在SyscallEntryFunction里读取对应寄存器的值,并存入TLS:

VOID SyscallEntry(THREADID tid, CONTEXT* ctx, SYSCALL_STANDARD std, VOID* v) {
    ADDRINT return_ip;

    // 适配不同架构的寄存器
    #ifdef TARGET_IA32
        return_ip = PIN_GetContextReg(ctx, REG_EDX);
    #elif defined(TARGET_IA32E)
        return_ip = PIN_GetContextReg(ctx, REG_RCX);
    #endif

    // 将返回地址存入当前线程的TLS
    PIN_SetThreadData(tls_key_return_ip, (VOID*)return_ip, tid);
}

3. 在系统调用出口取出返回地址

到SyscallExitFunction时,直接从TLS里取出之前保存的地址即可:

VOID SyscallExit(THREADID tid, CONTEXT* ctx, SYSCALL_STANDARD std, VOID* v) {
    // 从TLS中获取当前线程的系统调用返回地址
    ADDRINT return_ip = (ADDRINT)PIN_GetThreadData(tls_key_return_ip, tid);

    // 这里可以对返回地址做任意处理,比如打印、记录等
    printf("系统调用完成,返回地址:0x%lx\n", return_ip);
}

4. 注册插桩函数

最后在主函数里注册这两个插桩函数:

int main(int argc, char* argv[]) {
    if (PIN_Init(argc, argv)) {
        // 这里可以返回自定义的用法提示
        return 1;
    }

    PIN_AddSyscallEntryFunction(SyscallEntry, NULL);
    PIN_AddSyscallExitFunction(SyscallExit, NULL);

    PIN_StartProgram();
    return 0;
}

注意事项

  • 如果需要兼容int 0x80这种老式32位系统调用(SYSCALL_STANDARD_IA32_INT80),返回地址是存在用户栈里的,这时候需要用PIN_GetContextReg(ctx, REG_ESP)拿到栈指针,再读取栈上的对应位置(一般是栈顶的第一个值)。
  • 一定要用TLS,否则多线程同时触发系统调用时,返回地址会被覆盖,导致数据错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:15:34