我有 ASM 代码:
extern my_func
extern printf
extern exit
global _start
section .data
...
section .text
_start:
...
call printf
...
call my_func
...
call exit
和C代码:
int my_func(int a, int b)
{
return a+b;
}
我在 64 位机器上使用 fedora。我希望可执行文件是 32 位的。 对于动态链接,我这样做:
nasm -f elf32 asm.asm ; this gives me asm.o
gcc -m32 -Wall -c c_code.c ; this gives me c_code.o
ld c_code.o asm.o -melf_i386 -L /usr/lib/ -lc -I /lib/ld-linux.so.2 ; this gives me a.out which runs fine and weights 5601 bytes.
我想做的是静态链接 libc。我执行以下操作:
gcc -o a2.out -m32 -static -m32 asm.o c_code.o
我得到错误:
asm.o: In function `_start':
asm.asm:(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-redhat-linux/4.8.3/../../../../lib64/crt1.o:(.text+0x0):
first defined here
collect2: error: ld returned 1 exit status
然后我在 ASM 代码中将 _start 更改为 main,整个链接正常! ldd 显示“不是动态可执行文件”。但是创建的文件重量为 721067 字节!我认为它静态编译了很多不必要的代码。 所以,我的第一个问题是:
1) 如何为所需的 printf 和退出函数静态链接 libc?
当我尝试
gcc -m32 -o a3.out -lc asm.o c_code.o ; ASM file has main instead of _start
我得到一个重量为 7406 字节的文件。 ldd 显示与重量为 5601 字节的 a.out 相同的动态库。
2) 为什么会有这种差异?看起来像一些额外的代码在我的代码中“连接”_start 和 main ... 3)用gcc和ld链接有什么区别?
非常感谢您的关注!
最佳答案
1) How can I link statically only libc for the required printf and exit functions?
尝试使用 -nostartfiles -static -nostdlib -lc
进行编译,这将避免添加 crt1.o 和 crtend.o。但请记住,这将禁用所有 Glibc 初始化代码,因此某些 Glibc 函数将无法工作。
2) Why is that difference? Looks like some additional code that "connects" _start with main in my code...
GCC 添加了执行初始化的启动文件 (crt*.o
)。有关详细信息,请参阅许多在线文章(例如 this one)。
3) What is the difference between linking with gcc and ld?
上面已经回答了,但通常您可以运行 gcc -v
并检查 ld(或 collect2)的参数。
关于静态编译 libc C 代码和 ASM 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41564885/