我正在学习amd64汇编程序,并尝试实现一个简单的Unix过滤器。由于未知的原因,甚至简化为最低版本(下面的代码),它也会随机崩溃。
我试图在GNU调试器(gdb)中调试该程序。在gdb的默认配置中,该程序运行良好,但是如果启用地址随机化(set disable-randomization off),该程序将开始崩溃(SIGSEGV)。清单中标记了有问题的说明:
format ELF64 executable
sys_read = 0
sys_write = 1
sys_exit = 60
entry $
foo:
label .inbuf at rbp - 65536
label .outbuf at .inbuf - 65536
label .endvars at .outbuf
mov rbp, rsp
mov rax, sys_read
mov rdi, 0
lea rsi, [.inbuf]
mov rdx, 65536
syscall
xor ebx, ebx
cmp eax, ebx
jl .read_error
jz .exit
mov r8, rax ; r8 - count of valid bytes in input buffer
xor r9, r9 ; …Run Code Online (Sandbox Code Playgroud) 我试图创建MAP_GROWSDOWN映射,期望它会自动增长。如手册页中所述:
MAP_GROWSDOWN
此标志用于堆栈。它向内核虚拟内存系统指示映射应该在内存中向下扩展。返回地址比在进程的虚拟地址空间中实际创建的内存区域低一页。 触摸映射下方“守卫”页面中的地址会导致 映射增长一页。这种增长可以重复,直到映射增长到下一个较低映射的高端页面内,此时触摸“保护”页面将产生
SIGSEGV信号。
所以我写了下面的例子来测试映射的增长:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdio.h>
int main(void){
char *mapped_ptr = mmap(NULL, 4096,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK | MAP_GROWSDOWN,
-1, 0);
if(mapped_ptr == MAP_FAILED){
int error_code = errno;
fprintf(stderr, "Cannot do MAP_FIXED mapping."
"Error code = %d, details = %s\n", error_code, strerror(error_code));
exit(EXIT_FAILURE);
}
volatile char *c_ptr_1 = mapped_ptr; //address returned by mmap
*c_ptr_1 …Run Code Online (Sandbox Code Playgroud) I'm trying to understand how stack works in Linux. I read AMD64 ABI sections about stack and process initialization and it is not clear how the stack should be mapped. Here is the relevant quote (3.4.1):
Stack State
This section describes the machine state that
exec(BA_OS) creates for new processes.
and
It is unspecified whether the data and stack segments are initially mapped with execute permissions or not. Applications which need to execute code on the stack or data …