c-为什么我在直接编译代码到可执行文件时会得到额外的系统调用,而不是编译到对象文件然后手动链接



我想在Ubuntu上使用GNU C编译器编译这段C代码,而不链接任何标准库,只执行以下代码。

static void exit(long long code)
{asm inline
("movq $60,%%raxn"
"movq %[code],%%rdin"
"syscall"
:
:[code]"rm"(code)
:"rax"
,"rdi");}
static void write(long long fd,char *msg,long long len)
{asm inline
("movq $0x1,%%raxn"
"movq %[fd],%%rdin"
"movq %[msg],%%rsin"
"movq %[len],%%rdxn"
"syscall"
:
:[fd]"rm"(fd)
,[msg]"rm"(msg)
,[len]"rm"(len)
:"rax"
,"rdi"
,"rsi"
,"rdx");}
#define PRINT(msg) write(1,msg,sizeof(msg))
void _start()
{PRINT("Hello World.n");
exit(0);}

我用cc example.c -ffreestanding -nostartfiles -O3 -o example编译。

当我调用输出文件时,我看到了很多使用strace的额外系统调用,这些调用本不应该存在:

  1. brk
  2. arch_prctl
  3. 访问
  4. mmap
  5. arch_prctl
  6. mpprotect

然后我像这样编译:cc example.c -c -O3 -o example.o; ld example.o -o example,它没有执行额外的系统调用。它甚至使文件大小变小了一些。

objdump -d完全相同。在objdump -D中,与第二种情况相比,我在第一种情况下发现了一些额外的符号(_DYNAMIC、__GNU_EH_FRAME_HDR、.inep(,但在代码中仍然没有任何额外系统调用的迹象。

你知道为什么我用cc example.c -ffreestanding -nostartfiles -O3 -o example而不是用cc example.c -c -O3 -o example.o; ld example.o -o example得到额外的系统调用吗?

我发现了发生的事情。

如果我用cc example.c -ffreestanding -nostartfiles -O3 -o example编译代码,编译器会生成一个动态链接的可执行文件。动态链接的可执行文件有一个.interp部分。这就是我在objdump -D中看到的。

动态链接的可执行文件通过程序解释器和动态链接器执行。我看到的其他系统调用来自动态链接器。我仍然不知道为什么可执行文件想要动态链接一个不链接任何库并且想要独立的程序中的任何内容。

如果您不希望动态链接器进行额外的系统调用,那么您应该为gcc提供额外的-static选项。如果没有发生动态链接,编译器不会自动执行此操作。

相关内容

  • 没有找到相关文章

最新更新