summarylogtreecommitdiffstats
path: root/static-vars-on-stack.patch
blob: ce97a331dec0ed6063de15b9e6e9cf6fa0b518e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Description: Put pointers to static variables as arguments on the new stack
 to get it working with gcc 7.
Author: Bernhard Übelacker <bernhardu@mailbox.org>
Forwarded: no
Bug-Debian: https://bugs.debian.org/898553
Last-Update: 2018-07-06

Index: b/grub/asmstub.c
===================================================================
--- a/grub/asmstub.c
+++ b/grub/asmstub.c
@@ -123,32 +123,42 @@
   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 @@
 
   /* Set our stack, and go for it. */
   simstack = (char *) PROTSTACKINIT;
-  doit ();
+  doit_wrapper ();
 
   /* I don't know if this is necessary really.  */
   sync ();