[libc-commits] [libc] [libc] Refactor AUXV handling with new auxv.h header library (PR #162326)
Schrodinger ZHU Yifan via libc-commits
libc-commits at lists.llvm.org
Tue Oct 7 10:30:03 PDT 2025
https://github.com/SchrodingerZhu updated https://github.com/llvm/llvm-project/pull/162326
>From 5fbf8d8127219dc8ca4690d9b58a881c8554534f Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 7 Oct 2025 13:13:58 -0400
Subject: [PATCH 1/4] [libc] Refactor AUXV handling with new auxv.h header
library
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch introduces a new centralized AUXV (auxiliary vector) handling
mechanism for LLVM libc on Linux, replacing the previous scattered
implementation across multiple files.
## Key Changes:
### New Files:
- **libc/src/__support/OSUtil/linux/auxv.h**: New header library providing
a clean interface for AUXV access with:
- `auxv::Entry` struct for AUXV entries (type and value)
- `auxv::Vector` class with iterator support for traversing AUXV
- `auxv::get()` function for retrieving specific AUXV values
- Thread-safe initialization with fallback mechanisms (prctl and /proc/self/auxv)
### Modified Files:
1. **libc/src/__support/OSUtil/linux/CMakeLists.txt**:
- Added `auxv` header library declaration with proper dependencies:
- libc.hdr.fcntl_macros
- libc.src.__support.OSUtil.osutil
- libc.src.__support.common
- libc.src.__support.CPP.optional
- libc.src.__support.threads.callonce
2. **libc/config/linux/app.h**:
- Removed `AuxEntry` struct (moved to auxv.h as `auxv::Entry`)
- Removed `auxv_ptr` from `AppProperties` struct
- Simplified application properties structure
3. **libc/src/sys/auxv/linux/getauxval.cpp**:
- Completely refactored to use new auxv.h interface
- Removed ~200 lines of complex initialization code
- Simplified to just call `auxv::get()` function
- Removed dependencies to external symbols (mman, prctl, fcntl, read, close, open)
4. **libc/src/sys/auxv/linux/CMakeLists.txt**:
- Updated dependencies to use new auxv header library
- Removed dependencies to external symbols (prctl, mman, fcntl, unistd, etc.)
5. **libc/startup/linux/do_start.cpp**:
- Updated to use new `auxv::Vector` interface
- Changed from pointer-based to iterator-based AUXV traversal
- Updated field names (`aux_entry->id` → `aux_entry.type`, `aux_entry->value` → `aux_entry.val`)
- Added call to `auxv::Vector::initialize_unsafe()` for early AUXV setup
6. **libc/startup/linux/CMakeLists.txt**:
- Added dependency on `libc.src.__support.OSUtil.linux.auxv`
---
libc/config/linux/app.h | 14 --
.../src/__support/OSUtil/linux/CMakeLists.txt | 12 +
libc/src/__support/OSUtil/linux/auxv.h | 145 ++++++++++++
libc/src/sys/auxv/linux/CMakeLists.txt | 13 +-
libc/src/sys/auxv/linux/getauxval.cpp | 223 +-----------------
libc/startup/linux/CMakeLists.txt | 1 +
libc/startup/linux/do_start.cpp | 15 +-
7 files changed, 174 insertions(+), 249 deletions(-)
create mode 100644 libc/src/__support/OSUtil/linux/auxv.h
diff --git a/libc/config/linux/app.h b/libc/config/linux/app.h
index f3d11da9fc14c..11ac6ee51e5a0 100644
--- a/libc/config/linux/app.h
+++ b/libc/config/linux/app.h
@@ -35,17 +35,6 @@ struct TLSImage {
uintptr_t align;
};
-// Linux manpage on `proc(5)` says that the aux vector is an array of
-// unsigned long pairs.
-// (see: https://man7.org/linux/man-pages/man5/proc.5.html)
-using AuxEntryType = unsigned long;
-// Using the naming convention from `proc(5)`.
-// TODO: Would be nice to use the aux entry structure from elf.h when available.
-struct AuxEntry {
- AuxEntryType id;
- AuxEntryType value;
-};
-
struct Args {
uintptr_t argc;
@@ -70,9 +59,6 @@ struct AppProperties {
// Environment data.
uintptr_t *env_ptr;
-
- // Auxiliary vector data.
- AuxEntry *auxv_ptr;
};
[[gnu::weak]] extern AppProperties app;
diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt
index f303e54ce7b3b..f6377ca9ff5a2 100644
--- a/libc/src/__support/OSUtil/linux/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt
@@ -24,6 +24,18 @@ add_object_library(
libc.include.sys_syscall
)
+add_header_library(
+ auxv
+ HDRS
+ auxv.h
+ DEPENDS
+ libc.hdr.fcntl_macros
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.CPP.optional
+ libc.src.__support.threads.callonce
+)
+
add_header_library(
getrandom
HDRS
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
new file mode 100644
index 0000000000000..e12add62a011d
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -0,0 +1,145 @@
+//===------------- Linux AUXV Header --------------------------*- 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_LINUX_AUXV_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AUXV_H
+
+#include "hdr/fcntl_macros.h" // For open flags
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
+#include "src/__support/threads/callonce.h"
+
+#include <linux/auxvec.h> // For AT_ macros
+#include <linux/mman.h> // For mmap flags
+#include <linux/prctl.h> // For prctl
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace auxv {
+struct Entry {
+ unsigned long type; // Entry type
+ unsigned long val; // Integer value
+};
+
+class Vector {
+ LIBC_INLINE_VAR static constexpr Entry END = {AT_NULL, AT_NULL};
+ LIBC_INLINE_VAR static const Entry *entries = &END;
+ LIBC_INLINE_VAR static CallOnceFlag init_flag = callonce_impl::NOT_CALLED;
+ LIBC_INLINE_VAR constexpr static size_t FALLBACK_AUXV_ENTRIES = 64;
+
+ LIBC_INLINE static void fallback_initialize_unsync();
+ LIBC_INLINE static const Entry *get_entries() {
+ if (LIBC_LIKELY(entries != &END))
+ return entries;
+ callonce(&init_flag, fallback_initialize_unsync);
+ return entries;
+ }
+
+public:
+ class Iterator {
+ const Entry *current;
+
+ public:
+ LIBC_INLINE explicit Iterator(const Entry *entry) : current(entry) {}
+ LIBC_INLINE Iterator &operator++() {
+ ++current;
+ return *this;
+ }
+ LIBC_INLINE const Entry &operator*() const { return *current; }
+ LIBC_INLINE bool operator!=(const Iterator &other) const {
+ return current->type != other.current->type;
+ }
+ LIBC_INLINE bool operator==(const Iterator &other) const {
+ return current->type == other.current->type;
+ }
+ };
+ using iterator = Iterator;
+ LIBC_INLINE static Iterator begin() { return Iterator(get_entries()); }
+ LIBC_INLINE static Iterator end() { return Iterator(&END); }
+ LIBC_INLINE static void initialize_unsafe(const Entry *auxv);
+};
+
+// Initializes the auxv entries.
+// This function is intended to be called once inside crt0.
+LIBC_INLINE void Vector::initialize_unsafe(const Entry *auxv) {
+ init_flag = callonce_impl::FINISH;
+ entries = auxv;
+}
+
+// When CRT0 does not setup the global array, this function is called.
+// As its name suggests, this function is not thread-safe and should be
+// backed by a callonce guard.
+// This initialize routine will do a mmap to allocate a memory region.
+// Since auxv tends to live throughout the program lifetime, we do not
+// munmap it.
+LIBC_INLINE void Vector::fallback_initialize_unsync() {
+ constexpr size_t AUXV_MMAP_SIZE = FALLBACK_AUXV_ENTRIES * sizeof(Entry);
+ long mmap_ret = syscall_impl<long>(SYS_mmap, nullptr, AUXV_MMAP_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ // We do not proceed if mmap fails.
+ if (mmap_ret <= 0)
+ return;
+
+ // Initialize the auxv array with AT_NULL entries.
+ Entry *vector = reinterpret_cast<Entry *>(mmap_ret);
+ for (size_t i = 0; i < FALLBACK_AUXV_ENTRIES; ++i) {
+ vector[i].type = AT_NULL;
+ vector[i].val = AT_NULL;
+ }
+ size_t avaiable_size = AUXV_MMAP_SIZE - sizeof(Entry);
+
+ // Attempt 1: use PRCTL to get the auxv.
+ // We guarantee that the vector is always padded with AT_NULL entries.
+ long prctl_ret = syscall_impl<long>(SYS_prctl, PR_GET_AUXV,
+ reinterpret_cast<unsigned long>(vector),
+ avaiable_size, 0, 0);
+ if (prctl_ret >= 0) {
+ entries = vector;
+ return;
+ }
+
+ // Attempt 2: read /proc/self/auxv.
+ int fd = syscall_impl<int>(SYS_open, "/proc/self/auxv", O_RDONLY | O_CLOEXEC);
+ if (fd < 0) {
+ syscall_impl<long>(SYS_munmap, vector, AUXV_MMAP_SIZE);
+ return;
+ }
+ uint8_t *cursor = reinterpret_cast<uint8_t *>(vector);
+ bool has_error = false;
+ while (avaiable_size != 0) {
+ long bytes_read = syscall_impl<long>(SYS_read, fd, cursor, avaiable_size);
+ if (bytes_read <= 0) {
+ if (bytes_read == -EINTR)
+ continue;
+ has_error = bytes_read < 0;
+ break;
+ }
+ avaiable_size -= bytes_read;
+ cursor += bytes_read;
+ }
+ syscall_impl<long>(SYS_close, fd);
+ if (has_error) {
+ syscall_impl<long>(SYS_munmap, vector, AUXV_MMAP_SIZE);
+ return;
+ }
+ entries = vector;
+}
+
+LIBC_INLINE cpp::optional<unsigned long> get(unsigned long type) {
+ Vector auxvec;
+ for (const auto &entry : auxvec) {
+ if (entry.type == type)
+ return entry.val;
+ }
+ return cpp::nullopt;
+}
+} // namespace auxv
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_AUXV_H
diff --git a/libc/src/sys/auxv/linux/CMakeLists.txt b/libc/src/sys/auxv/linux/CMakeLists.txt
index 4884184cc6053..39cfb7ba3f7ee 100644
--- a/libc/src/sys/auxv/linux/CMakeLists.txt
+++ b/libc/src/sys/auxv/linux/CMakeLists.txt
@@ -5,15 +5,6 @@ add_entrypoint_object(
HDRS
../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.errno.errno
- libc.config.app_h
- libc.src.fcntl.open
- libc.src.unistd.read
- libc.src.unistd.close
- libc.include.sys_auxv
+ libc.src.__support.OSUtil.linux.auxv
+ libc.src.__support.libc_errno
)
diff --git a/libc/src/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp
index b50c5845bcc2b..52d5a988a9494 100644
--- a/libc/src/sys/auxv/linux/getauxval.cpp
+++ b/libc/src/sys/auxv/linux/getauxval.cpp
@@ -7,227 +7,14 @@
//===----------------------------------------------------------------------===//
#include "src/sys/auxv/getauxval.h"
-#include "config/app.h"
-#include "hdr/fcntl_macros.h"
-#include "src/__support/OSUtil/fcntl.h"
-#include "src/__support/common.h"
+#include "src/__support/OSUtil/linux/auxv.h"
#include "src/__support/libc_errno.h"
-#include "src/__support/macros/config.h"
-#include <linux/auxvec.h>
-
-// for guarded initialization
-#include "src/__support/threads/callonce.h"
-#include "src/__support/threads/linux/futex_word.h"
-
-// -----------------------------------------------------------------------------
-// TODO: This file should not include other public libc functions. Calling other
-// public libc functions is an antipattern within LLVM-libc. This needs to be
-// cleaned up. DO NOT COPY THIS.
-// -----------------------------------------------------------------------------
-
-// for mallocing the global auxv
-#include "src/sys/mman/mmap.h"
-#include "src/sys/mman/munmap.h"
-
-// for reading /proc/self/auxv
-#include "src/sys/prctl/prctl.h"
-#include "src/unistd/read.h"
-
-// getauxval will work either with or without __cxa_atexit support.
-// In order to detect if __cxa_atexit is supported, we define a weak symbol.
-// We prefer __cxa_atexit as it is always defined as a C symbol whileas atexit
-// may not be created via objcopy yet. Also, for glibc, atexit is provided via
-// libc_nonshared.a rather than libc.so. So, it is may not be made ready for
-// overlay builds.
-extern "C" [[gnu::weak]] int __cxa_atexit(void (*callback)(void *),
- void *payload, void *);
namespace LIBC_NAMESPACE_DECL {
-
-constexpr static size_t MAX_AUXV_ENTRIES = 64;
-
-// Helper to recover or set errno
-class AuxvErrnoGuard {
-public:
- AuxvErrnoGuard() : saved(libc_errno), failure(false) {}
- ~AuxvErrnoGuard() { libc_errno = failure ? ENOENT : saved; }
- void mark_failure() { failure = true; }
-
-private:
- int saved;
- bool failure;
-};
-
-// Helper to manage the memory
-static AuxEntry *auxv = nullptr;
-
-class AuxvMMapGuard {
-public:
- constexpr static size_t AUXV_MMAP_SIZE = sizeof(AuxEntry) * MAX_AUXV_ENTRIES;
-
- AuxvMMapGuard()
- : ptr(LIBC_NAMESPACE::mmap(nullptr, AUXV_MMAP_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {}
- ~AuxvMMapGuard() {
- if (ptr != MAP_FAILED)
- LIBC_NAMESPACE::munmap(ptr, AUXV_MMAP_SIZE);
- }
- void submit_to_global() {
- // atexit may fail, we do not set it to global in that case.
- int ret = __cxa_atexit(
- [](void *) {
- LIBC_NAMESPACE::munmap(auxv, AUXV_MMAP_SIZE);
- auxv = nullptr;
- },
- nullptr, nullptr);
-
- if (ret != 0)
- return;
-
- auxv = reinterpret_cast<AuxEntry *>(ptr);
- ptr = MAP_FAILED;
- }
- bool allocated() const { return ptr != MAP_FAILED; }
- void *get() const { return ptr; }
-
-private:
- void *ptr;
-};
-
-class AuxvFdGuard {
-public:
- AuxvFdGuard() {
- auto result = internal::open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
- if (!result.has_value())
- fd = -1;
-
- fd = result.value();
- }
- ~AuxvFdGuard() {
- if (fd != -1)
- internal::close(fd);
- }
- bool valid() const { return fd != -1; }
- int get() const { return fd; }
-
-private:
- int fd;
-};
-
-static void initialize_auxv_once(void) {
- // If we cannot get atexit, we cannot register the cleanup function.
- if (&__cxa_atexit == nullptr)
- return;
-
- AuxvMMapGuard mmap_guard;
- if (!mmap_guard.allocated())
- return;
- auto *ptr = reinterpret_cast<AuxEntry *>(mmap_guard.get());
-
- // We get one less than the max size to make sure the search always
- // terminates. MMAP private pages are zeroed out already.
- size_t available_size = AuxvMMapGuard::AUXV_MMAP_SIZE - sizeof(AuxEntryType);
- // PR_GET_AUXV is only available on Linux kernel 6.1 and above. If this is not
- // defined, we direcly fall back to reading /proc/self/auxv. In case the libc
- // is compiled and run on separate kernels, we also check the return value of
- // prctl.
-#ifdef PR_GET_AUXV
- int ret = prctl(PR_GET_AUXV, reinterpret_cast<unsigned long>(ptr),
- available_size, 0, 0);
- if (ret >= 0) {
- mmap_guard.submit_to_global();
- return;
- }
-#endif
- AuxvFdGuard fd_guard;
- if (!fd_guard.valid())
- return;
- auto *buf = reinterpret_cast<char *>(ptr);
- libc_errno = 0;
- bool error_detected = false;
- // Read until we use up all the available space or we finish reading the file.
- while (available_size != 0) {
- ssize_t bytes_read =
- LIBC_NAMESPACE::read(fd_guard.get(), buf, available_size);
- if (bytes_read <= 0) {
- if (libc_errno == EINTR)
- continue;
- // Now, we either have an non-recoverable error or we have reached the end
- // of the file. Mark `error_detected` accordingly.
- if (bytes_read == -1)
- error_detected = true;
- break;
- }
- buf += bytes_read;
- available_size -= bytes_read;
- }
- // If we get out of the loop without an error, the auxv is ready.
- if (!error_detected)
- mmap_guard.submit_to_global();
-}
-
-static AuxEntry read_entry(int fd) {
- AuxEntry buf;
- size_t size = sizeof(AuxEntry);
- char *ptr = reinterpret_cast<char *>(&buf);
- while (size > 0) {
- ssize_t ret = LIBC_NAMESPACE::read(fd, ptr, size);
- if (ret < 0) {
- if (libc_errno == EINTR)
- continue;
- // Error detected, return AT_NULL
- buf.id = AT_NULL;
- buf.value = AT_NULL;
- break;
- }
- ptr += ret;
- size -= ret;
- }
- return buf;
-}
-
LLVM_LIBC_FUNCTION(unsigned long, getauxval, (unsigned long id)) {
- // Fast path when libc is loaded by its own initialization code. In this case,
- // app.auxv_ptr is already set to the auxv passed on the initial stack of the
- // process.
- AuxvErrnoGuard errno_guard;
-
- auto search_auxv = [&errno_guard](AuxEntry *auxv,
- unsigned long id) -> AuxEntryType {
- for (auto *ptr = auxv; ptr->id != AT_NULL; ptr++)
- if (ptr->id == id)
- return ptr->value;
-
- errno_guard.mark_failure();
- return AT_NULL;
- };
-
- // App is a weak symbol that is only defined if libc is linked to its own
- // initialization routine. We need to check if it is null.
- if (&app != nullptr)
- return search_auxv(app.auxv_ptr, id);
-
- static FutexWordType once_flag;
- LIBC_NAMESPACE::callonce(reinterpret_cast<CallOnceFlag *>(&once_flag),
- initialize_auxv_once);
- if (auxv != nullptr)
- return search_auxv(auxv, id);
-
- // Fallback to use read without mmap
- AuxvFdGuard fd_guard;
- if (fd_guard.valid()) {
- while (true) {
- AuxEntry buf = read_entry(fd_guard.get());
- if (buf.id == AT_NULL)
- break;
- if (buf.id == id)
- return buf.value;
- }
- }
-
- // cannot find the entry after all methods, mark failure and return 0
- errno_guard.mark_failure();
- return AT_NULL;
+ if (cpp::optional<unsigned long> val = auxv::get(id))
+ return *val;
+ libc_errno = ENOENT;
+ return 0;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt
index 7af1819c57c17..df2c4b9ec508c 100644
--- a/libc/startup/linux/CMakeLists.txt
+++ b/libc/startup/linux/CMakeLists.txt
@@ -105,6 +105,7 @@ add_object_library(
libc.src.stdlib.exit
libc.src.stdlib.atexit
libc.src.unistd.environ
+ libc.src.__support.OSUtil.linux.auxv
COMPILE_OPTIONS
-ffreestanding # To avoid compiler warnings about calling the main function.
-fno-builtin # avoid emit unexpected calls
diff --git a/libc/startup/linux/do_start.cpp b/libc/startup/linux/do_start.cpp
index 94c4ec7092861..a67bf188b1ae3 100644
--- a/libc/startup/linux/do_start.cpp
+++ b/libc/startup/linux/do_start.cpp
@@ -9,6 +9,7 @@
#include "config/linux/app.h"
#include "hdr/stdint_proxy.h"
#include "include/llvm-libc-macros/link-macros.h"
+#include "src/__support/OSUtil/linux/auxv.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/macros/config.h"
#include "src/__support/threads/thread.h"
@@ -88,17 +89,19 @@ void teardown_main_tls() { cleanup_tls(tls.addr, tls.size); }
// denoted by an AT_NULL entry.
ElfW(Phdr) *program_hdr_table = nullptr;
uintptr_t program_hdr_count = 0;
- app.auxv_ptr = reinterpret_cast<AuxEntry *>(env_end_marker + 1);
- for (auto *aux_entry = app.auxv_ptr; aux_entry->id != AT_NULL; ++aux_entry) {
- switch (aux_entry->id) {
+ auxv::Vector::initialize_unsafe(
+ reinterpret_cast<const auxv::Entry *>(env_end_marker + 1));
+ auxv::Vector auxvec;
+ for (const auto &aux_entry : auxvec) {
+ switch (aux_entry.type) {
case AT_PHDR:
- program_hdr_table = reinterpret_cast<ElfW(Phdr) *>(aux_entry->value);
+ program_hdr_table = reinterpret_cast<ElfW(Phdr) *>(aux_entry.val);
break;
case AT_PHNUM:
- program_hdr_count = aux_entry->value;
+ program_hdr_count = aux_entry.val;
break;
case AT_PAGESZ:
- app.page_size = aux_entry->value;
+ app.page_size = aux_entry.val;
break;
default:
break; // TODO: Read other useful entries from the aux vector.
>From 9c6f1d8f01a0314ba006c1bd78a0c5701c99f744 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 7 Oct 2025 13:19:11 -0400
Subject: [PATCH 2/4] annotate cold routine
---
libc/src/__support/OSUtil/linux/auxv.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index e12add62a011d..0ad726881be53 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -77,6 +77,7 @@ LIBC_INLINE void Vector::initialize_unsafe(const Entry *auxv) {
// This initialize routine will do a mmap to allocate a memory region.
// Since auxv tends to live throughout the program lifetime, we do not
// munmap it.
+[[gnu::cold]]
LIBC_INLINE void Vector::fallback_initialize_unsync() {
constexpr size_t AUXV_MMAP_SIZE = FALLBACK_AUXV_ENTRIES * sizeof(Entry);
long mmap_ret = syscall_impl<long>(SYS_mmap, nullptr, AUXV_MMAP_SIZE,
>From 3c82e6091110ebcf3c820dc7c02c6e0f19156f70 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 7 Oct 2025 13:21:42 -0400
Subject: [PATCH 3/4] fix syscall
---
libc/src/__support/OSUtil/linux/auxv.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index 0ad726881be53..e4b3f5b9c807d 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -17,6 +17,7 @@
#include <linux/auxvec.h> // For AT_ macros
#include <linux/mman.h> // For mmap flags
#include <linux/prctl.h> // For prctl
+#include <sys/syscall.h> // For syscall numbers
namespace LIBC_NAMESPACE_DECL {
>From 80c49584bb56f41a3824584f805a2224b7b196af Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Tue, 7 Oct 2025 13:29:48 -0400
Subject: [PATCH 4/4] fix
---
libc/src/__support/OSUtil/linux/auxv.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/OSUtil/linux/auxv.h b/libc/src/__support/OSUtil/linux/auxv.h
index e4b3f5b9c807d..17108e2e54794 100644
--- a/libc/src/__support/OSUtil/linux/auxv.h
+++ b/libc/src/__support/OSUtil/linux/auxv.h
@@ -107,7 +107,12 @@ LIBC_INLINE void Vector::fallback_initialize_unsync() {
}
// Attempt 2: read /proc/self/auxv.
+#ifdef SYS_openat
+ int fd = syscall_impl<int>(SYS_openat, AT_FDCWD, "/proc/self/auxv",
+ O_RDONLY | O_CLOEXEC);
+#else
int fd = syscall_impl<int>(SYS_open, "/proc/self/auxv", O_RDONLY | O_CLOEXEC);
+#endif
if (fd < 0) {
syscall_impl<long>(SYS_munmap, vector, AUXV_MMAP_SIZE);
return;
@@ -135,10 +140,9 @@ LIBC_INLINE void Vector::fallback_initialize_unsync() {
LIBC_INLINE cpp::optional<unsigned long> get(unsigned long type) {
Vector auxvec;
- for (const auto &entry : auxvec) {
+ for (const auto &entry : auxvec)
if (entry.type == type)
return entry.val;
- }
return cpp::nullopt;
}
} // namespace auxv
More information about the libc-commits
mailing list