CMake/ELF: replace 'extern "C++"' with exhaustive mangled expansions

Commit 946f15efb7 added the line
  extern "C++" { std::* };
but that was too good to be true. The intention was to catch Standard
Library inline symbols that got emitted in our own libraries, not use of
Standard Library types in our symbols. Unfortunately, that glob
expression matches the demangling literally and return types for
templates are demangled in their usual position to the left of the
function name.

For example,
  std::random_device qFoo();    // mangles as _Z4qFoov → "qFoo()"
but
  template <typename T> T qFoo();
  template std::random_device qFoo<std::random_device>();
mangles as _Z4qFooISt13random_deviceET_v and that demangles to
"std::random_device qFoo<std::random_device>()".

Therefore, we replace that with a full expansion according to the
mangling scheme. This includes a minor fix for the RTTI symbols, to
match nested names too (those with "N" in the name). It can't match
virtual override thunks ("Tv" and "Th"), because those have variable
length names and the matching is done by fnmatch(), not regex.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd178449cf68669cb6
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
Thiago Macieira 2023-09-12 16:15:14 -07:00
parent 4a6cbfbe5c
commit e456232ad3

View File

@ -23,10 +23,36 @@ function(qt_internal_add_linker_version_script target)
endif()
if(TEST_ld_version_script)
set(contents "NonQt { local:\n")
string(APPEND contents " _ZT?S*;\n") # {typeinfo {,name},vtable,VTT} for std::
string(APPEND contents " extern \"C++\" { std::*; };\n")
string(APPEND contents "};\nQt_${PROJECT_VERSION_MAJOR}_PRIVATE_API { qt_private_api_tag*;\n")
# Create a list of mangled symbol matches for all "std::" symbols. This
# list will catch most symbols, but will miss global-namespace symbols
# that only have std parameters.
# See https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name for reference
set(contents "NonQt {\nlocal:")
# For types: vtable, VTT, typeinfo, typeinfo name
foreach(ptrqualifier "" "P" "PK") # T, T *, const T * (volatile ignored)
string(APPEND contents "\n _ZT[VTIS]${ptrqualifier}S*;"
"_ZT[VTIS]${ptrqualifier}NS*;")
endforeach()
# For functions and variables
foreach(special ""
"G[VR]" # guard variables, extended-lifetime references
"GTt") # transaction entry points
foreach(cvqualifier "" "[VK]" "VK") # plain, const|volatile, const volatile
string(APPEND contents "\n ")
foreach(refqualifier "" "[RO]") # plain, & or &&
# For names in the std:: namespace, compression applies
# (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression)
string(APPEND contents
" _Z${special}${cvqualifier}${refqualifier}S*;" # plain
" _Z${special}N${cvqualifier}${refqualifier}S*;" # nested name
)
endforeach()
endforeach()
endforeach()
string(APPEND contents "\n};\nQt_${PROJECT_VERSION_MAJOR}_PRIVATE_API { qt_private_api_tag*;\n")
if(arg_PRIVATE_HEADERS)
foreach(ph ${arg_PRIVATE_HEADERS})
string(APPEND contents " @FILE:${ph}@\n")