【问题标题】:__isr_vectors variable not found when placed inside a static library__isr_vectors 变量放在静态库中时找不到
【发布时间】:2015-05-11 00:42:05
【问题描述】:

作为上一个问题 (sbrk function not found when placed in a static library) 的衍生问题: 我正在为具有 ARM Cortex M4 内核的 stm32f407 微控制器创建一个裸机应用程序。我正在尝试创建一个静态库,其中包含 cmsis、HAL 函数和中断向量表等基本内容,并将该静态库链接到我的主应用程序。但是,当中断向量表(一个名为__isr_vectors 的变量)被放置在静态库中时,该变量无法在链接中继续存在。

我可以把发生的事情拼凑起来:链接器有一个对象 main.o 和一些库。它获取在main.o 中找到的所有符号,并将所有符号从main.o 使用的库中或已被认为必要的其他符号使用的库中取出。在这个阶段还不需要__isr_vectors 变量,因为没有人明确引用这个变量,所以它被链接器抛出。然后,链接器搜索所有名为.isr_vector 的输入节以创建输出节.isr_vector。然而,到目前为止,没有任何符号存在,所以输出部分是空的,我的二进制文件没有中断表。

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

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

vectors.c:

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

main.c:

void _start(void) {}

链接.ld:

内存 { 闪存(rx):原点 = 0x08000000,长度 = 1024K }

ENTRY(_start)

部分 { .isr_vector:对齐(4) { 保持(*(.isr_vector)) } >闪光灯

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

}

命令:

"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 -ovectors.c.obj -cvectors.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.objvectors.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.avectors.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

【问题讨论】:

  • 你有--gc-sections。您是否尝试过 __isr_vectors 变量的 used 属性和/或链接器脚本中 .isr_vector 部分的 KEEP 语句?
  • 变量已经有used属性,声明如下:__attribute__ ((section(".isr_vector"),used)) pHandler __isr_vectors[] =链接器文件已经有KEEP语句,看起来像这样:KEEP(*(.isr_vector))仍然抛出变量离开
  • 我无法复制,它似乎对我有用。你能把所有东西(Makefile、启动、链接描述文件最小的主程序)放在一起并上传到某个地方吗?
  • 我通过wetransfer上传了一个.rar文件:we.tl/xfVcTvHkkL。该文件包含一个 Compile.cmd,它发出 6 个命令,用于编译和链接两个版本。之后,您可以比较两个 .map 文件,发现其中一个缺少 __isr_vectors 变量。对于编译,我使用了此处的 GNU ARM 可执行文件:launchpad.net/gcc-arm-embedded/4.9/4.9-2014-q4-major
  • 当我尝试从该存档中提取文件时,只有 main.c 成功。 rar 不是免费的,所以我的 Linux 客户端可能太旧了。压缩文件?

标签: gcc linker arm static-libraries linker-scripts


【解决方案1】:

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

在链接器脚本中,我将ENTRY

ENTRY(_start)

ENTRY(Reset_Handler)

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

void Reset_Handler(void) {
}

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

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


为了完整起见:

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 同样,我发现这可以通过在链接器文件中使用 EXTERN(__isr_vectors) 来完成。
    【解决方案3】:

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

    【讨论】:

    • 这种方法的问题在于,虽然它会生成正确的可执行文件,但在调试器中加载此应用程序时,调试器会尝试在 g_pfnVectors 处开始执行。
    • 根据 IDE 和调试器,您可以“告诉”调试器从哪里开始。 "*g_pfnVectors" 或类似的会很好用。
    猜你喜欢
    • 2015-05-07
    • 1970-01-01
    • 2017-08-05
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多