This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 1/3] posix: Remove dynamic memory allocation from execl{e,p}


On 02/08/2016 08:28 AM, Rasmus Villemoes wrote:
On Tue, Feb 02 2016, Rich Felker <dalias@libc.org> wrote:

On Mon, Feb 01, 2016 at 04:52:15PM +0000, Joseph Myers wrote:
On Mon, 1 Feb 2016, Adhemerval Zanella wrote:

+  char *argv[argc+1];
+  va_start (ap, arg);
+  argv[0] = (char*) arg;
+  for (i = 1; i < argc; i++)
+     argv[i] = va_arg (ap, char *);
+  argv[i] = NULL;

I don't see how you're ensuring this stack allocation is safe (i.e. if
it's too big, it doesn't corrupt memory that's in use by other threads).

There's no obligation to. If you pass something like a million
arguments to a variadic function, the compiler will generate code in
the caller that overflows the stack before the callee is even reached.
The size of the vla used in execl is exactly the same size as the
argument block on the stack used for passing arguments to execl from
its caller, and it's nobody's fault but the programmer's if this is
way too big. It's not a runtime variable.

This is true, and maybe it's not worth the extra complication, but if
we're willing to make arch-specific versions of execl and execle we can
avoid the double stack use and the time spent copying the argv
array. That won't remove the possible stack overflow, of course, but
then it'll in all likelihood happen in the user code and not glibc.

I like the idea. It's a quality of implementation issue, wherein by re-using the data that's (mostly) on the stack already we don't need twice again the amount of stack space for any given call.

I think that Adhemerval's patch should go in as a default implementation, and various targets can implement the assembly as desired.

I've tested the following on x86_64 and i686. I've compile-tested for x32 (but need a more complete x32 installation for testing), and alpha (testing is just slow).

Thoughts?


r~
>From f685eeedc6d7baf1bf822ef058e06bc1bcae4541 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 9 Feb 2016 11:53:32 +1100
Subject: [PATCH 1/5] Move posix/execl files to sysdeps/

This will allow them to be overridable.
---
 {posix => sysdeps/posix}/execl.c  | 0
 {posix => sysdeps/posix}/execle.c | 0
 {posix => sysdeps/posix}/execlp.c | 0
 3 files changed, 0 insertions(+), 0 deletions(-)
 rename {posix => sysdeps/posix}/execl.c (100%)
 rename {posix => sysdeps/posix}/execle.c (100%)
 rename {posix => sysdeps/posix}/execlp.c (100%)

diff --git a/posix/execl.c b/sysdeps/posix/execl.c
similarity index 100%
rename from posix/execl.c
rename to sysdeps/posix/execl.c
diff --git a/posix/execle.c b/sysdeps/posix/execle.c
similarity index 100%
rename from posix/execle.c
rename to sysdeps/posix/execle.c
diff --git a/posix/execlp.c b/sysdeps/posix/execlp.c
similarity index 100%
rename from posix/execlp.c
rename to sysdeps/posix/execlp.c
-- 
2.5.0

>From 447f711575e70c09fd883f28d86e175993025277 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 9 Feb 2016 12:53:17 +1100
Subject: [PATCH 2/5] x86_64: Implement execl{,e,p} without double stack
 allocation

---
 include/unistd.h                           |  1 +
 posix/execv.c                              |  1 +
 sysdeps/unix/sysv/linux/x86_64/64/execl.S  | 65 +++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/64/execle.S | 66 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/64/execlp.S | 52 +++++++++++++++++++++++
 5 files changed, 185 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/execl.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/execle.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/64/execlp.S

diff --git a/include/unistd.h b/include/unistd.h
index 5152f64..21b8135 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -9,6 +9,7 @@ rtld_hidden_proto (_exit, __noreturn__)
 libc_hidden_proto (alarm)
 libc_hidden_proto (confstr)
 libc_hidden_proto (execl)
+libc_hidden_proto (execv)
 libc_hidden_proto (execle)
 libc_hidden_proto (execlp)
 libc_hidden_proto (execvp)
diff --git a/posix/execv.c b/posix/execv.c
index 16c0a02..faca14f 100644
--- a/posix/execv.c
+++ b/posix/execv.c
@@ -24,3 +24,4 @@ execv (const char *path, char *const argv[])
 {
   return __execve (path, argv, __environ);
 }
+libc_hidden_def (execv)
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/execl.S b/sysdeps/unix/sysv/linux/x86_64/64/execl.S
new file mode 100644
index 0000000..29b4923
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/execl.S
@@ -0,0 +1,65 @@
+/* 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 portions of the argv argument list in registers.  */
+	push	%r9
+	cfi_adjust_cfa_offset(8)
+	push	%r8
+	cfi_adjust_cfa_offset(8)
+	push	%rcx
+	cfi_adjust_cfa_offset(8)
+	push	%rdx
+	cfi_adjust_cfa_offset(8)
+	push	%rsi
+	cfi_adjust_cfa_offset(8)
+
+	/* Load the address of the argv array.  */
+	mov	%rsp, %rsi
+
+	/* 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), %rdx
+	mov	(%rdx), %rdx
+#else
+	mov	__environ(%rip), %rdx
+#endif
+
+	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	$40
+
+END(execl)
+
+libc_hidden_def (execl)
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/execle.S b/sysdeps/unix/sysv/linux/x86_64/64/execle.S
new file mode 100644
index 0000000..c2fc5c9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/execle.S
@@ -0,0 +1,66 @@
+/* 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 portions of the argv argument list in registers.  */
+	push	%r9
+	cfi_adjust_cfa_offset(8)
+	push	%r8
+	cfi_adjust_cfa_offset(8)
+	push	%rcx
+	cfi_adjust_cfa_offset(8)
+	push	%rdx
+	cfi_adjust_cfa_offset(8)
+	push	%rsi
+	cfi_adjust_cfa_offset(8)
+
+	/* Load the address of the argv array.  */
+	mov	%rsp, %rsi
+
+	/* Restore return address to the stack.  */
+	push	%rax
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(%rip, 0)
+
+	/* Find the env argument.  It is the array element after the argv
+	   NULL terminator, which cannot be located before argv[1].  */
+	lea	8(%rsi), %rax
+	mov	(%rax), %rdx
+1:	add	$8, %rax
+	test	%rdx, %rdx
+	mov	(%rax), %rdx
+	jnz	1b
+
+	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	$40
+
+END(execle)
+
+libc_hidden_def (execle)
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/execlp.S b/sysdeps/unix/sysv/linux/x86_64/64/execlp.S
new file mode 100644
index 0000000..caa0895
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/execlp.S
@@ -0,0 +1,52 @@
+/* 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 portions of the argv argument list in registers.  */
+	push	%r9
+	cfi_adjust_cfa_offset(8)
+	push	%r8
+	cfi_adjust_cfa_offset(8)
+	push	%rcx
+	cfi_adjust_cfa_offset(8)
+	push	%rdx
+	cfi_adjust_cfa_offset(8)
+	push	%rsi
+	cfi_adjust_cfa_offset(8)
+
+	/* Load the address of the argv array.  */
+	mov	%rsp, %rsi
+
+	/* Restore return address to the stack.  */
+	push	%rax
+	cfi_adjust_cfa_offset(8)
+	cfi_rel_offset(%rip, 0)
+
+	call	HIDDEN_JUMPTARGET (execvp)
+
+	/* Pop all of the extra stack space in one go.  */
+	ret	$40
+END(execlp)
+
+libc_hidden_def (execlp)
-- 
2.5.0

>From 072dce81771f971f49f2480630842a2874a2c860 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 9 Feb 2016 13:12:33 +1100
Subject: [PATCH 3/5] i386: Implement execl{,e,p} without double stack
 allocation

---
 sysdeps/unix/sysv/linux/i386/execl.S  | 39 +++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/execle.S | 46 +++++++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/i386/execlp.S |  4 +++
 3 files changed, 89 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/i386/execl.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/execle.S
 create mode 100644 sysdeps/unix/sysv/linux/i386/execlp.S

diff --git a/sysdeps/unix/sysv/linux/i386/execl.S b/sysdeps/unix/sysv/linux/i386/execl.S
new file mode 100644
index 0000000..047ef48
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/execl.S
@@ -0,0 +1,39 @@
+/* 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)
+	mov	4(%esp), %edx
+	lea	8(%esp), %eax
+
+	push	%eax			/* alignment padding */
+	cfi_adjust_cfa_offset(4)
+	push	%eax			/* create argv argument */
+	cfi_adjust_cfa_offset(4)
+	push	%edx			/* create path argument */
+	cfi_adjust_cfa_offset(4)
+
+	/* Let execv deal with pic vs non-pic loading of __environ.  */
+	call	HIDDEN_JUMPTARGET (execv)
+
+	add	$12, %esp
+	cfi_adjust_cfa_offset(-12)
+	ret
+END(execl)
+
+libc_hidden_def (execl)
diff --git a/sysdeps/unix/sysv/linux/i386/execle.S b/sysdeps/unix/sysv/linux/i386/execle.S
new file mode 100644
index 0000000..34cc7bc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/execle.S
@@ -0,0 +1,46 @@
+/* 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)
+	lea	8(%esp), %eax	/* find argv array */
+
+	/* Find the env argument.  It is the array element after the argv
+	   NULL terminator, which cannot be located before argv[1].  */
+	mov	4(%eax), %edx
+	xor	%ecx, %ecx
+1:	inc	%ecx
+	test	%edx, %edx
+	mov	4(%eax, %ecx, 4), %edx
+	jnz	1b
+
+	push	%edx		/* create env argument */
+	cfi_adjust_cfa_offset(4)
+	push	%eax		/* create argv argument */
+	cfi_adjust_cfa_offset(4)
+	push	12(%esp)	/* copy path argument */
+	cfi_adjust_cfa_offset(4)
+
+	call	HIDDEN_JUMPTARGET (execve)
+
+	add	$12, %esp
+	cfi_adjust_cfa_offset(-12)
+	ret
+END(execle)
+
+libc_hidden_def (execle)
diff --git a/sysdeps/unix/sysv/linux/i386/execlp.S b/sysdeps/unix/sysv/linux/i386/execlp.S
new file mode 100644
index 0000000..d1c8806
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/execlp.S
@@ -0,0 +1,4 @@
+#define execl		execlp
+#define execv		execvp
+#define __GI_execv	__GI_execvp
+#include "execl.S"
-- 
2.5.0

>From 4577d8457637adac28ed34bc3f9ce0a936dc786e Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 9 Feb 2016 15:19:32 +1100
Subject: [PATCH 4/5] x32: Implement execl{,e,p} without double stack
 allocation

---
 sysdeps/unix/sysv/linux/x86_64/x32/execl.S  | 88 +++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/x32/execle.S | 87 ++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/x86_64/x32/execlp.S | 76 +++++++++++++++++++++++++
 3 files changed, 251 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/execl.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/execle.S
 create mode 100644 sysdeps/unix/sysv/linux/x86_64/x32/execlp.S

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 0000000..9139bad
--- /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 0000000..c7de7e0
--- /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 0000000..cad65f5
--- /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)
-- 
2.5.0

