Gcc ARM交叉编译器在标准C函数中生成无效的分支目标

Gcc ARM交叉编译器在标准C函数中生成无效的分支目标,gcc,compilation,linker,arm,embedded,Gcc,Compilation,Linker,Arm,Embedded,我正在开发一个定制的嵌入式项目(使用PlatformIO来设置构建环境),我发现对标准C函数(如memset、memcpy)的调用会生成虚假代码。反汇编显示,这两个函数(以及我从stdlib尝试过的其他函数)中的指令无条件地分支到不包含代码的位置,这当然会导致MCU(Cortex M4、Atmel D51)在尝试执行无意义代码时出现硬故障。没有编译器错误,只有由于指令无效而以硬故障形式出现的运行时错误 我认为我的编译环境有问题,因为PlatformIO有一些库用于同一处理器的Adafruit板,

我正在开发一个定制的嵌入式项目(使用PlatformIO来设置构建环境),我发现对标准C函数(如memset、memcpy)的调用会生成虚假代码。反汇编显示,这两个函数(以及我从stdlib尝试过的其他函数)中的指令无条件地分支到不包含代码的位置,这当然会导致MCU(Cortex M4、Atmel D51)在尝试执行无意义代码时出现硬故障。没有编译器错误,只有由于指令无效而以硬故障形式出现的运行时错误

我认为我的编译环境有问题,因为PlatformIO有一些库用于同一处理器的Adafruit板,这些库正确地链接了上面的函数。请注意,我是从Mac交叉编译的。下面是Adafruit和自定义项目对memset函数的分解:

Adafruit:

0x000012de: 02 44               add r2, r0
0x000012e0: 03 46               mov r3, r0
0x000012e2: 93 42               cmp r3, r2
0x000012e4: 00 d1               bne.n   0x12e8 <memset+10>
0x000012e6: 70 47               bx  lr
0x000012e8: 03 f8 01 1b         strb.w  r1, [r3], #1
0x000012ec: f9 e7               b.n 0x12e2 <memset+4>
自定义:

0x000005b4: 00 30               adds    r0, #0
0x000005b6: a0 e1               b.n 0x8fa           <--- branch to address with no code and hard-fault
0x000005b8: 02 20               movs    r0, #2
0x000005ba: 80 e0               b.n 0x6be
0x000005bc: 02 00               movs    r2, r0
0x000005be: 53 e1               b.n 0x868
0x000005c0: 1e ff 2f 01         vrhadd.u16  d0, d14, d31
0x000005c4: 01 10               asrs    r1, r0, #32
0x000005c6: c3 e4               b.n 0xffffff50
0x000005c8: fb ff ff ea                 ; <UNDEFINED> instruction: 0xfffbeaff
arm-none-eabi-ar rc .pio/build/commonsense/libFrameworkCommonSense.a .pio/build/commonsense/FrameworkCommonSense/commonsense.o .pio/build/commonsense/FrameworkCommonSense/cortex_handlers.o .pio/build/commonsense/FrameworkCommonSense/led.o .pio/build/commonsense/FrameworkCommonSense/pinConfig.o .pio/build/commonsense/FrameworkCommonSense/startup.o

arm-none-eabi-ranlib .pio/build/commonsense/libFrameworkCommonSense.a

arm-none-eabi-gcc -o .pio/build/commonsense/firmware.elf -T commonsense_linker.ld -mfpu=fpv4-sp-d16 -mthumb -Wl,--gc-sections -Wl,--check-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align --specs=nosys.specs --specs=nano.specs -mcpu=cortex-m4 .pio/build/commonsense/src/main.o -L.pio/build/commonsense -L/Users/work-reese/.platformio/packages/toolchain-gccarmnoneeabi/arm-none-eabi/lib -L/Users/work-reese/.platformio/packages/framework-cmsis/CMSIS/Lib/GCC -L/Users/work-reese/.platformio/packages/framework-commonsense/linker -Wl,--start-group .pio/build/commonsense/libFrameworkCommonSense.a -larm_cortexM4lf_math -lc_nano -lm -Wl,--end-group
这是使用arm交叉编译器7.2.1版,工具链包含libc、libc_nano、libm等的发行版。所有必要的库似乎都存在

请注意,我在上面为自定义版本的链接添加了一些额外的行,以便您可以从中查看它在构建什么
libFrameworkCommonSense.a
。这些文件都不包含任何stdlib调用,尽管cortex_处理程序在reset处理程序中没有u libc_init_数组,因为这也会以与memset相同的方式导致硬故障。两者之间的链接器脚本相同;再一次,我从adafruit项目中大量借用了中断处理程序和启动代码,但到目前为止,我还没有看到环境之间的任何实际差异

添加--print multi lib选项显示了几个应该可以工作的选项,即
thumb/v7e-m/fpv4 sp/softfp@mthumb@march=armv7e-m@mfpu=fpv4 sp-d16@mfloat-abi=softfp
,在给定编译器标志的情况下应选择该选项。奇怪的是,它在打印multilib选项时无法编译,原因是要归档的对象文件(arm none eabi ar)不在构建目录中。这可能不重要

以下是主文件的编译,其中包括对memset和memcpy的调用:

