【问题标题】:error when trying to link with static c standard library尝试与静态 c 标准库链接时出错
【发布时间】:2017-03-16 18:49:34
【问题描述】:

我的操作系统是 ubuntu 14.04 32bit,我的源程序 test.c 是:

#include <stdio.h>
int main(int argc, char *argv[])
{
        printf("test.");
        return;
}

我用命令编译它:

gcc -S test.c

作为 test.s 文件输出。我用命令组装它:

as -o test.o test.s

然后我想将它与 c 标准库静态链接。我搜索了libc.a 文件,位于/usr/lib/i386-linux-gnu/libc.a。所以我尝试将它与命令链接:

ld test.o /usr/lib/i386-linux-gnu/libc.a

但是出来很多错误信息:

ld: warning: cannot find entry symbol _start; defaulting to 0000000008048210
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x20): undefined reference to `_Unwind_GetIP'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x45): undefined reference to `_Unwind_GetGR'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x50): undefined reference to `_Unwind_GetCFA'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `__backtrace':
(.text+0xb1): undefined reference to `_Unwind_Backtrace'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o): In function `_IO_new_fclose':
(.text+0x1b1): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o):(.eh_frame+0x167): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o): In function `_IO_fflush':
(.text+0xd7): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o): In function `_IO_fputs':
(.text+0xf9): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o): In function `_IO_fwrite':
(.text+0x139): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o): In function `_IO_getdelim':
(.text+0x285): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o): In function `_IO_wfile_underflow':
(.text+0x5fc): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o):(.eh_frame+0x137): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(fileops.o): In function `_IO_new_file_underflow':
(.text+0x40b): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(fileops.o):(.eh_frame+0x1b3): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xbc6): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xc08): undefined reference to `__moddi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0x249d): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xcc9): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xd0b): undefined reference to `__moddi3'
...
...

我的问题是,为什么会出现这些错误消息?我正在尝试了解编译系统是如何工作的,所以我不知道如何解决这个问题,我更想知道它是如何出现的。似乎静态 C 库依赖于其他库,为什么以及这些库是什么?

编辑: 我这样做是因为我想知道事情是如何运作的,所以我宁愿避免使用gcc 脚本。

【问题讨论】:

  • 为什么要单独执行这些步骤而不是只使用 GCC 前端程序?我还建议您使用 GCC 选项 -v 查看 GCC 为内部库添加的内容。
  • 因为我正在努力学习编译系统,所以我宁愿“手工”工作,看看每个步骤是如何完成的。
  • 然后使用verbose选项看看GCC做了什么。
  • BTW Ubuntu 14.04 真的很老了。你应该升级它(然后你会得到一个更新的gcc ...)

标签: c assembly linker static-libraries


【解决方案1】:

您还需要crt0 启动对象文件(除了静态libc.a),它们特别定义了_start 入口点(在您的ELF 可执行文件中)并包含ABI 特定文件(序言和结语) 代码来调用您的main(并最终处理atexit(3) 注册的处理程序和stdio 刷新)。还需要低级别的libgcc。细节是复杂的并且是特定于实现的。要理解它们,请将您的测试代码编译为

gcc -v -static test.c -o mytest

(避免调用可执行文件test,因为它会与/usr/bin/test 或你的shell 的内建相冲突)

在实践中,最好至少链接gcc

如果您好奇,请利用 Linux 主要是 free software 并研究源代码(例如 GCCC standard librarybinutils 等...)。你可能会觉得musl-libc 很有趣。

我宁愿避免使用gcc 脚本

从技术上讲,gcc不是一个脚本,而是一个驱动程序(参见GCC 源代码中的gcc/gcc.c)。但它会运行ld,它确实运行一些linker scripts。实际编译由cc1 完成,由gcc 程序启动。

【讨论】:

  • 感谢您的链接。我在 README 文件中看到了很多法国名字,但不是你的,你参与了这个开发吗?
  • 我是 GCC 的 MAINTAINERS 之一。我是法国人,但有俄罗斯血统。另见gcc-melt.org
  • 通常人们会说他们是俄罗斯血统,这意味着他们是俄罗斯祖先的后裔。法语或俄语的家谱术语是否按字面意思翻译为“上升”树之类的?
  • 好吧,我的母语不是英语。但我的 4 个祖父母都是俄罗斯人。
  • 感谢回复,gcc的详细输出对我来说太全面了,我想我还没有准备好,我会努力学习更多的东西。
【解决方案2】:

您还必须链接gcc 内部库。最简单的方法是使用gcc 前端编译和链接-static 选项:

gcc -static -o test test.c

如果你坚持从汇编编译,你可以这样做:

gcc -static -o test test.s

您的系统可能不支持静态链接。

编辑:给 gcc -v 选项会告诉你它执行什么命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多