Closed nico closed 5 years ago
Nevermind comment 14. These lib files are import files written by the linker when it creates a dll.
Does setting CMAKE_LINKER imply that we use lld-link /lib
instead of lib.exe for static libraries? If not, lld-link isn't even creating the .lib file, right?
That became r362970.
There is an open question of why VC link.exe pulls in these objects when the archive is produced by link.exe instead of LLD, but I think we can leave that unanswered for now.
My comment there was the wrong way round. lld-link /wholearchive adds all .obj files from a .lib file but link.exe only adds .obj files that are referenced from the static library's symbol index (i.e. only .obj files with public symbols).
That's true, I kept debugging the problem, and I realized that the ASan tests actually do RUN: %clangxx_asan %s
, and this doesn't pass -fuse-ld=lld, so they get VC link, and that's when I observed this behavior.
I'll add an otherwise unused external symbol to these object files with some comments and call it a day.
My comment there was the wrong way round. lld-link /wholearchive adds all .obj files from a .lib file but link.exe only adds .obj files that are referenced from the static library's symbol index (i.e. only .obj files with public symbols).
Coincidentally, Nico ran into the relevant wholearchive behavior at the same time: llvm/llvm-bugzilla-archive#42180
That became r362849, but it still doesn't fix the bug. It looks like LLD doesn't handle -wholearchive: the way that MSVC does. LLD only seems to add object files that define symbols to the link, and we have an object (sanitizer_coverage_win_dynamic_runtime_thunk.cc) that defines no symbols and just contains .drective options.
I tried to come up with a proper fix that preserves our behavior and adds new tests: https://reviews.llvm.org/D62984
I don't recall running into any project that needed/used that feature yet, so I don't mind if you change it, especially if it doesn't break any existing tests. (Although, it might have worked and relied on with the existing behaviour that isn't covered by tests.) All variants of exporting with various mangling, with different behaviour between msvc and mingw, is a huge mess. The cases I've worked on should at least have test cases (mostly in lld).
In case it does break any of my usecases, I have pretty frequent testing so it should be noticed soon.
Looks like this code used to live in lld before it moved to llvm.
See e.g. https://reviews.llvm.org/rL297357 -- so it's covered by lld's tests. If those don't fail, then all's good I think.
(git blame 72fbd346c62f3c2bf30ffa99dd4ee55430ac995a lld/COFF/Librarian.cpp
)
Regressing functionality not covered by tests is fair game in my book :)
So, I've determined that the following patch fixes the bug, and it does so without breaking any tests:
diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index ff4a799be60..96c5427e936 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -106,26 +106,6 @@ static ImportNameType getNameType(StringRef Sym, StringRef ExtName, return IMPORT_NAME; }
-static Expected
static const std::string NullImportDescriptorSymbolName = "__NULL_IMPORT_DESCRIPTOR";
@@ -599,21 +579,16 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, ? IMPORT_ORDINAL : getNameType(SymbolName, E.Name, Machine, MinGW);
Expected
? SymbolName
: replace(SymbolName, E.Name, E.ExtName);
if (!Name)
return Name.takeError();
StringRef Name = E.ExtName.empty() ? SymbolName : StringRef(E.ExtName);
if (!E.AliasTarget.empty() && *Name != E.AliasTarget) {
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, false));
Members.push_back(OF.createWeakExternal(E.AliasTarget, *Name, true));
if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, false));
Members.push_back(OF.createWeakExternal(E.AliasTarget, Name, true)); continue; }
Members.push_back(
OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
OF.createShortImport(Name, E.Ordinal, ImportType, NameType)); }
return writeArchive(Path, Members, /WriteSymtab/ true,
However, it regresses some functionality. Suppose we have -export:foo=bar on the command line, but bar is stdcall, so it is decorated as _bar@8, and the export of "foo" should really be an export of "_foo@8" once decorated. That's what this "replace" code above implements, but there are no tests for it. I've been trying to do some experiments to determine the correct behavior, but it's been difficult.
Here's a reduced example:
$ cat t.c
int foo_def() { return 42; }
$ cl -c t.c
$ lld-link -nodefaultlib -noentry -dll t.obj && llvm-nm t.lib ... t.dll: 00000000 T __imp_foo_dll_def 00000000 T foo_dll_def
$ link -nodefaultlib -noentry -dll t.obj && llvm-nm t.lib ... t.dll: 00000000 T __imp_foo_dll 00000000 T foo_dll
I wonder how we got to foo_dll_def, since that requires inventing a new string that isn't present in the source.
I started looking at this. I can reproduce it with check-asan-dynamic, but I don't understand it yet.
Marcos's implementation of weak symbols for COFF is very complicated and hard to understand. We had that conversation the other week about how they aren't well supported on COFF.
I suppose it'll be faster to directly compare the .libs.
I noticed that the clang_rt.asan_dynamic-x86-64.lib produced by MSVC has different symbols than one produced by LLD.
Specifically, I see this:
--- asan-dynamic-syms-lld.txt 2019-06-03 13:45:20.060940200 -0700 +++ asan-dynamic-syms-msvc.txt 2019-06-03 13:45:30.273437100 -0700 ... clang_rt.asan_dynamic-x86_64.dll: -00000000 T imp_sanitizer_cov_trace_pc_guarddlldef -00000000 T sanitizer_cov_trace_pc_guarddlldef +00000000 T _impsanitizer_cov_trace_pc_guarddll +00000000 T sanitizer_cov_trace_pc_guard__dll
But, we're supposed to export ${sym}dll, not ${sym}dll__def. This is supposed to be controlled by these /export:alias=aliasee directives in sanitizer_coverage_libcdep_new.cc, dumped here:
$ dumpbin -directives projects/compiler-rt/lib/sanitizer_common/CMakeFiles/RTSanitizerCommonCoverage.x86_64.dir/sanitizer_coverage_libcdep_new.cc.obj ... /alternatename:sanitizer_cov_trace_pc_guard=sanitizer_cov_trace_pc_guarddef /export:sanitizer_cov_trace_pc_guarddll=sanitizer_cov_trace_pc_guard
So, LLD seems to have a bug in its implementation of -export:foo=bar. Maybe I can make a small repro.
I have to run for today. Will look tomorrow. +rnk in case it's obvious to him what's wrong.
Extended Description
When doing build of LLVM on Windows with CMAKE_LINKER set to lld-link, 3 tests fail.
I don't immediately see how the failures are related to things building with lld -- the test doesn't use lld.
Maybe the shared libasan linked by lld is missing symbols or something?
Full cmake invocation below.
-- Testing: 49878 tests, 32 threads -- Testing: 0 .. FAIL: AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-basic.cc (4634 of 49878) **** TEST 'AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-basic.cc' FAILED **** Script:
: 'RUN: at line 1'; rm -rf C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-basic.cc.tmp-dir : 'RUN: at line 2'; mkdir C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-basic.cc.tmp-dir && cd C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-basic.cc.tmp-dir : 'RUN: at line 3'; C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang.exe -fsanitize=address -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -gline-tables-only -gcodeview -gcolumn-info -shared-libasan -D_MT -D_DLL -Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames -fsanitize-coverage=func C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows\coverage-basic.cc -o test.exe : 'RUN: at line 4'; env ASAN_OPTIONS=coverage=1 ./test.exe : 'RUN: at line 6'; C:/b/s/w/ir/cache/vpython/21a792/Scripts/python.exe C:/b/s/w/ir/k/src/third_party/llvm/compiler-rt\lib\sanitizer_common\scripts\sancov.py print *.sancov | FileCheck C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows\coverage-basic.cc
Exit Code: 1120
Command Output (stdout):
$ ":" "RUN: at line 1" $ "rm" "-rf" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-basic.cc.tmp-dir" $ ":" "RUN: at line 2" $ "mkdir" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-basic.cc.tmp-dir" $ ":" "RUN: at line 3" $ "C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang.exe" "-fsanitize=address" "-mno-omit-leaf-frame-pointer" "-fno-omit-frame-pointer" "-fno-optimize-sibling-calls" "-gline-tables-only" "-gcodeview" "-gcolumn-info" "-shared-libasan" "-D_MT" "-D_DLL" "-Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames" "-fsanitize-coverage=func" "C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows\coverage-basic.cc" "-o" "test.exe"
command output:
coverage-basic-ce3187.o : error LNK2019: unresolved external symbol sanitizer_cov_trace_pc_guard referenced in function "void cdecl foo(void)" (?foo@@YAXXZ) coverage-basic-ce3187.o : error LNK2019: unresolved external symbol __sanitizer_cov_trace_pc_guard_init referenced in function sancov.module_ctor_trace_pc_guard test.exe : fatal error LNK1120: 2 unresolved externals
command stderr:
clang: warning: argument '-fsanitize-coverage=[func|bb|edge]' is deprecated, use '-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]' instead [-Wdeprecated] clang: error: linker command failed with exit code 1120 (use -v to see invocation)
error: command failed with exit status: 1120
--
Testing: 0 .. FAIL: AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-dll-stdio.cc (4672 of 49878) **** TEST 'AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-dll-stdio.cc' FAILED **** Script:
: 'RUN: at line 4'; rm -rf C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-dll-stdio.cc.tmp && mkdir C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-dll-stdio.cc.tmp && cd C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-dll-stdio.cc.tmp : 'RUN: at line 5'; C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang-cl.exe -fsanitize=address -Wno-deprecated-declarations -WX -D_HAS_EXCEPTIONS=0 -Zi -MD -fsanitize-coverage=func,trace-pc-guard -O0 C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows/dll_host.cc -Fet.exe : 'RUN: at line 6'; C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang-cl.exe -fsanitize=address -Wno-deprecated-declarations -WX -D_HAS_EXCEPTIONS=0 -Zi -MD -fsanitize-coverage=func,trace-pc-guard -LD -O0 C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows\coverage-dll-stdio.cc -Fet.dll : 'RUN: at line 7'; ./t.exe t.dll 2>&1 | FileCheck C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows\coverage-dll-stdio.cc
Exit Code: 1120
Command Output (stdout):
$ ":" "RUN: at line 4" $ "rm" "-rf" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-dll-stdio.cc.tmp" $ "mkdir" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Windows\Output\coverage-dll-stdio.cc.tmp" $ ":" "RUN: at line 5" $ "C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang-cl.exe" "-fsanitize=address" "-Wno-deprecated-declarations" "-WX" "-D_HAS_EXCEPTIONS=0" "-Zi" "-MD" "-fsanitize-coverage=func,trace-pc-guard" "-O0" "C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\Windows/dll_host.cc" "-Fet.exe"
command output:
dll_host-bea811.obj : error LNK2019: unresolved external symbol __sanitizer_cov_trace_pc_guard referenced in function main dll_host-bea811.obj : error LNK2019: unresolved external symbol __sanitizer_cov_trace_pc_guard_init referenced in function sancov.module_ctor_trace_pc_guard t.exe : fatal error LNK1120: 2 unresolved externals
command stderr:
clang-cl: error: linker command failed with exit code 1120 (use -v to see invocation)
error: command failed with exit status: 1120
--
Testing: 0 .. FAIL: AddressSanitizer-x86_64-windows-dynamic :: TestCases/coverage-disabled.cc (4747 of 49878) **** TEST 'AddressSanitizer-x86_64-windows-dynamic :: TestCases/coverage-disabled.cc' FAILED **** Script:
: 'RUN: at line 3'; rm -rf C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir : 'RUN: at line 4'; mkdir -p C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir : 'RUN: at line 6'; C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang.exe -fsanitize=address -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -gline-tables-only -gcodeview -gcolumn-info -shared-libasan -D_MT -D_DLL -Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames -fsanitize-coverage=func C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\coverage-disabled.cc -o C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp : 'RUN: at line 8'; env ASAN_OPTIONS=coverage_direct=0:coverage_dir='"C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir"':verbosity=1 C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp : 'RUN: at line 9'; not C:/b/s/w/ir/cache/vpython/21a792/Scripts/python.exe C:/b/s/w/ir/k/src/third_party/llvm/compiler-rt\lib\sanitizer_common\scripts\sancov.py print C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir/*.sancov 2>&1
Exit Code: 1120
Command Output (stdout):
$ ":" "RUN: at line 3" $ "rm" "-rf" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir" $ ":" "RUN: at line 4" $ "mkdir" "-p" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp-dir" $ ":" "RUN: at line 6" $ "C:/b/s/w/ir/k/src/third_party/llvm-build/Release+Asserts/./bin/clang.exe" "-fsanitize=address" "-mno-omit-leaf-frame-pointer" "-fno-omit-frame-pointer" "-fno-optimize-sibling-calls" "-gline-tables-only" "-gcodeview" "-gcolumn-info" "-shared-libasan" "-D_MT" "-D_DLL" "-Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames" "-fsanitize-coverage=func" "C:\b\s\w\ir\k\src\third_party\llvm\compiler-rt\test\asan\TestCases\coverage-disabled.cc" "-o" "C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp"
command output:
coverage-disabled-865ee1.o : error LNK2019: unresolved external symbol sanitizer_cov_trace_pc_guard referenced in function main coverage-disabled-865ee1.o : error LNK2019: unresolved external symbol sanitizer_cov_trace_pc_guard_init referenced in function sancov.module_ctor_trace_pc_guard C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts\projects\compiler-rt\test\asan\X86_64WindowsDynamicConfig\TestCases\Output\coverage-disabled.cc.tmp : fatal error LNK1120: 2 unresolved externals
command stderr:
clang: warning: argument '-fsanitize-coverage=[func|bb|edge]' is deprecated, use '-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc]' instead [-Wdeprecated] clang: error: linker command failed with exit code 1120 (use -v to see invocation)
error: command failed with exit status: 1120
--
Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. Testing Time: 294.36s
Failing Tests (3): AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-basic.cc AddressSanitizer-x86_64-windows-dynamic :: TestCases/Windows/coverage-dll-stdio.cc AddressSanitizer-x86_64-windows-dynamic :: TestCases/coverage-disabled.cc
Expected Passes : 42784 Expected Failures : 217 Unsupported Tests : 6874 Unexpected Failures: 3
CMake invocation: Running [u'C:\b\s\w\ir\k\src\third_party\depot_tools\win_toolchain\vs_files\818a152b3f1da991c1725d85be19a0f27af6bab4\win_sdk\bin\SetEnv.cmd', '/x64', '&&', 'cmake', '-GNinja', '-DCMAKE_BUILD_TYPE=Release', '-DLLVM_ENABLE_ASSERTIONS=OFF', '-DLLVM_ENABLE_PROJECTS=clang;compiler-rt;lld;chrometools', '-DLLVM_TARGETS_TO_BUILD=AArch64;ARM;Mips;PowerPC;SystemZ;WebAssembly;X86', '-DLLVM_ENABLE_PIC=OFF', '-DLLVM_ENABLE_UNWIND_TABLES=OFF', '-DLLVM_ENABLE_TERMINFO=OFF', '-DCLANG_PLUGIN_SUPPORT=OFF', '-DCLANG_ENABLE_STATIC_ANALYZER=OFF', '-DCLANG_ENABLE_ARCMT=OFF', '-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON', '-DBUG_REPORT_URL=https://crbug.com and run tools/clang/scripts/upload_crash.py (only works inside Google) which will upload a report', '-DCOMPILER_RT_USE_LIBCXX=NO', '-DLLVM_USE_CRT_RELEASE=MT', '-DCMAKE_C_COMPILER=C:/b/s/w/ir/k/src/third_party/llvm-bootstrap-install/bin/clang-cl.exe', '-DCMAKE_CXX_COMPILER=C:/b/s/w/ir/k/src/third_party/llvm-bootstrap-install/bin/clang-cl.exe', '-DCMAKE_LINKER=C:/b/s/w/ir/k/src/third_party/llvm-bootstrap-install/bin/lld-link.exe', '-DCOMPILER_RT_BUILD_CRT=OFF', '-DCOMPILER_RT_BUILD_LIBFUZZER=ON', '-DCOMPILER_RT_BUILD_PROFILE=ON', '-DCOMPILER_RT_BUILD_SANITIZERS=ON', '-DCOMPILER_RT_BUILD_XRAY=OFF', '-DCOMPILER_RT_BUILD_BUILTINS=OFF', '-DLLVM_ENABLE_THREADS=OFF', '-DCMAKE_C_FLAGS=/Zi /GS-', '-DCMAKE_CXX_FLAGS=/Zi /GS-', '-DCMAKE_EXE_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF', '-DCMAKE_SHARED_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF', '-DCMAKE_MODULE_LINKER_FLAGS=/DEBUG /OPT:REF /OPT:ICF', '-DCMAKE_INSTALL_PREFIX=C:\b\s\w\ir\k\src\third_party\llvm-build\Release+Asserts', '-DCHROMIUM_TOOLS_SRC=C:\b\s\w\ir\k\src\tools\clang', '-DCHROMIUM_TOOLS=blink_gc_plugin;translation_unit;plugins', 'C:\b\s\w\ir\k\src\third_party\llvm\llvm']
This is from https://chromium-review.googlesource.com/c/chromium/src/+/1636672