在x86-64 System V ABI中,指定后面的空间$rsp - 128
是所谓的红色区域,任何信号处理程序都不会触及。在我的机器上
$ ulimit -s
8192
我预计堆栈中只有 2 页。所以我写了下面的程序来测试红色区域可以扩大到多大:
PAGE_SIZE equ 0x1000
SYS_exit equ 0x3C
section .text
global _start
_start:
lea rcx, [rsp - 0x1f * PAGE_SIZE]
mov rax, rsp
loop:
sub rax, PAGE_SIZE
mov qword [rax], -1
cmp rax, rcx
jne loop
mov rax, SYS_exit
mov rdi, 0x20
所以我预计程序总是失败。但是程序有时会失败SEGV
,有时会很好地完成。
MAP_GROWSDOWN
该行为与文档完全相同:
该标志用于堆栈。它向内核虚拟内存系统指示映射应该在内存中向下扩展。返回地址比进程的虚拟地址空间中实际创建的内存区域低一页。触摸映射下方“保护”页面中的地址将导致映射增长一页。这种增长可以重复,直到映射增长到下一个较低映射的高端页面内,此时触摸“保护”页面将产生
SIGSEGV
信号。
正如在这个问题中所讨论的,映射是用这种方式创建的MAP_GROWSDOWN
并且PROT_GROWSDOWN
不会以这种方式增长:
volatile char *mapped_ptr = mmap(NULL, 4096,
PROT_READ | PROT_WRITE | PROT_GROWSDOWN,
MAP_GROWSDOWN | MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
mapped_ptr[4095] = 'a'; //OK!
mapped_ptr[0] = 'b'; //OK!
mapped_ptr[-1] = 'c'; //SEGV
问题:结合上面的推理,唯一使用MAP_GROWSDOWN
是否是主线程的[stack]
映射?