为什么在将代码直接编译为可执行文件而不是编译为目标文件然后手动链接时会得到额外的系统调用?
我想在 Ubuntu 上使用 GNU C 编译器编译此 C 代码,而不链接任何标准库,只执行以下代码。
static void exit(long long code)
{asm inline
("movq $60,%%rax\n"
"movq %[code],%%rdi\n"
"syscall"
:
:[code]"rm"(code)
:"rax"
,"rdi");}
static void write(long long fd,char *msg,long long len)
{asm inline
("movq $0x1,%%rax\n"
"movq %[fd],%%rdi\n"
"movq %[msg],%%rsi\n"
"movq %[len],%%rdx\n"
"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 -ffreestand -nostartfiles -O3 -o example 进行编译。
当我调用输出文件时,我看到许多不应该存在的额外系统调用 strace
:
- brk
- arch_prctl
- access
- mmap
- arch_prctl
- mprotect
然后我像这样编译: cc example.c - c -O3 -o 示例.o; ld example.o -o example
并且它没有执行额外的系统调用。它甚至使文件大小变得更小。
它的 objdump -d 完全相同。在 objdump -D 中,与第二种情况相比,我在第一种情况下发现了一些额外的符号(_DYNAMIC,__GNU_EH_FRAME_HDR,.interp),但代码中仍然没有任何额外系统调用的迹象。
你知道为什么我使用 cc example.c -ffreestand -nostartfiles -O3 -o example 得到额外的系统调用,而不是使用 cc example.c -c -O3 -o example.o ; ld example.o -o 示例?
I want to compile this C code with the GNU C Compiler on Ubuntu without linking any standard libraries, having only the following code execute.
static void exit(long long code)
{asm inline
("movq $60,%%rax\n"
"movq %[code],%%rdi\n"
"syscall"
:
:[code]"rm"(code)
:"rax"
,"rdi");}
static void write(long long fd,char *msg,long long len)
{asm inline
("movq $0x1,%%rax\n"
"movq %[fd],%%rdi\n"
"movq %[msg],%%rsi\n"
"movq %[len],%%rdx\n"
"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);}
I compiled with cc example.c -ffreestanding -nostartfiles -O3 -o example
.
When I called the output file I saw a lot of extra system calls with strace
that should not have been there:
- brk
- arch_prctl
- access
- mmap
- arch_prctl
- mprotect
I then compiled like this: cc example.c -c -O3 -o example.o; ld example.o -o example
and it did not do the extra syscalls. It even made the filesize somewhat smaller.
The objdump -d
of it was exactly the same. In the objdump -D
I found some extra symbols (_DYNAMIC,__GNU_EH_FRAME_HDR,.interp) in the first case compared to the second, but still no sign of any extra syscalls in the code.
Do you know why I get the extra system calls with cc example.c -ffreestanding -nostartfiles -O3 -o example
and not with cc example.c -c -O3 -o example.o; ld example.o -o example
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我知道发生了什么事。
如果我使用 cc example.c -ffreestand -nostartfiles -O3 -o example 编译代码,编译器会生成动态链接的可执行文件。动态链接的可执行文件有一个
.interp
部分。这就是我在 objdump -D 中看到的。动态链接的可执行文件通过程序解释器和动态链接器执行。我看到的额外系统调用来自动态链接器。我仍然不知道为什么可执行文件想要动态链接程序中不链接任何库并且想要独立的任何内容。
如果您不希望动态链接器进行额外的系统调用 - 您应该为 gcc 提供额外的
-static
选项。如果没有发生动态链接,编译器不会自动执行此操作。I found out what is happening.
If I compile the code with
cc example.c -ffreestanding -nostartfiles -O3 -o example
the compiler makes a dynamically linked executable. Dynamically linked executables have an.interp
section. That is what I was seeing in myobjdump -D
.Dynamically linked executables are executing via the program interpreter and the dynamic linker. The additional system calls I saw, came from the dynamic linker. I still do not know why the executable wants to dynamically link anything in a program that does not link any libraries and wants to be freestanding.
If you do not want the extra system calls from the dynamic linker - you should give gcc the extra
-static
option. The compiler does not automatically do this if there is no dynamic linking happening.