Mac 程序集:段错误与 libc 退出
Mac assembly: segfault with libc exit
我正在研究 x86_64 macOS 10.12 上的程序集。
我正在尝试调用 libc exit()
函数:
.section __TEXT,__text
.globl _main
_main:
pushq %rbp
movq %rsp, %rbp
movl , %edi
callq _exit
并编译它:
as exit2.s -o exit2.o
ld exit2.o -e _main -lc -o exit
结果是:
Segmentation fault: 11
为什么会这样?
编辑:问题在于链接 libc 和调用约定。
: you crash because you didn't initialize libc. There's probably a NULL pointer somewhere in the data structures that exit(3)
checks before actually exiting. e.g. it flushes stdout
if needed, and it runs any functions registered with atexit(3)
.
如果您不希望它完成所有这些工作,则可以直接使用 syscall
指令进行 sys_exit
系统调用,或者 call
瘦 _exit(2)
它的 libc 包装函数。 (基本情况与 Linux 相同,因为 exit(3)
与 _exit(2)
由 POSIX 标准化:参见 。
我认为 the tutorial you're following 大部分看起来不错,但也许某些旧版本的 OS X 允许在不调用任何 libc init 的情况下使用 libc 函数(包括 printf
?!?)职能。或者他们在编辑构建命令后没有测试他们的代码。 (假设他们进行了测试,也许是动态链接,这会起作用。)
OS X 在汇编中为符号名称添加前缀 _
,因此使用 call __exit
(两个下划线)来调用 _exit()
. (例如 call _printf
调用 C printf
函数)。
_exit(2)
可能 如果你在没有初始化 libc 的情况下调用它就不会崩溃,但是 在没有初始化的情况下调用任何 libc 函数仍然是个坏主意首先调用了 libc init 函数。最好直接进行系统调用(请参阅本教程后面的内容),或者更好的是,使用 gcc hello_asm.S -o hello_asm
构建它以确保 libc 已初始化。然后您可以按照本教程的其余部分进行操作,包括 printf
.
不要在静态可执行文件中调用 Mach-O 入口点 _main
或 main
。 CRT 启动代码还没有运行。通常的约定是称它为进程入口点_start
。
(注意OSX将CRT起始码放在动态链接器中,所以.
如果您使用 gcc exit2.o -o exit
而不是 ld
链接,则 libc 会为您初始化
我正在研究 x86_64 macOS 10.12 上的程序集。
我正在尝试调用 libc exit()
函数:
.section __TEXT,__text
.globl _main
_main:
pushq %rbp
movq %rsp, %rbp
movl , %edi
callq _exit
并编译它:
as exit2.s -o exit2.o
ld exit2.o -e _main -lc -o exit
结果是:
Segmentation fault: 11
为什么会这样?
编辑:问题在于链接 libc 和调用约定。
exit(3)
checks before actually exiting. e.g. it flushes stdout
if needed, and it runs any functions registered with atexit(3)
.
如果您不希望它完成所有这些工作,则可以直接使用 syscall
指令进行 sys_exit
系统调用,或者 call
瘦 _exit(2)
它的 libc 包装函数。 (基本情况与 Linux 相同,因为 exit(3)
与 _exit(2)
由 POSIX 标准化:参见
我认为 the tutorial you're following 大部分看起来不错,但也许某些旧版本的 OS X 允许在不调用任何 libc init 的情况下使用 libc 函数(包括 printf
?!?)职能。或者他们在编辑构建命令后没有测试他们的代码。 (假设他们进行了测试,也许是动态链接,这会起作用。)
OS X 在汇编中为符号名称添加前缀 _
,因此使用 call __exit
(两个下划线)来调用 _exit()
. (例如 call _printf
调用 C printf
函数)。
_exit(2)
可能 如果你在没有初始化 libc 的情况下调用它就不会崩溃,但是 在没有初始化的情况下调用任何 libc 函数仍然是个坏主意首先调用了 libc init 函数。最好直接进行系统调用(请参阅本教程后面的内容),或者更好的是,使用 gcc hello_asm.S -o hello_asm
构建它以确保 libc 已初始化。然后您可以按照本教程的其余部分进行操作,包括 printf
.
不要在静态可执行文件中调用 Mach-O 入口点 _main
或 main
。 CRT 启动代码还没有运行。通常的约定是称它为进程入口点_start
。
(注意OSX将CRT起始码放在动态链接器中,所以
gcc exit2.o -o exit
而不是 ld
链接,则 libc 会为您初始化