静态编译libc C代码和ASM代码

时间:2017-01-10 09:00:29

标签: c gcc assembly ld

我有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和exit函数静态链接libc?

当我尝试

gcc -m32 -o a3.out -lc asm.o c_code.o ; ASM file has main instead of _start

我得到一个权重7406字节的文件。 ldd显示与a.out相同的动态库,权重为5601字节。

2)为什么会有这种差异?看起来像我的代码中“连接”_start与main的一些额外代码...... 3)链接gcc和ld有什么区别?

非常感谢您的关注!

1 个答案:

答案 0 :(得分:0)

  

1)如何仅为所需的printf静态链接libc   和退出功能?

尝试使用-nostartfiles -static -nostdlib -lc进行编译,这将避免添加crt1.o和crtend.o。但请记住,这将禁用所有Glibc初始化代码,因此某些Glibc函数将无法工作。

  

2)为什么会有这种差异?看起来像一些额外的代码   "连接" _start with main in my code ...

GCC添加执行初始化的启动文件(crt*.o)。有关详细信息,请参阅许多在线文章(例如this one)。

  

3)使用gcc和ld链接有什么区别?

上面已经回答过,但一般情况下你可以运行gcc -v并检查ld(或者收集2)的论点。