[libc-commits] [libc] [libc] Set default visibility to 'hidden' and make entrypoints default (PR #97123)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Wed Jul 3 12:32:06 PDT 2024


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/97123

>From cf1c7bc088b720b3cf5efa7516f715d762616078 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Fri, 28 Jun 2024 18:19:35 -0500
Subject: [PATCH] [libc] Set default visibility to 'hidden' and make
 entrypoints default

Summary:
See for visibility: https://llvm.org/docs/LangRef.html#visibility-styles

Currently we build everything with default visibility, meaning that all
internal symbols are preemptable and visible to any `.so` they're linked
into. What we want is hidden visibility for all the internal parts, and
default visibility for the API functions / exposed globals.

This patch is based on https://github.com/llvm/llvm-project/pull/97109.
---
 .../modules/LLVMLibCCompileOptionRules.cmake  |  5 ++++-
 libc/config/config.json                       |  4 ++++
 libc/config/gpu/config.json                   |  5 +++++
 libc/docs/configure.rst                       |  1 +
 libc/docs/dev/entrypoints.rst                 |  3 ++-
 libc/src/__support/File/linux/stderr.cpp      |  9 ++++----
 libc/src/__support/File/linux/stdin.cpp       |  9 ++++----
 libc/src/__support/File/linux/stdout.cpp      |  9 ++++----
 libc/src/__support/common.h                   | 21 +++++++++++++++----
 libc/src/errno/libc_errno.cpp                 |  9 +++-----
 libc/src/stdio/generic/stderr.cpp             |  3 ++-
 libc/src/stdio/generic/stdin.cpp              |  3 ++-
 libc/src/stdio/generic/stdout.cpp             |  3 ++-
 libc/src/stdio/gpu/stderr.cpp                 |  5 ++++-
 libc/src/stdio/gpu/stdin.cpp                  |  5 ++++-
 libc/src/stdio/gpu/stdout.cpp                 |  5 ++++-
 libc/src/stdlib/atexit.cpp                    |  9 +++-----
 libc/src/stdlib/atexit.h                      |  6 ++++++
 libc/src/stdlib/exit.cpp                      |  3 +--
 libc/src/unistd/environ.cpp                   |  7 ++++---
 libc/src/unistd/getopt.cpp                    | 10 ++++-----
 libc/test/IntegrationTest/test.cpp            |  8 +++++++
 libc/test/UnitTest/HermeticTestUtils.cpp      | 11 +++++++++-
 23 files changed, 105 insertions(+), 48 deletions(-)

diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
index 28379213029a3..0934e3102dcf5 100644
--- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
+++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake
@@ -41,6 +41,7 @@ function(_get_common_compile_options output_var flags)
 
   if(LLVM_COMPILER_IS_GCC_COMPATIBLE)
     list(APPEND compile_options "-fpie")
+    list(APPEND compile_options "-fvisibility=hidden")
 
     if(LLVM_LIBC_FULL_BUILD)
       list(APPEND compile_options "-DLIBC_FULL_BUILD")
@@ -78,6 +79,9 @@ function(_get_common_compile_options output_var flags)
     if (LIBC_CONF_ENABLE_STACK_PROTECTOR)
       list(APPEND compile_options "-fstack-protector-strong")
     endif()
+    if(LIBC_CONF_VISIBILITY)
+      list(APPEND compile_options "-DLIBC_VISIBILITY=${LIBC_CONF_VISIBILITY}")
+    endif()
     list(APPEND compile_options "-Wall")
     list(APPEND compile_options "-Wextra")
     # -DLIBC_WNO_ERROR=ON if you can't build cleanly with -Werror.
@@ -102,7 +106,6 @@ function(_get_common_compile_options output_var flags)
   endif()
   if (LIBC_TARGET_OS_IS_GPU)
     list(APPEND compile_options "-nogpulib")
-    list(APPEND compile_options "-fvisibility=hidden")
     list(APPEND compile_options "-fconvergent-functions")
     list(APPEND compile_options "-flto")
     list(APPEND compile_options "-Wno-multi-gpu")
diff --git a/libc/config/config.json b/libc/config/config.json
index 11433c15d762e..3e20c0528561c 100644
--- a/libc/config/config.json
+++ b/libc/config/config.json
@@ -32,6 +32,10 @@
     }
   },
   "codegen": {
+    "LIBC_CONF_VISIBILITY": {
+      "value": "default",
+      "doc": "Visibility to use on all exported C library symbols."
+    },
     "LIBC_CONF_KEEP_FRAME_POINTER": {
       "value": true,
       "doc": "Keep frame pointer in functions for better debugging experience."
diff --git a/libc/config/gpu/config.json b/libc/config/gpu/config.json
index 53f232e31cc8a..f5c7bf70d77b8 100644
--- a/libc/config/gpu/config.json
+++ b/libc/config/gpu/config.json
@@ -12,5 +12,10 @@
     "LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE": {
       "value": false
     }
+  },
+  "codegen": {
+    "LIBC_CONF_VISIBILITY": {
+      "value": "hidden"
+    }
   }
 }
diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst
index 016e2e5aa5876..95b8d129de9cf 100644
--- a/libc/docs/configure.rst
+++ b/libc/docs/configure.rst
@@ -28,6 +28,7 @@ to learn about the defaults for your platform and target.
 * **"codegen" options**
     - ``LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR``: Enable -fstack-protector-strong to defend against stack smashing attack.
     - ``LIBC_CONF_KEEP_FRAME_POINTER``: Keep frame pointer in functions for better debugging experience.
+    - ``LIBC_CONF_VISIBILITY``: Visibility to use on all exported C library symbols.
 * **"malloc" options**
     - ``LIBC_CONF_FREELIST_MALLOC_BUFFER_SIZE``: Default size for the constinit freelist buffer used for the freelist malloc implementation (default 1o 1GB).
 * **"printf" options**
diff --git a/libc/docs/dev/entrypoints.rst b/libc/docs/dev/entrypoints.rst
index 3c24a922a2947..280137b286d2d 100644
--- a/libc/docs/dev/entrypoints.rst
+++ b/libc/docs/dev/entrypoints.rst
@@ -5,4 +5,5 @@ Entrypoints in LLVM libc
 
 A public function or a global variable provided by LLVM-libc is called an
 entrypoint. The notion of entrypoints is ingrained in LLVM-libc's
-source layout, build system and source code.
+source layout, build system and source code. Entrypoints will be given the
+visibility defined in the ``LIBC_CONF_VISIBILITY`` configuration.
diff --git a/libc/src/__support/File/linux/stderr.cpp b/libc/src/__support/File/linux/stderr.cpp
index 65d7865720ffe..b3b0aaa5344a5 100644
--- a/libc/src/__support/File/linux/stderr.cpp
+++ b/libc/src/__support/File/linux/stderr.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "file.h"
+#include "src/__support/File/linux/file.h"
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -18,6 +20,5 @@ File *stderr = &StdErr;
 
 } // namespace LIBC_NAMESPACE
 
-extern "C" {
-FILE *stderr = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdErr);
-}
+LLVM_LIBC_GLOBAL(FILE *,
+                 stderr) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdErr);
diff --git a/libc/src/__support/File/linux/stdin.cpp b/libc/src/__support/File/linux/stdin.cpp
index c9a363bb7c65a..774c1a495d2c6 100644
--- a/libc/src/__support/File/linux/stdin.cpp
+++ b/libc/src/__support/File/linux/stdin.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "file.h"
+#include "src/__support/File/linux/file.h"
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -19,6 +21,5 @@ File *stdin = &StdIn;
 
 } // namespace LIBC_NAMESPACE
 
-extern "C" {
-FILE *stdin = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdIn);
-} // extern "C"
+LLVM_LIBC_GLOBAL(FILE *,
+                 stdin) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdIn);
diff --git a/libc/src/__support/File/linux/stdout.cpp b/libc/src/__support/File/linux/stdout.cpp
index 314692ecbfe1e..33c93abbd3feb 100644
--- a/libc/src/__support/File/linux/stdout.cpp
+++ b/libc/src/__support/File/linux/stdout.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "file.h"
+#include "src/__support/File/linux/file.h"
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -19,6 +21,5 @@ File *stdout = &StdOut;
 
 } // namespace LIBC_NAMESPACE
 
-extern "C" {
-FILE *stdout = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdOut);
-} // extern "C"
+LLVM_LIBC_GLOBAL(FILE *,
+                 stdout) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::StdOut);
diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h
index 53951dc131c28..3aadf810da073 100644
--- a/libc/src/__support/common.h
+++ b/libc/src/__support/common.h
@@ -16,14 +16,26 @@
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/properties/architectures.h"
 
+#define __LIBC_MACRO_TO_STRING(str) #str
+#define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str)
+
 #ifndef LLVM_LIBC_FUNCTION_ATTR
 #define LLVM_LIBC_FUNCTION_ATTR
 #endif
 
