tags 897390 = patch quit
Hello Eugene, I am not sure if gcc is here to blame as grub is here doing something unusual. Also there might be some (yet unknown) command line switch to gcc to restore old behaviour... Nevertheless I was curious on getting that working again ... Attached patch is not relying on having the static variables accessible after the stack got switched by putting pointer to them on the new stack. Tested so far: - i386/amd64: /usr/sbin/grub works. - amd64: grub-install works with a ext2 boot partition [1]. Booting the system after that worked too. For some reason it did not want to install to a ext4 system partition, but this might be a different problem (probably #748793). Kind regards, Bernhard PS.: You might leave 898...@bugs.debian.org always in CC, so your emails are added to the Debian bug. [1] Output of grub-install without the patch: # LANG=C grub-install /dev/sda Searching for GRUB installation directory ... found: /boot/grub Segmentation fault cmp: EOF on /tmp/grubJw13E3 which is empty Segmentation fault cmp: EOF on /tmp/grubJw13E3 which is empty Segmentation fault cmp: EOF on /tmp/grubJw13E3 which is empty Segmentation fault cmp: EOF on /tmp/grubJw13E3 which is empty Segmentation fault cmp: EOF on /tmp/grubJw13E3 which is empty The file /boot/grub/stage1 not read correctly. [2] Output of grub-install with the patch: # LANG=C grub-install /dev/sda Searching for GRUB installation directory ... found: /boot/grub Installation finished. No error reported. This is the contents of the device map /boot/grub/device.map. Check if this is correct or not. If any of the lines is incorrect, fix it and re-run the script `grub-install'. (fd0) /dev/fd0 (hd0) /dev/disk/by-id/ata-QEMU_HARDDISK_QM00001 (hd1) /dev/disk/by-id/ata-QEMU_HARDDISK_QM00002 Am 05.07.2018 um 21:09 schrieb Eugene Berdnikov: > Hello Bernhard. > > On Thu, Jul 05, 2018 at 06:10:44PM +0200, Bernhard Übelacker wrote: >> Hello Eugene, >> I just tried to reproduce the issue and collect some more information. >> Unfortunately grub-legacy has not yet a dbgsym package. >> But is also crashing with a self built package. > ... >> Unfortunately gcc-7 generates this sequence: >> mov 0xc(%esp),%eax >> mov %eax,%ebx >> movl $0x0,0xee8(%eax) >> >> So i guess gcc-7 relies to have the address of some area holding the static >> variables >> at the stack "0xc(%esp)", but as we switched stacks some lines before we get >> just a 0 into register $eax. > > Thank you very mush for this excellent job! > Unfortunately I can't help anymore, because I am sysadmin, not a programmer, > and have no skills and resources for communication with gcc developers. > > Grub-legacy is very good software, much more convinient and useful then > grub2. I use old builds in my environment. and hope this situation > will be resolved in the future... > > Have a good luck, and thanks again! >
From da061e19b041840ea3f21df944d5f9c12dec4369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <bernha...@mailbox.org> Date: Fri, 6 Jul 2018 18:16:58 +0200 Subject: Put pointers to static variables as arguments on the new stack to get it working with gcc 7. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=898553 --- grub/asmstub.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/grub/asmstub.c b/grub/asmstub.c index 52b21c4..39f7585 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -123,32 +123,42 @@ grub_stage2 (void) char *scratch, *simstack; int i; - auto void doit (void); + auto void doit_wrapper (void); + auto void doit (jmp_buf *p_env_for_exit, int *p_status); + void doit_wrapper (void) + { + asm volatile ("movl %%esp, %0\n\t" + "movl %2, %%esp\n\t" /* Make sure our stack lives in the simulated memory area. */ + "pushl %1\n\t" /* Put realstack on the new stack */ + "pushl %3\n\t" /* Put &status on the new stack */ + "pushl %4\n\t" /* Put &env_for_exit on the new stack */ + "call *%5\n\t" /* Call doit */ + "popl %0\n\t" /* Remove &env_for_exit from the stack */ + "popl %0\n\t" /* Remove &status from the stack */ + "popl %0\n\t" /* Retrieve realstack from the new stack */ + "movl %1, %%esp\n" /* Switch back to the original stack */ + : "=&r" (realstack) + : "0" (realstack), "r" (simstack), "r" (&status), "r" (&env_for_exit), "r" (doit)); + } + /* We need a nested function so that we get a clean stack frame, regardless of how the code is optimized. */ - void doit (void) + void doit (jmp_buf *p_env_for_exit, int *p_status) { - /* Make sure our stack lives in the simulated memory area. */ - asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n" - : "=&r" (realstack) : "r" (simstack)); - /* Do a setjmp here for the stop command. */ - if (! setjmp (env_for_exit)) + if (! setjmp (*p_env_for_exit)) { /* Actually enter the generic stage2 code. */ - status = 0; + *p_status = 0; init_bios_info (); } else { /* If ERRNUM is non-zero, then set STATUS to non-zero. */ if (errnum) - status = 1; + *p_status = 1; } - - /* Replace our stack before we use any local variables. */ - asm volatile ("movl %0, %%esp\n" : : "r" (realstack)); } assert (grub_scratch_mem == 0); @@ -211,7 +221,7 @@ grub_stage2 (void) /* Set our stack, and go for it. */ simstack = (char *) PROTSTACKINIT; - doit (); + doit_wrapper (); /* I don't know if this is necessary really. */ sync (); -- 2.18.0