http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46644
Summary: Built-in memcpy() does not test for unaligned destination address on ARM Product: gcc Version: 4.4.3 Status: UNCONFIRMED Severity: major Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: eblot...@gmail.com Foreword: this bug might be related to 46483 (over-aggresive memcpy() optimization) although the input instructions to trigger the issue seem to be different. Using GCC 4.4.3 up to at least 4.5.1, with a ARM-EABI target (AAPCS variant, not tested with a Linux-modified EABI), for ARMv4/ARMv5 architectures - at least. GCC performs aggressive memcpy() optimization, replacing the memcpy() function call with direct ARM instructions. When a 16-bit value is copied, GCC "forgets" to handle the un-aligned destination address cases. Code example: void memcpy_test(void) { extern uint16_t * msrc; // actual address is not known on purpose extern uint16_t * mdst; // actual address is not known on purpose memcpy(mdst, msrc, sizeof(uint16_t)); } Generated code: 00000000 <memcpy_test>: 0: e59f2014 ldr r2, [pc, #20] ; 1c <memcpy_test+0x1c> 4: e59f3014 ldr r3, [pc, #20] ; 20 <memcpy_test+0x20> 8: e5922000 ldr r2, [r2] c: e5933000 ldr r3, [r3] 10: e1d220b0 ldrh r2, [r2] 14: e1c320b0 strh r2, [r3] 18: e12fff1e bx lr Here 'ldrh' and 'strh' have replaced the memcpy() call. However, if mdst or msrc are not aligned, the ARM CPU cannot properly copy the 16-bit values: destination contains a wrong value, and surrounding bytes may be overridden with the actual value. This issue does NOT occurs if: * mdst or msrc are not 16-bit pointers * -O0 is used (memcpy() optimization is disabled) In the above cases, the code looks like the expected one, that is: 00000000 <memcpy_test>: 0: e92d4008 push {r3, lr} 4: e59f3018 ldr r3, [pc, #24] ; 24 <memcpy_test+0x24> 8: e5930000 ldr r0, [r3] c: e59f3014 ldr r3, [pc, #20] ; 28 <memcpy_test+0x28> 10: e3a02002 mov r2, #2 14: e5931000 ldr r1, [r3] 18: ebfffffe bl 0 <memcpy> 1c: e8bd4008 pop {r3, lr} 20: e12fff1e bx lr However, the same issue can be reproduced if msrc and mdst pointer are 32-bit value pointers (uint32_t *). In this case, the generated and invalid code is: 00000000 <memcpy_test>: 0: e59f2014 ldr r2, [pc, #20] ; 1c <memcpy_test+0x1c> 4: e59f3014 ldr r3, [pc, #20] ; 20 <memcpy_test+0x20> 8: e5922000 ldr r2, [r2] c: e5933000 ldr r3, [r3] 10: e1d220b0 ldrh r2, [r2] 14: e1c320b0 strh r2, [r3] 18: e12fff1e bx lr GCC build options: Target: arm-eabi Configured with: ../configure --prefix=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.4.3 --target=arm-eabi --disable-shared --with-gnu-as --with-gnu-ld --with-newlib --enable-softfloat --disable-bigendian --disable-fpu --disable-underscore --enable-multilibs --with-float=soft --enable-interwork --with-fpu=fpa --with-multilib-list=interwork --with-abi=aapcs --enable-languages=c,c++ --disable-__cxa_atexit --with-gmp=/usr/local/homebrew/Cellar/gmp/5.0.1 --with-mpfr=/usr/local/homebrew/Cellar/mpfr/2.4.2 --with-ppl=/usr/local/homebrew/Cellar/ppl/0.10.2 --with-cloog=/usr/local/homebrew/Cellar/cloog-ppl/0.15.7 --with-libelf=/usr/local/homebrew/Cellar/libelf/0.8.13 --with-gxx-include-dir=/usr/local/homebrew/Cellar/gcc-arm-ecos/4.4.3/arm-eabi/include Thread model: single gcc version 4.4.3