arm-none-eabi-gcc -o .pio/build/commonsense/src/main.o -c -std=gnu11 -mfpu=fpv4-sp-d16 -Og -g3 -mlong-calls --specs=nano.specs -specs=nosys.specs -fdata-sections -ffunction-sections -mfloat-abi=softfp -march=armv7e-m -mfpu=fpv4-sp-d16 -marm -mthumb-interwork -ffunction-sections -fdata-sections -Wall -mthumb -nostdlib --param max-inline-insns-single=500 -mcpu=cortex-m4 -DPLATFORMIO=50003 -D__SAMD51P20A__ -D__SAMD51__ -D__FPU_PRESENT -DARM_MATH_CM4 -DENABLE_CACHE -DVARIANT_QSPI_BAUD_DEFAULT=50000000 -DDEBUG -DADAFRUIT_LINKER -DF_CPU=120000000L -Iinclude -Isrc -I/Users/work-reese/.platformio/packages/framework-cmsis/CMSIS/Include -I/Users/work-reese/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL -I/Users/work-reese/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/samd51 -I/Users/work-reese/.platformio/packages/framework-commonsense -I/Users/work-reese/.platformio/packages/framework-commonsense/core -I/Users/work-reese/.platformio/packages/framework-commonsense/hal -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/include -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/utils/include -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/utils/src -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/src -I/Users/work-reese/.platformio/packages/framework-commonsense/hpl -I/Users/work-reese/.platformio/packages/framework-commonsense/hri -I/Users/work-reese/.platformio/packages/framework-commonsense/sample src/main.c
有人知道我为什么会在错误链接的库函数中出现这种行为吗?我对它进行了近一周的抨击,向它抛出了许多编译器标志组合,但都无济于事。我觉得有些东西我忽略了,但不知道是什么。我很高兴提供更多信息


附带问题:什么是_libc_init_array(),在程序启动期间调用它有多必要?我在adafruit和Atmel Studio项目的重置处理程序中看到了这一点。它在它们的启动文件中本地声明为函数原型,但在我自己的环境中复制相同的东西会在处理器尝试调用该函数时导致硬故障。我应该认为它是libc或类似程序的一部分。

似乎问题出在尝试使用编译器标志-mfloat abi=softfp时。我切换到-mfloat abi=hard,这些链接问题似乎消失了。我确认错误的开关也会破坏adafruit环境

基于我是否只将硬件用于浮点运算,而不是将软件仿真和硬件混合用于FPs,我会出现这样的错误,这似乎仍然很奇怪。我的代码也没有使用浮点

我设置为'softfp'的部分原因是我找到的FreeRTOS端口提到我应该使用此交换机。希望这不会妨碍我使用它

我的问题仍然是关于_libc_init_array(),因为当我运行它时,它仍然会产生一个硬错误——它的反汇编看起来也很奇怪,分支位于奇数位置(即异常表)

我发现对标准C函数(如memset、memcpy)的调用会生成伪代码。反汇编显示,这两个函数(以及我从stdlib尝试过的其他函数)中的指令无条件地分支到不包含代码的位置,这当然会导致MCU(Cortex M4、Atmel D51)在尝试执行无意义代码时出现硬故障

实际上,这是ARM代码而不是thumb代码。当你们试着把它分解成拇指的时候,这是胡说八道,但把它分解成手臂的时候,它看起来是有道理的

当然,您的处理器不能执行ARM代码,只能执行thumb代码,而且在任何情况下,即使是在ARM模式下也可能遇到它的处理器。因此,这一硬断层并不神秘


目前尚不清楚的是,在thumb项目中,如何使用ARM代码。乍一看,您对编译器的实际调用似乎是在指定thumb,因此我猜问题代码实际上是由于链接了错误的库而到达的。

-nostlib
那么,可能包括一个标准库?我在构建时设置了-nostlib,然后在链接时删除了该标志。我还尝试在链接时包含-nostlib和isntead包含-lc或-lc_nano。这些都没有效果。在我下面发布的答案中,当我更改浮点标志时,我让它开始工作。也许我不太了解multilib,但我知道打印时显示的大多数选项都明确提到“thumb”。这不意味着标准库的某些版本支持thumb模式吗?如您所见,我在linker命令中提供了-mthumb。此外,大多数较新的cortex-m处理器不能同时执行ARM和thumb吗?我以为有办法切换模式。我在反汇编中看到了16位和32位指令。至于为什么会发生这种情况,可能是平台IO提供的arm工具链有问题。不,也不。不清楚-mthumb对链接器是否有任何意义,它不创建指令,而只是将您提供的链接对象连接在一起,以及
arm-none-eabi-gcc -o .pio/build/commonsense/src/main.o -c -std=gnu11 -mfpu=fpv4-sp-d16 -Og -g3 -mlong-calls --specs=nano.specs -specs=nosys.specs -fdata-sections -ffunction-sections -mfloat-abi=softfp -march=armv7e-m -mfpu=fpv4-sp-d16 -marm -mthumb-interwork -ffunction-sections -fdata-sections -Wall -mthumb -nostdlib --param max-inline-insns-single=500 -mcpu=cortex-m4 -DPLATFORMIO=50003 -D__SAMD51P20A__ -D__SAMD51__ -D__FPU_PRESENT -DARM_MATH_CM4 -DENABLE_CACHE -DVARIANT_QSPI_BAUD_DEFAULT=50000000 -DDEBUG -DADAFRUIT_LINKER -DF_CPU=120000000L -Iinclude -Isrc -I/Users/work-reese/.platformio/packages/framework-cmsis/CMSIS/Include -I/Users/work-reese/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL -I/Users/work-reese/.platformio/packages/framework-cmsis-atmel/CMSIS/Device/ATMEL/samd51 -I/Users/work-reese/.platformio/packages/framework-commonsense -I/Users/work-reese/.platformio/packages/framework-commonsense/core -I/Users/work-reese/.platformio/packages/framework-commonsense/hal -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/include -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/utils/include -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/utils/src -I/Users/work-reese/.platformio/packages/framework-commonsense/hal/src -I/Users/work-reese/.platformio/packages/framework-commonsense/hpl -I/Users/work-reese/.platformio/packages/framework-commonsense/hri -I/Users/work-reese/.platformio/packages/framework-commonsense/sample src/main.c