Why does MSVC Linker (and lld-link) behave weirdly when entry point is manually set?

94 views Asked by At

I was trying to compile a program in Windows using clang so that I can use cmdline options similar to gcc while statically linking to the UCRT library (ucrt.lib). Besides, I also want to specify the entry point to control when to initialize the runtime. Then I found some weird behaviors.

Take this snippet for example:

#include <memory.h>

char src[1000], dest[1000]; // Large enough to avoid inline memcpy

int main(void) {
    memcpy(dest, src, sizeof (src));
//  memcpy_s(dest, sizeof (dest), src, sizeof (src));
    return 233;
}

Obviously, using normal options, it is okay to compile:

> clang test.c -Xlinker /SUBSYSTEM:CONSOLE -o test-llvm.exe

However, after specifying /ENTRY, memcpy (and some other library functions, if used) becomes undefined, quite like specifying -nostdlib.

> clang test.c -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe
lld-link: error: undefined symbol: memcpy
>>> referenced by ...\test.o:(main)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

We can manually add the library though, but the error is still there afterwards.

> clang test.c -lucrt -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe
lld-link: error: undefined symbol: memcpy
>>> referenced by ...\test.o:(main)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

The strangest thing is, if I make the commented line back (memcpy not altered), the whole file will compile without problems.

> clang test-s.c -lucrt -Xlinker /SUBSYSTEM:CONSOLE -Xlinker /ENTRY:main -o test-llvm.exe

But why would memcpy_s affect the whole linking process? Is that a bug?
I have also tried changing the linker to LLD by -fuse-ld=lld and it produced identical results.

I once guessed it may be related to intrinsic functions, but adding options like -fno-builtin -ffreestanding doesn't change anything as well.

0

There are 0 answers