https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116334
Bug ID: 116334 Summary: LTO dllimport generates ureferenced symbol and unused code Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: lto Assignee: unassigned at gcc dot gnu.org Reporter: pali at kernel dot org Target Milestone: --- When compiling single source application with calls external dllimport function then LTO generates unreferenced symbol and unused dead code in the final binary. When same source is compiled without LTO then there is no dead code in binary. Take following example: __declspec(dllimport) extern int __stdcall MessageBoxA(void *, const char *, const char *, unsigned int); __attribute__((used)) int WinMainCRTStartup(void) { MessageBoxA((void *)0, "Message", "Title", 0); return 0; } And compile it without LTO: $ i686-w64-mingw32-gcc unreferenced.c -o unreferenced.exe -mwindows -nostartfiles -nostdlib -luser32 -Wl,--disable-runtime-pseudo-reloc -W -Wall -Os Compiled binary under objdump looks like: $ objdump -d unreferenced.exe unreferenced.exe: file format pei-i386 Disassembly of section .text: 00401000 <_WinMainCRTStartup>: 401000: 55 push %ebp 401001: 31 c0 xor %eax,%eax 401003: 31 d2 xor %edx,%edx 401005: 89 e5 mov %esp,%ebp 401007: 83 ec 18 sub $0x18,%esp 40100a: 89 44 24 0c mov %eax,0xc(%esp) 40100e: c7 44 24 08 00 20 40 movl $0x402000,0x8(%esp) 401015: 00 401016: c7 44 24 04 06 20 40 movl $0x402006,0x4(%esp) 40101d: 00 40101e: 89 14 24 mov %edx,(%esp) 401021: ff 15 30 40 40 00 call *0x404030 401027: 31 c0 xor %eax,%eax 401029: 83 ec 10 sub $0x10,%esp 40102c: c9 leave 40102d: c3 ret 40102e: 90 nop 40102f: 90 nop 00401030 <__CTOR_LIST__>: 401030: ff (bad) 401031: ff (bad) 401032: ff (bad) 401033: ff 00 incl (%eax) 401035: 00 00 add %al,(%eax) ... 00401038 <__DTOR_LIST__>: 401038: ff (bad) 401039: ff (bad) 40103a: ff (bad) 40103b: ff 00 incl (%eax) 40103d: 00 00 add %al,(%eax) ... Now compile it again but with enabled LTO with additional -flto switch. objdump shows: $ objdump -d unreferenced.exe unreferenced.exe: file format pei-i386 Disassembly of section .text: 00401000 <_WinMainCRTStartup>: 401000: 55 push %ebp 401001: 31 c0 xor %eax,%eax 401003: 31 d2 xor %edx,%edx 401005: 89 e5 mov %esp,%ebp 401007: 83 ec 18 sub $0x18,%esp 40100a: 89 44 24 0c mov %eax,0xc(%esp) 40100e: c7 44 24 08 00 20 40 movl $0x402000,0x8(%esp) 401015: 00 401016: c7 44 24 04 06 20 40 movl $0x402006,0x4(%esp) 40101d: 00 40101e: 89 14 24 mov %edx,(%esp) 401021: ff 15 30 40 40 00 call *0x404030 401027: 31 c0 xor %eax,%eax 401029: 83 ec 10 sub $0x10,%esp 40102c: c9 leave 40102d: c3 ret 40102e: 90 nop 40102f: 90 nop 00401030 <_MessageBoxA@16>: 401030: ff 25 30 40 40 00 jmp *0x404030 401036: 90 nop 401037: 90 nop 00401038 <__CTOR_LIST__>: 401038: ff (bad) 401039: ff (bad) 40103a: ff (bad) 40103b: ff 00 incl (%eax) 40103d: 00 00 add %al,(%eax) ... 00401040 <__DTOR_LIST__>: 401040: ff (bad) 401041: ff (bad) 401042: ff (bad) 401043: ff 00 incl (%eax) 401045: 00 00 add %al,(%eax) ... At address 0x401030 there is dead code (nothing references address 0x401030) and also unreferenced symbol _MessageBoxA@16.