+#ifndef LIBC_VISIBILITY
+#define LIBC_VISIBILITY default
+#endif
+
+#ifndef LLVM_LIBC_VISIBILITY
+#define LLVM_LIBC_VISIBILITY                                                   \
+  [[gnu::visibility(LIBC_MACRO_TO_STRING(LIBC_VISIBILITY))]]
+#endif
+
 // MacOS needs to be excluded because it does not support aliasing.
 #if defined(LIBC_COPT_PUBLIC_PACKAGING) && (!defined(__APPLE__))
 #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)                           \
-  LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name)                       \
+  LLVM_LIBC_FUNCTION_ATTR LLVM_LIBC_VISIBILITY decltype(LIBC_NAMESPACE::name)  \
       __##name##_impl__ __asm__(#name);                                        \
   decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]];                   \
   type __##name##_impl__ arglist
@@ -35,6 +47,10 @@
 #define LLVM_LIBC_FUNCTION(type, name, arglist)                                \
   LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
 
+// Defines a global variable meant to be exported by the C library.
+#define LLVM_LIBC_GLOBAL(type, name)                                           \
+  LLVM_LIBC_VISIBILITY type name __asm__(#name)
+
 namespace LIBC_NAMESPACE {
 namespace internal {
 LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) {
@@ -46,9 +62,6 @@ LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) {
 } // namespace internal
 } // namespace LIBC_NAMESPACE
 
-#define __LIBC_MACRO_TO_STRING(str) #str
-#define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str)
-
 // LLVM_LIBC_IS_DEFINED checks whether a particular macro is defined.
 // Usage: constexpr bool kUseAvx = LLVM_LIBC_IS_DEFINED(__AVX__);
 //
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index bd1438c226143..752567c9b2dc6 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -8,13 +8,12 @@
 
 #include "libc_errno.h"
 #include "src/__support/CPP/atomic.h"
+#include "src/__support/common.h"
 
 #ifdef LIBC_TARGET_ARCH_IS_GPU
 // LIBC_THREAD_LOCAL on GPU currently does nothing. So essentially this is just
 // a global errno for gpu to use for now.
-extern "C" {
-LIBC_THREAD_LOCAL LIBC_NAMESPACE::cpp::Atomic<int> __llvmlibc_errno;
-}
+LLVM_LIBC_GLOBAL(LIBC_NAMESPACE::cpp::Atomic<int>, __llvmlibc_errno);
 
 void LIBC_NAMESPACE::Errno::operator=(int a) {
   __llvmlibc_errno.store(a, cpp::MemoryOrder::RELAXED);
@@ -33,9 +32,7 @@ LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_internal_errno; }
 #elif defined(LIBC_FULL_BUILD)
 // This mode is for public libc archive, hermetic, and integration tests.
 // In full build mode, we provide the errno storage ourselves.
-extern "C" {
-LIBC_THREAD_LOCAL int __llvmlibc_errno;
-}
+LLVM_LIBC_GLOBAL(LIBC_THREAD_LOCAL int, __llvmlibc_errno);
 
 void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_errno = a; }
 LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_errno; }
diff --git a/libc/src/stdio/generic/stderr.cpp b/libc/src/stdio/generic/stderr.cpp
index 31b618f6928a0..7b5d65420b710 100644
--- a/libc/src/stdio/generic/stderr.cpp
+++ b/libc/src/stdio/generic/stderr.cpp
@@ -7,7 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/File/file.h"
+#include "src/__support/common.h"
 
 #include <stdio.h>
 
-extern "C" FILE *stderr;
+LLVM_LIBC_GLOBAL(FILE *, stderr);
diff --git a/libc/src/stdio/generic/stdin.cpp b/libc/src/stdio/generic/stdin.cpp
index f99ea898dfcd1..b0287cf6928ca 100644
--- a/libc/src/stdio/generic/stdin.cpp
+++ b/libc/src/stdio/generic/stdin.cpp
@@ -7,7 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/File/file.h"
+#include "src/__support/common.h"
 
 #include <stdio.h>
 
-extern "C" FILE *stdin;
+LLVM_LIBC_GLOBAL(FILE *, stdin);
diff --git a/libc/src/stdio/generic/stdout.cpp b/libc/src/stdio/generic/stdout.cpp
index 2d5aaf5667260..049918bb94d78 100644
--- a/libc/src/stdio/generic/stdout.cpp
+++ b/libc/src/stdio/generic/stdout.cpp
@@ -7,7 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/File/file.h"
+#include "src/__support/common.h"
 
 #include <stdio.h>
 
