问题描述
我有一个嵌入式平台,它在静态库中引入了自己的stdlib函数,例如malloc
和printf
。我需要使用LTO编译该库。不幸的是,在这种组合中(-flto
+ -nostdlib
+与来自.a
的stdlib替换链接),链接程序找不到函数。
我准备了可以在大多数Unix机器上运行的MWE,但是由于它包含多个文件,因此我将其放入存储库中: https://github.com/stefanct/lto_static_libs
int puts(const char *s) {
return 2;
}
使用-flto
将其编译为目标文件,使用gcc-ar
将其放入静态库中,并最终在与应用程序链接时使用它。
在我的设置中(从源代码构建的GCC 11分支和从Debian Buster构建的GNU ld 2.31.1),我得到以下结果:
未设置任何选项:确定-库中的printf
被标准函数覆盖(?):
$ make -B
Using GCC 11.0.0
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -c -o libtest.o libtest.c
lto-dump -list libtest.o
Type Visibility Size Name
function default 4 lib_func
function default 4 puts
function default 4 printf
gcc-nm libtest.o
00000000 T lib_func
00000000 T printf
00000000 T puts
rm -f libtest.a
gcc-ar -cvq libtest.a libtest.o
a - libtest.o
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -c -o main.o main.c
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -o exe main.o -L. -ltest
$ ./exe
hurga
没有stdlib,也没有LTO:好-链接可以正常工作(ish-运行segfaults,但是我猜这是可以预期的,可以与-nodefaultlibs
一起解决,但是我不在乎)
$ make -B nostdlib=y nolto=y
Using GCC 11.0.0
gcc -Wall -Wextra -Wno-unused-parameter -c -o libtest.o libtest.c
gcc-nm libtest.o
0000000000000074 T lib_func
0000000000000000 T printf
0000000000000065 T puts
rm -f libtest.a
gcc-ar -cvq libtest.a libtest.o
a - libtest.o
gcc -Wall -Wextra -Wno-unused-parameter -c -o main.o main.c
gcc -Wall -Wextra -Wno-unused-parameter -o exe main.o -L. -ltest -nostdlib
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
没有stdlib,但启用了LTO:突然找不到看跌期权。
但是,正如您所看到的,放入库中的目标文件包含的功能就很好(甚至gcc-mn libtest.a
都显示了同样的功能)。
我想解决这种情况。为什么会这样?
$ make -B nostdlib=y
Using GCC 11.0.0
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -c -o libtest.o libtest.c
lto-dump -list libtest.o
Type Visibility Size Name
function default 4 lib_func
function default 4 puts
function default 4 printf
gcc-nm libtest.o
00000000 T lib_func
00000000 T printf
00000000 T puts
rm -f libtest.a
gcc-ar -cvq libtest.a libtest.o
a - libtest.o
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -c -o main.o main.c
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -o exe main.o -L. -ltest -nostdlib
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
/usr/bin/ld: /tmp/cczvyrrg.ltrans0.ltrans.o: in function `main':
<artificial>:(.text+0xe): undefined reference to `puts'
collect2: error: ld returned 1 exit status
make: *** [makefile:39: exe] Error 1
有趣的是,如果我们在同一库中调用另一个不相关(非标准)的函数,事情又会开始起作用!?
$ make -B nostdlib=y libfunc=y
Using GCC 11.0.0
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -D LIB_FUNC -c -o libtest.o libtest.c
lto-dump -list libtest.o
Type Visibility Size Name
function default 4 lib_func
function default 4 puts
function default 4 printf
gcc-nm libtest.o
00000000 T lib_func
00000000 T printf
00000000 T puts
rm -f libtest.a
gcc-ar -cvq libtest.a libtest.o
a - libtest.o
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -D LIB_FUNC -c -o main.o main.c
gcc -Wall -Wextra -Wno-unused-parameter -flto -ffat-lto-objects -D LIB_FUNC -o exe main.o -L. -ltest -nostdlib
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
我在binutils / ld中看到错误了吗?这是上游固定的吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)