c - _sbrk 函数在放置在静态库中时找不到

标签 c gcc linker arm

我正在为具有 ARM Cortex M4 内核的 stm32f407 微 Controller 创建一个裸机应用程序。因此,我将亲自交付 _sbrk 等功能的实现。我现在发现,当我尝试创建一个包含 _sbrk 的静态库,并将其与我的 main.c 链接到应用程序时,链接器说

"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".

如果我从静态库中取出相同的函数,并将其放入 main.c,一切都可以正常编译/链接/运行。

我几乎可以肯定这与链接器读取所有库的顺序有关,并且当我自己的静态库被读取时,还不需要定义_sbrk,因此被抛出,只是在稍后链接标准库之一时才发现无论如何都需要它。但是,我自己没有指定任何标准库,因此无法更改链接这些库的顺序。我还尝试将 _sbrk 函数声明为 __attribute __ ((__ used__ )),以为链接器不会丢弃该函数,但是,唉,这并没有解决我的问题。

所以我的问题是,如何将 _sbrk 放入静态库中,而不会遇到未解析的引用?

更新:链接最终应用程序的命令是:

C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"

其中 AR10B2~.EXE 解析为 arm-none-eabi-g++.exe

添加以下内容使事物链接:

-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"

libcmsis_stm.cmsis_stm.a 库是使用以下命令构建的:

C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj

其中 ARM-NO~2.EXE 解析为 arm-none-eabi-ar.exe

所以还有一个问题:我想将中断 vector 表(它是一个变量)放入静态库中,但链接器丢弃了该变量,因为没有源文件需要该变量。是否有一种机制可以在链接器处理链接器文件中的输出部分之前保留该变量?

最佳答案

ld 链接到一个库时,它只会选择那些当时需要的函数(因为引用了链接到的翻译单元的函数之前)。链接器将忘记所有其他功能(以后不会考虑库)。

因此链接顺序很重要。通常你会链接你的应用程序对象文件(它引用 malloc),然后是标准库(它提供 malloc 并反过来引用 _sbrk) ,然后是提供 _sbrk 的(应用程序)库。

所以链接应该是这样的

arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp

_sbrk 函数由 libapp 提供。

因此,要链接的对象的顺序很重要。

更新

如评论之一所述:如果您在编译期间使用 -g 添加调试符号,那么您还必须链接到 libg (-lg)。

arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp

关于c - _sbrk 函数在放置在静态库中时找不到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28895703/

相关文章:

c - 英特尔 AVX 在 C 中的 _mm256_load_si256 整数运算不一致

c++ - 为什么这个 C++ 代码在不同的编译器上给出不同的输出?

c - "Undefined reference"共享库和 ldflags 错误

c - C 语言编程中的 double 指针

c++ - Typedef-name 与 C++ 中的 struct 标记冲突

c++ - 防止 C 整数溢出

linux - 不支持配置arm-buildroot-linux-gnu

c - 使用 GCC 编译时出现汇编错误

android - 如何将 .o 文件添加到 Android ndk 构建