From 19b7f854a274812d9c95fc7aaf134a12530c105f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 23 Jan 2012 11:46:58 -0200 Subject: [PATCH] Enable -mno-direct-extern-access and ELF protected visibility The -mno-direct-extern-access tells the compiler and linker that references to symbols outside this ELF module mustn't be direct and must instead always go through the GOT or PLT (the PLT can additionally be disabled with -fno-plt). The ELF protected visibility tells the compiler and linker that this symbol is present in the dynamic symbol table as an export, but it cannot be interposed by another ELF module. This option is required for user code to link properly to Qt, otherwise they will get linker errors (assuming GNU binutils >= 2.39) or runtime failures (glibc >= 2.35). Both versions of glibc and binutils are older than GCC 12, so it's a safe assumption they are in use and downgrading the toolchain or libc is not supported. Adding this option to the compilation is assured for CMake and qmake-based projects. For example, all accessess to QCoreApplication::self in QtCore, after this change and with GCC 12 are relocation-free and direct: 000000000013ebf0 : 13ebf0: cmpq $0x0,0x4f73d0(%rip) # 635fc8 13ebf8: setne %al 13ebfb: je a90fe 13ec01: ret Meanwhile, accesses to the same variable in other modules are indirect via the GOT: 66650: mov 0x876e1(%rip),%rax # edd38 66657: cmpq $0x0,(%rax) This replaces the -Bsymbolic and -Bsymbolic-functions (broken) functionality that Qt has been using or attempting to use since ~2006. See https://gitlab.com/x86-psABIs/x86-64-ABI/-/issues/8#note_606975128 Change-Id: Iad4b0a3e5c06570b9f5f571b26ed564aa0811e47 Reviewed-by: Alexandru Croitor Reviewed-by: Lars Knoll --- cmake/QtModuleHelpers.cmake | 3 ++- cmake/QtPlatformTargetHelpers.cmake | 3 +++ configure.cmake | 13 ++++++++++++- mkspecs/common/gcc-base.conf | 2 +- mkspecs/features/qt.prf | 7 +++++++ mkspecs/features/unix/mno_extern_direct_access.prf | 2 ++ src/corelib/global/qcompilerdetection.h | 10 +++++++++- src/corelib/global/qglobal.h | 5 +++-- src/corelib/kernel/qcoreapplication.cpp | 2 +- 9 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 mkspecs/features/unix/mno_extern_direct_access.prf diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index eedf05b4fa4..d72cd545644 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -202,7 +202,8 @@ function(qt_internal_add_module target) qt_internal_get_framework_info(fw ${target}) endif() - if(QT_FEATURE_reduce_relocations AND UNIX AND NOT is_interface_lib) + if(NOT QT_FEATURE_no_extern_direct_access AND QT_FEATURE_reduce_relocations AND + UNIX AND NOT is_interface_lib) # On x86 and x86-64 systems with ELF binaries (especially Linux), due to # a new optimization in GCC 5.x in combination with a recent version of # GNU binutils, compiling Qt applications with -fPIE is no longer diff --git a/cmake/QtPlatformTargetHelpers.cmake b/cmake/QtPlatformTargetHelpers.cmake index 36b661741b1..270ed3167b9 100644 --- a/cmake/QtPlatformTargetHelpers.cmake +++ b/cmake/QtPlatformTargetHelpers.cmake @@ -30,6 +30,9 @@ function(qt_internal_setup_public_platform_target) target_compile_options(Platform INTERFACE "-stdlib=libc++") target_link_options(Platform INTERFACE "-stdlib=libc++") endif() + if (QT_FEATURE_no_extern_direct_access) + target_compile_options(Platform INTERFACE "-mno-direct-extern-access") + endif() qt_set_msvc_cplusplus_options(Platform INTERFACE) diff --git a/configure.cmake b/configure.cmake index 92d501a4d1a..2274f1554de 100644 --- a/configure.cmake +++ b/configure.cmake @@ -189,6 +189,11 @@ qt_config_compiler_supports_flag_test(optimize_debug FLAG "-Og" ) +qt_config_compiler_supports_flag_test(no_extern_direct_access + LABEL "-mno-direct-extern-access support" + FLAG "-mno-direct-extern-access" +) + qt_config_linker_supports_flag_test(enable_new_dtags LABEL "new dtags support" FLAG "--enable-new-dtags" @@ -695,7 +700,13 @@ qt_feature("reduce_exports" PRIVATE ) qt_feature_definition("reduce_exports" "QT_VISIBILITY_AVAILABLE") qt_feature_config("reduce_exports" QMAKE_PUBLIC_QT_CONFIG) -qt_feature("reduce_relocations" PRIVATE +qt_feature("no_extern_direct_access" PRIVATE + LABEL "Use protected visibility and -mno-direct-extern-access" + CONDITION NOT WIN32 AND TEST_no_extern_direct_access +) +qt_feature_definition("no_extern_direct_access" "QT_USE_PROTECTED_VISIBILITY") +qt_feature_config("no_extern_direct_access" QMAKE_PUBLIC_QT_CONFIG) +qt_feature("reduce_relocations" PUBLIC LABEL "Reduce amount of relocations" CONDITION NOT WIN32 AND TEST_reduce_relocations ) diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 1c27f34441a..ae58326289f 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -45,7 +45,7 @@ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g QMAKE_CFLAGS_DEBUG += -g QMAKE_CFLAGS_SHLIB += $$QMAKE_CFLAGS_PIC QMAKE_CFLAGS_STATIC_LIB += $$QMAKE_CFLAGS_PIC -QMAKE_CFLAGS_APP += $$QMAKE_CFLAGS_PIC +QMAKE_CFLAGS_APP += QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden QMAKE_CFLAGS_EXCEPTIONS_OFF += -fno-exceptions diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 6fb657e6f2b..0e03027bc33 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -58,6 +58,13 @@ qaxserver { !force_import_plugins:!contains(TEMPLATE, ".*app"):!if(contains(TEMPLATE, ".*lib"):dll): \ CONFIG -= import_plugins +unix { + contains(QT_CONFIG, no_extern_direct_access): CONFIG += mno_extern_direct_access + else:contains(QT_CONFIG, reduce_relocations):!contains(TEMPLATE, .*lib): { + QMAKE_CFLAGS += $$QMAKE_CFLAGS_PIC + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_PIC + } +} # qmake variables cannot contain dashes, so normalize the names first CLEAN_QT = $$replace(QT, -private$, _private) diff --git a/mkspecs/features/unix/mno_extern_direct_access.prf b/mkspecs/features/unix/mno_extern_direct_access.prf new file mode 100644 index 00000000000..816e28bb43c --- /dev/null +++ b/mkspecs/features/unix/mno_extern_direct_access.prf @@ -0,0 +1,2 @@ +QMAKE_CFLAGS += -mno-direct-extern-access +QMAKE_CXXFLAGS += -mno-direct-extern-access diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 00b55c7ab49..b3b3bd600c5 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -214,7 +214,12 @@ # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) # elif defined(QT_VISIBILITY_AVAILABLE) -# define Q_DECL_EXPORT __attribute__((visibility("default"))) +# define Q_DECL_EXPORT_OVERRIDABLE __attribute__((visibility("default"), weak)) +# ifdef QT_USE_PROTECTED_VISIBILITY +# define Q_DECL_EXPORT __attribute__((visibility("protected"))) +# else +# define Q_DECL_EXPORT __attribute__((visibility("default"))) +# endif # define Q_DECL_IMPORT __attribute__((visibility("default"))) # define Q_DECL_HIDDEN __attribute__((visibility("hidden"))) # endif @@ -1151,6 +1156,9 @@ #ifndef Q_DECL_EXPORT # define Q_DECL_EXPORT #endif +#ifndef Q_DECL_EXPORT_OVERRIDABLE +# define Q_DECL_EXPORT_OVERRIDABLE Q_DECL_EXPORT +#endif #ifndef Q_DECL_IMPORT # define Q_DECL_IMPORT #endif diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 8747c6774b7..ab0f4a1ecfd 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1289,8 +1289,9 @@ inline int qIntCast(float f) { return int(f); } #define QT_MODULE(x) -#if !defined(QT_BOOTSTRAPPED) && defined(QT_REDUCE_RELOCATIONS) && defined(__ELF__) && \ - (!defined(__PIC__) || (defined(__PIE__) && defined(Q_CC_GNU) && Q_CC_GNU >= 500)) +#if defined(QT_BOOTSTRAPPED) || defined(QT_USE_PROTECTED_VISIBILITY) || !defined(__ELF__) || defined(__PIC__) +// this is fine +#elif defined(QT_REDUCE_RELOCATIONS) # error "You must build your code with position independent code if Qt was built with -reduce-relocations. "\ "Compile your code with -fPIC (and not with -fPIE)." #endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index af0be3ff75d..fa0c2486cc7 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -255,7 +255,7 @@ void QCoreApplicationPrivate::processCommandLineArguments() // Support for introspection -extern "C" void Q_CORE_EXPORT qt_startup_hook() +extern "C" void Q_DECL_EXPORT_OVERRIDABLE qt_startup_hook() { }