Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lld-link: duplicate symbol: ___chkstk_ms with addSharedLibrary #15107

Closed
DeadRobotDev opened this issue Mar 29, 2023 · 18 comments
Closed

lld-link: duplicate symbol: ___chkstk_ms with addSharedLibrary #15107

DeadRobotDev opened this issue Mar 29, 2023 · 18 comments
Labels
bug Observed behavior contradicts documented or intended behavior os-windows
Milestone

Comments

@DeadRobotDev
Copy link

Zig Version

0.11.0-dev.2298+5d63d1115

Steps to Reproduce and Observed Behavior

Operating System: Windows 10 Home 19045.2728

  1. Run zig build

If you replace addSharedLibrary with addStaticLibrary, there are no errors.

zig build-exe sandbox Debug native: error: the following command failed with 1 compilation errors:
C:\Users\Personal\Programs\bin\zig\0.11.0-dev.2298+5d63d1115\files\zig.exe build-exe W:\c\duplicate_symbol_repro\source\main.c W:\c\duplicate_symbol_repro\zig-cache\o\068335d453b8dd6ae99ff5e57fc2a431\lib.lib -lc --cache-dir W:\c\duplicate_symbol_repro\zig-
cache --global-cache-dir C:\Users\Personal\AppData\Local\zig --name sandbox --enable-cache --listen=-
Build Summary: 1/4 steps succeeded; 1 failed (disable with -fno-summary)
install transitive failure
+- install sandbox transitive failure
   +- zig build-exe sandbox Debug native 1 errors
      +- zig build-lib lib Debug native success 1s MaxRSS:32M
error: lld-link: duplicate symbol: ___chkstk_ms
    note: defined at compiler_rt.lib(compiler_rt.lib.obj)
    note: defined at lib.dll
// build.zig
const std = @import("std");

pub fn build(b: *std.Build) !void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardOptimizeOption(.{});

    const lib = b.addSharedLibrary(.{
        .name = "lib",
        .target = target,
        .optimize = mode,
    });
    lib.addCSourceFile("source/lib.c", &.{});
    lib.linkLibC();

    const exe = b.addExecutable(.{
        .name = "sandbox",
        .target = target,
        .optimize = mode,
    });
    exe.addCSourceFile("source/main.c", &.{});
    exe.linkLibC();
    exe.linkLibrary(lib);
    exe.install();

    const run_cmd = exe.run();
    run_cmd.step.dependOn(b.getInstallStep());

    if (b.args) |args| {
        run_cmd.addArgs(args);
    }

    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
}
// source/main.c
#include "lib.h"

int
main(void)
{
	greeter("Fletcher");

	return 0;
}
// source/lib.h
#if !defined(LIB_H)
#define LIB_H

void greeter(const char* name);

#endif // LIB_H
// source/lib.c
#include "lib.h"

#include <stdio.h>

void greeter(const char* name)
{
	printf("Hello, %s!\n", name);
}

Expected Behavior

Compile with no warnings and errors.

@DeadRobotDev DeadRobotDev added the bug Observed behavior contradicts documented or intended behavior label Mar 29, 2023
@kubkon
Copy link
Member

kubkon commented Mar 31, 2023

Does it also happen when building an executable rather than a DLL? If so, we are probably re-exporting the offending symbols one too many times in our compiler-rt implementation.

@kubkon kubkon added this to the 0.11.0 milestone Mar 31, 2023
@DeadRobotDev
Copy link
Author

If I build the DLL as a separate executable, no.

In the current build script, I am linking the library to an executable. And that is what causes the issue.

@kcbanner
Copy link
Contributor

kcbanner commented Apr 17, 2023

I think I've gotten to the bottom of this. It comes down to behavior added here https://reviews.llvm.org/D38760 to LLD, which causes all symbols to be exported if none are explicitly marked for export. This is a mingw thing, link.exe doesn't do this.

This is the function that does this in COFF/Driver.cpp:

// In MinGW, if no symbols are chosen to be exported, then all symbols are
// automatically exported by default. This behavior can be forced by the
// -export-all-symbols option, so that it happens even when exports are
// explicitly specified. The automatic behavior can be disabled using the
// -exclude-all-symbols option, so that lld-link behaves like link.exe rather
// than MinGW in the case that nothing is explicitly exported.
void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
    ...

So, on *-windows-gnu, if you don't use __declspec(dllexport) at all, then all symbols get exported, which includes ___chkstk__ms. See the full comparison below.

If using *-windows-msvc then the link.exe behaviour is replicated (nothing exported if no exports are explicit).

It seems there are a couple ways we could solve this issue:

  • Mark the compiler_rt symbols as not being exported when included in a DLL, although I'm not sure how this would look.
  • Pass -exclude-all-symbols to lld-link. I tested this and it replicates the link.exe behaviour. If nothing is explictly exported, then no symbols are exported. If explicit exports are used, only things explicitly exported are exported. However, this would change behaviour from the default mingw behaviour.

I can work on a PR for this, but it would be great to get your feedback on which direction to go @kubkon

Building the DLL with MSVC:

c:\cygwin64\home\kcbanner\temp\chkstk>dumpbin /EXPORTS zig-out\bin\msvc-shared.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30141.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file zig-out\bin\msvc-shared.dll

File Type: DLL

  Section contains the following exports for msvc-shared.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001090 add
          2    1 00001000 add_mult

  Summary

        2000 .data
        1000 .pdata
        9000 .rdata
        1000 .reloc
        C000 .text
        1000 _RDATA

