[libc-commits] [libc] 86bde5a - [libc] implement prctl (#74386)
via libc-commits
libc-commits at lists.llvm.org
Tue Dec 5 12:31:04 PST 2023
Author: Schrodinger ZHU Yifan
Date: 2023-12-05T12:31:00-08:00
New Revision: 86bde5adc8f20a619c7ccbfee5d9bf92c5429226
URL: https://github.com/llvm/llvm-project/commit/86bde5adc8f20a619c7ccbfee5d9bf92c5429226
DIFF: https://github.com/llvm/llvm-project/commit/86bde5adc8f20a619c7ccbfee5d9bf92c5429226.diff
LOG: [libc] implement prctl (#74386)
Implement `prctl` as specified in
https://man7.org/linux/man-pages/man2/prctl.2.html.
This patch also includes test cases covering two simple use cases:
1. `PR_GET_NAME/PR_SET_NAME`: where userspace data is passed via arg2.
2. `PR_GET_THP_DISABLE`: where return value is passed via syscal retval.
Added:
libc/src/sys/prctl/CMakeLists.txt
libc/src/sys/prctl/linux/CMakeLists.txt
libc/src/sys/prctl/linux/prctl.cpp
libc/src/sys/prctl/prctl.h
libc/test/src/sys/prctl/CMakeLists.txt
libc/test/src/sys/prctl/linux/CMakeLists.txt
libc/test/src/sys/prctl/linux/prctl_test.cpp
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/arm/entrypoints.txt
libc/config/linux/riscv/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/include/sys/prctl.h.def
libc/src/sys/CMakeLists.txt
libc/test/src/sys/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 7a60c44570c4e..60e0e2b29aed3 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -165,6 +165,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.wait.wait4
libc.src.sys.wait.waitpid
+ # sys/prctl.h entrypoints
+ libc.src.sys.prctl.prctl
+
# termios.h entrypoints
libc.src.termios.cfgetispeed
libc.src.termios.cfgetospeed
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index b7783ace90a88..123c7e33377ad 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -92,6 +92,9 @@ set(TARGET_LIBC_ENTRYPOINTS
# sys/mman.h entrypoints
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
+
+ # sys/prctl.h entrypoints
+ libc.src.sys.prctl.prctl
)
set(TARGET_LIBM_ENTRYPOINTS
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 28687ef8e234e..948708e35f45d 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -171,6 +171,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.wait.wait4
libc.src.sys.wait.waitpid
+ # sys/prctl.h entrypoints
+ libc.src.sys.prctl.prctl
+
# termios.h entrypoints
libc.src.termios.cfgetispeed
libc.src.termios.cfgetospeed
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 43266e0e5b66e..13b81d3b7ca70 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -174,6 +174,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.wait.wait4
libc.src.sys.wait.waitpid
+ # sys/prctl.h entrypoints
+ libc.src.sys.prctl.prctl
+
# termios.h entrypoints
libc.src.termios.cfgetispeed
libc.src.termios.cfgetospeed
diff --git a/libc/include/sys/prctl.h.def b/libc/include/sys/prctl.h.def
index 3c29719837ca1..0a11543d07296 100644
--- a/libc/include/sys/prctl.h.def
+++ b/libc/include/sys/prctl.h.def
@@ -15,8 +15,6 @@
// the macros itself.
#include <linux/prctl.h>
-// TODO: Define the prctl macros.
-
%%public_api()
#endif // LLVM_LIBC_SYS_PRCTL_H
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index bf869ddc6a23c..12e2020f013ab 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -7,3 +7,4 @@ add_subdirectory(sendfile)
add_subdirectory(stat)
add_subdirectory(utsname)
add_subdirectory(wait)
+add_subdirectory(prctl)
diff --git a/libc/src/sys/prctl/CMakeLists.txt b/libc/src/sys/prctl/CMakeLists.txt
new file mode 100644
index 0000000000000..a78c3c5a40bc0
--- /dev/null
+++ b/libc/src/sys/prctl/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+ prctl
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.prctl
+)
diff --git a/libc/src/sys/prctl/linux/CMakeLists.txt b/libc/src/sys/prctl/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..05d336441f4d0
--- /dev/null
+++ b/libc/src/sys/prctl/linux/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_entrypoint_object(
+ prctl
+ SRCS
+ prctl.cpp
+ HDRS
+ ../prctl.h
+ DEPENDS
+ libc.include.sys_prctl
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
diff --git a/libc/src/sys/prctl/linux/prctl.cpp b/libc/src/sys/prctl/linux/prctl.cpp
new file mode 100644
index 0000000000000..b68b7621555dc
--- /dev/null
+++ b/libc/src/sys/prctl/linux/prctl.cpp
@@ -0,0 +1,37 @@
+//===---------- Linux implementation of the prctl function ----------------===//
+//
+// 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/prctl/prctl.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, prctl,
+ (int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5)) {
+ long ret =
+ LIBC_NAMESPACE::syscall_impl(SYS_prctl, option, arg2, arg3, arg4, arg5);
+ // The manpage states that "... return the nonnegative values described
+ // above. All other option values return 0 on success. On error,
+ // -1 is returned, and errno is set to indicate the error."
+ // According to the kernel implementation
+ // (https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/kernel/sys.c#L2442),
+ // return value from the syscall is set to 0 on default so we do not need to
+ // set the value on success manually.
+ if (ret < 0) {
+ libc_errno = static_cast<int>(-ret);
+ return -1;
+ }
+ return static_cast<int>(ret);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/prctl/prctl.h b/libc/src/sys/prctl/prctl.h
new file mode 100644
index 0000000000000..baa0676d4254b
--- /dev/null
+++ b/libc/src/sys/prctl/prctl.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for prctl ---------------------------*-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_SYS_PRCTL_PRCTL_H
+#define LLVM_LIBC_SRC_SYS_PRCTL_PRCTL_H
+
+#include <sys/prctl.h>
+
+namespace LIBC_NAMESPACE {
+
+int prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_PRCTL_PRCTL_H
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 5ef97fe817700..a87e77da7d2cd 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -7,3 +7,4 @@ add_subdirectory(socket)
add_subdirectory(stat)
add_subdirectory(utsname)
add_subdirectory(wait)
+add_subdirectory(prctl)
diff --git a/libc/test/src/sys/prctl/CMakeLists.txt b/libc/test/src/sys/prctl/CMakeLists.txt
new file mode 100644
index 0000000000000..b4bbe81c92ff2
--- /dev/null
+++ b/libc/test/src/sys/prctl/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/sys/prctl/linux/CMakeLists.txt b/libc/test/src/sys/prctl/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..25e9b8fd8a007
--- /dev/null
+++ b/libc/test/src/sys/prctl/linux/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_custom_target(libc_sys_prctl_unittests)
+
+add_libc_unittest(
+ prctl_test
+ SUITE
+ libc_sys_prctl_unittests
+ SRCS
+ prctl_test.cpp
+ DEPENDS
+ libc.include.sys_prctl
+ libc.include.errno
+ libc.src.sys.prctl.prctl
+ libc.src.errno.errno
+)
diff --git a/libc/test/src/sys/prctl/linux/prctl_test.cpp b/libc/test/src/sys/prctl/linux/prctl_test.cpp
new file mode 100644
index 0000000000000..643c9513b36eb
--- /dev/null
+++ b/libc/test/src/sys/prctl/linux/prctl_test.cpp
@@ -0,0 +1,44 @@
+//===-- Unittests for prctl -----------------------------------------------===//
+//
+// 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/errno/libc_errno.h"
+#include "src/sys/prctl/prctl.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include <errno.h>
+#include <sys/prctl.h>
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+
+TEST(LlvmLibcSysPrctlTest, GetSetName) {
+ char name[17];
+ unsigned long name_addr = 0;
+ ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0),
+ Fails(EFAULT, -1));
+
+ name_addr = reinterpret_cast<unsigned long>("libc-test");
+ ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_SET_NAME, name_addr, 0, 0, 0),
+ Succeeds());
+
+ name_addr = reinterpret_cast<unsigned long>(name);
+ ASSERT_THAT(LIBC_NAMESPACE::prctl(PR_GET_NAME, name_addr, 0, 0, 0),
+ Succeeds());
+ ASSERT_STREQ(name, "libc-test");
+}
+
+TEST(LlvmLibcSysPrctlTest, GetTHPDisable) {
+ // Manually check errno since the return value logic here is not
+ // covered in ErrnoSetterMatcher.
+ libc_errno = 0;
+ int ret = LIBC_NAMESPACE::prctl(PR_GET_THP_DISABLE, 0, 0, 0, 0);
+ ASSERT_EQ(libc_errno, 0);
+ // PR_GET_THP_DISABLE return (as the function result) the current
+ // setting of the "THP disable" flag for the calling thread, which
+ // is either 1, if the flag is set; or 0, if it is not.
+ ASSERT_TRUE(ret == 0 || ret == 1);
+}
More information about the libc-commits
mailing list