This is the mail archive of the
libc-ports@sources.redhat.com
mailing list for the libc-ports project.
[ARM] Alignment trap in dynamic linker
- From: Ladislav Michl <Ladislav dot Michl at seznam dot cz>
- To: libc-ports at sourceware dot org
- Date: Wed, 18 Nov 2009 21:01:53 +0100
- Subject: [ARM] Alignment trap in dynamic linker
- Reply-to: Ladislav Michl <ladis at linux-mips dot org>
I sent this issue to crossgcc mailing list with no luck, so lets give it
a try here...
I built ARM EABI toolchain using OSELAS.Toolchain
arm-v4t-linux-gnueabi_gcc-4.4.0_glibc-2.9_binutils-2.19.1_kernel-2.6.29-sanitized.ptxconfig
and run freshly built userland with 2.6.32-rc5 kernel on OMAP5910 (ARM925)
based board. Running every single binary triggers alignment trap.
Here's illustrative example (after boot):
# cat /proc/cpu/alignment
User: 201
System: 0
Skipped: 0
Half: 0
Word: 0
Multi: 0
User faults: 0 (ignored)
# echo 3 > /proc/cpu/alignment
# cat /proc/cpu/alignment
Alignment trap: cat (236) PC=0x4000aba8 Instr=0xe7951002 Address=0x4022b9a7 FSR 0x001
Alignment trap: cat (236) PC=0x4000abb4 Instr=0xe7851002 Address=0x4022b9a7 FSR 0x811
Alignment trap: cat (236) PC=0x4000aba8 Instr=0xe7951002 Address=0x4022bffa FSR 0x001
Alignment trap: cat (236) PC=0x4000abb4 Instr=0xe7851002 Address=0x4022bffa FSR 0x801
User: 205
System: 0
Skipped: 0
Half: 0
Word: 4
Multi: 0
User faults: 3 (fixup+warn)
Looking at process map shows that 0x4000aba8 belongs to /lib/ld-2.9.so address
space and objdump finds out alignment trap is triggered from
elf_machine_rel_relative. I found similar problem described here:
http://www.opensubscriber.com/message/fedora-devel-list@redhat.com/5545902.html
and blindly modified it for arm and unaligned access went away...
--- glibc-ports-2.9/sysdeps/arm/dl-machine.h.orig 2009-11-03 22:03:57.000000000 +0100
+++ glibc-ports-2.9/sysdeps/arm/dl-machine.h 2009-11-03 22:11:45.000000000 +0100
@@ -568,13 +568,22 @@
}
# endif
+union arm_unaligned_data {
+ Elf32_Addr l_addr;
+} __attribute__ ((packed));
+
auto inline void
__attribute__ ((always_inline))
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
void *const reloc_addr_arg)
{
- Elf32_Addr *const reloc_addr = reloc_addr_arg;
- *reloc_addr += l_addr;
+ if (((long)reloc_addr_arg) & 0x3) {
+ union arm_unaligned_data *const lpdata = reloc_addr_arg;
+ lpdata->l_addr += l_addr;
+ } else {
+ Elf32_Addr *const reloc_addr = reloc_addr_arg;
+ *reloc_addr += l_addr;
+ }
}
# ifndef RTLD_BOOTSTRAP
However this solution didn't went into repository so the right fix is probably
different. Anyone seen this? I will happily RTFM, just point me where to find
it.
Thanks,
ladis