forked from OSchip/llvm-project
[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
|
||||
libc.src.__support.threads.thread
|
||||
libc.src.stdlib.atexit
|
||||
libc.src.stdlib.exit)
|
||||
libc.src.stdlib.exit
|
||||
libc.src.unistd.environ)
|
||||
list(REMOVE_DUPLICATES fq_deps_list)
|
||||
|
||||
# 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}
|
||||
${fq_target_name}.__copy_loader__
|
||||
${fq_libc_target_name}
|
||||
libc.utils.IntegrationTest.test)
|
||||
libc.utils.IntegrationTest.test
|
||||
${INTEGRATION_TEST_DEPENDS})
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${fq_target_name}
|
||||
|
|
|
@ -377,6 +377,9 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.time.mktime
|
||||
libc.src.time.nanosleep
|
||||
libc.src.time.clock_gettime
|
||||
|
||||
# unistd.h entrypoints
|
||||
libc.src.unistd.environ
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ def DirentAPI : PublicAPI<"dirent.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"> {
|
||||
|
|
|
@ -143,6 +143,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.unistd.dup
|
||||
libc.src.unistd.dup2
|
||||
libc.src.unistd.dup3
|
||||
libc.src.unistd.execve
|
||||
libc.src.unistd.fchdir
|
||||
libc.src.unistd.fsync
|
||||
libc.src.unistd.ftruncate
|
||||
|
@ -412,6 +413,8 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.time.clock_gettime
|
||||
|
||||
# unistd.h entrypoints
|
||||
libc.src.unistd.environ
|
||||
libc.src.unistd.execv
|
||||
libc.src.unistd.fork
|
||||
libc.src.unistd.__llvm_libc_syscall
|
||||
)
|
||||
|
|
|
@ -175,6 +175,8 @@ add_gen_header(
|
|||
.llvm_libc_common_h
|
||||
.llvm-libc-macros.file_seek_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.pid_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(__bsearchcompare_t HDR __bsearchcompare_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(__mutex_type HDR __mutex_type.h DEPENDS .__futex_word)
|
||||
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 <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" int main(int, char **, char **);
|
||||
|
||||
|
@ -147,6 +148,9 @@ __attribute__((noinline)) static void do_start() {
|
|||
while (*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
|
||||
// denoted by an AT_NULL entry.
|
||||
Elf64_Phdr *programHdrTable = nullptr;
|
||||
|
|
|
@ -6,11 +6,13 @@ add_loader_object(
|
|||
libc.config.linux.app_h
|
||||
libc.include.sys_mman
|
||||
libc.include.sys_syscall
|
||||
libc.include.unistd
|
||||
libc.src.__support.threads.thread
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.stdlib.exit
|
||||
libc.src.stdlib.atexit
|
||||
libc.src.string.memory_utils.memcpy_implementation
|
||||
libc.src.unistd.environ
|
||||
COMPILE_OPTIONS
|
||||
-fno-omit-frame-pointer
|
||||
-ffreestanding # To avoid compiler warnings about calling the main function.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" int main(int, char **, char **);
|
||||
|
||||
|
@ -167,6 +168,9 @@ extern "C" void _start() {
|
|||
while (*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
|
||||
// denoted by an AT_NULL entry.
|
||||
Elf64_Phdr *programHdrTable = nullptr;
|
||||
|
|
|
@ -45,6 +45,9 @@ def ConstStructDirentPtrPtr : ConstType<StructDirentPtrPtr>;
|
|||
def StructTimeSpec : NamedType<"struct timespec">;
|
||||
def StructTimeSpecPtr : PtrType<StructTimeSpec>;
|
||||
|
||||
def ExecArgvT : NamedType<"__exec_argv_t">;
|
||||
def ExecEnvpT : NamedType<"__exec_envp_t">;
|
||||
|
||||
def POSIX : StandardSpec<"POSIX"> {
|
||||
PtrType CharPtr = PtrType<CharType>;
|
||||
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
|
||||
|
@ -299,6 +302,8 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
"unistd.h",
|
||||
[], // Macros
|
||||
[
|
||||
ExecArgvT,
|
||||
ExecEnvpT,
|
||||
OffTType,
|
||||
SSizeTType,
|
||||
SizeTType,
|
||||
|
@ -342,6 +347,16 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"execv",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstCharPtr>, ArgSpec<ExecArgvT>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"execve",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstCharPtr>, ArgSpec<ExecArgvT>, ArgSpec<ExecEnvpT>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fork",
|
||||
RetValSpec<PidT>,
|
||||
|
@ -512,6 +527,9 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<SSizeTType>,
|
||||
[ArgSpec<IntType>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
|
||||
>,
|
||||
],
|
||||
[
|
||||
ObjectSpec<"environ", "char **">,
|
||||
]
|
||||
>;
|
||||
|
||||
|
|
|
@ -58,6 +58,20 @@ add_entrypoint_object(
|
|||
.${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(
|
||||
fsync
|
||||
ALIAS
|
||||
|
@ -211,3 +225,11 @@ add_entrypoint_object(
|
|||
DEPENDS
|
||||
.${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
|
||||
)
|
||||
|
||||
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(
|
||||
fsync
|
||||
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.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