|
|
077c9d |
commit a55e109709af55e6ed67d3f9536cac5d929c982e
|
|
|
077c9d |
Author: Carlos O'Donell <carlos@redhat.com>
|
|
|
077c9d |
Date: Wed Sep 5 01:16:42 2018 -0400
|
|
|
077c9d |
|
|
|
077c9d |
Fix tst-setcontext9 for optimized small stacks.
|
|
|
077c9d |
|
|
|
077c9d |
If the compiler reduces the stack usage in function f1 before calling
|
|
|
077c9d |
into function f2, then when we swapcontext back to f1 and continue
|
|
|
077c9d |
execution we may overwrite registers that were spilled to the stack
|
|
|
077c9d |
while f2 was executing. Later when we return to f2 the corrupt
|
|
|
077c9d |
registers will be reloaded from the stack and the test will crash. This
|
|
|
077c9d |
was most commonly observed on i686 with __x86.get_pc_thunk.dx and
|
|
|
077c9d |
needing to save and restore $edx. Overall i686 has few registers and
|
|
|
077c9d |
the spilling to the stack is bound to happen, therefore the solution to
|
|
|
077c9d |
making this test robust is to split function f1 into two parts f1a and
|
|
|
077c9d |
f1b, and allocate f1b it's own stack such that subsequent execution does
|
|
|
077c9d |
not overwrite the stack in use by function f2.
|
|
|
077c9d |
|
|
|
077c9d |
Tested on i686 and x86_64.
|
|
|
077c9d |
|
|
|
077c9d |
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
|
|
|
077c9d |
(cherry picked from commit 791b350dc725545e3f9b5db0f97ebdbc60c9735f)
|
|
|
077c9d |
|
|
|
077c9d |
diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c
|
|
|
077c9d |
index 4636ce9030fa38a7..db8355766ca7b906 100644
|
|
|
077c9d |
--- a/stdlib/tst-setcontext9.c
|
|
|
077c9d |
+++ b/stdlib/tst-setcontext9.c
|
|
|
077c9d |
@@ -41,26 +41,55 @@ f2 (void)
|
|
|
077c9d |
}
|
|
|
077c9d |
|
|
|
077c9d |
static void
|
|
|
077c9d |
-f1 (void)
|
|
|
077c9d |
+f1b (void)
|
|
|
077c9d |
{
|
|
|
077c9d |
- puts ("start f1");
|
|
|
077c9d |
- if (getcontext (&ctx[2]) != 0)
|
|
|
077c9d |
- {
|
|
|
077c9d |
- printf ("%s: getcontext: %m\n", __FUNCTION__);
|
|
|
077c9d |
- exit (EXIT_FAILURE);
|
|
|
077c9d |
- }
|
|
|
077c9d |
if (done)
|
|
|
077c9d |
{
|
|
|
077c9d |
- puts ("set context in f1");
|
|
|
077c9d |
+ puts ("set context in f1b");
|
|
|
077c9d |
if (setcontext (&ctx[3]) != 0)
|
|
|
077c9d |
{
|
|
|
077c9d |
printf ("%s: setcontext: %m\n", __FUNCTION__);
|
|
|
077c9d |
exit (EXIT_FAILURE);
|
|
|
077c9d |
}
|
|
|
077c9d |
}
|
|
|
077c9d |
+ exit (EXIT_FAILURE);
|
|
|
077c9d |
+}
|
|
|
077c9d |
+
|
|
|
077c9d |
+static void
|
|
|
077c9d |
+f1a (void)
|
|
|
077c9d |
+{
|
|
|
077c9d |
+ char st2[32768];
|
|
|
077c9d |
+ puts ("start f1a");
|
|
|
077c9d |
+ if (getcontext (&ctx[2]) != 0)
|
|
|
077c9d |
+ {
|
|
|
077c9d |
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
|
|
|
077c9d |
+ exit (EXIT_FAILURE);
|
|
|
077c9d |
+ }
|
|
|
077c9d |
+ ctx[2].uc_stack.ss_sp = st2;
|
|
|
077c9d |
+ ctx[2].uc_stack.ss_size = sizeof st2;
|
|
|
077c9d |
+ ctx[2].uc_link = &ctx[0];
|
|
|
077c9d |
+ makecontext (&ctx[2], (void (*) (void)) f1b, 0);
|
|
|
077c9d |
f2 ();
|
|
|
077c9d |
}
|
|
|
077c9d |
|
|
|
077c9d |
+/* The execution path through the test looks like this:
|
|
|
077c9d |
+ do_test (call)
|
|
|
077c9d |
+ -> "making contexts"
|
|
|
077c9d |
+ -> "swap contexts"
|
|
|
077c9d |
+ f1a (via swapcontext to ctx[1], with alternate stack)
|
|
|
077c9d |
+ -> "start f1a"
|
|
|
077c9d |
+ f2 (call)
|
|
|
077c9d |
+ -> "swap contexts in f2"
|
|
|
077c9d |
+ f1b (via swapcontext to ctx[2], with alternate stack)
|
|
|
077c9d |
+ -> "set context in f1b"
|
|
|
077c9d |
+ do_test (via setcontext to ctx[3], main stack)
|
|
|
077c9d |
+ -> "setcontext"
|
|
|
077c9d |
+ f2 (via setcontext to ctx[4], with alternate stack)
|
|
|
077c9d |
+ -> "end f2"
|
|
|
077c9d |
+
|
|
|
077c9d |
+ We must use an alternate stack for f1b, because if we don't then the
|
|
|
077c9d |
+ result of executing an earlier caller may overwrite registers
|
|
|
077c9d |
+ spilled to the stack in f2. */
|
|
|
077c9d |
static int
|
|
|
077c9d |
do_test (void)
|
|
|
077c9d |
{
|
|
|
077c9d |
@@ -79,7 +108,7 @@ do_test (void)
|
|
|
077c9d |
ctx[1].uc_stack.ss_sp = st1;
|
|
|
077c9d |
ctx[1].uc_stack.ss_size = sizeof st1;
|
|
|
077c9d |
ctx[1].uc_link = &ctx[0];
|
|
|
077c9d |
- makecontext (&ctx[1], (void (*) (void)) f1, 0);
|
|
|
077c9d |
+ makecontext (&ctx[1], (void (*) (void)) f1a, 0);
|
|
|
077c9d |
puts ("swap contexts");
|
|
|
077c9d |
if (swapcontext (&ctx[3], &ctx[1]) != 0)
|
|
|
077c9d |
{
|