This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v2 1/3] posix: Remove dynamic memory allocation from execl{e,p}
- From: Richard Henderson <rth at twiddle dot net>
- To: Rasmus Villemoes <rv at rasmusvillemoes dot dk>, libc-alpha at sourceware dot org
- Date: Tue, 9 Feb 2016 22:35:54 +1100
- Subject: Re: [PATCH v2 1/3] posix: Remove dynamic memory allocation from execl{e,p}
- Authentication-results: sourceware.org; auth=none
- References: <1454343665-1706-1-git-send-email-adhemerval dot zanella at linaro dot org> <1454343665-1706-2-git-send-email-adhemerval dot zanella at linaro dot org> <alpine dot DEB dot 2 dot 10 dot 1602011648030 dot 2674 at digraph dot polyomino dot org dot uk> <20160202163335 dot GJ9349 at brightrain dot aerifal dot cx> <878u2wfbwv dot fsf at rasmusvillemoes dot dk>
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