【问题标题】:_sbrk function not found when placed in a static library放置在静态库中时找不到 _sbrk 函数
【发布时间】:2015-05-07 21:01:33
【问题描述】:

我正在为具有 ARM Cortex M4 内核的 stm32f407 微控制器创建一个裸机应用程序。因此,我自己提供了像_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):在函数 _sbrk_r 中:sbrkr.c:(.text._sbrk_r+0xc):未定义对“_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\ vector_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

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

【问题讨论】:

  • 你不需要将它定义为main。在你的主模块中引用它应该足够了,从一个未使用的函数dummy_sbrk_caller,比如说,你用__attribute__((__used__))声明。
  • 您是否尝试在标准 C 库之后在您的应用程序库中链接?喜欢-o out main.o -lc -lm -lapp
  • 您在链接阶段使用的命令行是什么样的?图书馆的顺序很重要。另见stackoverflow.com/questions/13235748/…
  • 是的,我已经尝试过了,或者至少,我已经尝试过 main.o -lc 。我现在看到有问题的库是 libg,而不是 libc。在上面的句子中添加 -lg 确实可以解决问题。这让我想知道,隐式链接库的总列表是什么?
  • 我可以增加一点赌注吗?虽然重新排序库列表并复制其中一些库使链接器能够找到_sbrk,但我遇到了与中断向量表相关的问题。我也想将该表(名为 __isr_vectors)放入单独的静态库中,但由于它仅由链接器脚本本身使用,而不是由任何代码使用,因此它没有被链接。 “dummy_sbrk_caller”技巧有效,但我想知道是否有更好的方法可以通过链接一直保持 __isr_vectors 表

标签: c gcc linker arm


【解决方案1】:

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

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

所以链接应该看起来像

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

_sbrk 函数由libapp 提供。

所以要链接的对象的顺序很重要。

更新

如其中一个 cmets 所述:如果您在编译期间使用 -g 添加调试符号,那么您也必须链接到 libg (-lg)。

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

【讨论】:

    猜你喜欢
    • 2015-05-11
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2017-08-05
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多