This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/46644] New: Built-in memcpy() does not test for unaligned destination address on ARM
- From: "eblot.ml at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 24 Nov 2010 19:15:15 +0000
- Subject: [Bug target/46644] New: Built-in memcpy() does not test for unaligned destination address on ARM
- Auto-submitted: auto-generated
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: unassigned@gcc.gnu.org
ReportedBy: eblot.ml@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