From b151c7e36a26a4168d0384c88295099e4b6470d0 Mon Sep 17 00:00:00 2001 From: Izaak Schroeder Date: Sat, 6 Jul 2024 16:01:59 -0700 Subject: [PATCH] [libc] Add `dlfcn.h` placeholder (#97501) Adds `dlopen` and friends. This is needed as part of the effort to compile `libunwind` + `libc` without baremetal mode. This is part of https://github.com/llvm/llvm-project/issues/97191. This should still be spec compliant, since `dlopen` always returns `NULL` and `dlerror` always returns an error message. > If dlopen() fails for any reason, it returns NULL. > The function dlclose() returns 0 on success, and nonzero on error. > Since the value of the symbol could actually be NULL (so that a NULL return from dlsym() need not indicate an error), the correct way to test for an error is to call dlerror() to clear any old error conditions, then call dlsym(), and then call dlerror() again, saving its return value into a variable, and check whether this saved value is not NULL. See: - https://linux.die.net/man/3/dlopen --- libc/config/linux/aarch64/entrypoints.txt | 6 ++++ libc/config/linux/x86_64/entrypoints.txt | 6 ++++ libc/docs/dev/undefined_behavior.rst | 4 +++ libc/spec/posix.td | 35 ++++++++++++++++++++ libc/src/CMakeLists.txt | 1 + libc/src/dlfcn/CMakeLists.txt | 40 +++++++++++++++++++++++ libc/src/dlfcn/dlclose.cpp | 18 ++++++++++ libc/src/dlfcn/dlclose.h | 18 ++++++++++ libc/src/dlfcn/dlerror.cpp | 20 ++++++++++++ libc/src/dlfcn/dlerror.h | 18 ++++++++++ libc/src/dlfcn/dlopen.cpp | 18 ++++++++++ libc/src/dlfcn/dlopen.h | 18 ++++++++++ libc/src/dlfcn/dlsym.cpp | 18 ++++++++++ libc/src/dlfcn/dlsym.h | 18 ++++++++++ 14 files changed, 238 insertions(+) create mode 100644 libc/src/dlfcn/CMakeLists.txt create mode 100644 libc/src/dlfcn/dlclose.cpp create mode 100644 libc/src/dlfcn/dlclose.h create mode 100644 libc/src/dlfcn/dlerror.cpp create mode 100644 libc/src/dlfcn/dlerror.h create mode 100644 libc/src/dlfcn/dlopen.cpp create mode 100644 libc/src/dlfcn/dlopen.h create mode 100644 libc/src/dlfcn/dlsym.cpp create mode 100644 libc/src/dlfcn/dlsym.h diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index a6aeb0685bca48..6c67e4bbadee7e 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -17,6 +17,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.ctype.tolower libc.src.ctype.toupper + # dlfcn.h entrypoints + libc.src.dlfcn.dlclose + libc.src.dlfcn.dlerror + libc.src.dlfcn.dlopen + libc.src.dlfcn.dlsym + # errno.h entrypoints libc.src.errno.errno diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 271763d8fe869a..2ca8f00d2de50a 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -17,6 +17,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.ctype.tolower libc.src.ctype.toupper + # dlfcn.h entrypoints + libc.src.dlfcn.dlclose + libc.src.dlfcn.dlerror + libc.src.dlfcn.dlopen + libc.src.dlfcn.dlsym + # errno.h entrypoints libc.src.errno.errno diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst index c97a539ca8da45..3faae3134ce2a4 100644 --- a/libc/docs/dev/undefined_behavior.rst +++ b/libc/docs/dev/undefined_behavior.rst @@ -89,3 +89,7 @@ The C23 standard states that if the value of the ``rnd`` argument of the the value of a math rounding direction macro, the direction of rounding is unspecified. LLVM's libc chooses to use the ``FP_INT_TONEAREST`` rounding direction in this case. + +Non-const Constant Return Values +-------------------------------- +Some libc functions, like ``dlerror()``, return ``char *`` instead of ``const char *`` and then tell the caller they promise not to to modify this value. Any modification of this value is undefined behavior. diff --git a/libc/spec/posix.td b/libc/spec/posix.td index d14047548e104f..1878b1ee2ae412 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -222,6 +222,40 @@ def POSIX : StandardSpec<"POSIX"> { [] // Functions >; + HeaderSpec DlFcn = HeaderSpec< + "dlfcn.h", + [ + Macro<"RTLD_LAZY">, + Macro<"RTLD_NOW">, + Macro<"RTLD_GLOBAL">, + Macro<"RTLD_LOCAL">, + ], + [], // Types + [], // Enumerations + [ + FunctionSpec< + "dlclose", + RetValSpec, + [ArgSpec] + >, + FunctionSpec< + "dlerror", + RetValSpec, + [] + >, + FunctionSpec< + "dlopen", + RetValSpec, + [ArgSpec, ArgSpec] + >, + FunctionSpec< + "dlsym", + RetValSpec, + [ArgSpec, ArgSpec] + >, + ] + >; + HeaderSpec FCntl = HeaderSpec< "fcntl.h", [], // Macros @@ -1690,6 +1724,7 @@ def POSIX : StandardSpec<"POSIX"> { ArpaInet, CType, Dirent, + DlFcn, Errno, FCntl, PThread, diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt index 09b16be1e2d42e..9597e2380172b5 100644 --- a/libc/src/CMakeLists.txt +++ b/libc/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(__support) add_subdirectory(ctype) +add_subdirectory(dlfcn) add_subdirectory(errno) add_subdirectory(fenv) add_subdirectory(inttypes) diff --git a/libc/src/dlfcn/CMakeLists.txt b/libc/src/dlfcn/CMakeLists.txt new file mode 100644 index 00000000000000..e3a51ba65764d4 --- /dev/null +++ b/libc/src/dlfcn/CMakeLists.txt @@ -0,0 +1,40 @@ +add_entrypoint_object( + dlclose + SRCS + dlclose.cpp + HDRS + dlclose.h +) + +add_entrypoint_object( + dlerror + SRCS + dlerror.cpp + HDRS + dlerror.h + DEPENDS + libc.include.dlfcn + libc.src.errno.errno +) + +add_entrypoint_object( + dlopen + SRCS + dlopen.cpp + HDRS + dlopen.h + DEPENDS + libc.include.dlfcn + libc.src.errno.errno +) + +add_entrypoint_object( + dlsym + SRCS + dlsym.cpp + HDRS + dlsym.h + DEPENDS + libc.include.dlfcn + libc.src.errno.errno +) diff --git a/libc/src/dlfcn/dlclose.cpp b/libc/src/dlfcn/dlclose.cpp new file mode 100644 index 00000000000000..1f1bfabd798010 --- /dev/null +++ b/libc/src/dlfcn/dlclose.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of dlclose -----------------------------------------===// +// +// 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 "dlclose.h" + +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +// TODO(@izaakschroeder): https://github.com/llvm/llvm-project/issues/97917 +LLVM_LIBC_FUNCTION(int, dlclose, (void *)) { return -1; } + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/dlfcn/dlclose.h b/libc/src/dlfcn/dlclose.h new file mode 100644 index 00000000000000..27c0207d726e49 --- /dev/null +++ b/libc/src/dlfcn/dlclose.h @@ -0,0 +1,18 @@ +//===-- Implementation header of dlclose ------------------------*- 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_DLFCN_DLCLOSE_H +#define LLVM_LIBC_SRC_DLFCN_DLCLOSE_H + +namespace LIBC_NAMESPACE { + +int dlclose(void *); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_DLFCN_DLCLOSE_H diff --git a/libc/src/dlfcn/dlerror.cpp b/libc/src/dlfcn/dlerror.cpp new file mode 100644 index 00000000000000..711b5a39420b66 --- /dev/null +++ b/libc/src/dlfcn/dlerror.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of delerror ----------------------------------------===// +// +// 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 "dlerror.h" + +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +// TODO(@izaakschroeder): https://github.com/llvm/llvm-project/issues/97918 +LLVM_LIBC_FUNCTION(char *, dlerror, ()) { + return const_cast("unsupported"); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/dlfcn/dlerror.h b/libc/src/dlfcn/dlerror.h new file mode 100644 index 00000000000000..966496016d3ebd --- /dev/null +++ b/libc/src/dlfcn/dlerror.h @@ -0,0 +1,18 @@ +//===-- Implementation header of dlerror ------------------------*- 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_DLFCN_DLERROR_H +#define LLVM_LIBC_SRC_DLFCN_DLERROR_H + +namespace LIBC_NAMESPACE { + +char *dlerror(); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_DLFCN_DLERROR_H diff --git a/libc/src/dlfcn/dlopen.cpp b/libc/src/dlfcn/dlopen.cpp new file mode 100644 index 00000000000000..9fa4d061c9c82a --- /dev/null +++ b/libc/src/dlfcn/dlopen.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of dlopen -----------------------------------------===// +// +// 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 "dlopen.h" + +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +// TODO(@izaakschroeder): https://github.com/llvm/llvm-project/issues/97919 +LLVM_LIBC_FUNCTION(void *, dlopen, (const char *, int)) { return nullptr; } + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/dlfcn/dlopen.h b/libc/src/dlfcn/dlopen.h new file mode 100644 index 00000000000000..4565953efd4943 --- /dev/null +++ b/libc/src/dlfcn/dlopen.h @@ -0,0 +1,18 @@ +//===-- Implementation header of dlopen -------------------------*- 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_DLFCN_DLOPEN_H +#define LLVM_LIBC_SRC_DLFCN_DLOPEN_H + +namespace LIBC_NAMESPACE { + +void *dlopen(const char *, int); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_DLFCN_DLOPEN_H diff --git a/libc/src/dlfcn/dlsym.cpp b/libc/src/dlfcn/dlsym.cpp new file mode 100644 index 00000000000000..4c8dac698f61d7 --- /dev/null +++ b/libc/src/dlfcn/dlsym.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of dlsym ------------------------------------------===// +// +// 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 "dlsym.h" + +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +// TODO(@izaakschroeder): https://github.com/llvm/llvm-project/issues/97920 +LLVM_LIBC_FUNCTION(void *, dlsym, (void *, const char *)) { return nullptr; } + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/dlfcn/dlsym.h b/libc/src/dlfcn/dlsym.h new file mode 100644 index 00000000000000..8157ac3e3fd4ca --- /dev/null +++ b/libc/src/dlfcn/dlsym.h @@ -0,0 +1,18 @@ +//===-- Implementation header of dlsym --------------------------*- 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_DLFCN_DLSYM_H +#define LLVM_LIBC_SRC_DLFCN_DLSYM_H + +namespace LIBC_NAMESPACE { + +void *dlsym(void *, const char *); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_DLFCN_DLSYM_H