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&arch=sparc64&ver=24.5%2B1-5&stamp=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 <unexec+1204> ldx [ %g4 + 0x18 ], %g2 // info reg g4 => 0xffff80011458013b -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) 0xffff8001126aa000 "\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);