I’m trying to set up a cross compile for linux ELF files on Windows using clang and a version of ld which has been compiled to have elf64 support. The clang compile part is fine, it outputs ELF obj files that work when linked on linux. My test case cpp is just main containing a printf statement.
To attempt a link on windows I copied over all of the libraries from my ubuntu install and specified the ones that are needed as linker arguments in the right order (as they appear on the ld invocation performed by g++). The problem is, the output file is slightly different than the one produced on linux and it won’t run as an executable. I noticed, for example, that in the version linked on windows there is the undefined symbol “printf” which appears to have become “puts” instead in the linux version.
Anyway I’m wondering if anyone knows what is happening here.
My actual linking arguments are like this:
LFLAGS = --build-id --eh-frame-hdr --oformat elf64-x86-64 -m elf_x86_64 --hash-style=gnu --as-needed -z relro --verbose LIBDIRS = -LI:\Linux\gcc\x86_64-linux-gnu\4.8.1 -LI:\Linux\libs\lib\x86_64-linux-gnu -LI:\Linux\libs\lib -LI:\Linux\lib\x86_64-linux-gnu -LI:\Linux\lib LIBS = I:Linuxlibslibx86_64-linux-gnu\ld-2.17.so I:\Linux\lib\x86_64-linux-gnu\crt1.o I:\Linux\lib\x86_64-linux-gnu\crti.o I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o Test.o I:Linuxlibx86_64-linux-gnu\libstdc++.so.6.0.18 I:Linuxlibslibx86_64-linux-gnu\libgcc_s.so.1 I:Linuxgccx86_64-linux-gnu4.8.1\libgcc.a I:Linuxlibslibx86_64-linux-gnu\libc.so.6 I:Linuxlibx86_64-linux-gnu\libc_nonshared.a I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o I:\Linux\lib\x86_64-linux-gnu\crtn.o all: $(MAIN) ./ld-new.exe $(LFLAGS) $(LIBDIRS) $(LIBS) -o Test $(MAIN): clang $(CFLAGS) $(SYSINCLUDES) -o $(OBJS) -x c++ $(SRCS)
Linking on linux:
================================================== attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o succeeded /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o succeeded /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o succeeded /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o attempt to open Test.o succeeded Test.o attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so succeeded -lstdc++ (/usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so) attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libm.so failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libm.a failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.so succeeded -lm (/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.so) attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so succeeded -lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so) attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.so failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a succeeded attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libc.so failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libc.a failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libc.so succeeded opened script file /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libc.so opened script file /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libc.so attempt to open /lib/x86_64-linux-gnu/libc.so.6 succeeded /lib/x86_64-linux-gnu/libc.so.6 attempt to open /usr/lib/x86_64-linux-gnu/libc_nonshared.a succeeded (/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS attempt to open /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 succeeded /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so succeeded -lgcc_s (/usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_s.so) attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.so failed attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a succeeded attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o succeeded /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o attempt to open /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o succeeded /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o ld-linux-x86-64.so.2 needed by /lib/x86_64-linux-gnu/libc.so.6 found ld-linux-x86-64.so.2 at /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
nm output on linux:
k@system:/shared$ nm ./Test 0000000000601040 B __bss_start 0000000000601040 b completed.6992 0000000000601030 D __data_start 0000000000601030 W data_start 0000000000400470 t deregister_tm_clones 00000000004004e0 t __do_global_dtors_aux 0000000000600e18 t __do_global_dtors_aux_fini_array_entry 0000000000601038 D __dso_handle 0000000000600e28 d _DYNAMIC 0000000000601040 D _edata 0000000000601048 B _end 00000000004005e4 T _fini 0000000000400500 t frame_dummy 0000000000600e10 t __frame_dummy_init_array_entry 0000000000400718 r __FRAME_END__ 0000000000601000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 00000000004003e0 T _init 0000000000600e18 t __init_array_end 0000000000600e10 t __init_array_start 00000000004005f0 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000600e20 d __JCR_END__ 0000000000600e20 d __JCR_LIST__ w _Jv_RegisterClasses 00000000004005e0 T __libc_csu_fini 0000000000400550 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 000000000040052d T main U puts@@GLIBC_2.2.5 00000000004004a0 t register_tm_clones 0000000000400440 T _start 0000000000601040 D __TMC_END__
Linking on Windows:
================================================== attempt to open I:Linuxlibslibx86_64-linux-gnuld-2.17.so succeeded I:Linuxlibslibx86_64-linux-gnuld-2.17.so attempt to open I:Linuxlibx86_64-linux-gnucrt1.o succeeded I:Linuxlibx86_64-linux-gnucrt1.o attempt to open I:Linuxlibx86_64-linux-gnucrti.o succeeded I:Linuxlibx86_64-linux-gnucrti.o attempt to open I:Linuxgccx86_64-linux-gnu4.8.1crtbegin.o succeeded I:Linuxgccx86_64-linux-gnu4.8.1crtbegin.o attempt to open Test.o succeeded Test.o attempt to open I:Linuxlibx86_64-linux-gnulibstdc++.so.6.0.18 succeeded I:Linuxlibx86_64-linux-gnulibstdc++.so.6.0.18 attempt to open I:Linuxlibslibx86_64-linux-gnulibm-2.17.so succeeded I:Linuxlibslibx86_64-linux-gnulibm-2.17.so attempt to open I:Linuxgccx86_64-linux-gnu4.8.1libgcc.a succeeded attempt to open I:Linuxlibx86_64-linux-gnulibc.so succeeded opened script file I:Linuxlibx86_64-linux-gnulibc.so attempt to open /lib/x86_64-linux-gnu/libc.so.6 succeeded /lib/x86_64-linux-gnu/libc.so.6 attempt to open /usr/lib/x86_64-linux-gnu/libc_nonshared.a succeeded (I:/Linux/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS attempt to open /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 succeeded /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 attempt to open I:Linuxlibx86_64-linux-gnulibc_nonshared.a succeeded attempt to open I:Linuxgccx86_64-linux-gnu4.8.1crtend.o succeeded I:Linuxgccx86_64-linux-gnu4.8.1crtend.o attempt to open I:Linuxlibx86_64-linux-gnucrtn.o succeeded I:Linuxlibx86_64-linux-gnucrtn.o ld-linux-x86-64.so.2 needed by I:/Linux/libs/lib/x86_64-linux-gnu/libc-2.17.so found ld-2.17.so at I:Linuxlibslibx86_64-linux-gnuld-2.17.so
nm output of windows generated executable file
k@system:/shared$ nm ./Test 0000000000601040 B __bss_start 0000000000601040 b completed.6992 0000000000601030 D __data_start 0000000000601030 W data_start 0000000000400470 t deregister_tm_clones 00000000004004e0 t __do_global_dtors_aux 0000000000600e18 t __do_global_dtors_aux_fini_array_entry 0000000000601038 D __dso_handle 0000000000600e28 d _DYNAMIC 0000000000601040 D _edata 0000000000601048 B _end 00000000004005f4 T _fini 0000000000400500 t frame_dummy 0000000000600e10 t __frame_dummy_init_array_entry 0000000000400728 r __FRAME_END__ 0000000000601000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 00000000004003d8 T _init 0000000000600e18 t __init_array_end 0000000000600e10 t __init_array_start 0000000000400600 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000600e20 d __JCR_END__ 0000000000600e20 d __JCR_LIST__ w _Jv_RegisterClasses 00000000004005f0 T __libc_csu_fini 0000000000400560 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 0000000000400530 T main U printf@@GLIBC_2.2.5 00000000004004a0 t register_tm_clones 0000000000400440 T _start 0000000000601040 D __TMC_END__ k@system:/shared$ ./Test bash: ./Test: No such file or directory
EDIT- more information
By won’t run I mean ubuntu gives the message:
bash: ./Test: No such file or directory
Here is the result of file/ldd
k@system:/shared$ file ./Test ./Test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xee999db5a0e77d05f50d8fd78a27fc3ac52584b1, not stripped k@system:/shared$ ldd ./Test linux-vdso.so.1 => (0x00007ffff2bfe000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5e2b60c000) /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f5e2b9eb000)
EDIT 2-
I’ve since tried to get closer to replicating the exact linking process on linux.
LFLAGS = --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker I:\Linux\libs\lib\x86_64-linux-gnu\ld-2.17.so -z relro --verbose LIBDIRS = -LI:\Linux\gcc\x86_64-linux-gnu\4.8.1 -LI:\Linux\libs\lib\x86_64-linux-gnu -LI:\Linux\libs\lib -LI:\Linux\lib\x86_64-linux-gnu -LI:\Linux\lib LIBS_BEGIN = I:\Linux\lib\x86_64-linux-gnu\crt1.o I:\Linux\lib\x86_64-linux-gnu\crti.o I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o LIBS_END = I:\Linux\lib\gcc\x86_64-linux-gnu\4.8.1\libstdc++.so I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1 I:\Linux\gcc\x86_64-linux-gnu\4.8.1\libgcc.a I:\Linux\lib\x86_64-linux-gnu\libc_nonshared.a I:\Linux\libs\lib\x86_64-linux-gnu\ld-linux-x86-64.so.2 I:\Linux\libs\lib\x86_64-linux-gnu\libc.so.6 I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1 I:\Linux\gcc\x86_64-linux-gnu\4.8.1\libgcc.a I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o I:\Linux\lib\x86_64-linux-gnu\crtn.o all: $(MAIN) ./ld-new.exe $(LFLAGS) -o Test $(LIBS_BEGIN) $(LIBDIRS) $(OBJS) $(LIBS_END)
Updated linking on windows:
================================================== attempt to open I:Linuxlibx86_64-linux-gnucrt1.o succeeded I:Linuxlibx86_64-linux-gnucrt1.o attempt to open I:Linuxlibx86_64-linux-gnucrti.o succeeded I:Linuxlibx86_64-linux-gnucrti.o attempt to open I:Linuxgccx86_64-linux-gnu4.8.1crtbegin.o succeeded I:Linuxgccx86_64-linux-gnu4.8.1crtbegin.o attempt to open Test.o succeeded Test.o attempt to open I:Linuxlibgccx86_64-linux-gnu4.8.1libstdc++.so succeeded I:Linuxlibgccx86_64-linux-gnu4.8.1libstdc++.so attempt to open I:Linuxlibslibx86_64-linux-gnulibgcc_s.so.1 succeeded I:Linuxlibslibx86_64-linux-gnulibgcc_s.so.1 attempt to open I:Linuxgccx86_64-linux-gnu4.8.1libgcc.a succeeded attempt to open I:Linuxlibx86_64-linux-gnulibc_nonshared.a succeeded (I:Linuxlibx86_64-linux-gnulibc_nonshared.a)elf-init.oS attempt to open I:Linuxlibslibx86_64-linux-gnuld-linux-x86-64.so.2 succeede d I:Linuxlibslibx86_64-linux-gnuld-linux-x86-64.so.2 attempt to open I:Linuxlibslibx86_64-linux-gnulibc.so.6 succeeded I:Linuxlibslibx86_64-linux-gnulibc.so.6 attempt to open I:Linuxlibslibx86_64-linux-gnulibgcc_s.so.1 succeeded I:Linuxlibslibx86_64-linux-gnulibgcc_s.so.1 attempt to open I:Linuxgccx86_64-linux-gnu4.8.1libgcc.a succeeded attempt to open I:Linuxgccx86_64-linux-gnu4.8.1crtend.o succeeded I:Linuxgccx86_64-linux-gnu4.8.1crtend.o attempt to open I:Linuxlibx86_64-linux-gnucrtn.o succeeded I:Linuxlibx86_64-linux-gnucrtn.o ld-linux-x86-64.so.2 needed by I:Linuxlibslibx86_64-linux-gnulibc.so.6 found ld-linux-x86-64.so.2 at I:Linuxlibslibx86_64-linux-gnuld-linux-x86-64 .so.2
Updated nm run on the file “Test”
0000000000601040 B __bss_start 0000000000601040 b completed.6992 0000000000601030 D __data_start 0000000000601030 W data_start 0000000000400490 t deregister_tm_clones 0000000000400500 t __do_global_dtors_aux 0000000000600e18 t __do_global_dtors_aux_fini_array_entry 0000000000601038 D __dso_handle 0000000000600e28 d _DYNAMIC 0000000000601040 D _edata 0000000000601048 B _end 0000000000400614 T _fini 0000000000400520 t frame_dummy 0000000000600e10 t __frame_dummy_init_array_entry 0000000000400748 r __FRAME_END__ 0000000000601000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__ 00000000004003f8 T _init 0000000000600e18 t __init_array_end 0000000000600e10 t __init_array_start 0000000000400620 R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable 0000000000600e20 d __JCR_END__ 0000000000600e20 d __JCR_LIST__ w _Jv_RegisterClasses 0000000000400610 T __libc_csu_fini 0000000000400580 T __libc_csu_init U __libc_start_main@@GLIBC_2.2.5 0000000000400550 T main U printf@@GLIBC_2.2.5 00000000004004c0 t register_tm_clones 0000000000400460 T _start 0000000000601040 D __TMC_END__
Result of llvm-readobj on the file:
I:LLVM_BUILDVC1264Releasebin>llvm-readobj -file-headers Test File: Test Format: ELF64-x86-64 Arch: x86_64 AddressSize: 64bit LoadName: ElfHeader { Ident { Magic: (7F 45 4C 46) Class: 64-bit (0x2) DataEncoding: LittleEndian (0x1) FileVersion: 1 OS/ABI: SystemV (0x0) ABIVersion: 0 Unused: (00 00 00 00 00 00 00) } Type: Executable (0x2) Machine: EM_X86_64 (0x3E) Version: 1 Entry: 0x400460 ProgramHeaderOffset: 0x40 SectionHeaderOffset: 0x11C0 Flags [ (0x0) ] HeaderSize: 64 ProgramHeaderEntrySize: 56 ProgramHeaderCount: 9 SectionHeaderEntrySize: 64 SectionHeaderCount: 30 StringTableSectionIndex: 27
And the actual linked, ostensibly executable file itself:
https://dl.dropboxusercontent.com/u/1735585/Test
Advertisement
Answer
The “No such file or directory” error can be a bit confusing if the file is there and executable. You will also get that error on executing a file if the ELF interpreter (the program that performs the shared library linking) isn’t found.
That is what happens here. The relevant lines from readelf -l Test
:
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238 0x000000000000002e 0x000000000000002e R 1 [Requesting program interpreter: I:Linuxlibslibx86_64-linux-gnuld-2.17.so]
Obviously that interpreter will not be found on a Linux system. For some reason ldd
shows a file mapping to the correct interpreter for that entry.
I can’t tell you how to fix that in your Windows build environment, but with a correct interpreter ldd
won’t show a mapping. For example:
$ ldd /bin/true linux-vdso.so.1 (0x00007fff1bbff000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f94ff99f000) /lib64/ld-linux-x86-64.so.2 (0x00007f94ffd73000)