+-
系统调用如何存储在pt_regs中?
include/asm/ptrace.h:
struct pt_regs {
     long ebx;
     long ecx;
     long edx;
     long esi;
     long edi;
     long ebp;
     long eax;
     int xds;
     int xes;
     long orig_eax;
     long eip;
     int xcs;
     long eflags;
     long esp;
     int xss;
};

我想知道在给定pt_regs结构的情况下我是如何查看/访问系统调用的?

最佳答案
ptrace允许跟踪器运行跟踪程序(tracee),但在每次进入和退出系统调用时自动停止(暂停). ptrace(PTRACE_GETREGS, pid, &regs, &regs)允许跟踪器在进入时获取系统调用的参数,从系统调用退出结果值到结构user_regs_struct regs;在< sys / user.h>中定义头文件. (指定指向它的指针,因为addr和数据指针都避免使用特殊套接字SPARC系统.有关背景信息,请参阅上面的手册页.)

系统调用参数在寄存器中,但它取决于使用哪个寄存器的体系结构.有关详细信息,请参见man 2 syscall.

C库在< sys / user.h>中定义struct user_regs_struct.对于当前安装的架构.对于与体系结构无关的代码,您需要找到一个可以为您抽象细节的库,或者自己编写一个垫片. (这并不困难;只是有15个架构需要支持,并收集每个架构的细节,测试它们,并将它们全部组合到#if defined().. #elif defined().. #else #error …#endif`序列是很多工作,细节是绝对正确的.所以直截了当的努力.)

例如,在i386上,系统调用号(参见/usr/include/bits/syscall.h)位于eax寄存器中,返回值也在eax中.每个系统调用最多可以提供六个参数;从第一个开始,它们存储在ebx,ecx,edx,esi,edi和ebp寄存器中,从左到右依次读取. (Linux内核不支持系统调用的浮点参数,因此基本上所有的syscall参数都被提升为long,这与i386上的指针大小相同.用户空间虚拟内存也是平的,即指针只是简单的32-位地址,不包含段寄存器引用.)

作为一个详细的例子,让我们考虑一下tracee在进入时停止说read syscall的情况. Linux中的这个系统调用使用与POSIX.1 read()函数相同的接口,除了在发生错误时设置errno而不是返回-1,它将返回-errornumber而不是;即-EAGAIN,-EINTR等.

跟踪器通知(通过wait()waitpid())tracee停止,并使用上述ptrace(PTRACE_GETREGS,pid,& regs,& regs)调用获得寄存器.文件描述符在regs.ebx中,指向缓冲区的指针在regs.ecx中,要写入的字节数在regs.edx中.

如果跟踪器继续并等待tracee在所述系统调用的出口处停止,则regs.eax将包含结果值.如果为零,则描述符的另一端已关闭(关闭)连接.如果是正数,则是读取缓冲区的字节数.如果是负数,则将错误编号(将存储在errno中)作为否定. (是的,Linux中的errno值保证是小的正(非零)整数.)

点击查看更多相关文章

转载注明原文:系统调用如何存储在pt_regs中? - 乐贴网