5

As a spin-off of a previous question (sbrk function not found when placed in a static library): I'm creating a bare-metal application for the stm32f407 microcontroller, which has an ARM Cortex M4 core. I'm trying to create a static library containing basic stuff like cmsis, the HAL functions, and the interrupt vector table, and link that static library to my main application. However, when the interrupt vector table (which is a variable named __isr_vectors) is placed inside the static library, the variable does not survive linking.

I can piece together what happens: The linker has an object main.o, and a few libraries. It takes all symbols found in main.o, and it takes all symbols out of the libraries that are used by main.o or that are used by other symbols that are already deemed necessary. The __isr_vectors variable is not yet needed at this stage, since no one references this variable explicitly, so it is thrown out by the linker. Then, the linker searches for all input sections named .isr_vector in order to create the output section .isr_vector. However, no symbols survived up to this moment, so that output section is left empty, and my binary is left without an interrupt table.

I know of one trick to get the __isr_vector to survive: reference it in a dummy function in main.c. However, this is kinda ugly and error-prone (you can forget to do that when building a new application against the same static library). So here's my question: Is there another way to make the __isr_vector survive, so that I can just link in my static library and be done with it?

These are the files and steps to reproduce the problem:

vectors.c:

__ attribute__ ((section(".isr_vector"), used)) void* __isr_vectors = 0;

main.c:

void _start(void) {}

link.ld:

MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K }

ENTRY(_start)

SECTIONS { .isr_vector : ALIGN(4) { KEEP(*(.isr_vector)) } >FLASH

   .text : ALIGN(4)
   {
       *(.text .text.*)
   } >FLASH

}

Commands:

"C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-gcc.exe" -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -std=gnu11 -o main.c.obj -c main.c "C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-gcc.exe" -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -std=gnu11 -o vectors.c.obj -c vectors.c

"C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-gcc.exe" -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -std=gnu11 -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-Tlink.ld -Wl,-Map=test_linker.without_library.map main.c.obj vectors.c.obj -o test_linker.without_library.elf

"C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-ar.exe cq libtest_linker.lib.a vectors.c.obj

"C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-ranlib.exe" libtest_linker.lib.a

"C:\Program Files (x86)\GNU Tools ARM Embedded\4.9 2014q4\bin\arm-none-eabi-gcc.exe" -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -std=gnu11 -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-Tlink.ld -Wl,-Map=test_linker.with_library.map main.c.obj -o test_linker.with_library.elf libtest_linker.lib.a

4

3 回答 3

4

我对您的文件进行了两项更改:

在链接器脚本中,我更改了ENTRYfrom

ENTRY(_start)

ENTRY(Reset_Handler)

在vectors.c中我添加了这个函数:

void Reset_Handler(void) {
}

诀窍是这Reset_Handler是翻译单元中的一个功能,vectors.c_start在其他地方。

现在 whenReset_Handler被链接(由 强制ENTRY),__isr_vectors似乎也被考虑了!因此,似乎必须链接该翻译单元中的另一个函数才能“拖动”该变量。


为了完整起见:

  • 通常,在,Reset_Handler中引用__isr_vectors并最终Reset_Handler调用(在您的情况下是)。因此,这不仅仅是一种解决方法,无论如何您可能都需要它。main_start

  • 我已添加-fdata-sections到编译命令

于 2015-03-19T22:29:01.243 回答
2

我在同一种环境中遇到了这个问题(arm-none-eabi-gcc-cs-5.2.0-3.fc23.x86_64, arm-none-eabi-binutils-cs-2.25-2.fc23.x86_64 on Fedora 23).

链接器似乎没有尝试读取存档的内容,因为它已经拥有所需的所有符号。这可能是一种优化或错误。

强制为“使用”符号读取存档的另一种解决方案是强制链接器 ld 将 __isr_vectors 视为未定义,使用-u __isr_vectors.

作为 gcc 选项,-Xlinker -u -Xlinker __isr_vectors-Wl,-u,__isr_vectors.

于 2015-12-16T09:11:05.997 回答
1

这更像是已发布答案的后续:我建议您只需将链接器脚本中的 ENTRY 更改为: ENTRY(g_pfnVectors) 我认为这是较少的工作,并且不需要更改原始源文件。如果源文件中不存在 g_pfnVectors,则它是我们文件中向量表本身的名称。酌情修改。

于 2016-01-29T17:08:15.490 回答