首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ARM GCC生产未对齐STRD

ARM GCC生产未对齐STRD
EN

Stack Overflow用户
提问于 2021-10-18 09:34:13
回答 2查看 265关注 0票数 1

我用GCC编写了一个ARM皮质M3的程序。

我的程序导致了一个硬故障,我正在试图排除它。

GCC版本是10.3.1,但我也用旧版本(即9.2)确认了这一点。

只有在启用优化时( (-O3). )才会发生硬错误。

有问题的功能如下:

代码语言:javascript
复制
void XTEA_decrypt(XTEA_t * xtea, uint32_t data[2])
{
    uint32_t d0 = data[0];
    uint32_t d1 = data[1];
    uint32_t sum = XTEA_DELTA * XTEA_NUMBER_OF_ROUNDS;

    for (int i = XTEA_NUMBER_OF_ROUNDS; i != 0; i--)
    {
        d1 -= (((d0 << 4) ^ (d0 >> 5)) + d0) ^ (sum + xtea->key[(sum >> 11) & 3]);
        sum -= XTEA_DELTA;
        d0 -= (((d1 << 4) ^ (d1 >> 5)) + d1) ^ (sum + xtea->key[sum & 3]);
    }

    data[0] = d0;
    data[1] = d1;
}

我注意到错误发生在直线上:

代码语言:javascript
复制
    data[0] = d0;

拆开这个,给我:

代码语言:javascript
复制
49          data[0] = d0;
0000f696:   lsrs    r0, r3, #5
0000f698:   eor.w   r0, r0, r3, lsl #4
0000f69c:   add     r0, r3
0000f69e:   ldr.w   r12, [sp, #4]
0000f6a2:   eors    r5, r0
0000f6a4:   subs    r2, r2, r5
0000f6a6:   strd    r2, r3, [r12]
0000f6aa:   add     sp, #12
0000f6ac:   ldmia.w sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
0000f6b0:   ldr     r3, [sp, #576]  ; 0x240
0000f6b2:   b.n     0xfda4 <parseNode+232>

具体而言,冒犯的界限是:

代码语言:javascript
复制
0000f6a6:   strd    r2, r3, [r12]

GCC生成的代码使用strd的未对齐内存地址,这在我的体系结构中是不允许的。

如何解决这个问题呢?

这是编译器的错误,还是代码混淆了GCC?

GCC身上有没有改变这种行为的旗帜?

上述函数属于外部库,因此我无法修改它。

然而,我更喜欢让GCC生成正确指令的解决方案,而不是修改代码,因为我需要确保这个bug实际上是被修复的,而且它不会潜伏在代码的其他地方。

更新

根据评论中的建议,我怀疑函数本身是用未对齐的数据调用的。

我检查了整个堆栈框架,所有以前的函数调用,我的代码不包含强制转换、缓冲区中的未对齐索引等,这与我最初设想的不同。

问题是缓冲区本身是不对齐的,因为它被定义为:

代码语言:javascript
复制
typedef struct {
    uint32_t var1;
    uint32_t var2;
    uint8_t var3;
    uint8_t buffer[BUFFER_SIZE];
    uint16_t var4;
    // More variables here...
} HDLC_t;

(然后由外部库强制转换为uint32_t )。

var3buffer之间交换位置解决了这个问题。

问题是,这个结构是在一个不在我控制范围内的库中定义的。

那么,GCC能不能在图书馆之间发现这个问题,或者把数据对齐,或者警告我这个问题?

EN

回答 2

Stack Overflow用户

发布于 2021-10-18 14:12:18

那么,GCC能不能在图书馆之间发现这个问题,或者把数据对齐,或者警告我这个问题?

是的,它可以,它做,它必须这样做,以便符合C。如果您在默认设置下运行gcc并尝试将uint8_t指针(HDLC_t buffer成员)传递给需要uint32_t [2]的函数,则会发生这种情况。

警告:从不兼容的指针类型传递'XTEA_decrypt‘的参数2-warning兼容-指针-类型

这违反了约束,这意味着代码是无效的C,编译器已经告诉了您很多。请参阅当C编译器发现错误时,它必须做什么?,如果您希望阻止gcc C从无效的C代码中生成二进制可执行文件,您可以打开-pedantic-errors

至于如何修复代码,如果您一直使用这个structmemcpy,将buffer成员放入一个临时的uint32_t [2]数组中,然后将该数组传递给函数。

您也可以将struct成员声明为_Alignas(uint32_t) uint8_t buffer[100];,但是如果您可以修改结构,您最好重新安排它,因为_Alignas将插入3个浪费的填充字节。

票数 3
EN

Stack Overflow用户

发布于 2021-10-18 09:51:47

最简单的方法是将data对齐到8字节。

您应该声明数组如下:

代码语言:javascript
复制
__attribute__((aligned(8))) uint32_t data[2];
票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69613802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档