]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
powerpc64: Always restore TOC on longjmp [BZ #21895]
authorRogerio Alves <rcardoso@linux.vnet.ibm.com>
Mon, 16 Jul 2018 18:07:10 +0000 (15:07 -0300)
committerTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Mon, 16 Jul 2018 19:08:41 +0000 (16:08 -0300)
This patch changes longjmp to always restore the TOC pointer (r2 register)
to the caller frame on powerpc64 and powerpc64le.  This is related to bug
21895 that reports a situation where you have a static longjmp to a
shared object file.

[BZ #21895]
* sysdeps/powerpc/powerpc64/__longjmp-common.S: Remove condition code for
restoring r2 in longjmp.
* sysdeps/powerpc/powerpc64/Makefile: Added tst-setjmp-bug21895-static to
test list.
Added rules to build test tst-setjmp-bug21895-static.
Added module setjmp-bug21895 and rules to build a shared object from it.
* sysdeps/powerpc/powerpc64/setjmp-bug21895.c: New test file.
* sysdeps/powerpc/powerpc64/tst-setjmp-bug21895-static.c: New test file.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
ChangeLog
sysdeps/powerpc/powerpc64/Makefile
sysdeps/powerpc/powerpc64/__longjmp-common.S
sysdeps/powerpc/powerpc64/setjmp-bug21895.c [new file with mode: 0644]
sysdeps/powerpc/powerpc64/tst-setjmp-bug21895-static.c [new file with mode: 0644]

index b921f906665d4491c0d068c45fbbe9d69e70d5b0..65dd07f41ca56dc2bb90825f4deebf3b0df9e63f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2018-07-16  Rogerio A. Cardoso  <rcardoso@linux.vnet.ibm.com>
+
+       [BZ #21895]
+       * sysdeps/powerpc/powerpc64/__longjmp-common.S: Remove condition code for
+       restore r2 on longjmp.
+       * sysdeps/powerpc/powerpc64/Makefile: Added tst-setjmp-bug21895-static to
+       test list.
+       Added rules to build test tst-setjmp-bug21895-static.
+       Added module setjmp-bug21895 and rules to build a shared object from it.
+       * sysdeps/powerpc/powerpc64/setjmp-bug21895.c: New test file.
+       * sysdeps/powerpc/powerpc64/tst-setjmp-bug21895-static.c: New test file.
+
 2018-07-15  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * benchtests/bench-strcasestr.c: Rename __strnlen to strnlen.
index 9d15db0328b8db98570f8fa923682be96a0d8af8..a0bd0c9504270a8767be0ccb0f4d398a95b43420 100644 (file)
@@ -47,3 +47,15 @@ ifeq ($(subdir),gmon)
 CFLAGS-mcount.c += $(no-special-regs)
 sysdep_routines += ppc-mcount
 endif
+
+ifeq ($(subdir),setjmp)
+tests += tst-setjmp-bug21895-static
+tests-static += tst-setjmp-bug21895-static
+modules-names += setjmp-bug21895
+
+$(objpfx)tst-setjmp-bug21895-static: $(common-objpfx)dlfcn/libdl.a
+$(objpfx)tst-setjmp-bug21895-static.out: $(objpfx)setjmp-bug21895.so
+
+tst-setjmp-bug21895-static-ENV = \
+       LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)setjmp:$(common-objpfx)elf
+endif
index 0e10b8de19aff8d1f5f58eded06baf37fe711d7f..99c17c5797e17f4ab3226e0ab35eb1b6ce0bfdee 100644 (file)
@@ -130,9 +130,6 @@ L(no_vmx):
        ld r0,(JB_LR*8)(r3)
        ld r14,((JB_GPRS+0)*8)(r3)
        lfd fp14,((JB_FPRS+0)*8)(r3)
-#if defined SHARED && !IS_IN (rtld)
-       std r2,FRAME_TOC_SAVE(r1)       /* Restore the callers TOC save area.  */
-#endif
        ld r15,((JB_GPRS+1)*8)(r3)
        lfd fp15,((JB_FPRS+1)*8)(r3)
        ld r16,((JB_GPRS+2)*8)(r3)
@@ -152,7 +149,7 @@ L(no_vmx):
        second argument (-4@4), and target address (8@0), respectively.  */
        LIBC_PROBE (longjmp, 3, 8@3, -4@4, 8@0)
        mtlr r0
-/*     std r2,FRAME_TOC_SAVE(r1)       Restore the TOC save area.  */
+       std r2,FRAME_TOC_SAVE(r1)       /* Restore the TOC save area.  */
        ld r21,((JB_GPRS+7)*8)(r3)
        lfd fp21,((JB_FPRS+7)*8)(r3)
        ld r22,((JB_GPRS+8)*8)(r3)
diff --git a/sysdeps/powerpc/powerpc64/setjmp-bug21895.c b/sysdeps/powerpc/powerpc64/setjmp-bug21895.c
new file mode 100644 (file)
index 0000000..945a251
--- /dev/null
@@ -0,0 +1,51 @@
+/* Shared object part of test for setjmp interoperability with static
+   dlopen BZ #21895.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <setjmp.h>
+
+/* Copy r1 adress to a local variable.  */
+#define GET_STACK_POINTER(sp)    \
+  ({                             \
+    asm volatile ("mr %0, 1\n\t"  \
+                 : "=r" (sp));   \
+  })
+
+jmp_buf jb;
+void (*bar)(jmp_buf, unsigned long);
+
+void
+lbar (unsigned long sp)
+{
+  bar(jb, sp);
+  for(;;);
+}
+
+void
+foo (void)
+{
+  unsigned long sp;
+  /* Copy r1 (stack pointer) to sp. It will be use later to get
+     TOC area.  */
+  GET_STACK_POINTER(sp);
+  setjmp(jb);
+  lbar(sp);
+
+  for(;;);
+}
diff --git a/sysdeps/powerpc/powerpc64/tst-setjmp-bug21895-static.c b/sysdeps/powerpc/powerpc64/tst-setjmp-bug21895-static.c
new file mode 100644 (file)
index 0000000..31ee88c
--- /dev/null
@@ -0,0 +1,75 @@
+/* Test setjmp interoperability with static dlopen BZ #21895.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+/* Set TOC area pointed by sp to zero.  */
+#define SET_TOC_TO_ZERO(sp)                                     \
+  ({                                                            \
+    unsigned int zero = 0;                                      \
+    asm volatile ("std %0, 24(%1)\n\t" :: "r" (zero), "r" (sp)); \
+  })
+
+static void
+bar (jmp_buf jb, unsigned long sp)
+{
+  static int i;
+  if (i++==1)
+    exit(0);   /* Success.  */
+
+  /* This will set TOC are on caller frame (foo) to zero. __longjmp
+     must restore r2 otherwise a segmentation fault will happens after
+     it jumps back to foo.  */
+  SET_TOC_TO_ZERO(sp);
+  longjmp(jb, i);
+}
+
+static int
+do_test (void)
+{
+  void *h = dlopen("setjmp-bug21895.so", RTLD_NOW);
+  if (!h)
+    {
+      puts(dlerror());
+      return 1;
+    }
+
+  void (*pfoo)(void) = dlsym(h, "foo");
+  if (!pfoo)
+    {
+      puts(dlerror());
+      return 1;
+    }
+
+  void (**ppbar)(jmp_buf, unsigned long) = dlsym(h, "bar");
+  if (!ppbar)
+    {
+      puts(dlerror());
+      return 1;
+    }
+
+  *ppbar = bar;
+  pfoo();
+
+  for(;;);
+}
+
+#include <support/test-driver.c>