Skip to content
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

Release overlay GCC build fails with "aliased to external symbol" #60481

Open
liam-clink opened this issue Feb 2, 2023 · 11 comments
Open

Release overlay GCC build fails with "aliased to external symbol" #60481

liam-clink opened this issue Feb 2, 2023 · 11 comments

Comments

@liam-clink
Copy link

liam-clink commented Feb 2, 2023

CMake invocation: (C/C++ compilers set to GCC/G++)

cmake -S ../llvm -B . -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/llvm-15_temp -DLLVM_TARGETS_TO_BUILD="X86" -DLLVM_ENABLE_PROJECTS="all"
[1/7688] Building CXX object projects/libc/src/stdlib/CMakeFiles/libc.src.stdlib.bsearch.dir/bsearch.cpp.o
FAILED: projects/libc/src/stdlib/CMakeFiles/libc.src.stdlib.bsearch.dir/bsearch.cpp.o 
/home/liam/gcc-12.2.0/bin/g++ -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/liam/Documents/GitHub/llvm-project/build/projects/libc/src/stdlib -I/home/liam/Documents/GitHub/llvm-project/libc/src/stdlib -I/home/liam/Documents/GitHub/llvm-project/build/include -I/home/liam/Documents/GitHub/llvm-project/llvm/include -I/home/liam/Documents/GitHub/llvm-project/build/projects/libc/include -I/home/liam/Documents/GitHub/llvm-project/libc -I/home/liam/Documents/GitHub/llvm-project/build/projects/libc -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wmisleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -fpie -ffreestanding -fno-builtin -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -DLLVM_LIBC_PUBLIC_PACKAGING -std=c++17 -MD -MT projects/libc/src/stdlib/CMakeFiles/libc.src.stdlib.bsearch.dir/bsearch.cpp.o -MF projects/libc/src/stdlib/CMakeFiles/libc.src.stdlib.bsearch.dir/bsearch.cpp.o.d -o projects/libc/src/stdlib/CMakeFiles/libc.src.stdlib.bsearch.dir/bsearch.cpp.o -c /home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.cpp
In file included from /home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.cpp:10:
/home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.cpp:16:28: error: 'void* __llvm_libc::bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*))' aliased to external symbol 'bsearch'
   16 | LLVM_LIBC_FUNCTION(void *, bsearch,
      |                            ^~~~~~~
/home/liam/Documents/GitHub/llvm-project/libc/src/__support/common.h:33:31: note: in definition of macro 'LLVM_LIBC_FUNCTION'
   33 |   decltype(__llvm_libc::name) name [[gnu::alias(#name)]];                      \
      |                               ^~~~
/home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.cpp:16:28: warning: 'void* __llvm_libc::bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*))' specifies less restrictive attribute than its target 'void* bsearch(const void*, const void*, size_t, size_t, __compar_fn_t)': 'nonnull' [-Wmissing-attributes]
   16 | LLVM_LIBC_FUNCTION(void *, bsearch,
      |                            ^~~~~~~
/home/liam/Documents/GitHub/llvm-project/libc/src/__support/common.h:33:31: note: in definition of macro 'LLVM_LIBC_FUNCTION'
   33 |   decltype(__llvm_libc::name) name [[gnu::alias(#name)]];                      \
      |                               ^~~~
In file included from /usr/include/stdlib.h:833,
                 from /home/liam/gcc-12.2.0/include/c++/12.2.0/cstdlib:75,
                 from /home/liam/gcc-12.2.0/include/c++/12.2.0/stdlib.h:36,
                 from /home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.h:9,
                 from /home/liam/Documents/GitHub/llvm-project/libc/src/stdlib/bsearch.cpp:9:
/usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h:20:1: note: 'void* __llvm_libc::bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*))' target declared here
   20 | bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
      | ^~~~~~~
@llvmbot
Copy link
Member

llvmbot commented Feb 2, 2023

@llvm/issue-subscribers-libc

@DavidSpickett
Copy link
Collaborator

Just been looking at this myself, this only happens for overlay mode. It's the overlaying mechanism that leads to this error I think.

Reading the gcc docs:
https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html

"It is an error if `__f' is not defined in the same translation unit."

clang does not document it so I don't know if clang allows this on purpose or not.

I also found https://stackoverflow.com/questions/7649979/gcc-alias-to-function-outside-of-translation-unit-aka-is-this-even-the-right-t asking about this with another project. No obvious solution from C, but some ideas with linker scripts and such.

I should note that the libc project only officially supports clang at this time. The gcc buildbots they have build the full mode so they won't have hit this.

@sivachandra
Copy link
Collaborator

Interestingly, this seems to happen only for release mode builds with -DCMAKE_BUILD_TYPE=Release. I am not able to reproduce this for debug builds.

@sivachandra
Copy link
Collaborator

Ah, looks like bsearch gets defined as an extern inline function in glibc's stdlib.h under release build and so the alias here is conflicting with that extern inline function.

@mikhailramalho
Copy link
Member

I also started to get the same error for readlinkat in RelWithDebInfo mode:

In file included from /home/mgadelha/tools/llvm-project/libc/src/__support/OSUtil/linux/syscall.h:12,
                 from /home/mgadelha/tools/llvm-project/libc/src/__support/OSUtil/syscall.h:13,
                 from /home/mgadelha/tools/llvm-project/libc/src/unistd/linux/readlinkat.cpp:11:
/home/mgadelha/tools/llvm-project/libc/src/unistd/linux/readlinkat.cpp:20:29: error: ‘ssize_t __llvm_libc::readlinkat(int, const char*, char*, size_t)’ aliased to external symbol ‘readlinkat’
   20 | LLVM_LIBC_FUNCTION(ssize_t, readlinkat,
      |                             ^~~~~~~~~~
/home/mgadelha/tools/llvm-project/libc/src/__support/common.h:30:31: note: in definition of macro ‘LLVM_LIBC_FUNCTION’
   30 |   decltype(__llvm_libc::name) name [[gnu::alias(#name)]];                      \
      |                               ^~~~
/home/mgadelha/tools/llvm-project/libc/src/unistd/linux/readlinkat.cpp:20:29: warning: ‘ssize_t __llvm_libc::readlinkat(int, const char*, char*, size_t)’ specifies less restrictive attributes than its target ‘ssize_t readlinkat(int, const char*, char*, size_t)’: ‘leaf’, ‘nonnull’, ‘nothrow’ [-Wmissing-attributes]
   20 | LLVM_LIBC_FUNCTION(ssize_t, readlinkat,
      |                             ^~~~~~~~~~
/home/mgadelha/tools/llvm-project/libc/src/__support/common.h:30:31: note: in definition of macro ‘LLVM_LIBC_FUNCTION’
   30 |   decltype(__llvm_libc::name) name [[gnu::alias(#name)]];                      \
      |                               ^~~~
In file included from /usr/include/features.h:486,
                 from /usr/include/unistd.h:25,
                 from /home/mgadelha/tools/llvm-project/libc/src/unistd/readlinkat.h:12,
                 from /home/mgadelha/tools/llvm-project/libc/src/unistd/linux/readlinkat.cpp:9:
/usr/include/x86_64-linux-gnu/bits/unistd.h:144:1: note: ‘ssize_t __llvm_libc::readlinkat(int, const char*, char*, size_t)’ target declared here
  144 | __NTH (readlinkat (int __fd, const char *__restrict __path,
      | ^~~~~

It builds fine in Debug mode.

@erkinalp
Copy link

erkinalp commented May 29, 2023

Suggested re-title: "Standard library re-aliasing issues in overlay mode builds only in the release configuration"

@DavidSpickett DavidSpickett changed the title __llvm_libc::bsearch() aliased to external symbol 'bsearch' Release overlay GCC build fails with "aliased to external symbol" Apr 17, 2024
@nickdesaulniers
Copy link
Member

Looks like gcc will error for aliases created with the alias attributes, but not asm aliases.

https://godbolt.org/z/xsxrTavnx

@nickdesaulniers
Copy link
Member

Simpler reproducer:

$ cd <new build dir>
$ cmake ../llvm -DLLVM_ENABLE_PROJECTS="libc" -DCMAKE_BUILD_TYPE=Release -G Ninja
$ ninja libc.src.stdlib.bsearch

nickdesaulniers added a commit to nickdesaulniers/llvm-project that referenced this issue Apr 19, 2024
When building overlay mode with GCC in release mode, glibc's stdlib.h contains
an extern inline declaration of bsearch.  This breaks our use of the gnu::alias
function attribute in LLVM_LIBC_FUNCTION with GCC because GCC checks that the
aliasee is defined in the same TU (clang does not).

We're looking at also potentially updating our definition of LLVM_LIBC_FUNCTION
from libc/src/__support/common.h. Upon testing, I was able to get
-Wnonnull-compare diagnostics from GCC in our definition of bsearch because
glibc declares bsearch with the fugly nonnull function attribute.

There's more we can do here though to improve our implementation of bsearch.
7.24.5.1 says:

    Pointer arguments on such a call shall still have valid values, as
    described in 7.1.4.

We could also use either function attributes or parameter attributes to denote
these should not be null (for users/callers) and perhaps still check for
non-null explicitly under some yet to be discussed hardening configurations in
the future.

Fixes: llvm#60481
Link: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute
@nickdesaulniers
Copy link
Member

Looks like gcc will error for aliases created with the alias attributes, but not asm aliases.

https://godbolt.org/z/xsxrTavnx

So clang can diagnose this, but seemingly only at -O0. I hit asserts in LLVM when I try to build that test case with optimizations enabled though.

I have a fix for the immediate issue of bsearch, but it won't close out this issue because we hit similar but slightly trickier to fix cases for 3 other functions (wctob, vprintf, and atof).

nickdesaulniers added a commit that referenced this issue Apr 22, 2024
When building overlay mode with GCC in release mode, glibc's stdlib.h
contains
an extern inline declaration of bsearch. This breaks our use of the
gnu::alias
function attribute in LLVM_LIBC_FUNCTION with GCC because GCC checks
that the
aliasee is defined in the same TU (clang does not).

We're looking at also potentially updating our definition of
LLVM_LIBC_FUNCTION
from libc/src/__support/common.h. Upon testing, I was able to get
-Wnonnull-compare diagnostics from GCC in our definition of bsearch
because
glibc declares bsearch with the fugly nonnull function attribute.

There's more we can do here though to improve our implementation of
bsearch.
7.24.5.1 says:

    Pointer arguments on such a call shall still have valid values, as
    described in 7.1.4.

We could also use either function attributes or parameter attributes to
denote
these should not be null (for users/callers) and perhaps still check for
non-null explicitly under some yet to be discussed hardening
configurations in
the future.

Link: #60481
Link:
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-nonnull-function-attribute
@lntue
Copy link
Contributor

lntue commented Sep 19, 2024

Turns out the problems are from extra extern inline definitions of libc functions in the system headers when building with gcc. Those inclusions are guarded by __USE_FORTIFY_LEVEL and __USE_EXTERN_INLINES, which are in turn guarded by: _FORTIFY_SOURCE and __NO_INLINE__ / __OPTIMIZE__.

A solution for this issue is:

  • Divert all those header inclusions to proxy headers
  • Update the guards before and after including those system headers in overlay mode with something like:
#ifdef _FORTIFY_SOURCE
#define LIBC_OLD_FORTIFY_SOURCE _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
#endif

#ifndef __NO_INLINE__
#define __NO_INLINE__ 1
#define LIBC_SET_NO_INLINE
#endif

#include <stdio.h>

#ifdef LIBC_OLD_FORTIFY_SOURCE
#define _FORTIFY_SOURCE LIBC_OLD_FORTIFY_SOURCE
#undef LIBC_OLD_FORTIFY_SOURCE
#endif

#ifdef LIBC_SET_NO_INLINE
#undef __NO_INLINE__
#undef LIBC_SET_NO_INLINE
#endif
  • List of headers having __USE_FORTIFY_LEVEL:
/usr/include/fcntl.h
/usr/include/mqueue.h
/usr/include/setjmp.h
/usr/include/stdio.h
/usr/include/stdlib.h
/usr/include/string.h
/usr/include/strings.h
/usr/include/unistd.h
/usr/include/wchar.h
  • List of headers having __USE_EXTERN_INLINES:
/usr/include/argp.h
/usr/include/argz.h
/usr/include/ctype.h
/usr/include/pthread.h
/usr/include/stdio.h
/usr/include/stdlib.h
/usr/include/threads.h
/usr/include/wchar.h

lntue added a commit that referenced this issue Sep 20, 2024
Also protect against extern inline function definitions added when
building with gcc: #60481.
@RossComputerGuy
Copy link
Member

I've ran into this same problem recently with a couple different files:

libc> FAILED: src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.openat.dir/openat.cpp.o
libc> /nix/store/2r2xi5pbg29bsmqywsm5zgl8l7adky4i-gcc-wrapper-13.3.0/bin/g++ -DLIBC_NAMESPACE=__llvm_libc -D_DEBUG -I/build/libc-src-20.0.0-unstable-2024-12-05/libc -isystem /build/libc-src-20.0.0-unstable-2024-12-05/libc/build/include -g -std=gnu++17 -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS -DLIBC_COPT_PUBLIC_PACKAGING -MD -MT src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.openat.dir/openat.cpp.o -MF src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.openat.dir/openat.cpp.o.d -o src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.openat.dir/openat.cpp.o -c /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/openat.cpp
libc> In file included from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/OSUtil/linux/syscall.h:13,
libc>                  from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/OSUtil/syscall.h:15,
libc>                  from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/openat.cpp:11:
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/openat.cpp:22:25: error: 'int __llvm_libc::openat(int, const char*, int, ...)' aliased to external symbol 'openat'
libc>    22 | LLVM_LIBC_FUNCTION(int, openat, (int dfd, const char *path, int flags, ...)) {
libc>       |                         ^~~~~~
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/common.h:46:34: note: in definition of macro 'LLVM_LIBC_FUNCTION_IMPL'
libc>    46 |   decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]];                   \
libc>       |                                  ^~~~
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/openat.cpp:22:1: note: in expansion of macro 'LLVM_LIBC_FUNCTION'
libc>    22 | LLVM_LIBC_FUNCTION(int, openat, (int dfd, const char *path, int flags, ...)) {
libc>       | ^~~~~~~~~~~~~~~~~~
libc> FAILED: src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.open.dir/open.cpp.o
libc> /nix/store/2r2xi5pbg29bsmqywsm5zgl8l7adky4i-gcc-wrapper-13.3.0/bin/g++ -DLIBC_NAMESPACE=__llvm_libc -D_DEBUG -I/build/libc-src-20.0.0-unstable-2024-12-05/libc -isystem /build/libc-src-20.0.0-unstable-2024-12-05/libc/build/include -g -std=gnu++17 -DLIBC_QSORT_IMPL=LIBC_QSORT_QUICK_SORT -DLIBC_ADD_NULL_CHECKS -DLIBC_COPT_PUBLIC_PACKAGING -MD -MT src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.open.dir/open.cpp.o -MF src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.open.dir/open.cpp.o.d -o src/fcntl/linux/CMakeFiles/libc.src.fcntl.linux.open.dir/open.cpp.o -c /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/open.cpp
libc> In file included from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/OSUtil/linux/syscall.h:13,
libc>                  from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/OSUtil/syscall.h:15,
libc>                  from /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/open.cpp:11:
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/open.cpp:23:25: error: 'int __llvm_libc::open(const char*, int, ...)' aliased to external symbol 'open'
libc>    23 | LLVM_LIBC_FUNCTION(int, open, (const char *path, int flags, ...)) {
libc>       |                         ^~~~
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/__support/common.h:46:34: note: in definition of macro 'LLVM_LIBC_FUNCTION_IMPL'
libc>    46 |   decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]];                   \
libc>       |                                  ^~~~
libc> /build/libc-src-20.0.0-unstable-2024-12-05/libc/src/fcntl/linux/open.cpp:23:1: note: in expansion of macro 'LLVM_LIBC_FUNCTION'
libc>    23 | LLVM_LIBC_FUNCTION(int, open, (const char *path, int flags, ...)) {
libc>       | ^~~~~~~~~~~~~~~~~~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants