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

Inappropriate RUNPATH of clangd binary #1997

Open
juicymio opened this issue Apr 2, 2024 · 5 comments · May be fixed by #2006
Open

Inappropriate RUNPATH of clangd binary #1997

juicymio opened this issue Apr 2, 2024 · 5 comments · May be fixed by #2006

Comments

@juicymio
Copy link

juicymio commented Apr 2, 2024

runpath of the release of clangd is: " $ORIGIN/../lib:"

> readelf -d ./clangd

Dynamic section at offset 0x3260b20 contains 30 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/../lib:]
...  

The colon at the end results in that if any library can't be find at "$ORIGIN/../lib", the program will search current directory. If something like libc.so.6 exists in current directory, clangd will mistakenly try to load it. Like this:(the version of libc.so.6 at current directory is GLIBC_2.35, so there isn't version symbol "GLIBC_2.36")

❯ ls
ld-linux-x86-64.so.2  libc.so.6  main.c  pwn  s.out
❯ /tmp/clangd_17.0.3/bin/clangd
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required
 by /usr/lib/libpthread.so.0)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libpthread.so.0)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/librt.so.1)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/librt.so.1)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/libdl.so.2)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libdl.so.2)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/libm.so.6)
/tmp/clangd_17.0.3/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libm.so.6)

The situation of using clangd through a plugin in an editor like neovim is similar. Once execute nvim main.c, clangd will crash.

Logs

[ERROR][2024-04-02 14:13:24] .../vim/lsp/rpc.lua:734    "rpc"    "/home/juicymio/.local/share/nvim/mason/bin/clangd"    "stderr"    "/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/libpthread.so.0)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libpthread.so.0)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/librt.so.1)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/librt.so.1)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/libdl.so.2)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libdl.so.2)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_2.36' not found (required by /usr/lib/libm.so.6)\n/home/juicymio/.local/share/nvim/mason/bin/clangd: libc.so.6: version `GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libm.so.6)\n"

Suggest solution
Delete the colon, change the runpath into:
$ORIGIN/../lib
Sorry that I don't know how to modify the runpath of clangd in this project.
System information

Output of clangd --version:

clangd version 17.0.3 (https://github.com/llvm/llvm-project 888437e1b60011b8a375dd30928ec925b448da57)
Features: linux+grpc
Platform: x86_64-unknown-linux-gnu

Editor/LSP plugin: neovim, mason.nvim

Operating system: archlinux

@zyn0217
Copy link

zyn0217 commented Apr 5, 2024

I think this is not a particular issue to clangd, but to every llvm binary built from CMake that ends up getting configured with llvm_setup_rpath, which is called by llvm_add_library that brings up this behavior.

If something like libc.so.6 exists in current directory, clangd will mistakenly try to load it.

I don't see clangd is doing anything wrong: if you put clangd binary somewhere under the system directory e.g. /usr/local/bin/clangd, then /usr/local/lib or /usr/lib is expected to have your glibc libraries installed; otherwise, the path that causes such confusion for clangd is probably inappropriate: that looks more like an independent software collection (e.g. /opt/rh/... compared to your system's default), and you should build/use the clangd that matches the version of that glibc.

@juicymio
Copy link
Author

juicymio commented Apr 5, 2024

@zyn0217 The problem is clangd shouldn't search the working directory(where it is executed) for libraries.
If I put clangd binary in /usr/local/bin, and put main.c and libc.so.6 in ~/myproject/. Then execute nvim ./main.c, which execute /usr/local/bin/clangd in ~/myproject. It will search $ORIGIN/../lib(/usr/local/lib in this case) first.But Glibc shouldn't lies in /usr/local/lib.Then clangd will search through ~/myproject/ and find my libc.so.6. Why does it search my project first instead of go directly to /usr/lib?

@zyn0217
Copy link

zyn0217 commented Apr 5, 2024

Honestly, I don't see where the trailing colon gets added from the cmake script. Where did you get your clangd binary? Was that from our github release page?

@juicymio
Copy link
Author

juicymio commented Apr 5, 2024

@zyn0217
Copy link

zyn0217 commented Apr 5, 2024

I have searched some documents, and now I believe this is a feature of CMake that helps replace rpaths after installing a target. See this and this.

AFAIU, the trailing colons will be added by CMake automatically if the target would get installed and BUILD_RPATH is set, and they will be replaced at the installation step. OTOH, our CI of building clangd provides the artifacts without performing installation, which leaves behind the trailing colons to the released binaries.

To quickly reproduce such behavior of CMake, one can create the following CMakeLists.txt and a C++ file named main.cpp.

cmake_minimum_required(VERSION 3.20)

project(testing)

set(_build_rpath "\$ORIGIN/../lib")

add_executable(main main.cpp)
target_compile_options(main PUBLIC "-std=c++17")

set_property(TARGET main APPEND PROPERTY BUILD_RPATH "${_build_rpath}")

install(TARGETS main)
int main() {}

then running the command cmake --build ./Build --verbose --clean-first would give us such:

[2/2] : && /usr/local/bin/clang++  -fuse-ld=mold CMakeFiles/main.dir/main.cpp.o -o main  -Wl,-rpath,"\$ORIGIN/../lib:"

(Note the trailing colon, and it will be gone if we remove the install command.)

That said, I don't have a better idea of resolving this issue. Configuring LLVM with CMAKE_NO_BUILTIN_CHRPATH=OFF appears promising, but that makes it spit out configuration failures on my Linux system, many of which are like:

The install of the Remarks target requires changing an RPATH from the build
  tree, but this is not supported with the Ninja generator unless on an
  ELF-based or XCOFF-based platform.  The CMAKE_BUILD_WITH_INSTALL_RPATH
  variable may be set to avoid this relinking step.

@zyn0217 zyn0217 linked a pull request Apr 8, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants