gpt4 book ai didi

gcc - GNU Arm 嵌入式工具链 : undefined reference to `__sync_synchronize'

转载 作者:行者123 更新时间:2023-12-05 06:09:44 25 4
gpt4 key购买 nike

我正在尝试更新裸机嵌入式项目的工具链。我们在 Windows 上构建,到目前为止,我们一直在使用版本 5.4.1 20160609(发布)[ARM/embedded-5-branch 修订版 237715]。

现在我正在尝试版本 9.3.1 20200408(发布)(9-2020-q2-update),但我在链接时遇到一个 undefined symbol 的问题:__sync_synchronize 被报告为丢失,我不知道来自哪个来源这个符号应该解决。我是否必须链接我缺少的库?我是否应该为编译器提供不同的标志,以便它为该函数生成代码?

下面是一个示例,它可以很好地使用旧工具链进行编译和链接,但使用新工具链会失败。在这两种情况下都使用了这个命令行:

arm-none-eabi-g++ -mthumb -specs=nosys.specs 示例.cpp

准确的失败信息是:

c:/projects/cpt_tools/gcc-arm-none-eabi/9.3.1/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld.exe: C:\Users\noone\AppData\Local\Temp\ccSZkMXN.o: 在函数 'use_static_inst(int)' 中:sample.cpp:(。 text+0xc):未定义对“__sync_synchronize”collect2.exe 的引用:错误:ld 返回 1 退出状态

顺便说一句:当我在 Linux 上运行测试时没有区别:

noone@nowhere:~/gcc-arm-none-eabi-9-2020-q2-update/bin$ ./arm-none-eabi-g++ -mthumb -specs=nosys.specs sample.cpp/media/persistent_storage/home/rmatano/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld:/tmp/ccltslyj.o: 在函数 'use_static_inst(int)' 中:/>sample.cpp:(.text+0xc): 未定义对 '__sync_synchronize 的引用' collect2: error: ld 返回了 1 个退出状态

我发现了这个问题 GCC Linaro cross compile fails on linker step on a Windows host这似乎处理同样的问题。但是我不能使用指定 -mcpu=cortex-a9 的建议解决方案,因为我的代码应该在相当旧的硬件 ('-cpu=arm926ej-s') 上运行。

这里是sample.cpp的内容:

// compile with 'arm-none-eabi-g++.exe -mthumb -specs=nosys.specs sample.cpp'
//
// result: in function `use_static_inst(int)':
// sample.cpp:(.text+0x18): undefined reference to `__sync_synchronize'

class A
{
int m_i;

public:

A(int i) : m_i(i)
{
}

int value(int x)
{
return m_i + x;
}
};


int use_static_inst(int x)
{
// in preparation for calling the ctor of this static instance
// the compiler generates a call to __sync_synchronize
static A a(0);

return a.value(x);
}

int main(int argc, char* argv[])
{
return use_static_inst(argc);
}

最佳答案

免责声明:我不在我的专业领域内。

缺少的功能是实现内存屏障。这在多核 CPU 中是必需的,例如 Cortex-A9,但在您的 arm926ej-s 上不太可能需要。由于您使用的工具链明确针对 Cortex-M 和 Cortex-R CPU,因此如果新工具链没有针对 ARM9 CPU 进行大量(或根本没有)测试,我不会感到惊讶。

我的第一条评论是,恕我直言,你不应该让编译器使用它的默认设置,并明确你所针对的确切 ARM 架构和 CPU - 请注意,这不能解决你的问题,链接器错误仍然存​​在:

arm-none-eabi-g++ -march=armv5tej -mcpu=arm926ej-s -mthumb -specs=nosys.specs sample.cpp 

需要注意的一件有趣的事情是,使用 -marm 进行编译不会触发链接器错误:

arm-none-eabi-g++ -march=armv5tej -mcpu=arm926ej-s -marm -specs=nosys.specs sample.cpp 

在这种情况下,为 __sync_synchronize() 生成的代码将是:

00011014 <__sync_synchronize>:
11014: f44f 637a mov.w r3, #4000 ; 0xfa0
11018: f6cf 73ff movt r3, #65535 ; 0xffff
1101c: 4718 bx r3
1101e: bf00 nop

我的理解是这会导致程序分支到地址 0xffff0fa0,这看起来有点奇怪:我们正在使用 arm-none-eabi 工具链,生成的代码似乎试图触发 Linux kuser_memory_barrier 的执行 - 请参阅文档 here .这可能是它相当于在 Linux 环境中调用 __sync_synchronize()。恕我直言,这是工具链中未检测到的错误。

现在,__sync_synchronize() 是一个 gcc 内置函数,并且确实发出了一个完整的内存屏障。例如,当以 Cortex-A9 为目标时,它将生成数据内存屏障 dmb ish 指令。此指令是必需的,因为 Cortex-A9 确实支持乱序执行,因此程序可能需要在某些点执行完整的内存屏障,更具体地说,如果存在多个内核。

有趣的是,用于在 Linux 5.9.6 中实现 kuser_memory_barrier 的代码(文件 arch/arm64/kernel/kuser32.S)也使用了 dmb ish:

__kuser_memory_barrier:         // 0xffff0fa0
.inst 0xf57ff05b // dmb ish
.inst 0xe12fff1e // bx lr

也就是说,如果需要数据内存屏障,底层硬件可能需要为内置实现提供最低限度的支持。

因为它看起来像 arm926ej-s 只有 Instruction Memory Barrier IMB 指令可用,这可能只是 arm926ej-s 不支持乱序执行,在这种情况下不需要调用 __sync_synchronize(),您可以尝试提供一个空的/什么都不做的 __sync_synchronize() 并且仍然是安全的。您需要确定是否属于这种情况。

请注意,arm926ej-s 引用手册在谈到紧耦合内存接口(interface)事务时只提到了乱序,但同样,您需要深入研究。您可能还应该查看为 __cxa_guard_acquire()__cxa_guard_release() 生成的代码,以便充分了解它们与您的硬件的关系。您可能不想在多线程应用程序中调试奇怪的问题。

例如,通过查看它们在 gcc-arm-none-eabi-9-2020-q2-update/arm-none-eabi/lib/libstdc++_nano.a 中的实现,我没有看到任何可能阻止它们在您的目标上使用的具体说明,但我再次不熟悉 arm926ej-s 指令集,您是最终应该调用的人:

Disassembly of section .text.__cxa_guard_acquire:

00000000 <__cxa_guard_acquire>:
0: e5902000 ldr r2, [r0]
4: e3120001 tst r2, #1
8: e1a03000 mov r3, r0
c: 1a000006 bne 2c <__cxa_guard_acquire+0x2c>
10: e5d02001 ldrb r2, [r0, #1]
14: e3520000 cmp r2, #0
18: 0a000000 beq 20 <__cxa_guard_acquire+0x20>
1c: e7f000f0 udf #0
20: e3a00001 mov r0, #1
24: e5c30001 strb r0, [r3, #1]
28: e12fff1e bx lr
2c: e3a00000 mov r0, #0
30: e12fff1e bx lr

Disassembly of section .text.__cxa_guard_abort:

00000000 <__cxa_guard_abort>:
0: e3a03000 mov r3, #0
4: e5c03001 strb r3, [r0, #1]
8: e12fff1e bx lr

Disassembly of section .text.__cxa_guard_release:

00000000 <__cxa_guard_release>:
0: e3a03001 mov r3, #1
4: e5803000 str r3, [r0]
8: e12fff1e bx lr

guard_error.o: file format elf32-littlearm

这些额外的预防措施可能是必要的,因为您在 2019 年发布的 C++ 编译器上使用的 CPU 系列已有将近 20 年的历史。

关于gcc - GNU Arm 嵌入式工具链 : undefined reference to `__sync_synchronize' ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64658430/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com