-extern "C" FILE *stdout;
+LLVM_LIBC_GLOBAL(FILE *, stdout);
diff --git a/libc/src/stdio/gpu/stderr.cpp b/libc/src/stdio/gpu/stderr.cpp
index 70846827064a3..47697d7b7916f 100644
--- a/libc/src/stdio/gpu/stderr.cpp
+++ b/libc/src/stdio/gpu/stderr.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -13,4 +15,5 @@ static struct {
 } stub;
 FILE *stderr = reinterpret_cast<FILE *>(&stub);
 } // namespace LIBC_NAMESPACE
-extern "C" FILE *stderr = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
+LLVM_LIBC_GLOBAL(FILE *,
+                 stderr) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
diff --git a/libc/src/stdio/gpu/stdin.cpp b/libc/src/stdio/gpu/stdin.cpp
index 1a58461c3dec9..f76b33f12c0d6 100644
--- a/libc/src/stdio/gpu/stdin.cpp
+++ b/libc/src/stdio/gpu/stdin.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -13,4 +15,5 @@ static struct {
 } stub;
 FILE *stdin = reinterpret_cast<FILE *>(&stub);
 } // namespace LIBC_NAMESPACE
-extern "C" FILE *stdin = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
+LLVM_LIBC_GLOBAL(FILE *,
+                 stdin) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
diff --git a/libc/src/stdio/gpu/stdout.cpp b/libc/src/stdio/gpu/stdout.cpp
index abeeff2ce9f53..511f423d28448 100644
--- a/libc/src/stdio/gpu/stdout.cpp
+++ b/libc/src/stdio/gpu/stdout.cpp
@@ -6,6 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/common.h"
+
 #include <stdio.h>
 
 namespace LIBC_NAMESPACE {
@@ -13,4 +15,5 @@ static struct {
 } stub;
 FILE *stdout = reinterpret_cast<FILE *>(&stub);
 } // namespace LIBC_NAMESPACE