Building the DLL with zig build, using __declspec(dllexport) in the C code

c:\cygwin64\home\kcbanner\temp\chkstk>dumpbin /EXPORTS zig-out\bin\shared.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30141.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file zig-out\bin\shared.dll

File Type: DLL

  Section contains the following exports for shared.dll

    00000000 characteristics
           0 time date stamp
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001190 add = add
          2    1 00001000 add_mult = add_mult

  Summary

        1000 .buildid
        2000 .data
        2000 .pdata
        5000 .rdata
        1000 .reloc
       21000 .text
        1000 .tls

Building the DLL with zig, not using __declspec(dllexport) in the c code

c:\cygwin64\home\kcbanner\temp\chkstk>dumpbin /exports zig-out\bin\shared.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30141.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file zig-out\bin\shared.dll

File Type: DLL

  Section contains the following exports for shared.dll

    00000000 characteristics
           0 time date stamp
        0.00 version
           1 ordinal base
          49 number of functions
          49 number of names

    ordinal hint RVA      name

          1    0 000010C0 _CRT_INIT = _CRT_INIT
          2    1 00028030 _CRT_MT = _CRT_MT
          3    2 00002090 _FindPESection = _FindPESection
          4    3 000020E0 _FindPESectionByName = _FindPESectionByName
          5    4 00002220 _FindPESectionExec = _FindPESectionExec
          6    5 00002290 _GetPEImageBase = _GetPEImageBase
          7    6 000022D0 _IsNonwritableInCurrentImage = _IsNonwritableInCurrentImage
          8    7 00002060 _ValidateImageBase = _ValidateImageBase
          9    8 00024EC0 __RUNTIME_PSEUDO_RELOC_LIST_END__ = __RUNTIME_PSEUDO_RELOC_LIST_END__
         10    9 00024EC0 __RUNTIME_PSEUDO_RELOC_LIST__ = __RUNTIME_PSEUDO_RELOC_LIST_END__
         11    A 00003AF0 ___chkstk_ms = ___chkstk_ms
         12    B 00001D80 ___w64_mingwthr_add_key_dtor = ___w64_mingwthr_add_key_dtor
         13    C 00001E00 ___w64_mingwthr_remove_key_dtor = ___w64_mingwthr_remove_key_dtor
         14    D 00001520 __do_global_ctors = __do_global_ctors
         15    E 000014D0 __do_global_dtors = __do_global_dtors
         16    F 00001620 __dyn_tls_init = __dyn_tls_init
         17   10 000220B8 __dyn_tls_init_callback = __dyn_tls_init_callback
         18   11 00001590 __main = __main
         19   12 000021E0 __mingw_GetSectionCount = __mingw_GetSectionCount
         20   13 00002170 __mingw_GetSectionForAddress = __mingw_GetSectionForAddress
         21   14 00001E90 __mingw_TLScallback = __mingw_TLScallback
         22   15 00028088 __mingw_app_type = __mingw_app_type
         23   16 00002360 __mingw_enum_import_library_names = __mingw_enum_import_library_names
         24   17 0002807C __mingw_initltsdrot_force = __mingw_initltsdrot_force
         25   18 00028080 __mingw_initltsdyn_force = __mingw_initltsdyn_force
         26   19 00028084 __mingw_initltssuo_force = __mingw_initltssuo_force
         27   1A 00028000 __mingw_module_is_dll = __mingw_module_is_dll
         28   1B 00028010 __native_dllmain_reason = __native_dllmain_reason
         29   1C 00028070 __native_startup_lock = __native_startup_lock
         30   1D 00028068 __native_startup_state = __native_startup_state
         31   1E 00028014 __native_vcclrit_reason = __native_vcclrit_reason
         32   1F 00001690 __tlregdtor = __tlregdtor
         33   20 00024EC0 __xc_a = __RUNTIME_PSEUDO_RELOC_LIST_END__
         34   21 00024EC8 __xc_z = __xc_z
         35   22 00024EE0 __xi_a = __xi_a
         36   23 00024EF0 __xi_z = __xi_z
         37   24 00024EF8 __xl_a = __xl_a
         38   25 00024F00 __xl_c = __xl_c
         39   26 00024F08 __xl_d = __xl_d
         40   27 00024F10 __xl_z = __xl_z
         41   28 00003AB0 _alloca = _alloca
         42   29 0002C008 _tls_end = _tls_end
         43   2A 00028078 _tls_index = _tls_index
         44   2B 0002C000 _tls_start = _tls_start
         45   2C 00022090 _tls_used = _tls_used
         46   2D 00001060 add = add
         47   2E 00001000 add_mult = add_mult
         48   2F 00021A10 fpreset = _fpreset
         49   30 00024EE8 pcinit = pcinit

  Summary

        1000 .buildid
        2000 .data
        2000 .pdata
        5000 .rdata
        1000 .reloc
       21000 .text
        1000 .tls

@kubkon
Copy link
Member

kubkon commented May 31, 2023

I haven't looked in detail into this but here's my main observation with a suggestion of exploring the problem space a little more. The collision happens when trying to link an executable with a shared library. When linking executable, regardless if linking with a shared object or not, we always provide a static lib of compiler-rt symbols each marked as weak so that they can easily be overwritten by user's definition if available. Here, for some reason, we get a collision. When creating a shared object all compiler-rt symbols were re-exported (and their binding promoted to strong as is customary I believe tho not sure if required, we could investigate that in our self-hosted linkers). So we have a situation like this:

$ link main.o -llib -L. libcompiler_rt.a

Symbols in libcompiler_rt.a are still supposed to be exported as weak, therefore why is the linker reporting a collision if it should take the stronger definition? If we rearrange the inputs, it becomes more tricky, but I would still not expect any collisions unless I am missing something vital here.

None of this is satisfactory as I don't want the shared object to re-export compiler-rt symbols ever. @kcbanner would you be up for some more investigation here? The next step would be to figure out why the collision is actually happening in the linker. I would also like to learn how the linker handles symbol binding promotion, in particular upgrading weak to strong. I realise it would have been so much simpler to reason about and fix if we had a working traditional COFF linker but sadly we are not there yet, and I currently don't have the cycles to spare - too deep in ELF currently. Also, I am happy to push this issue back to 0.12 milestone - I'd rather we solved it properly the first time round than put a bandaid on it and let it burst again in the near future.

Also, does this problem also repro when build a shared object from Zig sources and not C?

@kubkon
Copy link
Member

kubkon commented May 31, 2023

For comparison, it doesn't look like this problem happens with ELF:

$ zig cc lib.c -shared -o liblib.so --verbose
clang version 16.0.1 (https://github.com/llvm/llvm-project cd89023f797900e4492da58b7bed36f702120011)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/kubkon/dev/examples/shared
 (in-process)
 "/home/kubkon/opt/bin/zig" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -main-file-name lib.c -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -mllvm -treat-scalable-fixed-error-as-warning -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -v -fcoverage-compilation-dir=/home/kubkon/dev/examples/shared -nostdsysteminc -nobuiltininc -resource-dir /home/kubkon/opt/lib/clang/16 -dependency-file /home/kubkon/.cache/zig/tmp/1baa910638a61bf9-lib.o.d -MT /home/kubkon/.cache/zig/tmp/1baa910638a61bf9-lib.o -sys-header-deps -MV -isystem /home/kubkon/opt/lib/zig/include -isystem /nix/store/dwsi3wsqpqm0hpzdm9fsxc7q732p9xwi-glibc-2.34-210-dev/include -isystem /nix/store/9bj5frjj62k1vqk68kk7rx0zxm2ip7mp-lldb-15.0.7-dev/include -isystem /nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/include -isystem /nix/store/pdllykvxhfqjpkn4samm89i61h613v9n-qemu-7.0.0/include -isystem /nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/include -isystem /nix/store/579lkbash00ylhs8yaqfpvgnfrhjv67a-zlib-1.2.12-dev/include -isystem /nix/store/vakcc74vp08y1rb1rb1cla6885ayklk3-zstd-1.5.2-dev/include -isystem /nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/include -isystem /nix/store/9bj5frjj62k1vqk68kk7rx0zxm2ip7mp-lldb-15.0.7-dev/include -isystem /nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/include -isystem /nix/store/pdllykvxhfqjpkn4samm89i61h613v9n-qemu-7.0.0/include -isystem /nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/include -isystem /nix/store/579lkbash00ylhs8yaqfpvgnfrhjv67a-zlib-1.2.12-dev/include -isystem /nix/store/vakcc74vp08y1rb1rb1cla6885ayklk3-zstd-1.5.2-dev/include -isystem /nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/include -D __GLIBC_MINOR__=34 -D _DEBUG -source-date-epoch 315532800 -O0 -fdebug-compilation-dir=/home/kubkon/dev/examples/shared -ferror-limit 19 -fsanitize=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound -fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound -fno-sanitize-memory-param-retval -fno-sanitize-address-use-odr-indicator -stack-protector 2 -stack-protector-buffer-size 4 -fgnuc-version=4.2.1 -fcolor-diagnostics -fno-spell-checking -target-cpu znver1 -target-feature -16bit-mode -target-feature -32bit-mode -target-feature -3dnow -target-feature -3dnowa -target-feature +64bit -target-feature +adx -target-feature +aes -target-feature +allow-light-256-bit -target-feature -amx-bf16 -target-feature -amx-fp16 -target-feature -amx-int8 -target-feature -amx-tile -target-feature +avx -target-feature +avx2 -target-feature -avx512bf16 -target-feature -avx512bitalg -target-feature -avx512bw -target-feature -avx512cd -target-feature -avx512dq -target-feature -avx512er -target-feature -avx512f -target-feature -avx512fp16 -target-feature -avx512ifma -target-feature -avx512pf -target-feature -avx512vbmi -target-feature -avx512vbmi2 -target-feature -avx512vl -target-feature -avx512vnni -target-feature -avx512vp2intersect -target-feature -avx512vpopcntdq -target-feature -avxifma -target-feature -avxneconvert -target-feature -avxvnni -target-feature -avxvnniint8 -target-feature +bmi -target-feature +bmi2 -target-feature +branchfusion -target-feature -cldemote -target-feature +clflushopt -target-feature +clwb -target-feature +clzero -target-feature +cmov -target-feature -cmpccxadd -target-feature +crc32 -target-feature +cx16 -target-feature +cx8 -target-feature -enqcmd -target-feature -ermsb -target-feature +f16c -target-feature -false-deps-getmant -target-feature -false-deps-lzcnt-tzcnt -target-feature -false-deps-mulc -target-feature -false-deps-mullq -target-feature -false-deps-perm -target-feature -false-deps-popcnt -target-feature -false-deps-range -target-feature -fast-11bytenop -target-feature +fast-15bytenop -target-feature -fast-7bytenop -target-feature +fast-bextr -target-feature -fast-gather -target-feature -fast-hops -target-feature +fast-lzcnt -target-feature +fast-movbe -target-feature +fast-scalar-fsqrt -target-feature +fast-scalar-shift-masks -target-feature -fast-shld-rotate -target-feature -fast-variable-crosslane-shuffle -target-feature +fast-variable-perlane-shuffle -target-feature +fast-vector-fsqrt -target-feature -fast-vector-shift-masks -target-feature +fma -target-feature -fma4 -target-feature +fsgsbase -target-feature -fsrm -target-feature +fxsr -target-feature -gfni -target-feature -harden-sls-ijmp -target-feature -harden-sls-ret -target-feature -hreset -target-feature -idivl-to-divb -target-feature -idivq-to-divl -target-feature -invpcid -target-feature -kl -target-feature -lea-sp -target-feature -lea-uses-ag -target-feature -lvi-cfi -target-feature -lvi-load-hardening -target-feature -lwp -target-feature +lzcnt -target-feature -macrofusion -target-feature +mmx -target-feature +movbe -target-feature -movdir64b -target-feature -movdiri -target-feature +mwaitx -target-feature +nopl -target-feature -pad-short-functions -target-feature +pclmul -target-feature -pconfig -target-feature -pku -target-feature +popcnt -target-feature -prefer-128-bit -target-feature -prefer-256-bit -target-feature -prefer-mask-registers -target-feature -prefetchi -target-feature -prefetchwt1 -target-feature +prfchw -target-feature -ptwrite -target-feature -raoint -target-feature +rdpid -target-feature -rdpru -target-feature +rdrnd -target-feature +rdseed -target-feature -retpoline -target-feature -retpoline-external-thunk -target-feature -retpoline-indirect-branches -target-feature -retpoline-indirect-calls -target-feature -rtm -target-feature +sahf -target-feature +sbb-dep-breaking -target-feature -serialize -target-feature -seses -target-feature -sgx -target-feature +sha -target-feature -shstk -target-feature -slow-3ops-lea -target-feature -slow-incdec -target-feature -slow-lea -target-feature -slow-pmaddwd -target-feature -slow-pmulld -target-feature +slow-shld -target-feature -slow-two-mem-ops -target-feature -slow-unaligned-mem-16 -target-feature -slow-unaligned-mem-32 -target-feature -soft-float -target-feature +sse -target-feature +sse2 -target-feature +sse3 -target-feature +sse4.1 -target-feature +sse4.2 -target-feature +sse4a -target-feature -sse-unaligned-mem -target-feature +ssse3 -target-feature -tagged-globals -target-feature -tbm -target-feature -tsxldtrk -target-feature -uintr -target-feature -use-glm-div-sqrt-costs -target-feature -use-slm-arith-costs -target-feature -vaes -target-feature -vpclmulqdq -target-feature +vzeroupper -target-feature -waitpkg -target-feature +wbnoinvd -target-feature -widekl -target-feature +x87 -target-feature -xop -target-feature +xsave -target-feature +xsavec -target-feature +xsaveopt -target-feature +xsaves -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/kubkon/.cache/zig/tmp/1baa910638a61bf9-lib.o -x c lib.c
clang -cc1 version 16.0.1 based upon LLVM 16.0.1 default target x86_64-unknown-linux-gnu
ignoring duplicate directory "/nix/store/9bj5frjj62k1vqk68kk7rx0zxm2ip7mp-lldb-15.0.7-dev/include"
ignoring duplicate directory "/nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/include"
ignoring duplicate directory "/nix/store/pdllykvxhfqjpkn4samm89i61h613v9n-qemu-7.0.0/include"
ignoring duplicate directory "/nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/include"
ignoring duplicate directory "/nix/store/579lkbash00ylhs8yaqfpvgnfrhjv67a-zlib-1.2.12-dev/include"
ignoring duplicate directory "/nix/store/vakcc74vp08y1rb1rb1cla6885ayklk3-zstd-1.5.2-dev/include"
ignoring duplicate directory "/nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/kubkon/opt/lib/zig/include
 /nix/store/dwsi3wsqpqm0hpzdm9fsxc7q732p9xwi-glibc-2.34-210-dev/include
 /nix/store/9bj5frjj62k1vqk68kk7rx0zxm2ip7mp-lldb-15.0.7-dev/include
 /nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/include
 /nix/store/pdllykvxhfqjpkn4samm89i61h613v9n-qemu-7.0.0/include
 /nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/include
 /nix/store/579lkbash00ylhs8yaqfpvgnfrhjv67a-zlib-1.2.12-dev/include
 /nix/store/vakcc74vp08y1rb1rb1cla6885ayklk3-zstd-1.5.2-dev/include
 /nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/include
End of search list.
LLD Link... ld.lld --error-limit=0 -O0 --gc-sections --eh-frame-hdr -znow -m elf_x86_64 -shared -o liblib.so /nix/store/scd5n7xsn0hh0lvhhnycr9gx0h8xfzsl-glibc-2.34-210/lib/crti.o -rpath /nix/store/mj25wmr1j5xj84n550lwabwmg0g2cxar-nix-shell/lib64 -rpath /nix/store/mj25wmr1j5xj84n550lwabwmg0g2cxar-nix-shell/lib -L /nix/store/anwb3ljfsn0pv0d0s0xxnx123flc7fdg-lldb-15.0.7-lib/lib -L /nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/lib -L /nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/lib -L /nix/store/q7k32ydcqlram7f0l6b1y2c4cs07765y-zlib-1.2.12/lib -L /nix/store/l7j222k357y8fbh9gj283mv7s1nh1vrx-zstd-1.5.2/lib -L /nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/lib -L /nix/store/anwb3ljfsn0pv0d0s0xxnx123flc7fdg-lldb-15.0.7-lib/lib -L /nix/store/s1283aqd7i2spsq66c1w98mgijyjaycb-gdb-12.1/lib -L /nix/store/xpwwghl72bb7f48m51amvqiv1l25pa01-python3-3.9.13/lib -L /nix/store/q7k32ydcqlram7f0l6b1y2c4cs07765y-zlib-1.2.12/lib -L /nix/store/l7j222k357y8fbh9gj283mv7s1nh1vrx-zstd-1.5.2/lib -L /nix/store/q2jrx19954l8qs8d6li8f6i27pbs6ykj-wasmtime-9.0.2-dev/lib -L /nix/store/scd5n7xsn0hh0lvhhnycr9gx0h8xfzsl-glibc-2.34-210/lib -dynamic-linker /nix/store/scd5n7xsn0hh0lvhhnycr9gx0h8xfzsl-glibc-2.34-210/lib/ld-linux-x86-64.so.2 /home/kubkon/.cache/zig/o/f5adcdd7a24666dd0b134420b164ad79/lib.o --as-needed -lm -lpthread -lc -ldl -lrt -lutil /home/kubkon/.cache/zig/o/eff376fbda2bc5f9441ee6d2d2de6780/libcompiler_rt.a /nix/store/scd5n7xsn0hh0lvhhnycr9gx0h8xfzsl-glibc-2.34-210/lib/crtn.o
$ readelf -s liblib.so                                                                                                                                                                                                                                                     Wed 31 May 2023 11:22:00 CEST

Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (2)
     3: 0000000000001430    36 FUNC    GLOBAL DEFAULT   14 greeter

Symbol table '.symtab' contains 9 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS lib.c
     2: 000000000000140c     0 FUNC    LOCAL  HIDDEN    12 _init
     3: 0000000000001424     0 FUNC    LOCAL  HIDDEN    13 _fini
     4: 00000000000025f8     0 NOTYPE  LOCAL  HIDDEN    18 _GLOBAL_OFFSET_TABLE_
     5: 0000000000002480     0 NOTYPE  LOCAL  HIDDEN    16 _DYNAMIC
     6: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     7: 0000000000001430    36 FUNC    GLOBAL DEFAULT   14 greeter
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf                                                                                                                                                                                

@andrewrk andrewrk modified the milestones: 0.11.0, 0.11.1 Jul 22, 2023
@kristoff-it
Copy link
Member

@marler8997 and I hit this while working on a build script for Orca (https://github.com/allyourcodebase/orca)

@linusg
Copy link
Contributor

linusg commented Nov 19, 2023

Doesn't seem to be limited to shared libraries, I also hit this while trying to link a Rust-built static library:

error: lld-link: duplicate symbol: ___chkstk_ms
    note: defined at src/x86_64.rs:18
    note:            libicu_capi_staticlib.a(compiler_builtins-888a947cf30049df.compiler_builtins.b1c7720c06bbefd5-cgu.3.rcgu.o)
    note: defined at compiler_rt.lib(compiler_rt.lib.obj)

@linusg
Copy link
Contributor

linusg commented Dec 9, 2023

And once more, this time due to compiler_rt.lib being indirectly included via another Zig-built lib (https://github.com/kassane/winpthreads-zigbuild):

error: lld-link: duplicate symbol: ___chkstk_ms
    note: defined at winpthreads.lib(compiler_rt.obj)
    note: defined at src/x86_64.rs:18
    note:            libicu_capi_staticlib.a(compiler_builtins-73257fe88da021c4.compiler_builtins.c3351aefbf3c2e22-cgu.3.rcgu.o)

@hammerfunctor
Copy link

Also met this when I try to build djvulibre using zig c++:

wget http://downloads.sourceforge.net/djvu/djvulibre-3.5.28.tar.gz
tar xzf djvulibre-3.5.28.tar.gz && cd djvulibre-3.5.28
./configure CC="zig cc" CXX="zig c++ -std=c++11" AR="zig ar" RANLIB="zig ranlib"
make

Log:

...
./GBitmap.h:623:3: warning: 'register' storage class specifier is deprecated and incompatible with C++17 [-Wdeprecated-register]
  register int z=*data++;
  ^~~~~~~~~
./GBitmap.h:631:3: warning: 'register' storage class specifier is deprecated and incompatible with C++17 [-Wdeprecated-register]
  register int z=*data++;
  ^~~~~~~~~
2 warnings generated.
  CXX      libdjvulibre_la-debug.lo
  CXX      libdjvulibre_la-miniexp.lo
  CXXLD    libdjvulibre.la
LLD Link... ld.lld: error: duplicate symbol: _init
>>> defined at /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/crti.o:(.init+0x0)
>>> defined at crti.S:66 (/usr/lib/zig/libc/glibc/sysdeps/x86_64/crti.S:66)
>>>            /home/huzf/.cache/zig/o/905667224a4a4a5efcdacd5278c5af4b/crti.o:(.init+0x0)

ld.lld: error: duplicate symbol: _fini
>>> defined at /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/crti.o:(.fini+0x0)
>>> defined at crti.S:84 (/usr/lib/zig/libc/glibc/sysdeps/x86_64/crti.S:84)
>>>            /home/huzf/.cache/zig/o/905667224a4a4a5efcdacd5278c5af4b/crti.o:(.fini+0x0)
make[2]: *** [Makefile:584: libdjvulibre.la] Error 1
make[2]: Leaving directory '/home/huzf/zigs/djvulibre-3.5.28/libdjvu'
make[1]: *** [Makefile:429: all-recursive] Error 1
make[1]: Leaving directory '/home/huzf/zigs/djvulibre-3.5.28'
make: *** [Makefile:361: all] Error 2

@dcov
Copy link

dcov commented Feb 11, 2024

Also encountering this when linking wasmtime on windows:

error: lld-link: duplicate symbol: ___chkstk_ms
    note: defined at src/x86_64.rs:18
    note:            libwasmtime.a(compiler_builtins-d13d1e3b0b541614.compiler_builtins.5d0826b571c4f15c-cgu.134.rcgu.o)
    note: defined at compiler_rt.lib(compiler_rt.lib.obj)

@rsepassi
Copy link
Contributor

rsepassi commented Feb 26, 2024

Like @linusg and @dcov, hitting this when using Zig as the cross-compiler and linker for Rust. Temporary workaround for the crt symbols is to manually filter out the rust-provided crt object files from the link command. But I don't have a workaround for the ___chkstk_ms issue when targeting windows (any ideas?).

@maxxnino
Copy link

I attempted to create a shared library, but encountered an error when running zig build. I’m currently using Windows 11 and zig version 0.12.0-dev.3212+40e64245f.

zig build                       
install
└─ install zlo
   └─ zig build-lib zlo Debug native 1 errors
error: lld-link: ___chkstk_ms was replaced
error: the following command failed with 1 compilation errors:
//build.zig
pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const lib = b.addSharedLibrary(.{
        .name = "zlo",
        .root_source_file = .{ .path = "src/root.zig" },
        .target = target,
        .optimize = optimize,
    });
    const ziglua = b.dependency("ziglua", .{
        .target = target,
        .optimize = optimize,
        .lang = .lua53,
        .shared = true,
    });
    lib.root_module.addImport("ziglua", ziglua.module("ziglua"));
    b.installArtifact(lib);
}
//src/root.zig
const ziglua = @import("ziglua");
fn zlo(lua: *ziglua.Lua) i32 {
    lua.newLib(&.{
        .{ .name = "add", .func = ziglua.wrap(add) },
    });
    return 1;
}
fn add(lua: *ziglua.Lua) i32 {
    const a = lua.toInteger(1) catch 0;
    const b = lua.toInteger(2) catch 0;
    lua.pushInteger(a + b);
    return 1;
}
comptime {
    _ = ziglua.exportFn("zlo", zlo);
}

@andrewrk andrewrk modified the milestones: 0.13.0, 0.12.0 Mar 14, 2024
@andrewrk andrewrk modified the milestones: 0.12.0, 0.13.0 Mar 22, 2024
@rsepassi
Copy link
Contributor

So I thought I should be able to work around this by simply asking zig cc to skip including compiler_rt.lib since as far as I can tell, it's including it automatically and I believe Rust already takes care of all the rt facilities it needs. I would have expected -nostdlib and/or -nodefaultlibs to skip the inclusion of compiler_rt but that doesn't seem to work; I get the same error.

Bug or intended?

Also, @kubkon, you mentioned that the compiler_rt symbols should have weak linkage, but they're marked with strong linkage here:

@export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage });

Bug or intended?

@rsepassi
Copy link
Contributor

rsepassi commented Apr 2, 2024

Hacky workaround for the rust case is to unpack the rust rlib (ar x), rm the object file that contains __chkstk_ms, repack the library ar rcs, and replace it in the linker command line. Ugly but works.

@juliannoble
Copy link
Contributor

juliannoble commented Apr 10, 2024

I encountered the ___chkstk_ms duplicate symbol when trying to build zlib for windows.
In the specific case of zlib - defining ZLIB_DLL adds a dllexport attribute
(hint taken from https://mingw-users.narkive.com/Mu0lTkFW/all-symbols-exported-from-shared-library regarding qualifying any symbol with dllexport stopping all being exported by default)
Anyway - I'm generally grasping at straws with all this stuff - but the above flag allowed me to build an exe linked to the shared lib and it seems to work.
(edit: further reading suggests it's probably not a good idea to build zlib on windows anyway and the recommendation is to use the prebuilt zlib1.dll from the zlib website. That goes against the grain .. but anyway, interesting exercise)

rsepassi added a commit to rsepassi/zig that referenced this issue May 31, 2024
@kubkon mentioned that `compiler_rt` symbols should have weak linkage, but that wasn't the case for `__chkstk_ms` which was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

ziglang#15107
andrewrk pushed a commit to rsepassi/zig that referenced this issue Jul 11, 2024
@kubkon mentioned that `compiler_rt` symbols should have weak linkage, but that wasn't the case for `__chkstk_ms` which was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

ziglang#15107
andrewrk pushed a commit that referenced this issue Jul 11, 2024
* Update `__chkstk_ms` to have weak linkage

`__chkstk_ms` was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

#15107

* Update stack_probe.zig to weak linkage for all symbols
@linusg
Copy link
Contributor

linusg commented Jul 12, 2024

I can confirm this is fixed for me by #20138 🎉

@Vexu Vexu closed this as completed Jul 15, 2024
eric-saintetienne pushed a commit to eric-saintetienne/zig that referenced this issue Jul 16, 2024
* Update `__chkstk_ms` to have weak linkage

`__chkstk_ms` was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

ziglang#15107

* Update stack_probe.zig to weak linkage for all symbols
SammyJames pushed a commit to SammyJames/zig that referenced this issue Aug 7, 2024
* Update `__chkstk_ms` to have weak linkage

`__chkstk_ms` was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

ziglang#15107

* Update stack_probe.zig to weak linkage for all symbols
igor84 pushed a commit to igor84/zig that referenced this issue Aug 11, 2024
* Update `__chkstk_ms` to have weak linkage

`__chkstk_ms` was causing conflicts during linking in some circumstances (specifically with linking object files from Rust sources). This PR switches `__chkstk_ms` to have weak linkage.

ziglang#15107

* Update stack_probe.zig to weak linkage for all symbols
@delta1024
Copy link

Hello,
I am currently converting lua to a build.zig and when i run the following command:

zig build -Dtarget=x86_64-windows

I get the following output:

install
└─ install lua
   └─ zig build-exe lua Debug x86_64-windows 1 errors
error: lld-link: duplicate symbol: ___chkstk_ms
    note: defined at /usr/lib/zig/compiler_rt/stack_probe.zig:261
    note:            compiler_rt.lib(compiler_rt.lib.obj)
    note: defined at lua.dll
error: the following command failed with 1 compilation errors:
/usr/bin/zig build-exe -cflags -std=gnu99 -Wall -Wextra -- /home/jake/.cache/zig/p/12206df90729936e110f5d2574437be370fc4367b5f44afcc77749ac421547bc8ff0/src/lua.c /home/jake/code/packages/zig/liblua/.zig-cache/o/09a3141b0364d26b43f51cd45fb0f76a/lua.lib -ODebug -target x86_64-windows -mcpu baseline -I /home/jake/.cache/zig/p/12206df90729936e110f5d2574437be370fc4367b5f44afcc77749ac421547bc8ff0/src -I /home/jake/code/packages/zig/liblua/.zig-cache/o/c81292f59dbba72e6461cecb828656d6 -DLUA_BUILD_AS_DLL=1 -Mroot -lc --cache-dir /home/jake/code/packages/zig/liblua/.zig-cache --global-cache-dir /home/jake/.cache/zig --name lua --listen=- 
Build Summary: 8/11 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install lua transitive failure
   └─ zig build-exe lua Debug x86_64-windows 1 errors
error: the following build command failed with exit code 1:
/home/jake/code/packages/zig/liblua/.zig-cache/o/7ee906c05eadb76ad4b1becb4b8c0fc8/build /usr/bin/zig /home/jake/code/packages/zig/liblua /home/jake/code/packages/zig/liblua/.zig-cache /home/jake/.cache/zig --seed 0xbc12e33f -Zbc4cf8e3a16c8b63 -Dtarget=x86_64-windows

Build.zig.zon:

.{
    .name = "lua",

    .version = "5.4.7",

    .dependencies = .{
        .lua = .{
            .url = "https://www.lua.org/ftp/lua-5.4.7.tar.gz",
            .hash = "12206df90729936e110f5d2574437be370fc4367b5f44afcc77749ac421547bc8ff0",
        },
    },

    .paths = .{
        "build.zig",
        "build.zig.zon",
        "LICENSE",
        "README.md",
    },
}

Build.zig

const std = @import("std");
const Build = std.Build;
const StringList = std.ArrayList([]const u8);
const ResolvedTarget = Build.ResolvedTarget;
const OptimizeMode = std.builtin.OptimizeMode;
const version = std.SemanticVersion{
    .major = 5,
    .minor = 4,
    .patch = 7,
};
const lib_name = "lua";
const exe_name = lib_name;
const compiler_name = "luac";

pub fn build(b: *Build) !void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{ .preferred_optimize_mode = .ReleaseFast });

    const build_shared = b.option(bool, "shared", "build as shared library") orelse target.result.isMinGW();
    const use_readline =
        if (target.result.os.tag == .linux)
        b.option(bool, "use_readline", "readline support for linux") orelse false
    else
        null;

    const lua_src = b.dependency("lua", .{});

    const lib =
        b.addStaticLibrary(artifactOptions(
        .{ .shared = false },
        .{ .target = target, .optimize = optimize },
    ));
    const shared = if (build_shared)
        b.addSharedLibrary(artifactOptions(
            .{ .shared = true },
            .{ .target = target, .optimize = optimize },
        ))
    else
        null;
    const exe = b.addExecutable(artifactOptions(.exe, .{
        .target = target,
        .optimize = optimize,
    }));
    const exec = b.addExecutable(artifactOptions(.exec, .{
        .target = target,
        .optimize = optimize,
    }));
    if (!target.result.isMinGW()) {
        lib.linkSystemLibrary("m");
        exe.linkSystemLibrary("m");
        exec.linkSystemLibrary("m");
    }
    const build_targets = [_]?*Build.Step.Compile{
        lib,
        exe,
        exec,
        shared,
    };
    // Common compile flags
    for (&build_targets) |tr| {
        if (tr == null)
            continue;
        const t = tr.?;
        t.linkLibC();
        t.addIncludePath(lua_src.path("src"));
        switch (target.result.os.tag) {
            .aix => {
                t.defineCMacro("LUA_USE_POSIX", null);
                t.defineCMacro("LUA_USE_DLOPEN", null);
                t.linkSystemLibrary("dl");
            },
            .freebsd, .netbsd, .openbsd => {
                t.defineCMacro("LUA_USE_LINUX", null);
                t.defineCMacro("LUA_USE_READLINE", null);
                t.addIncludePath(.{ .cwd_relative = "/usr/include/edit" });
                t.linkSystemLibrary("edit");
            },
            .ios => {
                t.defineCMacro("LUA_USE_IOS", null);
            },
            .linux => {
                t.defineCMacro("LUA_USE_LINUX", null);
                t.linkSystemLibrary("dl");
                if (use_readline.?) {
                    t.defineCMacro("LUA_USE_READLINE", null);
                    t.linkSystemLibrary("readline");
                }
            },
            .macos => {
                t.defineCMacro("LUA_USE_MACOSX", null);
                t.defineCMacro("LUA_USE_READLINE", null);
                t.linkSystemLibrary("readline");
            },
            .solaris => {
                t.defineCMacro("LUA_USE_POSIX", null);
                t.defineCMacro("LUA_USE_DLOPEN", null);
                t.defineCMacro("_REENTRANT", null);
                t.linkSystemLibrary("dl");
            },
            else => {},
        }
    }
    if (target.result.isMinGW()) {
        lib.defineCMacro("LUA_BUILD_AS_DLL", null);
        exe.defineCMacro("LUA_BUILD_AS_DLL", null);
    }
    if (shared) |s| {
        s.addCSourceFiles(.{
            .root = lua_src.path("src"),
            .files = &base_src,
            .flags = &cflags,
        });

        s.installHeadersDirectory(
            lua_src.path("src"),
            "",
            .{ .include_extensions = &lua_inc },
        );
    }

    lib.addCSourceFiles(.{
        .root = lua_src.path("src"),
        .files = &base_src,
        .flags = &cflags,
    });

    lib.installHeadersDirectory(
        lua_src.path("src"),
        "",
        .{ .include_extensions = &lua_inc },
    );

    exe.addCSourceFile(.{
        .file = lua_src.path("src/lua.c"),
        .flags = &cflags,
    });

    exec.addCSourceFile(.{
        .file = lua_src.path("src/luac.c"),
        .flags = &cflags,
    });

    if (shared) |s| {
        exe.linkLibrary(s);
        b.installArtifact(s);
    } else {
        exe.linkLibrary(lib);
        b.installArtifact(lib);
    }

    exec.linkLibrary(lib);

    b.installArtifact(exe);
    b.installArtifact(exec);
    b.installDirectory(.{
        .source_dir = lua_src.path("doc"),
        .include_extensions = &.{".1"},
        .install_dir = .{ .custom = "man" },
        .install_subdir = "man1",
    });

    const run_step = b.step("run", "run lua interpreter");
    const run_cmd = b.addRunArtifact(exe);
    run_step.dependOn(&run_cmd.step);
    const unpack_step = b.step("unpack", "unpack source");
    const unpack_cmd = b.addInstallDirectory(.{
        .source_dir = lua_src.path(""),
        .install_dir = .prefix,
        .install_subdir = "",
    });
    unpack_step.dependOn(&unpack_cmd.step);
}
const ArtifactTarget = union(enum) {
    // True if shared options
    shared: bool,
    exe,
    exec,
};
const ArtifactTargetOptions = struct {
    target: ResolvedTarget,
    optimize: OptimizeMode,
};
fn artifactOptions(comptime options: ArtifactTarget, opts: ArtifactTargetOptions) switch (options) {
    .exe, .exec => Build.ExecutableOptions,
    .shared => |shared| if (shared)
        Build.SharedLibraryOptions
    else
        Build.StaticLibraryOptions,
} {
    const t = opts.target.result.os.tag;
    return switch (options) {
        .shared => |shared| if (shared) blk: {
            switch (t) {
                else => break :blk .{
                    .name = lib_name,
                    .target = opts.target,
                    .optimize = opts.optimize,
                    .strip = true,
                },
            }
        } else blk: {
            switch (t) {
                else => break :blk .{
                    .name = lib_name,
                    .target = opts.target,
                    .optimize = opts.optimize,
                },
            }
        },
        .exe => switch (t) {
            else => .{
                .name = exe_name,
                .target = opts.target,
                .optimize = opts.optimize,
            },
        },
        .exec => switch (t) {
            else => .{
                .name = compiler_name,
                .target = opts.target,
                .optimize = opts.optimize,
            },
        },
    };
}

const cflags = [_][]const u8{
    "-std=gnu99",
    "-Wall",
    "-Wextra",
};

const core_src = [_][]const u8{
    "lapi.c",
    "lcode.c",
    "lctype.c",
    "ldebug.c",
    "ldo.c",
    "ldump.c",
    "lfunc.c",
    "lgc.c",
    "llex.c",
    "lmem.c",
    "lobject.c",
    "lopcodes.c",
    "lparser.c",
    "lstate.c",
    "lstring.c",
    "ltable.c",
    "ltm.c",
    "lundump.c",
    "lvm.c",
    "lzio.c",
};
const lib_src = [_][]const u8{
    "lauxlib.c",
    "lbaselib.c",
    "lcorolib.c",
    "ldblib.c",
    "liolib.c",
    "lmathlib.c",
    "loadlib.c",
    "loslib.c",
    "lstrlib.c",
    "ltablib.c",
    "lutf8lib.c",
    "linit.c",
};
const base_src = core_src ++ lib_src;

const lua_inc = [_][]const u8{
    "lua.h",
    "luaconf.h",
    "lualib.h",
    "lauxlib.h",
    "lua.hpp",
};

zig version:

0.13.0

@linusg
Copy link
Contributor

linusg commented Aug 15, 2024

0.13.0 was released on June 7, the fix got merged on July 11. Use zig master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior os-windows
Projects
None yet
Development

No branches or pull requests