[libc] Add POSIX execv and execve functions.
The POSIX global variable environ has also been added. Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D135351
This commit is contained in:
parent
eaa583c330
commit
3f965818b6
|
@ -431,7 +431,8 @@ function(add_integration_test test_name)
|
||||||
APPEND fq_deps_list
|
APPEND fq_deps_list
|
||||||
libc.src.__support.threads.thread
|
libc.src.__support.threads.thread
|
||||||
libc.src.stdlib.atexit
|
libc.src.stdlib.atexit
|
||||||
libc.src.stdlib.exit)
|
libc.src.stdlib.exit
|
||||||
|
libc.src.unistd.environ)
|
||||||
list(REMOVE_DUPLICATES fq_deps_list)
|
list(REMOVE_DUPLICATES fq_deps_list)
|
||||||
|
|
||||||
# We don't want memory functions to be dependencies on integration tests.
|
# We don't want memory functions to be dependencies on integration tests.
|
||||||
|
@ -533,7 +534,8 @@ function(add_integration_test test_name)
|
||||||
add_dependencies(${fq_target_name}
|
add_dependencies(${fq_target_name}
|
||||||
${fq_target_name}.__copy_loader__
|
${fq_target_name}.__copy_loader__
|
||||||
${fq_libc_target_name}
|
${fq_libc_target_name}
|
||||||
libc.utils.IntegrationTest.test)
|
libc.utils.IntegrationTest.test
|
||||||
|
${INTEGRATION_TEST_DEPENDS})
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${fq_target_name}
|
TARGET ${fq_target_name}
|
||||||
|
|
|
@ -377,6 +377,9 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||||
libc.src.time.mktime
|
libc.src.time.mktime
|
||||||
libc.src.time.nanosleep
|
libc.src.time.nanosleep
|
||||||
libc.src.time.clock_gettime
|
libc.src.time.clock_gettime
|
||||||
|
|
||||||
|
# unistd.h entrypoints
|
||||||
|
libc.src.unistd.environ
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ def DirentAPI : PublicAPI<"dirent.h"> {
|
||||||
}
|
}
|
||||||
|
|
||||||
def UniStdAPI : PublicAPI<"unistd.h"> {
|
def UniStdAPI : PublicAPI<"unistd.h"> {
|
||||||
let Types = ["off_t", "pid_t", "size_t", "ssize_t", "uid_t"];
|
let Types = ["__exec_argv_t", "__exec_envp_t", "off_t", "pid_t", "size_t", "ssize_t", "uid_t"];
|
||||||
}
|
}
|
||||||
|
|
||||||
def SysResourceAPI : PublicAPI<"sys/resource.h"> {
|
def SysResourceAPI : PublicAPI<"sys/resource.h"> {
|
||||||
|
|
|
@ -143,6 +143,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||||
libc.src.unistd.dup
|
libc.src.unistd.dup
|
||||||
libc.src.unistd.dup2
|
libc.src.unistd.dup2
|
||||||
libc.src.unistd.dup3
|
libc.src.unistd.dup3
|
||||||
|
libc.src.unistd.execve
|
||||||
libc.src.unistd.fchdir
|
libc.src.unistd.fchdir
|
||||||
libc.src.unistd.fsync
|
libc.src.unistd.fsync
|
||||||
libc.src.unistd.ftruncate
|
libc.src.unistd.ftruncate
|
||||||
|
@ -412,6 +413,8 @@ if(LLVM_LIBC_FULL_BUILD)
|
||||||
libc.src.time.clock_gettime
|
libc.src.time.clock_gettime
|
||||||
|
|
||||||
# unistd.h entrypoints
|
# unistd.h entrypoints
|
||||||
|
libc.src.unistd.environ
|
||||||
|
libc.src.unistd.execv
|
||||||
libc.src.unistd.fork
|
libc.src.unistd.fork
|
||||||
libc.src.unistd.__llvm_libc_syscall
|
libc.src.unistd.__llvm_libc_syscall
|
||||||
)
|
)
|
||||||
|
|
|
@ -175,6 +175,8 @@ add_gen_header(
|
||||||
.llvm_libc_common_h
|
.llvm_libc_common_h
|
||||||
.llvm-libc-macros.file_seek_macros
|
.llvm-libc-macros.file_seek_macros
|
||||||
.llvm-libc-macros.unistd_macros
|
.llvm-libc-macros.unistd_macros
|
||||||
|
.llvm-libc-types.__exec_argv_t
|
||||||
|
.llvm-libc-types.__exec_envp_t
|
||||||
.llvm-libc-types.off_t
|
.llvm-libc-types.off_t
|
||||||
.llvm-libc-types.pid_t
|
.llvm-libc-types.pid_t
|
||||||
.llvm-libc-types.size_t
|
.llvm-libc-types.size_t
|
||||||
|
|
|
@ -2,6 +2,8 @@ add_header(off64_t HDR off64_t.h)
|
||||||
add_header(size_t HDR size_t.h)
|
add_header(size_t HDR size_t.h)
|
||||||
add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
|
add_header(__bsearchcompare_t HDR __bsearchcompare_t.h)
|
||||||
add_header(__call_once_func_t HDR __call_once_func_t.h)
|
add_header(__call_once_func_t HDR __call_once_func_t.h)
|
||||||
|
add_header(__exec_argv_t HDR __exec_argv_t.h)
|
||||||
|
add_header(__exec_envp_t HDR __exec_envp_t.h)
|
||||||
add_header(__futex_word HDR __futex_word.h)
|
add_header(__futex_word HDR __futex_word.h)
|
||||||
add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word)
|
add_header(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word)
|
||||||
add_header(__pthread_once_func_t HDR __pthread_once_func_t.h)
|
add_header(__pthread_once_func_t HDR __pthread_once_func_t.h)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===-- Definition of type __exec_argv_t ----------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef __LLVM_LIBC_TYPES_EXEC_ARGV_T_H__
|
||||||
|
#define __LLVM_LIBC_TYPES_EXEC_ARGV_T_H__
|
||||||
|
|
||||||
|
typedef char *const __exec_argv_t[];
|
||||||
|
|
||||||
|
#endif // __LLVM_LIBC_TYPES_EXEC_ARGV_T_H__
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===-- Definition of type __exec_envp_t ----------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef __LLVM_LIBC_TYPES_EXEC_ENVP_T_H__
|
||||||
|
#define __LLVM_LIBC_TYPES_EXEC_ENVP_T_H__
|
||||||
|
|
||||||
|
typedef char *const __exec_envp_t[];
|
||||||
|
|
||||||
|
#endif // __LLVM_LIBC_TYPES_EXEC_ENVP_T_H__
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
extern "C" int main(int, char **, char **);
|
extern "C" int main(int, char **, char **);
|
||||||
|
|
||||||
|
@ -147,6 +148,9 @@ __attribute__((noinline)) static void do_start() {
|
||||||
while (*env_end_marker)
|
while (*env_end_marker)
|
||||||
++env_end_marker;
|
++env_end_marker;
|
||||||
|
|
||||||
|
// Initialize the POSIX global declared in unistd.h
|
||||||
|
environ = reinterpret_cast<char **>(env_ptr);
|
||||||
|
|
||||||
// After the env array, is the aux-vector. The end of the aux-vector is
|
// After the env array, is the aux-vector. The end of the aux-vector is
|
||||||
// denoted by an AT_NULL entry.
|
// denoted by an AT_NULL entry.
|
||||||
Elf64_Phdr *programHdrTable = nullptr;
|
Elf64_Phdr *programHdrTable = nullptr;
|
||||||
|
|
|
@ -6,11 +6,13 @@ add_loader_object(
|
||||||
libc.config.linux.app_h
|
libc.config.linux.app_h
|
||||||
libc.include.sys_mman
|
libc.include.sys_mman
|
||||||
libc.include.sys_syscall
|
libc.include.sys_syscall
|
||||||
|
libc.include.unistd
|
||||||
libc.src.__support.threads.thread
|
libc.src.__support.threads.thread
|
||||||
libc.src.__support.OSUtil.osutil
|
libc.src.__support.OSUtil.osutil
|
||||||
libc.src.stdlib.exit
|
libc.src.stdlib.exit
|
||||||
libc.src.stdlib.atexit
|
libc.src.stdlib.atexit
|
||||||
libc.src.string.memory_utils.memcpy_implementation
|
libc.src.string.memory_utils.memcpy_implementation
|
||||||
|
libc.src.unistd.environ
|
||||||
COMPILE_OPTIONS
|
COMPILE_OPTIONS
|
||||||
-fno-omit-frame-pointer
|
-fno-omit-frame-pointer
|
||||||
-ffreestanding # To avoid compiler warnings about calling the main function.
|
-ffreestanding # To avoid compiler warnings about calling the main function.
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
extern "C" int main(int, char **, char **);
|
extern "C" int main(int, char **, char **);
|
||||||
|
|
||||||
|
@ -167,6 +168,9 @@ extern "C" void _start() {
|
||||||
while (*env_end_marker)
|
while (*env_end_marker)
|
||||||
++env_end_marker;
|
++env_end_marker;
|
||||||
|
|
||||||
|
// Initialize the POSIX global declared in unistd.h
|
||||||
|
environ = reinterpret_cast<char **>(env_ptr);
|
||||||
|
|
||||||
// After the env array, is the aux-vector. The end of the aux-vector is
|
// After the env array, is the aux-vector. The end of the aux-vector is
|
||||||
// denoted by an AT_NULL entry.
|
// denoted by an AT_NULL entry.
|
||||||
Elf64_Phdr *programHdrTable = nullptr;
|
Elf64_Phdr *programHdrTable = nullptr;
|
||||||
|
|
|
@ -45,6 +45,9 @@ def ConstStructDirentPtrPtr : ConstType<StructDirentPtrPtr>;
|
||||||
def StructTimeSpec : NamedType<"struct timespec">;
|
def StructTimeSpec : NamedType<"struct timespec">;
|
||||||
def StructTimeSpecPtr : PtrType<StructTimeSpec>;
|
def StructTimeSpecPtr : PtrType<StructTimeSpec>;
|
||||||
|
|
||||||
|
def ExecArgvT : NamedType<"__exec_argv_t">;
|
||||||
|
def ExecEnvpT : NamedType<"__exec_envp_t">;
|
||||||
|
|
||||||
def POSIX : StandardSpec<"POSIX"> {
|
def POSIX : StandardSpec<"POSIX"> {
|
||||||
PtrType CharPtr = PtrType<CharType>;
|
PtrType CharPtr = PtrType<CharType>;
|
||||||
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
|
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
|
||||||
|
@ -299,6 +302,8 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||||
"unistd.h",
|
"unistd.h",
|
||||||
[], // Macros
|
[], // Macros
|
||||||
[
|
[
|
||||||
|
ExecArgvT,
|
||||||
|
ExecEnvpT,
|
||||||
OffTType,
|
OffTType,
|
||||||
SSizeTType,
|
SSizeTType,
|
||||||
SizeTType,
|
SizeTType,
|
||||||
|
@ -342,6 +347,16 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||||
RetValSpec<IntType>,
|
RetValSpec<IntType>,
|
||||||
[ArgSpec<IntType>]
|
[ArgSpec<IntType>]
|
||||||
>,
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"execv",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<ConstCharPtr>, ArgSpec<ExecArgvT>]
|
||||||
|
>,
|
||||||
|
FunctionSpec<
|
||||||
|
"execve",
|
||||||
|
RetValSpec<IntType>,
|
||||||
|
[ArgSpec<ConstCharPtr>, ArgSpec<ExecArgvT>, ArgSpec<ExecEnvpT>]
|
||||||
|
>,
|
||||||
FunctionSpec<
|
FunctionSpec<
|
||||||
"fork",
|
"fork",
|
||||||
RetValSpec<PidT>,
|
RetValSpec<PidT>,
|
||||||
|
@ -512,6 +527,9 @@ def POSIX : StandardSpec<"POSIX"> {
|
||||||
RetValSpec<SSizeTType>,
|
RetValSpec<SSizeTType>,
|
||||||
[ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
|
[ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
|
||||||
>,
|
>,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
ObjectSpec<"environ", "char **">,
|
||||||
]
|
]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,20 @@ add_entrypoint_object(
|
||||||
.${LIBC_TARGET_OS}.fork
|
.${LIBC_TARGET_OS}.fork
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
execv
|
||||||
|
ALIAS
|
||||||
|
DEPENDS
|
||||||
|
.${LIBC_TARGET_OS}.execv
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
execve
|
||||||
|
ALIAS
|
||||||
|
DEPENDS
|
||||||
|
.${LIBC_TARGET_OS}.execve
|
||||||
|
)
|
||||||
|
|
||||||
add_entrypoint_object(
|
add_entrypoint_object(
|
||||||
fsync
|
fsync
|
||||||
ALIAS
|
ALIAS
|
||||||
|
@ -211,3 +225,11 @@ add_entrypoint_object(
|
||||||
DEPENDS
|
DEPENDS
|
||||||
.${LIBC_TARGET_OS}.write
|
.${LIBC_TARGET_OS}.write
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
environ
|
||||||
|
SRCS
|
||||||
|
environ.cpp
|
||||||
|
HDRS
|
||||||
|
environ.h
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===-- Declaration of POSIX environ --------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
// This is initialized to the correct value by the statup code.
|
||||||
|
extern "C" char **environ = nullptr;
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,18 @@
|
||||||
|
//===-- Declaration of POSIX environ ----------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_LIBC_SRC_UNISTD_ENVIRON_H
|
||||||
|
#define LLVM_LIBC_SRC_UNISTD_ENVIRON_H
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
extern "C" char **environ;
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_UNISTD_ENVIRON_H
|
|
@ -0,0 +1,18 @@
|
||||||
|
//===-- Implementation header for execv -------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_LIBC_SRC_UNISTD_EXECV_H
|
||||||
|
#define LLVM_LIBC_SRC_UNISTD_EXECV_H
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int execv(const char *path, char *const argv[]);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_UNISTD_EXECV_H
|
|
@ -0,0 +1,18 @@
|
||||||
|
//===-- Implementation header for execve ------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_LIBC_SRC_UNISTD_EXECVE_H
|
||||||
|
#define LLVM_LIBC_SRC_UNISTD_EXECVE_H
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
int execve(const char *path, char *const argv[], char *const envp[]);
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_UNISTD_EXECVE_H
|
|
@ -105,6 +105,33 @@ add_entrypoint_object(
|
||||||
libc.src.errno.errno
|
libc.src.errno.errno
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
execv
|
||||||
|
SRCS
|
||||||
|
execv.cpp
|
||||||
|
HDRS
|
||||||
|
../execv.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.errno
|
||||||
|
libc.include.sys_syscall
|
||||||
|
libc.src.__support.OSUtil.osutil
|
||||||
|
libc.src.errno.errno
|
||||||
|
libc.src.unistd.environ
|
||||||
|
)
|
||||||
|
|
||||||
|
add_entrypoint_object(
|
||||||
|
execve
|
||||||
|
SRCS
|
||||||
|
execve.cpp
|
||||||
|
HDRS
|
||||||
|
../execve.h
|
||||||
|
DEPENDS
|
||||||
|
libc.include.errno
|
||||||
|
libc.include.sys_syscall
|
||||||
|
libc.src.__support.OSUtil.osutil
|
||||||
|
libc.src.errno.errno
|
||||||
|
)
|
||||||
|
|
||||||
add_entrypoint_object(
|
add_entrypoint_object(
|
||||||
fsync
|
fsync
|
||||||
SRCS
|
SRCS
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
//===-- Linux implementation of execv -------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/unistd/execv.h"
|
||||||
|
#include "src/unistd/environ.h"
|
||||||
|
|
||||||
|
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||||
|
#include "src/__support/common.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/syscall.h> // For syscall numbers.
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, execv, (const char *path, char *const argv[])) {
|
||||||
|
long ret =
|
||||||
|
__llvm_libc::syscall_impl(SYS_execve, path, argv, __llvm_libc::environ);
|
||||||
|
if (ret < 0) {
|
||||||
|
errno = -ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control will not reach here on success but have a return statement will
|
||||||
|
// keep the compilers happy.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -0,0 +1,33 @@
|
||||||
|
//===-- Linux implementation of execve ------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/unistd/execve.h"
|
||||||
|
#include "src/unistd/environ.h"
|
||||||
|
|
||||||
|
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||||
|
#include "src/__support/common.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/syscall.h> // For syscall numbers.
|
||||||
|
|
||||||
|
namespace __llvm_libc {
|
||||||
|
|
||||||
|
LLVM_LIBC_FUNCTION(int, execve,
|
||||||
|
(const char *path, char *const argv[], char *const envp[])) {
|
||||||
|
long ret = __llvm_libc::syscall_impl(SYS_execve, path, argv, envp);
|
||||||
|
if (ret < 0) {
|
||||||
|
errno = -ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control will not reach here on success but have a return statement will
|
||||||
|
// keep the compilers happy.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace __llvm_libc
|
|
@ -20,3 +20,65 @@ add_integration_test(
|
||||||
libc.src.sys.wait.waitpid
|
libc.src.sys.wait.waitpid
|
||||||
libc.src.unistd.fork
|
libc.src.unistd.fork
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
libc_execv_test_normal_exit
|
||||||
|
EXCLUDE_FROM_ALL
|
||||||
|
execv_test_normal_exit.cpp
|
||||||
|
)
|
||||||
|
set_target_properties(
|
||||||
|
libc_execv_test_normal_exit
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME libc_execv_test_normal_exit
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
libc_execv_test_signal_exit
|
||||||
|
EXCLUDE_FROM_ALL
|
||||||
|
execv_test_signal_exit.cpp
|
||||||
|
)
|
||||||
|
set_target_properties(
|
||||||
|
libc_execv_test_signal_exit
|
||||||
|
PROPERTIES
|
||||||
|
OUTPUT_NAME libc_execv_test_signal_exit
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_integration_test(
|
||||||
|
execv_test
|
||||||
|
SUITE
|
||||||
|
unistd-integration-tests
|
||||||
|
SRCS
|
||||||
|
execv_test.cpp
|
||||||
|
LOADER
|
||||||
|
libc.loader.linux.crt1
|
||||||
|
DEPENDS
|
||||||
|
libc_execv_test_normal_exit
|
||||||
|
libc_execv_test_signal_exit
|
||||||
|
libc.include.errno
|
||||||
|
libc.src.sys.wait.waitpid
|
||||||
|
libc.src.unistd.execv
|
||||||
|
libc.src.unistd.fork
|
||||||
|
ENV
|
||||||
|
EXECV_TEST=PASS
|
||||||
|
)
|
||||||
|
|
||||||
|
add_integration_test(
|
||||||
|
execve_test
|
||||||
|
SUITE
|
||||||
|
unistd-integration-tests
|
||||||
|
SRCS
|
||||||
|
execve_test.cpp
|
||||||
|
LOADER
|
||||||
|
libc.loader.linux.crt1
|
||||||
|
DEPENDS
|
||||||
|
libc_execv_test_normal_exit
|
||||||
|
libc_execv_test_signal_exit
|
||||||
|
libc.include.errno
|
||||||
|
libc.src.sys.wait.waitpid
|
||||||
|
libc.src.unistd.execve
|
||||||
|
libc.src.unistd.fork
|
||||||
|
ENV
|
||||||
|
EXECV_TEST=PASS
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
//===-- Unittests for execv -----------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/sys/wait/waitpid.h"
|
||||||
|
#include "src/unistd/execv.h"
|
||||||
|
#include "src/unistd/fork.h"
|
||||||
|
|
||||||
|
#include "utils/IntegrationTest/test.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
void fork_and_execv_normal_exit() {
|
||||||
|
pid_t pid = __llvm_libc::fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
const char *path = "libc_execv_test_normal_exit";
|
||||||
|
char *const argv[] = {
|
||||||
|
const_cast<char *>("execv_test_normal_exit"),
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
__llvm_libc::execv(path, argv);
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(pid > 0);
|
||||||
|
int status;
|
||||||
|
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
|
||||||
|
ASSERT_TRUE(cpid > 0);
|
||||||
|
ASSERT_EQ(cpid, pid);
|
||||||
|
ASSERT_TRUE(WIFEXITED(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fork_and_execv_signal_exit() {
|
||||||
|
pid_t pid = __llvm_libc::fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
const char *path = "libc_execv_test_signal_exit";
|
||||||
|
char *const argv[] = {
|
||||||
|
const_cast<char *>("execv_test_normal_exit"),
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
__llvm_libc::execv(path, argv);
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(pid > 0);
|
||||||
|
int status;
|
||||||
|
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
|
||||||
|
ASSERT_TRUE(cpid > 0);
|
||||||
|
ASSERT_EQ(cpid, pid);
|
||||||
|
ASSERT_FALSE(WIFEXITED(status));
|
||||||
|
ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_MAIN(int argc, char **argv, char **envp) {
|
||||||
|
fork_and_execv_normal_exit();
|
||||||
|
fork_and_execv_signal_exit();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *env = getenv("EXECV_TEST");
|
||||||
|
if (env == nullptr)
|
||||||
|
raise(SIGUSR1);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char *env = getenv("__MISSING_ENV_VAR__");
|
||||||
|
if (env == nullptr)
|
||||||
|
raise(SIGUSR1);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
//===-- Unittests for execve ----------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "src/sys/wait/waitpid.h"
|
||||||
|
#include "src/unistd/execve.h"
|
||||||
|
#include "src/unistd/fork.h"
|
||||||
|
|
||||||
|
#include "utils/IntegrationTest/test.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
void fork_and_execv_normal_exit(char **envp) {
|
||||||
|
pid_t pid = __llvm_libc::fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
const char *path = "libc_execv_test_normal_exit";
|
||||||
|
char *const argv[] = {
|
||||||
|
const_cast<char *>("execv_test_normal_exit"),
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
__llvm_libc::execve(path, argv, envp);
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(pid > 0);
|
||||||
|
int status;
|
||||||
|
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
|
||||||
|
ASSERT_TRUE(cpid > 0);
|
||||||
|
ASSERT_EQ(cpid, pid);
|
||||||
|
ASSERT_TRUE(WIFEXITED(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fork_and_execv_signal_exit(char **envp) {
|
||||||
|
pid_t pid = __llvm_libc::fork();
|
||||||
|
if (pid == 0) {
|
||||||
|
const char *path = "libc_execv_test_signal_exit";
|
||||||
|
char *const argv[] = {
|
||||||
|
const_cast<char *>("execv_test_normal_exit"),
|
||||||
|
nullptr,
|
||||||
|
};
|
||||||
|
__llvm_libc::execve(path, argv, envp);
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(pid > 0);
|
||||||
|
int status;
|
||||||
|
pid_t cpid = __llvm_libc::waitpid(pid, &status, 0);
|
||||||
|
ASSERT_TRUE(cpid > 0);
|
||||||
|
ASSERT_EQ(cpid, pid);
|
||||||
|
ASSERT_FALSE(WIFEXITED(status));
|
||||||
|
ASSERT_TRUE(WTERMSIG(status) == SIGUSR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_MAIN(int argc, char **argv, char **envp) {
|
||||||
|
fork_and_execv_normal_exit(envp);
|
||||||
|
fork_and_execv_signal_exit(envp);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue