【发布时间】:2018-12-29 04:09:48
【问题描述】:
我编写了以下代码来调用 syscall exit 而不与 glibc 链接:
// a.c
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
_Noreturn void _start()
{
register int syscall_num asm ("rax") = __NR_exit;
register int exit_code asm ("rdi") = 0;
// The actual syscall to exit
asm volatile ("syscall"
: /* no output Operands */
: "r" (syscall_num), "r" (exit_code));
}
Makefile:
.PHONY: clean
a.out: a.o
$(CC) -nostartfiles -nostdlib -Wl,--strip-all a.o
a.o: a.c
$(CC) -Oz -c a.c
clean:
rm a.o a.out
我将make 与CC=clang-7 一起使用,它工作得非常好,除了当我检查objdump -d a.out 生成的程序集时:
a.out: file format elf64-x86-64
Disassembly of section .text:
0000000000201000 <.text>:
201000: 6a 3c pushq $0x3c
201002: 58 pop %rax
201003: 31 ff xor %edi,%edi
201005: 0f 05 syscall
201007: c3 retq
在syscall 之后有一个无用的retq。我想知道,有没有办法在不诉诸于在汇编中编写整个函数的情况下删除它?
【问题讨论】:
-
有趣的事实:gcc 已经忽略了
ret只是因为_Noreturn声明。 godbolt.org/z/OLuoUO。但它仍然警告_Noreturn函数返回,即使它忽略了ret。但是,clang 和 ICC 需要__builtin_unreachable,并且还需要警告。顺便说一句,我简化了 asm 语句以使用"a"和"D"约束而不是 register-asm 本地变量。一个"memory"clobber 可以确保在 asm 语句之后没有任何东西可以重新排序,即使这可能已经不可能了。 -
@PeterCordes 我认为值得注意的是,使用 _Noreturn 时,
ret只有在使用 GCC 8.x+ 时才会消失,但在这些版本之前它不会消失。
标签: c assembly inline-assembly noreturn