fa3bfd
commit 533bb7c2ae156ff2d49b2e0b20b33810ba5e2721
fa3bfd
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
fa3bfd
Date:   Wed Nov 12 19:30:24 2014 +0530
fa3bfd
fa3bfd
    Fix stack alignment when loader is invoked directly
fa3bfd
    
fa3bfd
    The s390 ABI requires the stack pointer to be aligned at 8-bytes.
fa3bfd
    When a program is invoked as an argument to the dynamic linker,
fa3bfd
    _dl_start_user adjusts the stack to remove the dynamic linker
fa3bfd
    arguments so that the program sees only its name and arguments.  This
fa3bfd
    may result in the stack being misaligned since each argument shift is
fa3bfd
    only a word and not a double-word.
fa3bfd
    
fa3bfd
    This is now fixed shifting argv and envp down instead of shifting argc
fa3bfd
    up and reclaiming the stack.  This requires _dl_argv to be adjusted
fa3bfd
    and hence, is no longer relro.
fa3bfd
12745e
diff --git glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-machine.h glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-machine.h
5de29b
index c56185c..79f8ef9 100644
12745e
--- glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-machine.h
12745e
+++ glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-machine.h
5de29b
@@ -166,18 +166,49 @@ _dl_start_user:\n\
5de29b
 	# See if we were run as a command with the executable file\n\
5de29b
 	# name as an extra leading argument.\n\
5de29b
 	l     %r1,_dl_skip_args@GOT12(0,%r12)\n\
5de29b
-	l     %r1,0(%r1)          # load _dl_skip_args\n\
5de29b
+	l     %r1,0(%r1)	# load _dl_skip_args\n\
5de29b
+	ltr   %r1,%r1\n\
5de29b
+	je    .L4		# Skip the arg adjustment if there were none.\n\
5de29b
 	# Get the original argument count.\n\
5de29b
 	l     %r0,96(%r15)\n\
5de29b
 	# Subtract _dl_skip_args from it.\n\
5de29b
 	sr    %r0,%r1\n\
5de29b
-	# Adjust the stack pointer to skip _dl_skip_args words.\n\
5de29b
-	sll   %r1,2\n\
5de29b
-	ar    %r15,%r1\n\
5de29b
-	# Set the back chain to zero again\n\
5de29b
-	xc    0(4,%r15),0(%r15)\n\
5de29b
 	# Store back the modified argument count.\n\
5de29b
 	st    %r0,96(%r15)\n\
5de29b
+	# Copy argv and envp forward to account for skipped argv entries.\n\
5de29b
+	# We skipped at least one argument or we would not get here.\n\
5de29b
+	la    %r6,100(%r15)	# Destination pointer i.e. &argv[0]\n\
5de29b
+	lr    %r5,%r6\n\
5de29b
+	lr    %r0,%r1\n\
5de29b
+	sll   %r0,2\n		# Number of skipped bytes.\n\
5de29b
+	ar    %r5,%r0		# Source pointer = Dest + Skipped args.\n\
5de29b
+	# argv copy loop:\n\
5de29b
+.L1:	l     %r7,0(%r5)	# Load a word from the source.\n\
5de29b
+	st    %r7,0(%r6)	# Store the word in the destination.\n\
5de29b
+	ahi   %r5,4\n\
5de29b
+	ahi   %r6,4\n\
5de29b
+	ltr   %r7,%r7\n\
5de29b
+	jne   .L1		# Stop after copying the NULL.\n\
5de29b
+	# envp copy loop:\n\
5de29b
+.L2:	l     %r7,0(%r5)	# Load a word from the source.\n\
5de29b
+	st    %r7,0(%r6)	# Store the word in the destination.\n\
5de29b
+	ahi   %r5,4\n\
5de29b
+	ahi   %r6,4\n\
5de29b
+	ltr   %r7,%r7\n\
5de29b
+	jne   .L2		# Stop after copying the NULL.\n\
5de29b
+	# Now we have to zero out the envp entries after NULL to allow\n\
5de29b
+	# start.S to properly find auxv by skipping zeroes.\n\
5de29b
+	# zero out loop:\n\
5de29b
+	lhi   %r7,0\n\
5de29b
+.L3:	st    %r7,0(%r6)	# Store zero.\n\
5de29b
+	ahi   %r6,4		# Advance dest pointer.\n\
5de29b
+	ahi   %r1,-1		# Subtract one from the word count.\n\
5de29b
+	ltr   %r1,%r1\n\
5de29b
+	jne    .L3		# Keep copying if the word count is non-zero.\n\
5de29b
+	# Adjust _dl_argv\n\
5de29b
+	la    %r6,100(%r15)\n\
5de29b
+	l     %r1,_dl_argv@GOT12(0,%r12)\n\
5de29b
+	st    %r6,0(%r1)\n\
5de29b
 	# The special initializer gets called with the stack just\n\