-extern "C" FILE *stdout = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
+LLVM_LIBC_GLOBAL(FILE *,
+                 stdout) = reinterpret_cast<FILE *>(&LIBC_NAMESPACE::stub);
diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp
index ca3cbfe87a88c..a9103d4c0b842 100644
--- a/libc/src/stdlib/atexit.cpp
+++ b/libc/src/stdlib/atexit.cpp
@@ -13,19 +13,16 @@
 
 namespace LIBC_NAMESPACE {
 
-extern "C" {
-
-int __cxa_atexit(AtExitCallback *callback, void *payload, void *) {
+LLVM_LIBC_FUNCTION(int, __cxa_atexit,
+                   (AtExitCallback * callback, void *payload, void *)) {
   return add_atexit_unit(atexit_callbacks, {callback, payload});
 }
 
-void __cxa_finalize(void *dso) {
+LLVM_LIBC_FUNCTION(void, __cxa_finalize, (void *dso)) {
   if (!dso)
     call_exit_callbacks(atexit_callbacks);
 }
 
-} // extern "C"
-
 LLVM_LIBC_FUNCTION(int, atexit, (__atexithandler_t callback)) {
   return add_atexit_unit(
       atexit_callbacks,
diff --git a/libc/src/stdlib/atexit.h b/libc/src/stdlib/atexit.h
index 7faaf654247c2..6568100cee6f5 100644
--- a/libc/src/stdlib/atexit.h
+++ b/libc/src/stdlib/atexit.h
@@ -10,8 +10,14 @@
 #define LLVM_LIBC_SRC_STDLIB_ATEXIT_H
 
 #include "hdr/types/atexithandler_t.h"
+#include "src/stdlib/exit_handler.h"
+
 namespace LIBC_NAMESPACE {
 
+int __cxa_atexit(AtExitCallback *callback, void *payload, void *);
+
+void __cxa_finalize(void *dso);
+
 int atexit(__atexithandler_t);
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index 1f7ccbb556607..e9d88b4a20bee 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -7,11 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/stdlib/exit.h"
+#include "src/stdlib/atexit.h"
 #include "src/__support/OSUtil/exit.h"
 #include "src/__support/common.h"
 
-extern "C" void __cxa_finalize(void *);
-
 namespace LIBC_NAMESPACE {
 
 [[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) {
diff --git a/libc/src/unistd/environ.cpp b/libc/src/unistd/environ.cpp
index 2266c7203273d..19a243469b997 100644
--- a/libc/src/unistd/environ.cpp
+++ b/libc/src/unistd/environ.cpp
@@ -6,11 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/unistd/environ.h"
+#include "src/__support/common.h"
+
 namespace LIBC_NAMESPACE {
 
 // This is initialized to the correct value by the statup code.
-extern "C" {
-char **environ = nullptr;
-}
+LLVM_LIBC_GLOBAL(char **, environ) = nullptr;
 
 } // namespace LIBC_NAMESPACE
diff --git a/libc/src/unistd/getopt.cpp b/libc/src/unistd/getopt.cpp
index ccdfdc6c64666..14ee0ee381944 100644
--- a/libc/src/unistd/getopt.cpp
+++ b/libc/src/unistd/getopt.cpp
@@ -175,12 +175,10 @@ int getopt_r(int argc, char *const argv[], const char *optstring,
 
 namespace impl {
 
-extern "C" {
-char *optarg = nullptr;
-int optind = 1;
-int optopt = 0;
-int opterr = 0;
-}
+LLVM_LIBC_GLOBAL(char, *optarg) = nullptr;
+LLVM_LIBC_GLOBAL(int, optind) = 1;
+LLVM_LIBC_GLOBAL(int, optopt) = 0;
+LLVM_LIBC_GLOBAL(int, opterr) = 0;
 
 static unsigned optpos;
 
diff --git a/libc/test/IntegrationTest/test.cpp b/libc/test/IntegrationTest/test.cpp
index 2751f3180a8e3..b3715299ac977 100644
--- a/libc/test/IntegrationTest/test.cpp
+++ b/libc/test/IntegrationTest/test.cpp
@@ -28,6 +28,8 @@ void *memcpy(void *__restrict, const void *__restrict, size_t);
 void *memmove(void *dst, const void *src, size_t count);
 void *memset(void *ptr, int value, size_t count);
 int atexit(void (*func)(void));
+int __cxa_atexit(void (*func)(void *), void *payload, void *dso);
+void __cxa_finalize(void *dso);
 
 } // namespace LIBC_NAMESPACE
 
@@ -53,6 +55,12 @@ void *memset(void *ptr, int value, size_t count) {
 // This is needed if the test was compiled with '-fno-use-cxa-atexit'.
 int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
 
+int __cxa_atexit(void (*callback)(void *), void *payload, void *dso) {
+  return LIBC_NAMESPACE::__cxa_atexit(callback, payload, dso);
+}
+
+void __cxa_finalize(void *dso) { LIBC_NAMESPACE::__cxa_finalize(dso); }
+
 } // extern "C"
 
 // Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
diff --git a/libc/test/UnitTest/HermeticTestUtils.cpp b/libc/test/UnitTest/HermeticTestUtils.cpp
index ca854ad94393e..2f45ba3ac4584 100644
--- a/libc/test/UnitTest/HermeticTestUtils.cpp
+++ b/libc/test/UnitTest/HermeticTestUtils.cpp
@@ -23,6 +23,8 @@ void *memcpy(void *__restrict, const void *__restrict, size_t);
 void *memmove(void *dst, const void *src, size_t count);
 void *memset(void *ptr, int value, size_t count);
 int atexit(void (*func)(void));
+int __cxa_atexit(void (*func)(void *), void *payload, void *dso);
+void __cxa_finalize(void *dso);
 
 // TODO: It seems that some old test frameworks does not use
 // add_libc_hermetic_test properly. Such that they won't get correct linkage
@@ -73,6 +75,12 @@ void *memset(void *ptr, int value, size_t count) {
 // This is needed if the test was compiled with '-fno-use-cxa-atexit'.
 int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
 
+int __cxa_atexit(void (*callback)(void *), void *payload, void *dso) {
+  return LIBC_NAMESPACE::__cxa_atexit(callback, payload, dso);
+}
+
+void __cxa_finalize(void *dso) { LIBC_NAMESPACE::__cxa_finalize(dso); }
+
 constexpr uint64_t ALIGNMENT = alignof(uintptr_t);
 
 void *malloc(size_t s) {
@@ -115,7 +123,8 @@ void *__dso_handle = nullptr;
 
 #ifdef LIBC_TARGET_ARCH_IS_AARCH64
 // Due to historical reasons, libgcc on aarch64 may expect __getauxval to be
-// defined. See also https://gcc.gnu.org/pipermail/gcc-cvs/2020-June/300635.html
+// defined. See also
+// https://gcc.gnu.org/pipermail/gcc-cvs/2020-June/300635.html
 unsigned long __getauxval(unsigned long id) {
   return LIBC_NAMESPACE::getauxval(id);
 }



More information about the libc-commits mailing list