about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2016-02-09 15:19:32 +1100
committerRichard Henderson <rth@twiddle.net>2016-02-09 21:27:17 +1100
commit4577d8457637adac28ed34bc3f9ce0a936dc786e (patch)
tree50ceda50672eb7501ca3017e035a505e9fef4abf
parent072dce81771f971f49f2480630842a2874a2c860 (diff)
downloadglibc-4577d8457637adac28ed34bc3f9ce0a936dc786e.tar.gz
glibc-4577d8457637adac28ed34bc3f9ce0a936dc786e.tar.xz
glibc-4577d8457637adac28ed34bc3f9ce0a936dc786e.zip
x32: Implement execl{,e,p} without double stack allocation
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/execl.S88
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/execle.S87
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/execlp.S76
3 files changed, 251 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/execl.S b/sysdeps/unix/sysv/linux/x86_64/x32/execl.S
new file mode 100644
index 0000000000..9139bad32b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/execl.S
@@ -0,0 +1,88 @@
+/* Copyright (C) 2016 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 <sysdep.h>
+
+ENTRY(execl)
+	/* Move return address into a register.  */
+	pop	%rax
+	cfi_adjust_cfa_offset(-8)
+	cfi_register(%rip, %rax)
+
+	/* Save the arguments in registers.  Stop as soon as we detect
+	   the NULL terminator, as if we find one, we do not want to fall
+	   into the on-stack conversion loop.  */
+	sub	$24, %esp
+	cfi_adjust_cfa_offset(24)
+
+	mov	%edi, 4(%rsp)	/* argv[0] must be non-null.  */
+
+	mov	%edx, 8(%rsp)
+	test	%edx, %edx
+	jz	9f
+
+	mov	%ecx, 12(%rsp)
+	test	%ecx, %ecx
+	jz	9f
+
+	mov	%r8d, 16(%rsp)
+	test	%r8d, %r8d
+	jz	9f
+
+	mov	%r9d, 20(%rsp)
+	test	%r9d, %r9d
+	jz	9f
+
+	/* Convert the on-stack pointer arguments to in-place
+	   from a 64-bit padded array into a 32-bit packed array.
+           Note that this is memory is callee owned.  */
+	xor	%ecx, %ecx
+1:	mov	24(%rsp, %rcx, 8), %edx
+	mov	%edx, 24(%rsp, %rcx, 4)
+	inc	%ecx
+	test	%edx, %edx
+	jnz	1b
+
+9:
+	/* Restore return address to the stack.  */
+	push	%rax
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(%rip, 0)
+
+	/* Load __environ for the env parameter.  */
+#ifdef PIC
+	mov	__environ@GOTPCREL(%rip), %edx
+	mov	(%rdx), %edx
+#else
+	mov	__environ(%rip), %edx
+#endif
+
+	/* Load argv parameter.  Note that path (esi) is already loaded.  */
+	lea	12(%rsp), %edi
+
+	DO_CALL (execve, 3)
+
+	/* All returns are errors.  */
+	SYSCALL_SET_ERRNO
+	or	$-1, %rax
+
+	/* Pop all of the extra stack space in one go.  */
+	ret	$24
+
+END(execl)
+
+libc_hidden_def (execl)
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/execle.S b/sysdeps/unix/sysv/linux/x86_64/x32/execle.S
new file mode 100644
index 0000000000..c7de7e0ac0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/execle.S
@@ -0,0 +1,87 @@
+/* Copyright (C) 2016 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 <sysdep.h>
+
+ENTRY(execle)
+	/* Move return address into a register.  */
+	pop	%rax
+	cfi_adjust_cfa_offset(-8)
+	cfi_register(%rip, %rax)
+
+	/* Save the arguments in registers.  Stop as soon as we detect
+	   the NULL terminator, as if we find one, we do not want to fall
+	   into the on-stack conversion loop.  Move the potential ENV
+	   parameter in place in EDX on each exit path.  */
+	sub	$24, %esp
+	cfi_adjust_cfa_offset(24)
+
+	mov	%edi, 4(%rsp)	/* argv[0] must be non-null.  */
+
+	mov	%edx, 8(%rsp)
+	test	%edx, %edx
+	mov	%ecx, %edx
+	jz	9f
+
+	mov	%ecx, 12(%rsp)
+	test	%ecx, %ecx
+	mov	%r8d, %edx
+	jz	9f
+
+	mov	%r8d, 16(%rsp)
+	test	%r8d, %r8d
+	mov	%r9d, %edx
+	jz	9f
+
+	mov	%r9d, 20(%rsp)
+	test	%r9d, %r9d
+	mov	24(%rsp), %edx
+	jz	9f
+
+	/* Convert the on-stack pointer arguments to in-place
+	   from a 64-bit padded array into a 32-bit packed array.
+           Note that this is memory is callee owned, and that this
+	   loop exits with the ENV parameter loaded in EDX.  */
+	xor	%ecx, %ecx
+	mov	24(%rsp, %rcx, 8), %edx
+1:	mov	%edx, 24(%rsp, %rcx, 4)
+	inc	%ecx
+	test	%edx, %edx
+	mov	24(%rsp, %rcx, 8), %edx
+	jnz	1b
+
+9:
+	/* Restore return address to the stack.  */
+	push	%rax
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(%rip, 0)
+
+	/* Load argv parameter.  Note that path (esi) is already loaded.  */
+	lea	12(%rsp), %edi
+
+	DO_CALL (execve, 3)
+
+	/* All returns are errors.  */
+	SYSCALL_SET_ERRNO
+	or	$-1, %rax
+
+	/* Pop all of the extra stack space in one go.  */
+	ret	$24
+
+END(execle)
+
+libc_hidden_def (execle)
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/execlp.S b/sysdeps/unix/sysv/linux/x86_64/x32/execlp.S
new file mode 100644
index 0000000000..cad65f57c6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/execlp.S
@@ -0,0 +1,76 @@
+/* Copyright (C) 2016 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 <sysdep.h>
+
+ENTRY(execlp)
+	/* Move return address into a register.  */
+	pop	%rax
+	cfi_adjust_cfa_offset(-8)
+	cfi_register(%rip, %rax)
+
+	/* Save the arguments in registers.  Stop as soon as we detect
+	   the NULL terminator, as if we find one, we do not want to fall
+	   into the on-stack conversion loop.  */
+	sub	$24, %esp
+	cfi_adjust_cfa_offset(24)
+
+	mov	%edi, 4(%rsp)	/* argv[0] must be non-null.  */
+
+	mov	%edx, 8(%rsp)
+	test	%edx, %edx
+	jz	9f
+
+	mov	%ecx, 12(%rsp)
+	test	%ecx, %ecx
+	jz	9f
+
+	mov	%r8d, 16(%rsp)
+	test	%r8d, %r8d
+	jz	9f
+
+	mov	%r9d, 20(%rsp)
+	test	%r9d, %r9d
+	jz	9f
+
+	/* Convert the on-stack pointer arguments to in-place
+	   from a 64-bit padded array into a 32-bit packed array.
+           Note that this is memory is callee owned.  */
+	xor	%ecx, %ecx
+1:	mov	24(%rsp, %rcx, 8), %edx
+	mov	%edx, 24(%rsp, %rcx, 4)
+	inc	%ecx
+	test	%edx, %edx
+	jnz	1b
+
+9:
+	/* Restore return address to the stack.  */
+	push	%rax
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(%rip, 0)
+
+	/* Load argv parameter.  Note that path (esi) is already loaded.  */
+	lea	12(%rsp), %edi
+
+	call	HIDDEN_JUMPTARGET (execvp)
+
+	/* Pop all of the extra stack space in one go.  */
+	ret	$24
+
+END(execlp)
+
+libc_hidden_def (execlp)