为啥 GCC 会为 ARM Cortex-A9 产生非法未对齐访问

Posted

技术标签:

【中文标题】为啥 GCC 会为 ARM Cortex-A9 产生非法未对齐访问【英文标题】:Why does GCC produce illegal unalign accesses for ARM Cortex-A9为什么 GCC 会为 ARM Cortex-A9 产生非法未对齐访问 【发布时间】:2016-01-22 16:28:56 【问题描述】:

目标:ARM Cortex-A9 GCC 版本:4.9.2

大家好,

我在 GCC 生成核心时遇到问题,由于未对齐的访问导致数据中止。我隔离了一段显示问题的代码。我不知道如何让 GCC 正确处理这个问题。帮助将不胜感激!

struct B

    char c1;
    char c2;
    char c3;
    char c4;
;

struct A

    char c;
    struct B b;
    char c2;
;

int main(int argc, char** argv)

    struct A a;
    a.c2 = 42;    // Works fine
    a.b.c1 = 42   // Works fine, too
    struct B b;
    b = a.b;      // Crashes because of unaligned access
    return 0;

内存布局如下:

a           struct A    48  S:0x3FFFFFE0    R/W
  c         char        8   S:0x3FFFFFE0    R/W
  b         struct B    32  S:0x3FFFFFE1    R/W
    c1      char        8   S:0x3FFFFFE1    R/W
    c2      char        8   S:0x3FFFFFE2    R/W
    c3      char        8   S:0x3FFFFFE3    R/W
    c4      char        8   S:0x3FFFFFE4    R/W
  c2        char        8   S:0x3FFFFFE5    R/W

现在是前两个赋值命令,比如

a.c2 = 42;     : STRB     r3,[r11,#-7]       with r11 = 0x3FFFFFEC

已生产,并且工作正常。

但是,对于最后的分配,

b = a.b;       : LDR      r0,[r2,#0]         with r2 = 0x3FFFFFE1

产生由于未对齐的访问而导致数据中止的结果。 GCC 不会发出任何警告或任何相关信息。

有人知道怎么解决吗?

顺便说一句,所有结构声明中的对齐属性在我的项目中都不是一个选项。

【问题讨论】:

似乎工作ideone.com/vr3Szy 您正在使用什么特定的 GCC 构建/配置,使用什么调用选项,以及在什么情况下您设置了 SCTLR.A 位,或者正在访问非正常内存的其他内容,从而导致未对齐的 LDR 是否会出错(鉴于它是 v7 核心)? 程序本身是完全有效的 C++,所以不应该有任何警告。 我认为这是 GCC 中的一个错误。一种解决方法是强制 B 字对齐。 @Keith 这不是错误,当 GCC 认为它的目标是在正常内存上运行的 v7 内核时,它只会将 4 字节 memcpy 优化为一对 32 位加载/存储指令这样对齐就无关紧要了(就像在 x86 上一样)。真正的问题是 OP 系统的哪个方面导致该假设不成立。 【参考方案1】:

如果你使用-mno-unaligned-access,你会得到correct result。

令我惊讶的是,默认情况下它没有这样做,因为在 arm 上进行未对齐的内存访问经常是错误的。

【讨论】:

不需要使用链接缩短器,因为答案中的链接长度没有限制。 这应该不足为奇 - 考虑为链接示例提供动力的 GCC 的 Linaro arm-linux-gnueabihf 构建:这是针对 Linux 的,并且默认配置为为 v7 CPUS 发出代码,因此它知道在那些情况下发出未对齐的 LDR/STR 完全没问题,因此在没有被告知的情况下会很乐意这样做。当然,如果您随后获取该代码并在 v6 之前的 CPU(使用旧的未对齐访问模型)或不同的目标 ABI(例如 no-MMU 裸机)上运行它,就会出现问题,但这几乎不是编译器的错。 . 谢谢,帮助! :-)

以上是关于为啥 GCC 会为 ARM Cortex-A9 产生非法未对齐访问的主要内容,如果未能解决你的问题,请参考以下文章

SQLite3在ARM Cortex-A9开发板上的移植

你能帮我理解 ARM Cortex-A9 上的缓存行为吗?

飞思卡尔 iMX6q ARM 处理器的 gcc 选项

《基于ARM Cortex-A9的嵌入式Linux内核移植研究与实现》

ARM processors DMIPS/MHz comparison

[cpu]TI cortex-A9 查看cpu的频率