From: Richard Henderson Date: Tue, 9 Feb 2016 01:53:17 +0000 (+1100) Subject: x86_64: Implement execl{,e,p} without double stack allocation X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=447f711575e70c09fd883f28d86e175993025277;p=thirdparty%2Fglibc.git x86_64: Implement execl{,e,p} without double stack allocation --- diff --git a/include/unistd.h b/include/unistd.h index 5152f64f91c..21b81350b00 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 16c0a02c43b..faca14f6ef7 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 00000000000..29b492393bc --- /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 + . */ + +#include + +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 00000000000..c2fc5c93d5f --- /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 + . */ + +#include + +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 00000000000..caa08951e3d --- /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 + . */ + +#include + +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)