Mac程序集:使用libc退出段错误

时间:2018-01-15 21:07:55

标签: c macos assembly x86-64 mach

我正在使用macOS 10.12进入x86_64程序集。

我正在尝试调用libc exit()函数:

.section __TEXT,__text
.globl _main
_main:
    pushq %rbp
    movq %rsp, %rbp
    movl $5, %edi
    callq _exit

用以下代码编译:

as exit2.s -o exit2.o
ld exit2.o -e _main -lc -o exit

结果是:

Segmentation fault: 11

为什么会这样?

编辑:问题在于链接libc和调用约定。

1 个答案:

答案 0 :(得分:1)

@fuz is almost certainly correct因为您没有初始化libc而崩溃。在exit(3)实际退出之前检查的数据结构中某处可能是NULL指针。例如如果需要,它会刷新stdout,并运行使用atexit(3)注册的任何函数。

如果您不希望它完成所有工作,请使用sys_exit指令直接进行syscall系统调用,或call精简_exit(2)它的libc包装函数。 (情况的基础与Linux上的相同,因为exit(3)_exit(2)由POSIX标准化:请参阅Syscall implementation of exit()

我认为the tutorial you're following看起来很好看,但也许某些旧版本的OS X允许在不调用任何libc init函数的情况下使用libc函数(包括printf?!?)。否则,他们在编辑构建命令后没有测试他们的代码。 (假设他们进行了测试,可能是动态链接,这可行。)

OS X会在程序集中使用_作为前缀,因此请使用call __exit (两个下划线)来调用_exit()。 (例如call _printf调用C printf函数。

如果你在没有初始化libc的情况下调用它,那么

_exit(2) 可能会崩溃,但调用任何libc函数仍然是一个坏主意首先调用libc init函数。最好直接进行系统调用(参见教程后面的内容),甚至更好,用gcc hello_asm.S -o hello_asm构建它以确保初始化libc。然后,您可以按照本教程的其余部分进行操作,包括printf

请勿在静态可执行文件中调用Mach-O入口点_mainmain。 CRT启动代码还没有运行。通常的惯例是为进程入口点调用它_start

(请注意,OS X将CRT起始码放在动态链接器中,因此the "entry point" in a dynamically-linked executable is the C main function, unlike in Linux where dynamic executables can avoid the CRT startup code

如果您与gcc exit2.o -o exit而不是ld相关联,则会为您初始化libc,您使用该gcc -static -nostartfiles来执行相当于this.form.get('passwordRepeat').setErrors(null);的操作。)