为什么x86-64 Linux系统调用会修改RCX,值是什么意思?
我正在尝试使用sys_brk
syscall 在Linux中分配一些内存。这是我尝试过的:
BYTES_TO_ALLOCATE equ 0x08section .text
global _start
_start:
mov rax, 12
mov rdi, BYTES_TO_ALLOCATE
syscall
mov rax, 60
syscall
事情是按照linux调用约定,我希望返回值在rax
寄存器中(指向已分配内存的指针)。我在gdb中运行了此文件,并在进行了sys_brk
syscall
后注意到以下寄存器内容
在系统调用之前
rax 0xc 12rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x0 0
rdi 0x8 8
系统调用后
rax 0x401000 4198400rbx 0x0 0
rcx 0x40008c 4194444 ; <---- What does this value mean?
rdx 0x0 0
rsi 0x0 0
rdi 0x8 8
rcx
在这种情况下,我不太了解寄存器中的值。哪个指针可以用作我分配给它的8个字节的开头的指针sys_brk
?
回答:
系统调用返回值rax
始终位于中。请参阅i386和x86-64上的UNIX&Linux系统调用的调用约定是什么]。
注意,sys_brk
其接口与brk
/sbrk
POSIX函数略有不同;请参见Linuxbrk(2)
手册页的C库/内核差异部分。具体来说, ;arg和返回值都是指针。请参阅Assemblyx86brk()调用use。该答案需要投票,因为这是该问题上唯一的好答案。
您问题的另一个有趣的部分是:
在这种情况下,我不太了解rcx寄存器中的值
您正在了解syscall
/
sysret
指令的设计原理,以允许内核恢复用户空间执行,但仍然很快。
syscall
不进行任何加载或存储,仅修改寄存器。与其使用特殊的寄存器来保存返回地址,不如使用常规的整数寄存器。
。唯一的解决办法是,如果系统调用在内核内部修改了该进程的保存或值,则该调用
不起作用
。(是gdb使用的系统调用)。在那种情况下,Linux将使用而不是返回用户空间,因为较慢的一般情况可以做到这一点。(请参阅如果以64位代码使用32位int0x80LinuxABI会发生什么情况?了解Linux系统调用入口点的一些演练。大多数入口点来自32位进程,而不是来自64位进程。一点点的过程。)ptrace``rcx``r11``ptrace``iret``sysret``iret
)syscall
与其将返回地址压入内核堆栈(就像这样int 0x80
做), 不如:
- 设置RCX = RIP,R11 = RFLAGS(因此内核在执行之前甚至无法看到这些reg的原始值
syscall
)。 - 掩模
RFLAGS
从一个配置寄存器中(预先配置的掩模IA32_FMASK
MSR)。这使内核可以禁用中断(IF),直到完成swapgs
并设置rsp
为指向内核堆栈为止。即使cli
作为入口点的第一条指令,也存在一个漏洞窗口。即使cld
掩盖了DF
sorep movs
/ up,您也可以免费获得,stos
即使使用了user spacestd
。
有趣的事实:AMD的第一个提议syscall
/swapgs
设计并未掩盖RFLAGS,但在内核开发人员在amd64邮件列表上](大约在2000年,比第一个芯片问世几年之前)反馈后,他们对其进行了更改。
跳转到配置的
syscall
入口点(设置CS:RIP =IA32_LSTAR
)。CS
我认为,旧值并没有保存在任何地方。它没有做任何其他事情,内核必须使用它
swapgs
来访问保存了内核堆栈指针的信息块,因为它rsp
仍然具有来自用户空间的值。
因此,的设计syscall
需要系统调用ABI来注册,这就是为什么值就是它们的原因。
以上是 为什么x86-64 Linux系统调用会修改RCX,值是什么意思? 的全部内容, 来源链接: utcz.com/qa/421078.html