You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AARCH64下memcpy触发未对齐数据中止异常:工具链或newlibc Bug?

裸机AArch64环境下memcpy未对齐访问异常问题及修复咨询

环境与问题背景

在裸机项目中使用ARM GCC版本aarch64-none-elf-gcc-11.2.1,通过编译选项:

-L$AARCH64_GCC_PATH/aarch64-none-elf/lib -lc -lnosys -lg

成功调用malloc/memcpy等libc函数。尽管编译时添加了-mstrict-align选项,近期仍出现memcpy因未对齐访问触发的Data Abort异常。

经隔离测试发现:当复制设备类内存且size为0x8 + 0x4*n(n为自然数)时,即使src/dst指针对齐,memcpy汇编中的ldur x7, [x4, #-8]指令(位于地址6009c处)会将32位对齐、末位为0x4的地址加载到64位x寄存器,触发系统类内存的未对齐访问异常。

问题复现单元测试

#include <stdlib.h>
#include <string.h>
volatile int bssTest;

void swap(int a, int b) {
    memcpy((void*)0x500,(void*)0x1000,0xc);
}

触发异常的memcpy汇编代码

0000000000060040 <memcpy>:
   60040:   f9800020    prfm    pldl1keep, [x1]
   60044:   8b020024    add x4, x1, x2
   60048:   8b020005    add x5, x0, x2
   6004c:   f100405f    cmp x2, #0x10
   60050:   54000209    b.ls    60090 <memcpy+0x50>  // b.plast
   60054:   f101805f    cmp x2, #0x60
   60058:   54000648    b.hi    60120 <memcpy+0xe0>  // b.pmore
   6005c:   d1000449    sub x9, x2, #0x1
   60060:   a9401c26    ldp x6, x7, [x1]
   60064:   37300469    tbnz    w9, #6, 600f0 <memcpy+0xb0>
   60068:   a97f348c    ldp x12, x13, [x4, #-16]
   6006c:   362800a9    tbz w9, #5, 60080 <memcpy+0x40>
   60070:   a9412428    ldp x8, x9, [x1, #16]
   60074:   a97e2c8a    ldp x10, x11, [x4, #-32]
   60078:   a9012408    stp x8, x9, [x0, #16]
   6007c:   a93e2caa    stp x10, x11, [x5, #-32]
   60080:   a9001c06    stp x6, x7, [x0]
   60084:   a93f34ac    stp x12, x13, [x5, #-16]
   60088:   d65f03c0    ret
   6008c:   d503201f    nop
   60090:   f100205f    cmp x2, #0x8
   60094:   540000e3    b.cc    600b0 <memcpy+0x70>  // b.lo, b.ul, b.last
   60098:   f9400026    ldr x6, [x1]
   6009c:   f85f8087    ldur    x7, [x4, #-8]  // 触发异常的指令
   600a0:   f9000006    str x6, [x0]
   600a4:   f81f80a7    stur    x7, [x5, #-8]
   600a8:   d65f03c0    ret
   600ac:   d503201f    nop
   600b0:   361000c2    tbz w2, #2, 600c8 <memcpy+0x88>
   600b4:   b9400026    ldr w6, [x1]
   600b8:   b85fc087    ldur    w7, [x4, #-4]
   600bc:   b9000006    str w6, [x0]
   600c0:   b81fc0a7    stur    w7, [x5, #-4]
   600c4:   d65f03c0    ret
   600c8:   b4000102    cbz x2, 600e8 <memcpy+0xa8>
   600cc:   d341fc49    lsr x9, x2, #1
   600d0:   39400026    ldrb    w6, [x1]
   600d4:   385ff087    ldurb   w7, [x4, #-1]
   600d8:   38696828    ldrb    w8, [x1, x9]
   600dc:   39000006    strb    w6, [x0]
   600e0:   38296808    strb    w8, [x0, x9]
   600e4:   381ff0a7    sturb   w7, [x5, #-1]
   600e8:   d65f03c0    ret
   600ec:   d503201f    nop
   600f0:   a9412428    ldp x8, x9, [x1, #16]
   600f4:   a9422c2a    ldp x10, x11, [x1, #32]
   600f8:   a943342c    ldp x12, x13, [x1, #48]
   600fc:   a97e0881    ldp x1, x2, [x4, #-32]
   60100:   a97f0c84    ldp x4, x3, [x4, #-16]
   60104:   a9001c06    stp x6, x7, [x0]
   60108:   a9012408    stp x8, x9, [x0, #16]
   6010c:   a9022c0a    stp x10, x11, [x0, #32]
   60110:   a903340c    stp x12, x13, [x0, #48]
   60114:   a93e08a1    stp x1, x2, [x5, #-32]
   60118:   a93f0ca4    stp x4, x3, [x5, #-16]
   6011c:   d65f03c0    ret
   60120:   92400c09    and x9, x0, #0xf
   60124:   927cec03    and x3, x0, #0xfffffffffffffff0
   60128:   a940342c    ldp x12, x13, [x1]
   6012c:   cb090021    sub x1, x1, x9
   60130:   8b090042    add x2, x2, x9
   60134:   a9411c26    ldp x6, x7, [x1, #16]
   60138:   a900340c    stp x12, x13, [x0]
   6013c:   a9422428    ldp x8, x9, [x1, #32]
   60140:   a9432c2a    ldp x10, x11, [x1, #48]
   60144:   a9c4342c    ldp x12, x13, [x1, #64]!
   60148:   f1024042    subs    x2, x2, #0x90
   6014c:   54000169    b.ls    60178 <memcpy+0x138>  // b.plast
   60150:   a9011c66    stp x6, x7, [x3, #16]
   60154:   a9411c26    ldp x6, x7, [x1, #16]
   60158:   a9022468    stp x8, x9, [x3, #32]
   6015c:   a9422428    ldp x8, x9, [x1, #32]
   60160:   a9032c6a    stp x10, x11, [x3, #48]
   60164:   a9432c2a    ldp x10, x11, [x1, #48]
   60168:   a984346c    stp x12, x13, [x3, #64]!
   6016c:   a9c4342c    ldp x12, x13, [x1, #64]!
   60170:   f1010042    subs    x2, x2, #0x40
   60174:   54fffee8    b.hi    60150 <memcpy+0x110>  // b.pmore
   60178:   a97c0881    ldp x1, x2, [x4, #-64]
   6017c:   a9011c66    stp x6, x7, [x3, #16]
   60180:   a97d1c86    ldp x6, x7, [x4, #-48]
   60184:   a9022468    stp x8, x9, [x3, #32]
   60188:   a97e2488    ldp x8, x9, [x4, #-32]
   6018c:   a9032c6a    stp x10, x11, [x3, #48]
   60190:   a97f2c8a    ldp x10, x11, [x4, #-16]
   60194:   a904346c    stp x12, x13, [x3, #64]
   60198:   a93c08a1    stp x1, x2, [x5, #-64]
   6019c:   a93d1ca6    stp x6, x7, [x5, #-48]
   601a0:   a93e24a8    stp x8, x9, [x5, #-32]
   601a4:   a93f2caa    stp x10, x11, [x5, #-16]
   601a8:   d65f03c0    ret
   601ac:   00000000    udf #0

疑问

在启用-mstrict-align选项时,newlib或编译器是否应该针对32位对齐但非64位对齐的memcpy场景,自动使用32位w寄存器进行访问,避免触发未对齐访问异常?

求助内容

由于代码库特性,难以确保所有memcpy调用的size都是64位对齐,现寻求以下帮助:

  • 临时修复方案有哪些?
  • 若需要自行重写memcpy,应基于什么实现?

内容的提问来源于stack exchange,提问作者gnu-it

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:34:57