__isr_vectors 放置在静态库中时找不到变量

__isr_vectors variable not found when placed inside a static library

作为上一个问题的衍生问题 (): 我正在为具有 ARM Cortex M4 内核的 stm32f407 微控制器创建一个裸机应用程序。我正在尝试创建一个静态库,其中包含 cmsis、HAL 函数和中断向量 table 等基本内容,并将该静态库 link 添加到我的主应用程序。但是,当中断向量 table(这是一个名为 __isr_vectors 的变量)被放置在静态库中时,该变量无法存活 linking.

我可以拼凑出发生了什么:linker 有一个对象 main.o 和一些库。它获取在 main.o 中找到的所有符号,并从 main.o 使用的库中取出所有符号,或者从已经被认为必要的其他符号使用的库中取出所有符号。 __isr_vectors 变量在这个阶段还不需要,因为没有人显式地引用这个变量,所以它被 linker 扔掉了。然后,linker 搜索所有名为 .isr_vector 的输入部分,以创建输出部分 .isr_vector。然而,到目前为止,没有符号存活下来,所以输出部分是空的,我的二进制文件没有中断table。

我知道一个让 __isr_vector 存活下来的技巧:在 main.c 的虚拟函数中引用它。但是,这有点丑陋且容易出错(在针对同一个静态库构建新应用程序时,您可能会忘记这样做)。所以这是我的问题:是否有另一种方法可以使 __isr_vector 存活下来,这样我就可以 link 在我的静态库中完成它?

这些是重现问题的文件和步骤:

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

}

命令:

"C:\Program Files (x86)\GNU Tools ARM Embedded.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.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.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.9 2014q4\bin\arm-none-eabi-ar.exe cq libtest_linker.lib.a vectors.c.obj

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

"C:\Program Files (x86)\GNU Tools ARM Embedded.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

我对你的文件做了两处修改:

在链接描述文件中,我将 ENTRY

更改为
ENTRY(_start)

ENTRY(Reset_Handler)

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

void Reset_Handler(void) {
}

诀窍是 Reset_Handler 是翻译单元中的一个函数 vectors.c_start 在其他地方。

现在当 Reset_Handler 链接进来时(由 ENTRY 强制执行),__isr_vectors 似乎也被考虑在内!因此,似乎必须链接该翻译单元中的另一个函数才能 "drag along" 该变量。


为了完整起见:

  • 通常 Reset_Handler__isr_vectors 中引用,Reset_Handler 最终调用 main(在您的情况下是 _start ).所以这不仅仅是一个解决方法,无论如何你可能需要它。

  • 我在编译命令中添加了-fdata-sections

我在同类环境下遇到这个问题(arm-none-eabi-gcc-cs-5.2.0-3.fc23.x86_64,arm-none-eabi-binutils-cs-2.25-2.fc23.x86_64 在 Fedora 23 上)。

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

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

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

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