>From 5b78856069a21550d4b67b4c0a269915f37fce0f Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Tue, 9 Feb 2016 13:43:08 +1100
Subject: [PATCH 5/5] alpha: Implement execl{,e,p} without double stack
 allocation

---
 sysdeps/unix/sysv/linux/alpha/execl.S  | 52 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/execle.S | 58 ++++++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/execlp.S | 53 +++++++++++++++++++++++++++++++
 3 files changed, 163 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/alpha/execl.S
 create mode 100644 sysdeps/unix/sysv/linux/alpha/execle.S
 create mode 100644 sysdeps/unix/sysv/linux/alpha/execlp.S

diff --git a/sysdeps/unix/sysv/linux/alpha/execl.S b/sysdeps/unix/sysv/linux/alpha/execl.S
new file mode 100644
index 0000000..11f4307
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/execl.S
@@ -0,0 +1,52 @@
+/* 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)
+	cfi_startproc
+	ldgp	gp, 0(pv)
+	lda	sp, -48(sp)
+	cfi_adjust_cfa_offset(48)
+	.frame	sp, 48, ra
+	.prologue 1
+
+	/* Save the portions of the argv argument list in registers.  */
+	stq	a5, 40(sp)
+	stq	a4, 32(sp)
+	stq	a3, 24(sp)
+	stq	a2, 16(sp)
+	stq	a1,  8(sp)
+
+	/* Load the argv and envp arguments; path is already in place.  */
+	lda	a1, 8(sp)
+	ldq	a2, __environ
+
+	lda	v0, SYS_ify(execve)
+	call_pal PAL_callsys
+
+	/* Discard the stack frame now.  */
+	lda	sp, 48(sp)
+	cfi_adjust_cfa_offset(-48)
+
+	/* All returns are errors.  */
+	br	SYSCALL_ERROR_LABEL
+
+PSEUDO_END (execle)
+	cfi_endproc
+
+libc_hidden_def (execl)
diff --git a/sysdeps/unix/sysv/linux/alpha/execle.S b/sysdeps/unix/sysv/linux/alpha/execle.S
new file mode 100644
index 0000000..ce75ce3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/execle.S
@@ -0,0 +1,58 @@
+/* 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)
+	cfi_startproc
+	lda	sp, -48(sp)
+	cfi_adjust_cfa_offset(48)
+	.frame  sp, 48, ra
+	.prologue 0
+
+	/* Save the portions of the argv argument list in registers.  */
+	stq	a5, 40(sp)
+	stq	a4, 32(sp)
+	stq	a3, 24(sp)
+	stq	a2, 16(sp)
+	stq	a1,  8(sp)
+
+	/* Find the env argument.  It is the array element after the argv
+	   NULL terminator, which cannot be located before argv[1].  */
+	lda	t0, 16(sp)
+1:	ldq	t1, 0(t0)
+	addq	t0, 8, t0
+	bne	t1, 1b
+
+	/* Load the argv and envp arguments; path is already in place.  */
+	lda	a1, 8(sp)
+	ldq	a2, 0(t0)
+
+	lda	v0, SYS_ify(execve)
+	call_pal PAL_callsys
+
+	/* Discard the stack frame now.  */
+	lda	sp, 48(sp)
+	cfi_adjust_cfa_offset(-48)
+
+	/* All returns are errors.  */
+	br	SYSCALL_ERROR_LABEL
+
+PSEUDO_END (execle)
+	cfi_endproc
+
+libc_hidden_def (execle)
diff --git a/sysdeps/unix/sysv/linux/alpha/execlp.S b/sysdeps/unix/sysv/linux/alpha/execlp.S
new file mode 100644
index 0000000..b0ef76d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/execlp.S
@@ -0,0 +1,53 @@
+/* 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)
+	cfi_startproc
+	ldgp	gp, 0(pv)
+	lda	sp, -48(sp)
+	cfi_adjust_cfa_offset(48)
+	stq	ra, 0(sp)
+	cfi_rel_offset(ra, 0)
+	.prologue 1
+
+	/* Save the portions of the argv argument list in registers.  */
+	stq	a5, 40(sp)
+	stq	a4, 32(sp)
+	stq	a3, 24(sp)
+	stq	a2, 16(sp)
+	stq	a1,  8(sp)
+
+	/* Load the argv and envp arguments; path is already in place.  */
+	lda	a1, 8(sp)
+	ldq	a2, __environ
+#ifdef PIC
+	bsr	ra, __execvpe		!samegp
+#else
+	jsr	ra, __execvpe
+	ldgp	gp, 0(ra)
+#endif
+
+	lda	sp, 48(sp)
+	cfi_adjust_cfa_offset(-48)
+	ret
+
+END (execlp)
+	cfi_endproc
+
+libc_hidden_def (execlp)
-- 
2.5.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]