为什么从 _start 段错误返回?
Why does returning from _start segfault?
我试过不把代码放在main函数里,而是直接放到_start
:
segment .text
global _start
_start:
push rbp
mov rbp, rsp
; ... program logic ...
leave
ret
编译:
yasm -f elf64 main.s
ld -o main main.o
运行:
./main
Segmentation fault(core dumped)
我看完了,离开是
mov esp,ebp
pop ebp
但为什么弹出堆栈帧的这种尾声和指向前一帧基的设置基帧指针会导致分段错误?
确实,进行退出系统调用可以正常退出。
LEAVE
指令被定义为不会导致任何异常,因此它不可能是您的错误来源。你应该使用 GDB。调试器在解决这类问题方面非常有用。
事情是这样的:
$ gdb ./main
[...]
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? ()
(gdb) x /gx $rsp-8
0x7fffffffe650: 0x0000000000000001
所以,很可能你的程序运行完成了,但是堆栈上的第一件事就是0x0000000000000001。 RET
将其弹出到 RIP
寄存器中,然后由于该地址未映射而出现段错误。
我没有在 Linux 上写很多代码,但我敢打赌 _start
是使用退出系统调用所必需的。您可能 return 到有用地址的唯一方法是,如果内核在某处放置一个函数可以为您执行此操作。
根据ABI1,_start
入口处的栈是
没有"return address".
退出进程的唯一方法是通过 SYS_EXIT
xorl %edi, %edi ;Error code
movl , %eax ;SYS_EXIT
syscall
1 部分 3.4.1 初始堆栈和寄存器状态.
我试过不把代码放在main函数里,而是直接放到_start
:
segment .text
global _start
_start:
push rbp
mov rbp, rsp
; ... program logic ...
leave
ret
编译:
yasm -f elf64 main.s
ld -o main main.o
运行:
./main
Segmentation fault(core dumped)
我看完了,离开是
mov esp,ebp
pop ebp
但为什么弹出堆栈帧的这种尾声和指向前一帧基的设置基帧指针会导致分段错误?
确实,进行退出系统调用可以正常退出。
LEAVE
指令被定义为不会导致任何异常,因此它不可能是您的错误来源。你应该使用 GDB。调试器在解决这类问题方面非常有用。
事情是这样的:
$ gdb ./main
[...]
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? ()
(gdb) x /gx $rsp-8
0x7fffffffe650: 0x0000000000000001
所以,很可能你的程序运行完成了,但是堆栈上的第一件事就是0x0000000000000001。 RET
将其弹出到 RIP
寄存器中,然后由于该地址未映射而出现段错误。
我没有在 Linux 上写很多代码,但我敢打赌 _start
是使用退出系统调用所必需的。您可能 return 到有用地址的唯一方法是,如果内核在某处放置一个函数可以为您执行此操作。
根据ABI1,_start
入口处的栈是
没有"return address".
退出进程的唯一方法是通过 SYS_EXIT
xorl %edi, %edi ;Error code
movl , %eax ;SYS_EXIT
syscall
1 部分 3.4.1 初始堆栈和寄存器状态.