我可以使用动态符号表编译静态应用程序吗?

时间:2012-09-11 10:05:23

标签: gcc compiler-construction compilation linker

举一个简单的例子:

void foo() {}

int main()
{
       return 0;
}

我构建它并查看动态符号表:

$ g++ test.cpp -o test
$ nm --dynamic test
0804849c R _IO_stdin_used
         w __gmon_start__
         U __libc_start_main

正如所料,我没有看到foo。所以我构建包含未使用的符号。

$ gcc test.c -rdynamic -o test
$ nm --dynamic test
0804863c R _IO_stdin_used
         w _Jv_RegisterClasses
0804a010 A __bss_start
0804a008 D __data_start
         w __gmon_start__
080485e0 T __libc_csu_fini
08048570 T __libc_csu_init
         U __libc_start_main
0804a010 A _edata
0804a018 A _end
0804861c T _fini
08048638 R _fp_hw
08048438 T _init
080484a0 T _start
0804a008 W data_start
08048554 T foo
08048559 T main

您可以看到foo现在位于符号表中。现在我构建一个静态版本。

$ gcc test.c -rdynamic -static -o test
$ nm --dynamic test
nm: test: No symbols

我的符号已经消失,即使我明确指定了它们。

根据GCC手册页:

  

-static              在支持动态链接的系统上,这会阻止与共享库的链接。

我的函数foo()不是共享库。

如果我展开此应用程序并调用dlopen(),并且我加载的库需要调用foo(),则我的符号表不再包含对foo()和我的应用程序的引用会失败。

这发生在我身上recently

为什么-static否定-rdynamic以及如何解决它?

1 个答案:

答案 0 :(得分:0)

我认为静态链接到C库的可执行文件的想法,但提供对共享库的导出可能是一个破碎的概念。在这种情况下会发生什么?假设您的共享库分配了一些内存(使用它自己的C库副本),然后将其传递给可执行文件中的一个例程,该例程释放它(在C库的不同副本中)。这闻起来像个问题。如果需要静态链接某些库,可以在这些库之前使用-Wl,-Bstatic选项强制链接到静态版本。

此外,如果您需要更多地控制正在发生的事情,最好有单独的编译和链接步骤,并直接使用ld进行链接步骤。它并不一定有助于你正在使用的命令行选项,但我怀疑你可以找到“有效”的东西,除非上述问题。