Skip to content

[libc] Refactoring getauxval to use internal functions #144451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions libc/src/__support/OSUtil/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ add_object_library(
SRCS
exit.cpp
fcntl.cpp
mmap.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions are mostly few liners. Consider put them into header-only implementations, and create independent cmake targets with add_header_library for each one of them.

munmap.cpp
prctl.cpp
read.cpp
HDRS
io.h
syscall.h
Expand All @@ -22,6 +26,10 @@ add_object_library(
libc.hdr.types.struct_f_owner_ex
libc.hdr.types.off_t
libc.include.sys_syscall
libc.src.__support.macros.sanitizer
libc.hdr.types.size_t
libc.hdr.types.ssize_t
libc.include.unistd
)

add_header_library(
Expand Down
66 changes: 66 additions & 0 deletions libc/src/__support/OSUtil/linux/mmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===------ Linux implementation of the POSIX mmap function -----*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/OSUtil/mmap.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/error_or.h"

#include "src/__support/macros/config.h"
#include <linux/param.h> // For EXEC_PAGESIZE.
#include <sys/syscall.h> // For syscall numbers.
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY

namespace LIBC_NAMESPACE_DECL {
namespace internal {

// This function is currently linux only. It has to be refactored suitably if
// mmap is to be supported on non-linux operating systems also.
ErrorOr<void *> mmap(void *addr, size_t size, int prot, int flags, int fd,
off_t offset) {
// A lot of POSIX standard prescribed validation of the parameters is not
// done in this function as modern linux versions do it in the syscall.
// TODO: Perform argument validation not done by the linux syscall.

// EXEC_PAGESIZE is used for the page size. While this is OK for x86_64, it
// might not be correct in general.
// TODO: Use pagesize read from the ELF aux vector instead of EXEC_PAGESIZE.

#ifdef SYS_mmap2
offset /= EXEC_PAGESIZE;
long syscall_number = SYS_mmap2;
#elif defined(SYS_mmap)
long syscall_number = SYS_mmap;
#else
#error "mmap or mmap2 syscalls not available."
#endif

// We add an explicit cast to silence a "implicit conversion loses integer
// precision" warning when compiling for 32-bit systems.
long mmap_offset = static_cast<long>(offset);
long ret =
LIBC_NAMESPACE::syscall_impl(syscall_number, reinterpret_cast<long>(addr),
size, prot, flags, fd, mmap_offset);

// The mmap/mmap2 syscalls return negative values on error. These negative
// values are actually the negative values of the error codes. So, fix them
// up in case an error code is detected.
//
// A point to keep in mind for the fix up is that a negative return value
// from the syscall can also be an error-free value returned by the syscall.
// However, since a valid return address cannot be within the last page, a
// return value corresponding to a location in the last page is an error
// value.
if (LIBC_UNLIKELY(ret < 0 && ret > -EXEC_PAGESIZE))
return Error(static_cast<int>(-ret));

return reinterpret_cast<void *>(ret);
}

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
35 changes: 35 additions & 0 deletions libc/src/__support/OSUtil/linux/munmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===---- Linux implementation of the POSIX munmap function -----*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/OSUtil/munmap.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"

#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include <sys/syscall.h> // For syscall numbers.

namespace LIBC_NAMESPACE_DECL {
namespace internal {

// This function is currently linux only. It has to be refactored suitably if
// munmap is to be supported on non-linux operating systems also.
ErrorOr<int> munmap(void *addr, size_t size) {
int ret = LIBC_NAMESPACE::syscall_impl<int>(
SYS_munmap, reinterpret_cast<long>(addr), size);

if (LIBC_UNLIKELY(ret < 0))
return Error(-ret);

return 0;
}

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
40 changes: 40 additions & 0 deletions libc/src/__support/OSUtil/linux/prctl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===---- Linux implementation of the prctl function ------------*- 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
//
//===----------------------------------------------------------------------===//

#include "src/__support/OSUtil/prctl.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.

#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include <sys/syscall.h> // For syscall numbers.

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<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 (LIBC_UNLIKELY(ret < 0))
return Error(static_cast<int>(-ret));

return static_cast<int>(ret);
}

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
33 changes: 33 additions & 0 deletions libc/src/__support/OSUtil/linux/read.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===-- Linux implementation of read --------------------------------------===//
//
// 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/__support/OSUtil/read.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON
#include <sys/syscall.h> // For syscall numbers.

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<ssize_t> read(int fd, void *buf, size_t count) {
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_read, fd, buf, count);
if (LIBC_UNLIKELY(ret < 0))
return Error(static_cast<int>(-ret));

// The cast is important since there is a check that dereferences the pointer
// which fails on void*.
MSAN_UNPOISON(reinterpret_cast<char *>(buf), count);
return ret;
}

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL
26 changes: 26 additions & 0 deletions libc/src/__support/OSUtil/mmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===----------- Implementation header of the mmap function -----*- 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___SUPPORT_OSUTIL_MMAP_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H

#include "hdr/types/off_t.h"
#include "hdr/types/size_t.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<void *> mmap(void *addr, size_t size, int prot, int flags, int fd,
off_t offset);

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_MMAP_H
25 changes: 25 additions & 0 deletions libc/src/__support/OSUtil/munmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===--------- Implementation header of the munmap function -----*- 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___SUPPORT_OSUTIL_MUNMAP_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H

#include "hdr/types/off_t.h"
#include "hdr/types/size_t.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<int> munmap(void *addr, size_t size);

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_MUNMAP_H
26 changes: 26 additions & 0 deletions libc/src/__support/OSUtil/prctl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===--------- Implementation header of the prctl function -----*- 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___SUPPORT_OSUTIL_PRCTL_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H

#include "src/__support/error_or.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <sys/prctl.h>

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<int> prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_PRCTL_H
26 changes: 26 additions & 0 deletions libc/src/__support/OSUtil/read.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===--------- Implementation header of the read function -------*- 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___SUPPORT_OSUTIL_READ_H
#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_READ_H

#include "hdr/types/size_t.h"
#include "hdr/types/ssize_t.h"
#include "hdr/unistd_macros.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {
namespace internal {

ErrorOr<ssize_t> read(int fd, void *buf, size_t count);

} // namespace internal
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_READ_H
3 changes: 1 addition & 2 deletions libc/src/sys/auxv/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ add_entrypoint_object(
../getauxval.h
DEPENDS
libc.src.sys.prctl.prctl
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
libc.src.__support.threads.callonce
libc.src.__support.common
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
libc.config.app_h
libc.src.fcntl.open
Expand Down
Loading
Loading