In a comment to this question, Unexpected behaviour in simple pointer arithmetics in kernel space C code, Michael Petch wrote, "The 64-bit ELF format supports 32-bit code sections."
I have a working program that includes both 32- and 64-bit code and switches between them. I have never been able to figure out how to link compiler-generated 32- and 64-bit code together without a linker error, so all the 32-bit code is written in assembly. As the project has become more complex, maintenance of the 32-bit assembly code has become more onerous.
Here is what I have:
test32.cc is compiled with -m32
.
All the other source files are compiled without that flag and with -mcmodel=kernel
.
In the linker script:
OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
In the Makefile:
LD := ld
LDFLAGS := -Map $(TARGET).map -n --script $(LDSCRIPT)
$(LD) $(LDFLAGS) -b elf32-x86-64 $(OBJS64) -b elf32-i386 $(OBJS32) -o $@
I get the error:
ld: i386 architecture of input file 'test32.o' is incompatible with i386:x86-64 output
Changing OUTPUT_ARCH to i386 causes similar errors from all the 64-bit object modules.
I'm using:
gcc 5.4.1
GNU ld (GNU Binutils for Ubuntu) 2.26.1
bits 32
/bits 64
(.code32
/code64
with AS) directive, but you still produce an elf64 object. – Actinochemistryobjcopy -O elf32-i386
to convert each 64-bit object to elf32. Generate your 32-bit C code with-m32
. Then link everything together (ld -melf_i386) as a 32-bit elf executable? Of course calling functions directly between the two wouldn't work, and would require a thunking layer (including dealing with mode changes, argument passing, ABI differences etc). – Actinochemistrymcmodel=kernel
(my mistake), not sure if the idea of above would still have merit. – Actinochemistry