From 8f8b2e942976f4db245ab6227d83a42371518d12 Mon Sep 17 00:00:00 2001 From: Tolga Mizrak Date: Fri, 16 May 2025 08:01:21 +0200 Subject: [PATCH 1/2] bindexplib: Truncate short symbol names on first embedded null-terminator --- Source/bindexplib.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index f5c36b0302..1ddfaafe2f 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -254,7 +254,8 @@ public: */ if (pSymbolTable->N.Name.Short != 0) { symbol.clear(); - symbol.insert(0, (char const*)pSymbolTable->N.ShortName, 8); + symbol.insert(0, (char const*)pSymbolTable->N.ShortName, + strnlen((char const*)pSymbolTable->N.ShortName, 8)); } else { symbol = stringTable + pSymbolTable->N.Name.Long; } From 607d9cf5613bd335c29a0ad9609eca4698283fa6 Mon Sep 17 00:00:00 2001 From: Tolga Mizrak Date: Fri, 16 May 2025 08:01:45 +0200 Subject: [PATCH 2/2] WINDOWS_EXPORT_ALL_SYMBOLS: Do not export C++ operators declared extern "C" The pattern `extern "C" { inline bool operator==(...) {} }` appears in at least one Windows SDK header, `winnt.h`. Translation units that instantiate the inline symbol produce object files with a symbol named just `==`. Avoid exporting such symbols because the linker will not recognize them. Fixes: #24999 --- Source/bindexplib.cxx | 12 +++++++++-- Tests/RunCMake/AutoExportDll/hello.cxx | 30 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 1ddfaafe2f..bbcb0bccc9 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -290,9 +290,11 @@ public: symbol.compare(0, 4, vectorPrefix)) { SectChar = this->SectionHeaders[pSymbolTable->SectionNumber - 1] .Characteristics; - // skip symbols containing a dot or are from managed code + // Skip symbols containing a dot, are from managed code, + // or are C++ operators incorrectly declared extern "C". if (symbol.find('.') == std::string::npos && - !SymbolIsFromManagedCode(symbol)) { + !SymbolIsFromManagedCode(symbol) && + !SymbolIsOperatorExternC(symbol)) { // skip arm64ec thunk symbols if (this->SymbolArch != Arch::ARM64EC || (symbol.find("$ientry_thunk") == std::string::npos && @@ -337,6 +339,12 @@ private: symbol.find("$$J") != std::string::npos; } + bool SymbolIsOperatorExternC(std::string const& symbol) + { + return symbol.find_first_not_of("=<>+-*/%,?|~!^&[]()") == + std::string::npos; + } + std::set& Symbols; std::set& DataSymbols; DWORD_PTR SymbolCount; diff --git a/Tests/RunCMake/AutoExportDll/hello.cxx b/Tests/RunCMake/AutoExportDll/hello.cxx index 2dc0c9819b..e71d8eea44 100644 --- a/Tests/RunCMake/AutoExportDll/hello.cxx +++ b/Tests/RunCMake/AutoExportDll/hello.cxx @@ -21,3 +21,33 @@ HelloVFTable::~HelloVFTable() { } #endif + +#ifndef __SUNPRO_CC +// C++ operators incorrectly declared extern "C" should *not* be exported. +extern "C" { +bool operator==(Hello const&, Hello const&) +{ + return false; +} +bool operator!=(Hello const&, Hello const&) +{ + return false; +} +bool operator<(Hello const&, Hello const&) +{ + return false; +} +bool operator<=(Hello const&, Hello const&) +{ + return false; +} +bool operator>(Hello const&, Hello const&) +{ + return false; +} +bool operator>=(Hello const&, Hello const&) +{ + return false; +} +} +#endif