PIE+LTO causes Bitcoin-Qt to segfault at startup #867

issue whitslack openend this issue on April 22, 2025
  1. whitslack commented at 5:34 am on April 22, 2025: contributor
    • I still think this issue should be opened here

    Report

    When PIE and LTO are combined, Qt applications crash at startup. See Gentoo bug 954171. You can read all the gorey details about the underlying issue (that also affected Wireshark) here. Basically, the issue is that Qt’s qcompilerdetection.h prohibits building Qt with PIE because PIE breaks a critical assumption that Qt makes, but when a Qt application is built using LTO, the application’s -fPIE flag overrides Qt’s -fPIC flag and causes pieces of Qt to be optimized under the PIE model, which breaks it and causes it to segfault at runtime. The guard in qcompilerdetection.h is powerless to detect and prevent this because it’s implemented by a preprocessor directive, and the preprocessor is not involved during LTO. To fix this, Bitcoin-Qt has to choose either LTO or PIE but not both. In Gentoo we plan to work around this for now by filtering out -flto from the user’s flags, but it would be nicer to have an upstream solution.

  2. eli-schwartz commented at 5:56 am on April 22, 2025: none

    To be clear, the actual issue is that cmake has POSITION_INDEPENDENT_CODE, which claims to implement PIC, but it does not. It enables PIE instead, which is not what you actually asked for, and they are unfortunately different enough to matter.

    It’s quite fine to enforce -fPIC (and also to link with -pie), but cmake simply does not provide the necessary builtin functionality to do it correctly.

  3. hebasto commented at 10:06 am on April 22, 2025: member
    1. It seems reasonable to move this issue to the main repository to increase its visibility to the build system developers.

    2. I can’t reproduce the issue on Ubuntu 24.10 using GCC 14.2.0:

    0$ rm -rf build && cmake -B build -DCMAKE_C_FLAGS=-flto -DCMAKE_CXX_FLAGS=-flto -DBUILD_GUI=ON
    1$ cmake --build build -t bitcoin-qt
    2$ ./build/bin/bitcoin-qt
    

    This suggests the issue may be specific to the default compiler options. If so, please consider updating the OP accordingly.

    1. Based on several related discussions, the root cause appears to lie upstream—with Qt and / or CMake:
  4. thesamesam commented at 10:32 am on April 22, 2025: none

    Ubuntu builds their Qt with “reduce relocations” disabled, so it doesn’t hit this (see https://bugs.gentoo.org/933110#c5).

    The root cause is a mix between Qt, CMake, and the fact there’s no way for the toolchain to communicate a problem. CMake doesn’t seem particularly interested in fixing it given https://gitlab.kitware.com/cmake/cmake/-/issues/15570#note_477736. Qt says that the right thing to do is to honour their own recommendation (naturally).

    I spent a significant amount of time investigating it and I really don’t see an option besides changing CMake (and CMake doesn’t seem interested) than fixing upstream projects which use Qt to simply not use POSITION_INDEPENDENT_CODE and replace it with inlined -fPIC where appropriate and -pie at link-time.

  5. fanquake commented at 1:36 pm on April 22, 2025: member
    I remember us already having code to work around something similar to this. i.e: https://github.com/bitcoin/bitcoin/blob/dbc450c1b59b24421ba93f3e21faa8c673c0df4c/build-aux/m4/bitcoin_qt.m4#L182? Looks like it was just dropped, rather than ported to CMake?
  6. hebasto commented at 1:47 pm on April 22, 2025: member

    I remember us already having code to work around something similar to this. i.e: https://github.com/bitcoin/bitcoin/blob/dbc450c1b59b24421ba93f3e21faa8c673c0df4c/build-aux/m4/bitcoin_qt.m4#L182? Looks like it was just dropped, rather than ported to CMake?

    Was it related to LTO?

  7. thesamesam commented at 1:51 pm on April 22, 2025: none

    It’s the same problem. It just shows up worse with LTO because Qt’s sanity check can’t fire to tell you (at the point where the preprocessor is run, the right flags are in effect) and give you a build failure instead.

    The way that CMake handles this (which is buggy, at least for Qt) means it doesn’t show up without LTO, because it does pass -fPIC almost all of the time, just not the whole time (does -fPIE when linking). If CMake just did -fPIE for everything, you’d get an error instead.

  8. hebasto commented at 12:17 pm on April 23, 2025: member

    Is anyone aware of other distros that provide shared Qt libraries built with -reduce-relocations?

    (asking because I’m not quite familiar with Gentoo)

    Fedora, Debian/Ubuntu, and Arch do not have such an issue.

  9. thesamesam commented at 12:18 pm on April 23, 2025: none
    Fedora, Debian/Ubuntu, opensuse, Alpine disable it. Arch disables it but only for Qt 5 AFAICT (has it enabled for Qt 6). Looks like Void has it on.
  10. hebasto commented at 12:22 pm on April 23, 2025: member

    Arch disables it but only for Qt 5 AFAICT (has it enabled for Qt 6).

    Building on Arch with -flto does not expose any runtime issues (obviously, using Qt 6).

  11. thesamesam commented at 12:31 pm on April 23, 2025: none
  12. hebasto commented at 3:22 pm on April 23, 2025: member

    @whitslack @eli-schwartz @thesamesam

    Setting the required conditions aside, can you confirm whether the following patch resolves the issue on Gentoo:

     0--- a/src/qt/CMakeLists.txt
     1+++ b/src/qt/CMakeLists.txt
     2@@ -250,6 +250,8 @@ if(qt_lib_type STREQUAL "STATIC_LIBRARY")
     3   )
     4 endif()
     5 
     6+list(TRANSFORM CMAKE_CXX_LINK_OPTIONS_PIE REPLACE "${CMAKE_CXX_COMPILE_OPTIONS_PIE}" "${CMAKE_CXX_COMPILE_OPTIONS_PIC}")
     7+
     8 add_executable(bitcoin-qt
     9   main.cpp
    10   ../init/bitcoin-qt.cpp
    

    ?

  13. hebasto commented at 4:18 pm on April 23, 2025: member

    Interesting! It should happen since https://gitlab.archlinux.org/archlinux/packaging/packages/qt6-base/-/commit/5cd71aed56de955b182e20263a50cd91bf7b6aaa.

    This approach appears suitable for Gentoo’s Qt packages as well, since, according to this commit message, the -Bsymbolic and -Bsymbolic-functions functionality—underlying the -reduce-relocations option—is broken.

  14. joecool1029 commented at 10:10 pm on April 29, 2025: none
    @hebasto I can confirm the above resolves the issue. (I am the Gentoo bug reporter on this)
  15. thesamesam commented at 11:22 pm on April 29, 2025: none

    This approach appears suitable for Gentoo’s Qt packages as well […]

    Yes, this is the conclusion I reached as well. The original Qt commit adding the improved version didn’t have it optional, and I saw it referenced in headers which made me think the feature detection had enabled it – but it only detected it, didn’t enable it unless passed explicitly, as a followup Qt commit (a while later) disabled it until newer Binutils is widely adopted, I think.

    Anyway, you’re absolutely right, and it’s indeed a fix for us: we’re adopting the no-direct-extern-access Qt option which fixes reduce-relocations.

    I think the fix you mention is right for the reduce-relocations case, though (just that we in Gentoo, and anyone else using reduce-relocations, are best off using that newer feature on top to avoid hitting issues like this). Thank you!


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/gui. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-05-03 01:20 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me