5de29b
 	# as the application's entry point will see it; it can\n\
5de29b
 	# switch stacks if it moves these contents over.\n\
5de29b
@@ -185,7 +216,7 @@ _dl_start_user:\n\
5de29b
 	# Call the function to run the initializers.\n\
5de29b
 	# Load the parameters:\n\
5de29b
 	# (%r2, %r3, %r4, %r5) = (_dl_loaded, argc, argv, envp)\n\
5de29b
-	l     %r2,_rtld_local@GOT(%r12)\n\
5de29b
+.L4:	l     %r2,_rtld_local@GOT(%r12)\n\
5de29b
 	l     %r2,0(%r2)\n\
5de29b
 	l     %r3,96(%r15)\n\
5de29b
 	la    %r4,100(%r15)\n\
5de29b
@@ -198,6 +229,9 @@ _dl_start_user:\n\
5de29b
 	l     %r14,_dl_fini@GOT(%r12)\n\
5de29b
 	# Free stack frame\n\
5de29b
 	ahi   %r15,96\n\
5de29b
+	# Reload argc and argv for the user's entry point.\n\
5de29b
+	# l     %r2,0(%r15)\n\
5de29b
+	# la    %r3,4(%r15)\n\
5de29b
 	# Jump to the user's entry point (saved in %r8).\n\
5de29b
 	br    %r8\n\
5de29b
 .Llit:\n\
12745e
diff --git glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-sysdep.h glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-sysdep.h
5de29b
new file mode 100644
5de29b
index 0000000..b992778
5de29b
--- /dev/null
12745e
+++ glibc-2.17-c758a686/sysdeps/s390/s390-32/dl-sysdep.h
5de29b
@@ -0,0 +1,23 @@
5de29b
+/* System-specific settings for dynamic linker code.  S/390 version.
5de29b
+   Copyright (C) 2014 Free Software Foundation, Inc.
5de29b
+   This file is part of the GNU C Library.
5de29b
+
5de29b
+   The GNU C Library is free software; you can redistribute it and/or
5de29b
+   modify it under the terms of the GNU Lesser General Public
5de29b
+   License as published by the Free Software Foundation; either
5de29b
+   version 2.1 of the License, or (at your option) any later version.
5de29b
+
5de29b
+   The GNU C Library is distributed in the hope that it will be useful,
5de29b
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
5de29b
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5de29b
+   Lesser General Public License for more details.
5de29b
+
5de29b
+   You should have received a copy of the GNU Lesser General Public
5de29b
+   License along with the GNU C Library.  If not, see
5de29b
+   <http://www.gnu.org/licenses/>.  */
5de29b
+
5de29b
+#include_next <dl-sysdep.h>
5de29b
+
5de29b
+/* _dl_argv cannot be attribute_relro, because _dl_start_user
5de29b
+   might write into it after _dl_start returns.  */
5de29b
+#define DL_ARGV_NOT_RELRO 1