https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81342
--- Comment #5 from Anatol <anatol.pomozov at gmail dot com> --- Having 32bit preamble in 64bit code is a standard situation in x86 OS development. Bootloader (such as GRUB multiboot) leaves the system in 32bit protected mode. It is responsibility of the OS to finish 32bit initialization (where only i386 instructions can be used) and switch to 64bit code. Once 32bit initialization is done switching to 64code happens with "far jump with selector" instruction "jmp $CODE_SELECTOR, $START64" You cannot link 32bit and 64bit together (and least LD linker does not allow it). Thus one have to use a trick, either: 1) objcopy code32.o from elf32 to elf64 format 2) if code32 was an ASM code then use ".code32" GAS directive and compile file with 64bit flags. Here is an example of #2 from LK operation system https://github.com/littlekernel/lk/blob/master/arch/x86/64/start.S#L210 I tried both solution and they both work with GCC and CLANG. GCC crashes if I enable LTO for #1.