英文:
_write et al. pulled in when linking C++ lib with bare-metal ARM C project
问题
我已经交叉编译了一个外部的C++库/可重新链接的目标文件(针对ARM Cortex-M4),使用以下标志从源代码编译:
-fno-unwind-tables
-ffunction-sections
-fdata-sections
-fmessage-length=0
-std=c++11
-fno-rtti
-fno-exceptions
-fno-threadsafe-statics
-Wnon-virtual-dtor
-fno-unwind-tables
-ffreestanding
-fno-non-call-exceptions
-fno-use-cxa-atexit
-fno-common
-r
我使用相同的标志,使用-C
交叉编译了一个包装文件,该文件使用库的一些例程并导出一个extern "C"
包装函数。然后,我将生成的目标文件与上述库链接,同时传递额外的标志:
-static -r -nostartfiles -nolibc -nodefaultlibs -nostdlib
我有一个单独的裸机C项目,在其中我调用导出的C包装函数并将其与生成的库链接。
由于以下未定义的引用,此链接失败:
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-abort.o): in function `abort':
abort.c:(.text.abort+0xa): undefined reference to `_exit'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-signalr.o): in function `_kill_r':
signalr.c:(.text._kill_r+0x12): undefined reference to `_kill'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-writer.o): in function `_write_r':
writer.c:(.text._write_r+0x14): undefined reference to `_write'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-closer.o): in function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-fstatr.o): in function `_fstat_r':
fstatr.c:(.text._fstat_r+0x12): undefined reference to `_fstat'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-isattyr.o): in function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-lseekr.o): in function `_lseek_r':
lseekr.c:(.text._lseek_r+0x14): undefined reference to `_lseek'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-readr.o): in function `_read_r':
readr.c:(.text._read_r+0x14): undefined reference to `_read'
我可以通过向链接器传递--specs=nosys.specs
或简单地-lnosys
来解决此问题。
这里让我困惑的是:通过使用objdump --disassemble
、strings
或readelf -Ws
查看生成的ELF文件,我可以看到这些有问题的引用。但是,如果我查看原始C项目的生成物或我捆绑到项目中并链接到项目的任何C++生成物,我都看不到这些符号。
我的结论是它们必须是通过链接C++库的方式引入的,尽管我不理解为什么,我也不想盲目依赖于nosyslib
,以免以后遇到一些难以推理的错误。
英文:
I've cross-compiled (for ARM Cortex-M4) an external C++ library/relinkable object file from source with the following flags:
-fno-unwind-tables
-ffunction-sections
-fdata-sections
-fmessage-length=0
-std=c++11
-fno-rtti
-fno-exceptions
-fno-threadsafe-statics
-Wnon-virtual-dtor
-fno-unwind-tables
-ffreestanding
-fno-non-call-exceptions
-fno-use-cxa-atexit
-fno-common
-r
I've used the same flags to with -C
to cross-compile a wrapper file that uses some of the library routines and exports a single extern "C"
wrapped function. I then link the resulting object file with the aforementioned library by also passing additional flags:
-static -r -nostartfiles -nolibc -nodefaultlibs -nostdlib
I have a separate bare-metal C project in which I know call the exported C wrapper function and link it with the resulting library.
Doing this linking fails due to the following undefined references:
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-abort.o): in function `abort':
abort.c:(.text.abort+0xa): undefined reference to `_exit'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-signalr.o): in function `_kill_r':
signalr.c:(.text._kill_r+0x12): undefined reference to `_kill'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-writer.o): in function `_write_r':
writer.c:(.text._write_r+0x14): undefined reference to `_write'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-closer.o): in function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-fstatr.o): in function `_fstat_r':
fstatr.c:(.text._fstat_r+0x12): undefined reference to `_fstat'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-isattyr.o): in function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-lseekr.o): in function `_lseek_r':
lseekr.c:(.text._lseek_r+0x14): undefined reference to `_lseek'
../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-readr.o): in function `_read_r':
readr.c:(.text._read_r+0x14): undefined reference to `_read'
I'm able to resolve this by either passing --specs=nosys.specs
or simply -lnosys
to the linker.
Here's what's confusing me: looking at the produced ELF with either objdump --disassemble
, strings
or readelf -Ws
I can see the offending references. However, if I look at the artifact of the original C project or any of the C++ artifacts I bundle together and link to the project I don't see any of these symbols.
My conclusion was thus that they must get pulled in by the virtue of linking in the C++ library, although I don't understand why and I don't want to blindly rely on nosyslib
just to run into some hard-to-reason-about bugs later down the road.
答案1
得分: 0
我的结论是,它们必须通过链接到C++库中的优势被吸引,尽管我不理解为什么。
可能是因为您的g++版本或C++标准库版本在自由运行模式下存在错误。
可能是因为您正在构建的库包括一个或多个不在您正在编译的C++版本的允许列表上的头文件。或者它确实依赖于相关的函数。特别是,如果该库没有明确设计用于与自由运行实现一起使用,那么很难找到一组编译和链接选项的组合,使其在自由运行实现中正确工作。请注意,“编译和链接成功”只是“按预期工作”的一小部分。
可能还有其他问题。
我不希望盲目依赖nosyslib,以免以后遇到难以理解的错误。
nosyslib提供各种系统调用的存根版本,这些调用总是失败而不执行任何操作。如果程序没有正确检查并处理来自系统调用的错误,或者实际上需要某些系统调用成功才能执行其预期的工作,那么这可能是错误的来源。
如果这些未解决的引用是由您的工具链产生的一种虚假产物,意味着这些函数永远不会被调用(请参见上述有关组件是否设计用于自由运行模式的评论),那么nosyslib可能是一个稳健的解决方案。如果这些存根函数确实被调用,那么情况可能会更加不稳定。在没有彻底审查所有代码,包括“外部”库的代码的情况下,可能很难区分它们。
英文:
> My conclusion was thus that they must get pulled in by the virtue of linking in the C++ library, although I don't understand why
Possibly because your version of g++ or of the c++ standard library is buggy with respect to freestanding mode.
Possibly because the library you are building include
s one or more headers that are not on the allowed list for a freestanding implementation in the version of C++ you're compiling for. Or maybe it genuinely relies on the functions in question. In particular, if that library was not explicitly designed to be usable in conjunction with freestanding implementations, then it would be insanely lucky to find a combination of compile and link options that made it work correctly in a freestanding implementation. Note well that "compiles and links successfully" is only a small part of "works as intended".
Possibly some other issue.
> and I don't want to blindly rely on nosyslib just to run into some hard-to-reason-about bugs later down the road.
nosyslib provides stub versions of various system calls, which always fail without doing anything (else). This could be a source of bugs if the program does not properly check for and handle errors from syscalls, and / or if it in fact needs some of those syscalls to succeed in order to perform its intended work.
If those unresolved references are some kind of bogus artifact produced by your toolchain, meaning that no calls to those functions can ever actually be performed (see above comments about components being designed for freestanding mode), then nosyslib is probably a sturdy resolution. If the stub functions actually do get called then you're on much shakier ground. It may be hard to discern between these without a thorough review of all the code., including that of the "external" library.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论