【问题标题】:Structure alignment in aarch64aarch64中的结构对齐
【发布时间】:2018-02-24 07:56:00
【问题描述】:

用arm gcc交叉编译aarch64,结构如下:

struct lock {
    uint32_t lk;
};

总是被编译成一个与 8 个字节对齐的地址。 当我尝试将结构放到 4 字节对齐的地址上时,gcc 将在结构之前填充 4 个空字节以使其位于 8 字节对齐的地址上。

这是约定吗?或者我可以将其配置为 4 个字节对齐。

ldscript:

SECTIONS {
.init.data : {
         *(.init.data.v);
         *(.init.data.l);
 } > INIT_DATA
} 

在 .init.data.v 中有一个 uint32_t,然后在 .init.data.l 中有一个结构锁变量,但它们之间有一个 4 字节的填充。 如果代码在 .init.data.v 中有一个 uint32_t,然后在 .init.data.l 中有另一个 uint32_t,则没有 4 字节填充。

所以只有结构变量会导致这个 4 字节填充。

https://pastebin.com/kRsmPwrS

【问题讨论】:

  • 你的链接脚本是什么?
  • 我把这个结构体放在链接描述文件的一个用户定义的部分,从8字节对齐的地址开始,第一个变量是一个uint32_t,然后是这个结构体,但是它们之间有一个4字节的空填充
  • 我会尝试在链接描述文件中设置它。我现在没有任何类似的项目 - 所以不能尝试并且没有时间创建一个新项目。
  • 为什么要更改对齐方式?
  • 来自 Linaro 的某个人给了我下面的链接,它谈到了同样的问题,他鼓励报告对齐属性缺失的错误:gcc.gnu.org/ml/gcc-patches/2017-06/msg00317.html

标签: c gcc arm


【解决方案1】:

我猜,这是为了提高数据访问性能——你说的是 64 位 CPU。

【讨论】:

  • 能否让编译器将结构放入4字节对齐的地址?
  • 在 64 位 CPU 上将 4 字节对齐的地址转换为结构指针可以吗?
  • 可以试试这个:int x __attribute__ ((aligned (XXXX)))
  • 我尝试将 __attribute__((aligned(4)) __attribute__((packed(4)) 放在结构定义之后,它们都不起作用。
  • 我记得,对齐并不能保证。如果平台不支持所需的对齐,aligned atrubute 将被忽略。
【解决方案2】:

这个网站上有很多关于这个的问题。

您可能需要将-munaligned-access 传递给编译器以使其执行此操作,具体取决于您的确切目标处理器。这确实引出了为什么在这里的问题。

另见

Does AArch64 support unaligned access?

Linaro g++ aarch64 compilation cause unalignment fault

【讨论】:

    【解决方案3】:
    asm(".global _start; _start: b .");
    
    
    struct lock {
        unsigned int lk;
    };
    
    struct lock x;
    unsigned char a;
    unsigned short b;
    struct lock y;
    
    
    void centry ( void )
    {
    }
    

    Gcc 只是在尝试对齐

    Disassembly of section .text:
    
    0000000000001000 <_start>:
        1000:   14000000    b   1000 <_start>
        1004:   d503201f    nop
    
    0000000000001008 <centry>:
        1008:   d65f03c0    ret
    
    Disassembly of section .bss:
    
    0000000000002000 <b>:
        ...
    
    0000000000002008 <x>:
        ...
    
    0000000000002010 <y>:
        2010:   00000000    .inst   0x00000000 ; undefined
    
    0000000000002014 <a>:
        2014:   00000000    .inst   0x00000000 ; undefined
    

    如果你能避免它,你真的不应该抗拒它。如果您试图跨编译域指向结构,那么无论如何您都是在自找麻烦。

    asm(".global _start; _start: b .");
    
    
    struct lock {
        unsigned int lk;
    };
    
    struct lock x;
    unsigned char a;
    unsigned short b;
    unsigned int c;
    unsigned int d;
    struct lock y;
    unsigned int e;
    
    void centry ( void )
    {
    }
    

    成功了

    Disassembly of section .text:
    
    0000000000001000 <_start>:
        1000:   14000000    b   1000 <_start>
        1004:   d503201f    nop
    
    0000000000001008 <centry>:
        1008:   d65f03c0    ret
    
    Disassembly of section .bss:
    
    0000000000002000 <b>:
        ...
    
    0000000000002008 <x>:
        2008:   00000000    .inst   0x00000000 ; undefined
    
    000000000000200c <c>:
        200c:   00000000    .inst   0x00000000 ; undefined
    
    0000000000002010 <y>:
        2010:   00000000    .inst   0x00000000 ; undefined
    
    0000000000002014 <d>:
        2014:   00000000    .inst   0x00000000 ; undefined
    
    0000000000002018 <a>:
        2018:   00000000    .inst   0x00000000 ; undefined
    
    000000000000201c <e>:
        201c:   00000000    .inst   0x00000000 ; undefined
    

    我不会依赖这些设置或它们如何安排事物,您让编译器在结构上设置对齐和打包,以便理想情况下它不会产生对齐错误或性能损失。如果您开始惹麻烦,只是自找麻烦,可能需要几天或几年的时间才能遇到麻烦,但最终会的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 2014-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      相关资源
      最近更新 更多