[PATCH] Mark swapcontext returns_twice without indirect_return [BZ #23130]

Stian Halseth <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
swapcontext does not restore every callee-saved register on all targets.
On sparc the %l and %i registers are not in the saved context at all:
they live in the register window save area of the calling frame, which
another pass through that frame can overwrite.  stdlib/tst-setcontext2
fails on sparc64 for this reason at -O2 with PIC, where gcc keeps
&global in %i5 across swapcontext and reuses %i5 as the GOT base on
another path through the same frame.

Make the generic bits/indirect-return.h fall back to returns_twice where
indirect_return is unavailable, covering every affected target.  x86 and
aarch64 keep their own headers, which gate on CET and on GCS, so those
targets are unchanged.

string/tst-xbzero-opt.c calls swapcontext from an always_inline
function, which a returns_twice callee forbids; key its guard on the
availability of indirect_return rather than on __CET__.  It is the only
such site in the tree.

Tested on sparc64: full make check is clean, with no test that passed
before failing after.

Signed-off-by: Stian Halseth <[email protected]>
---
 bits/indirect-return.h  | 15 +++++++++++++--
 string/tst-xbzero-opt.c |  7 +++----
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/bits/indirect-return.h b/bits/indirect-return.h
index 819bd25b..4bfe3d35 100644
--- a/bits/indirect-return.h
+++ b/bits/indirect-return.h
@@ -21,5 +21,16 @@
 #endif
 
 /* __INDIRECT_RETURN is used on swapcontext to indicate if it requires
-   special compiler treatment.  */
-#define __INDIRECT_RETURN
+   special compiler treatment.  swapcontext does not restore every
+   callee-saved register on all targets -- on sparc the %l and %i
+   registers are not in the saved context at all -- so where
+   indirect_return is unavailable, returns_twice stops the compiler
+   assuming such a value survives the call.  Targets that need this only
+   under an optional feature override this file.  */
+#if __glibc_has_attribute (__indirect_return__)
+# define __INDIRECT_RETURN __attribute__ ((__indirect_return__))
+#elif __glibc_has_attribute (__returns_twice__)
+# define __INDIRECT_RETURN __attribute__ ((__returns_twice__))
+#else
+# define __INDIRECT_RETURN
+#endif
diff --git a/string/tst-xbzero-opt.c b/string/tst-xbzero-opt.c
index 3aa13d03..26e2ec1c 100644
--- a/string/tst-xbzero-opt.c
+++ b/string/tst-xbzero-opt.c
@@ -111,10 +111,9 @@ use_test_buffer (unsigned char *buf)
 /* Always check the test buffer immediately after filling it; this
    makes externally visible side effects depend on the buffer existing
    and having been filled in.  */
-#if defined __CET__ && !__glibc_has_attribute (__indirect_return__)
-/* Note: swapcontext returns via indirect branch when SHSTK is enabled.
-   Without indirect_return attribute, swapcontext is marked with
-   returns_twice attribute, which prevents always_inline to work.  */
+#if !__glibc_has_attribute (__indirect_return__)
+/* Without indirect_return, swapcontext is marked returns_twice, which
+   prevents always_inline from working.  */
 # define ALWAYS_INLINE
 #else
 # define ALWAYS_INLINE	__attribute__ ((always_inline))
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.