lld-link crash when linking intrinsics lib

Hello Rui,

I met couples of lld-link crash when enable the clang-cl + lld-link build toolchain for Uefi firmware. Below is a simplified example (main.c and intrinsics.c).

Uefi firmware is self-contained and doesn’t depend on the compiler intrinsics implementation, so we have our own intrinsics lib. It is weird that if I don’t use the llvm-lib but directly “lld-link /NODEFAULTLIB /ENTRY:main main.obj intrinsics.obj”, the below example can pass link. Please advise what’s wrong in this example.

$ cat main.c

typedef struct {

struct MAP_LIST {

unsigned long long VirtualAddress;

void *MapCookie;

} MapList[100];

} SNP_DRIVER;

SNP_DRIVER snp_instance;

int main()

{

SNP_DRIVER *Snp;

Snp = &snp_instance;

for (int Index = 0; Index < 100; Index++) {

Snp->MapList[Index].VirtualAddress = 0;

Snp->MapList[Index].MapCookie = 0;

}

return 0;

}

$ cat intrinsics.c

void * memset (void *dest, int ch, size_t count)

{

volatile char *Pointer;

Pointer = (char *)dest;

while (count-- != 0) {

*(Pointer++) = (char)ch;

}

return dest;

}

$ “/home/jshi19/llvm/releaseinstall/bin/clang-cl” /Fomain.obj /c --target=x86_64-pc-win32-coff -m64 /O1b2s -flto main.c

$ “/home/jshi19/llvm/releaseinstall/bin/clang-cl” /Fointrinsics.obj /c --target=x86_64-pc-win32-coff -m64 /O1b2s -flto intrinsics.c

$ “/home/jshi19/llvm/releaseinstall/bin/llvm-lib” /OUT:intrinsics.lib intrinsics.obj

$ “/home/jshi19/llvm/releaseinstall/bin/lld-link” /NODEFAULTLIB /ENTRY:main main.obj intrinsics.lib

Stack dump:

  1. Program arguments: /home/jshi19/llvm/releaseinstall/bin/lld-link /NODEFAULTLIB /ENTRY:main main.obj intrinsics.lib

#0 0x0000559a34ba5e4a llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x272e4a)

#1 0x0000559a34ba3d14 llvm::sys::RunSignalHandlers() (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x270d14)

#2 0x0000559a34ba3e52 SignalHandler(int) (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x270e52)

#3 0x00007f896c8ea890 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12890)

#4 0x0000559a34c11325 lld::coff::markLive(llvm::ArrayReflld::coff::Chunk*) (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x2de325)

#5 0x0000559a34bf0220 lld::coff::LinkerDriver::link(llvm::ArrayRef<char const*>) (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x2bd220)

#6 0x0000559a34bf0478 lld::coff::link(llvm::ArrayRef<char const*>, bool, llvm::raw_ostream&) (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x2bd478)

#7 0x0000559a34b2a300 main (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x1f7300)

#8 0x00007f896b3c1b97 __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/…/csu/libc-start.c:344:0

#9 0x0000559a34b8c27a _start (/home/jshi19/llvm/releaseinstall/bin/lld-link+0x25927a)

Segmentation fault (core dumped)

$ “/home/jshi19/llvm/releaseinstall/bin/clang-cl” --version

clang version 9.0.0 (https://github.com/llvm-mirror/clang.git 1f02068469ff18f5fc5728cafe9d96ee5f66c5b9) (https://github.com/llvm-project/llvm.git 330395ea4fce35b019b33797ff751be029a1f866)

Target: x86_64-pc-windows-msvc

Thread model: posix

InstalledDir: /home/jshi19/llvm/releaseinstall/bin

$ “/home/jshi19/llvm/releaseinstall/bin/lld-link” --version

LLD 9.0.0 (https://github.com/llvm-mirror/lld.git aa7adc0ec804b689771f11d52e39f83a16378f5f)

Thanks

Steven Shi

Intel\SSG\FID\Firmware Infrastructure

Hi Steven,

I confirmed that lld-link crashes with these inputs. That shouldn’t happen. I’ll debug this and get back to you. Thank you for reporting.

+Peter Collingbourne

LTO is used in this test case, and one source file defines its own memset function while the other file uses llvm.memset. Looks like LTO is confused by the user-defined memset. Could you take a look?

Steven,

Do you need to use LTO? I thought that LTO is a workaround to not produce an object file that cannot be handled by your ELF-to-COFF translation tool. If you are now doing a regular cross build, I guess you can remove -flto.

Hmm, you might need something like the ELF linker’s r338434/r339301 in the COFF linker.

Peter

Steven,

Do you need to use LTO? I thought that LTO is a workaround to not produce an object file that cannot be handled by your ELF-to-COFF translation tool. If you are now doing a regular cross build, I guess you can remove -flto.

Yes, I need the LTO for the smallest code size. Without LTO, my firmware image will be +30% larger which is not competitive with MSVC.

Thanks

Steven

Steven,

Do you need to use LTO? I thought that LTO is a workaround to not produce an object file that cannot be handled by your ELF-to-COFF translation tool. If you are now doing a regular cross build, I guess you can remove -flto.

Yes, I need the LTO for the smallest code size. Without LTO, my firmware image will be +30% larger which is not competitive with MSVC.

In the meantime you probably want to experiment clang-cl and lld without -flto. Once this issue is resolved, you can turn it on.

Hmm, you might need something like the ELF linker’s r338434/r339301 in the COFF linker.

Are you going to do that? If we need to port it in a straightforward way, I think I can do that, though.

Hmm, you might need something like the ELF linker’s r338434/r339301 in the COFF linker.

Are you going to do that? If we need to port it in a straightforward way, I think I can do that, though.

I wasn’t going to. It probably shouldn’t be too hard, but one thing to keep in mind is that the names in RuntimeLibcalls.def are unmangled (i.e. no ‘_’ prepended on Win/i386), so on that target we’d probably need to check both the mangled and unmangled names.

Peter