Source: emacs24
Severity: normal
Tags: upstream patch
User: debian-sp...@lists.debian.org
Usertags: sparc64
Dear Maintainer,
The emacs24 build is currently failing on sparc64 with a Bus
Error. You can see an example build log here:
https://buildd.debian.org/status/fetch.php?pkg=emacs24=sparc64=24.5%2B1-5=1448688813
I've attached a patch that corrects an unaligned pointer dereference
in src/unexelf.c. But my fix is more of a hack and probably not suitable
for submitting to upstream.
I'm going to continue looking at this issue to try to create a
more robust fix to offer upstream.
Below is a short explaination of what I've found looking into this
build failure.
The lucid build is failing with this error:
Loading /«BUILDDIR»/emacs24-24.5+1/debian/build-lucid/lisp/electric.el
(source)...
Loading /«BUILDDIR»/emacs24-24.5+1/debian/build-lucid/lisp/tooltip.el
(source)...
Finding pointers to doc strings...
Finding pointers to doc strings...done
Dumping under the name emacs
/bin/bash: line 7: 19090 Bus error ./temacs --batch --load loadup
bootstrap
make[3]: *** [bootstrap-emacs] Error 1
Makefile:815: recipe for target 'bootstrap-emacs' failed
make[3]: Leaving directory '/«BUILDDIR»/emacs24-24.5+1/debian/build-lucid/src'
make[2]: *** [src] Error 2
Makefile:389: recipe for target 'src' failed
Loading 'temacs' in gdb the bus error occurs in the file
src/unexelf.c, around line 980:
*/
if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset
|| (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
> new_data2_offset))
NEW_SECTION_H (nn).sh_offset += new_data2_incr;
With this instruction:
0x294c20 ldx [ %g4 + 0x18 ], %g2
// info reg g4 => 0x80011458013b -140732852076229
So it's trying to load an extended word (64bits, 8 bytes) from an
unaligned address.
NEW_SECTION_H is a macro that generates a pointer offset from
'new_section_h'.
static void *
entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
{
char *h = section_h;
return h + idx * entsize;
}
#define NEW_SECTION_H(n) \
(*(ElfW (Shdr) *) entry_address (new_section_h, n,
new_file_h->e_shentsize))
If 'new_section_h' is properly aligned this should be ok because it's
adding multiples of 'e_shentsize' which is 8. But new_section_h is
/not/ aligned so the resulting pointer is also not aligned.
Here is how 'new_section_h' is computed:
new_section_h = (ElfW (Shdr) *)
((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
GDB says the components of this sum have these values:
(gdb) print new_base
$6 = (caddr_t) 0x8001126aa000 "\177ELF\002\002\001"
(gdb) print old_file_h->e_shoff
$7 = 15751616
(gdb) print new_data2_incr
$8 = 16582459
'new_base' and 'old_file_h->e_shoff' are both 8 byte aligned but
'new_data2_incr' is not.
'new_data2_incr' is calculated this way:
new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
It seems like 'new_data2_incr' is just an offset so it would be ok to
round it up to the nearest multiple of 8, using a function already
used in the file:
new_data2_incr = round_up(new_data2_incr, (ElfW (Addr))8);
Adding this line to src/unexelf.c allows the build to finish normally.
-- System Information:
Debian Release: stretch/sid
APT prefers unreleased
APT policy: (500, 'unreleased'), (500, 'unstable')
Architecture: sparc64
Kernel: Linux 4.3.0-gentoo (SMP w/1 CPU core)
Locale: LANG=en_SG.UTF-8, LC_CTYPE=en_SG.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: unable to detect
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -779,6 +779,9 @@
the end of the old .data section (and thus the offset of the .bss
section) was unaligned. */
new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
+#ifdef __sparc_v9__
+ new_data2_incr = round_up(new_data2_incr, (ElfW (Addr))8);
+#endif
#ifdef UNEXELF_DEBUG
fprintf (stderr, "old_bss_index %td\n", old_bss_index);