diff --git a/Userland/DynamicLoader/CMakeLists.txt b/Userland/DynamicLoader/CMakeLists.txt index e66d584983b..39001febc46 100644 --- a/Userland/DynamicLoader/CMakeLists.txt +++ b/Userland/DynamicLoader/CMakeLists.txt @@ -5,12 +5,17 @@ set(SOURCES add_library(DynamicLoader_CompileOptions INTERFACE) target_compile_definitions(DynamicLoader_CompileOptions INTERFACE NO_TLS _DYNAMIC_LOADER) -target_compile_options(DynamicLoader_CompileOptions INTERFACE -fno-rtti -fpie -ffunction-sections -fdata-sections) +target_compile_options(DynamicLoader_CompileOptions INTERFACE $<$:-fno-rtti> -fpie -ffunction-sections -fdata-sections) target_link_options(DynamicLoader_CompileOptions INTERFACE -nolibc -nostdlib++ -nostartfiles -static-libgcc -fpie -Wl,--gc-sections) target_link_options(DynamicLoader_CompileOptions INTERFACE -fno-sanitize=undefined) # Sanitizer runtime is linked in manually add_executable(Loader.so ${SOURCES}) +# Mixing C and C++ results in linker errors with GCC > 16 and CMake < 4.0. +# The issue is fixed upstream in https://gitlab.kitware.com/cmake/cmake/-/merge_requests/12027. +# FIXME: Remove this workaround once we require a CMake version >= 4.1. +list(REMOVE_ITEM CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc_s_asneeded") + target_link_libraries(Loader.so PRIVATE DynamicLoader_CompileOptions DynamicLoader_LibELF DynamicLoader_LibCoreArgsParser) if (ENABLE_UNDEFINED_SANITIZER) target_link_libraries(Loader.so PRIVATE DynamicLoader_LibUBSanitizer) diff --git a/Userland/Libraries/LibC/CMakeLists.txt b/Userland/Libraries/LibC/CMakeLists.txt index bdbe7fc81c2..6b5c307a3da 100644 --- a/Userland/Libraries/LibC/CMakeLists.txt +++ b/Userland/Libraries/LibC/CMakeLists.txt @@ -3,7 +3,7 @@ set(SOURCES arch/${SERENITY_ARCH}/setjmp.S arpa/inet.cpp assert.cpp - ctype.cpp + ctype.c cxxabi.cpp dirent.cpp dlfcn.cpp diff --git a/Userland/Libraries/LibC/ctype.c b/Userland/Libraries/LibC/ctype.c new file mode 100644 index 00000000000..e1c7f12ada9 --- /dev/null +++ b/Userland/Libraries/LibC/ctype.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +char const _ctype_[1 + 256] = { + 0, + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + _C, _C, _C, _C, _C, _C, _C, _C, + (char)(_S | _B), _P, _P, _P, _P, _P, _P, _P, + _P, _P, _P, _P, _P, _P, _P, _P, + _N, _N, _N, _N, _N, _N, _N, _N, + _N, _N, _P, _P, _P, _P, _P, _P, + _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _U, _U, _U, _U, _U, + _U, _U, _U, _P, _P, _P, _P, _P, + _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _L, _L, _L, _L, _L, + _L, _L, _L, _P, _P, _P, _P, _C +}; + + +// "The following shall be declared as functions and may also be defined as macros." +// This means that these functions need to be declared with external linkage. +// For performance reasons, we want these functions to be inlinable so we provide +// the definition in the header file. This however causes compatibility issues +// between C and C++. +// In C++, the compiler generates a symbol for inline functions at will. In the end, +// multiple TUs might include one (in this case the linker takes care of only keeping +// one) or if the function is always inlined, no symbols are emitted at all, which +// conflicts with POSIX requirements. +// In C, the linker isn't required to de-duplicate symbols emitted from inline +// functions, so the compiler doesn't emit symbols for inline functions and it falls +// back on the user to provide one if needed. +// To solve this issue we use a dedicated C feature that anchors the function +// definition in this exact TU. + +// This link provides useful information on the different meanings of inline: +// https://stackoverflow.com/questions/216510/what-does-extern-inline-do + +__attribute__((gnu_inline)) inline int isalnum(int c); +__attribute__((gnu_inline)) inline int isalpha(int c); +__attribute__((gnu_inline)) inline int isascii(int c); +__attribute__((gnu_inline)) inline int iscntrl(int c); +__attribute__((gnu_inline)) inline int isdigit(int c); +__attribute__((gnu_inline)) inline int isxdigit(int c); +__attribute__((gnu_inline)) inline int isspace(int c); +__attribute__((gnu_inline)) inline int ispunct(int c); +__attribute__((gnu_inline)) inline int isprint(int c); +__attribute__((gnu_inline)) inline int isgraph(int c); +__attribute__((gnu_inline)) inline int islower(int c); +__attribute__((gnu_inline)) inline int isupper(int c); +__attribute__((gnu_inline)) inline int isblank(int c); +__attribute__((gnu_inline)) inline int toascii(int c); +__attribute__((gnu_inline)) inline int tolower(int c); +__attribute__((gnu_inline)) inline int toupper(int c); diff --git a/Userland/Libraries/LibC/ctype.cpp b/Userland/Libraries/LibC/ctype.cpp deleted file mode 100644 index c866ed6aaf9..00000000000 --- a/Userland/Libraries/LibC/ctype.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include - -extern "C" { - -char const _ctype_[1 + 256] = { - 0, - _C, _C, _C, _C, _C, _C, _C, _C, - _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C, - _C, _C, _C, _C, _C, _C, _C, _C, - _C, _C, _C, _C, _C, _C, _C, _C, - (char)(_S | _B), _P, _P, _P, _P, _P, _P, _P, - _P, _P, _P, _P, _P, _P, _P, _P, - _N, _N, _N, _N, _N, _N, _N, _N, - _N, _N, _P, _P, _P, _P, _P, _P, - _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U, - _U, _U, _U, _U, _U, _U, _U, _U, - _U, _U, _U, _U, _U, _U, _U, _U, - _U, _U, _U, _P, _P, _P, _P, _P, - _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L, - _L, _L, _L, _L, _L, _L, _L, _L, - _L, _L, _L, _L, _L, _L, _L, _L, - _L, _L, _L, _P, _P, _P, _P, _C -}; - -#undef isalnum -int isalnum(int c) -{ - return __inline_isalnum(c); -} - -#undef isalpha -int isalpha(int c) -{ - return __inline_isalpha(c); -} - -#undef iscntrl -int iscntrl(int c) -{ - return __inline_iscntrl(c); -} - -#undef isdigit -int isdigit(int c) -{ - return __inline_isdigit(c); -} - -#undef isxdigit -int isxdigit(int c) -{ - return __inline_isxdigit(c); -} - -#undef isspace -int isspace(int c) -{ - return __inline_isspace(c); -} - -#undef ispunct -int ispunct(int c) -{ - return __inline_ispunct(c); -} - -#undef isprint -int isprint(int c) -{ - return __inline_isprint(c); -} - -#undef isgraph -int isgraph(int c) -{ - return __inline_isgraph(c); -} - -#undef isupper -int isupper(int c) -{ - return __inline_isupper(c); -} - -#undef islower -int islower(int c) -{ - return __inline_islower(c); -} - -#undef isascii -int isascii(int c) -{ - return __inline_isascii(c); -} - -#undef isblank -int isblank(int c) -{ - return __inline_isblank(c); -} - -#undef toascii -int toascii(int c) -{ - return __inline_toascii(c); -} - -#undef tolower -int tolower(int c) -{ - return __inline_tolower(c); -} - -#undef toupper -int toupper(int c) -{ - return __inline_toupper(c); -} -} diff --git a/Userland/Libraries/LibC/ctype.h b/Userland/Libraries/LibC/ctype.h index 1947f3416b9..d04cf9df365 100644 --- a/Userland/Libraries/LibC/ctype.h +++ b/Userland/Libraries/LibC/ctype.h @@ -31,129 +31,88 @@ __BEGIN_DECLS */ extern char const _ctype_[1 + 256] __attribute__((visibility("default"))); -static inline int __inline_isalnum(int c) +extern inline __attribute__((gnu_inline)) int isalnum(int c) { return _ctype_[(unsigned char)(c) + 1] & (_U | _L | _N); } -static inline int __inline_isalpha(int c) +extern inline __attribute__((gnu_inline)) int isalpha(int c) { return _ctype_[(unsigned char)(c) + 1] & (_U | _L); } -static inline int __inline_isascii(int c) +extern inline __attribute__((gnu_inline)) int isascii(int c) { return (unsigned)c <= 127; } -static inline int __inline_iscntrl(int c) +extern inline __attribute__((gnu_inline)) int iscntrl(int c) { return _ctype_[(unsigned char)(c) + 1] & (_C); } -static inline int __inline_isdigit(int c) +extern inline __attribute__((gnu_inline)) int isdigit(int c) { return _ctype_[(unsigned char)(c) + 1] & (_N); } -static inline int __inline_isxdigit(int c) +extern inline __attribute__((gnu_inline)) int isxdigit(int c) { return _ctype_[(unsigned char)(c) + 1] & (_N | _X); } -static inline int __inline_isspace(int c) +extern inline __attribute__((gnu_inline)) int isspace(int c) { return _ctype_[(unsigned char)(c) + 1] & (_S); } -static inline int __inline_ispunct(int c) +extern inline __attribute__((gnu_inline)) int ispunct(int c) { return _ctype_[(unsigned char)(c) + 1] & (_P); } -static inline int __inline_isprint(int c) +extern inline __attribute__((gnu_inline)) int isprint(int c) { return _ctype_[(unsigned char)(c) + 1] & (_P | _U | _L | _N | _B); } -static inline int __inline_isgraph(int c) +extern inline __attribute__((gnu_inline)) int isgraph(int c) { return _ctype_[(unsigned char)(c) + 1] & (_P | _U | _L | _N); } -static inline int __inline_islower(int c) +extern inline __attribute__((gnu_inline)) int islower(int c) { return _ctype_[(unsigned char)(c) + 1] & (_L); } -static inline int __inline_isupper(int c) +extern inline __attribute__((gnu_inline)) int isupper(int c) { return _ctype_[(unsigned char)(c) + 1] & (_U); } -static inline int __inline_isblank(int c) +extern inline __attribute__((gnu_inline)) int isblank(int c) { return _ctype_[(unsigned char)(c) + 1] & (_B) || (c == '\t'); } -static inline int __inline_toascii(int c) +extern inline __attribute__((gnu_inline)) int toascii(int c) { return c & 127; } -static inline int __inline_tolower(int c) +extern inline __attribute__((gnu_inline)) int tolower(int c) { if (c >= 'A' && c <= 'Z') return c | 0x20; return c; } -static inline int __inline_toupper(int c) +extern inline __attribute__((gnu_inline)) int toupper(int c) { if (c >= 'a' && c <= 'z') return c & ~0x20; return c; } -#ifdef __cplusplus -extern "C" { -#endif - -int isalnum(int c); -int isalpha(int c); -int isascii(int c); -int iscntrl(int c); -int isdigit(int c); -int isxdigit(int c); -int isspace(int c); -int ispunct(int c); -int isprint(int c); -int isgraph(int c); -int islower(int c); -int isupper(int c); -int isblank(int c); -int toascii(int c); -int tolower(int c); -int toupper(int c); - -#ifdef __cplusplus -} -#endif -#define isalnum __inline_isalnum -#define isalpha __inline_isalpha -#define isascii __inline_isascii -#define iscntrl __inline_iscntrl -#define isdigit __inline_isdigit -#define isxdigit __inline_isxdigit -#define isspace __inline_isspace -#define ispunct __inline_ispunct -#define isprint __inline_isprint -#define isgraph __inline_isgraph -#define islower __inline_islower -#define isupper __inline_isupper -#define isblank __inline_isblank -#define toascii __inline_toascii -#define tolower __inline_tolower -#define toupper __inline_toupper - __END_DECLS diff --git a/Userland/Libraries/LibC/wctype.cpp b/Userland/Libraries/LibC/wctype.cpp index f026a34f1c3..b59b48496b7 100644 --- a/Userland/Libraries/LibC/wctype.cpp +++ b/Userland/Libraries/LibC/wctype.cpp @@ -33,62 +33,62 @@ extern "C" { int iswalnum(wint_t wc) { - return __inline_isalnum(wc); + return isalnum(wc); } int iswalpha(wint_t wc) { - return __inline_isalpha(wc); + return isalpha(wc); } int iswcntrl(wint_t wc) { - return __inline_iscntrl(wc); + return iscntrl(wc); } int iswdigit(wint_t wc) { - return __inline_isdigit(wc); + return isdigit(wc); } int iswxdigit(wint_t wc) { - return __inline_isxdigit(wc); + return isxdigit(wc); } int iswspace(wint_t wc) { - return __inline_isspace(wc); + return isspace(wc); } int iswpunct(wint_t wc) { - return __inline_ispunct(wc); + return ispunct(wc); } int iswprint(wint_t wc) { - return __inline_isprint(wc); + return isprint(wc); } int iswgraph(wint_t wc) { - return __inline_isgraph(wc); + return isgraph(wc); } int iswlower(wint_t wc) { - return __inline_islower(wc); + return islower(wc); } int iswupper(wint_t wc) { - return __inline_isupper(wc); + return isupper(wc); } int iswblank(wint_t wc) { - return __inline_isblank(wc); + return isblank(wc); } int iswctype(wint_t wc, wctype_t charclass) @@ -178,12 +178,12 @@ wctype_t wctype(char const* property) wint_t towlower(wint_t wc) { - return __inline_tolower(wc); + return tolower(wc); } wint_t towupper(wint_t wc) { - return __inline_toupper(wc); + return toupper(wc); } wint_t towctrans(wint_t wc, wctrans_t desc)