__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 本身的名称。酌情修改。
作为上一个问题的衍生问题 (__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 本身的名称。酌情修改。