C++ Windows上Linux的交叉编译(链接器输出文件不会在Linux上作为可执行文件运行,并且具有未定义的符号)

C++ Windows上Linux的交叉编译(链接器输出文件不会在Linux上作为可执行文件运行,并且具有未定义的符号),c++,linux,linker,cross-compiling,ld,C++,Linux,Linker,Cross Compiling,Ld,我正在尝试使用clang和ld版本在Windows上为linux ELF文件设置交叉编译,该版本已编译为支持elf64。clang编译部分很好,它输出ELF obj文件,在linux上链接时可以工作。我的测试用例cpp只是包含printf语句的main 为了在windows上尝试链接,我从ubuntu安装中复制了所有库,并以正确的顺序指定了作为链接器参数所需的库(正如g++执行的ld调用中显示的那样)。问题是,输出文件与linux上生成的文件稍有不同,它不会作为可执行文件运行。例如,我注意到,在

我正在尝试使用clang和ld版本在Windows上为linux ELF文件设置交叉编译,该版本已编译为支持elf64。clang编译部分很好,它输出ELF obj文件,在linux上链接时可以工作。我的测试用例cpp只是包含printf语句的main

为了在windows上尝试链接,我从ubuntu安装中复制了所有库,并以正确的顺序指定了作为链接器参数所需的库(正如g++执行的ld调用中显示的那样)。问题是,输出文件与linux上生成的文件稍有不同,它不会作为可执行文件运行。例如,我注意到,在windows上链接的版本中,有一个未定义的符号“printf”,它在linux版本中似乎变成了“put”

不管怎样,我想知道是否有人知道这里发生了什么

我的实际链接参数如下所示:

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:\Linux\libs\lib\x86_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:\Linux\lib\x86_64-linux-gnu\\libstdc++.so.6.0.18 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\libs\lib\x86_64-linux-gnu\\libc.so.6 I:\Linux\lib\x86_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) 
在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
linux上的nm输出:

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__
在Windows上链接:

==================================================
attempt to open I:\Linux\libs\lib\x86_64-linux-gnu\ld-2.17.so succeeded
I:\Linux\libs\lib\x86_64-linux-gnu\ld-2.17.so
attempt to open I:\Linux\lib\x86_64-linux-gnu\crt1.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crt1.o
attempt to open I:\Linux\lib\x86_64-linux-gnu\crti.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crti.o
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o succeeded
I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o
attempt to open Test.o succeeded
Test.o
attempt to open I:\Linux\lib\x86_64-linux-gnu\libstdc++.so.6.0.18 succeeded
I:\Linux\lib\x86_64-linux-gnu\libstdc++.so.6.0.18
attempt to open I:\Linux\libs\lib\x86_64-linux-gnu\libm-2.17.so succeeded
I:\Linux\libs\lib\x86_64-linux-gnu\libm-2.17.so
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\libgcc.a succeeded
attempt to open I:\Linux\lib\x86_64-linux-gnu\libc.so succeeded
opened script file I:\Linux\lib\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
(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:\Linux\lib\x86_64-linux-gnu\libc_nonshared.a succeeded
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o succeeded
I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o
attempt to open I:\Linux\lib\x86_64-linux-gnu\crtn.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crtn.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:\Linux\libs\lib\x86_64-linux-gnu\ld-2.17.so
windows生成的可执行文件的nm输出

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
编辑-更多信息

我所说的“不运行”是指ubuntu提供了以下信息:

bash: ./Test: No such file or directory
下面是文件/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) 
编辑2-

此后,我尝试在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)  
更新了windows上的链接:

==================================================
attempt to open I:\Linux\lib\x86_64-linux-gnu\crt1.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crt1.o
attempt to open I:\Linux\lib\x86_64-linux-gnu\crti.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crti.o
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o succeeded
I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtbegin.o
attempt to open Test.o succeeded
Test.o
attempt to open I:\Linux\lib\gcc\x86_64-linux-gnu\4.8.1\libstdc++.so succeeded
I:\Linux\lib\gcc\x86_64-linux-gnu\4.8.1\libstdc++.so
attempt to open I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1 succeeded
I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\libgcc.a succeeded
attempt to open I:\Linux\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 I:\Linux\libs\lib\x86_64-linux-gnu\ld-linux-x86-64.so.2 succeede
d
I:\Linux\libs\lib\x86_64-linux-gnu\ld-linux-x86-64.so.2
attempt to open I:\Linux\libs\lib\x86_64-linux-gnu\libc.so.6 succeeded
I:\Linux\libs\lib\x86_64-linux-gnu\libc.so.6
attempt to open I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1 succeeded
I:\Linux\libs\lib\x86_64-linux-gnu\libgcc_s.so.1
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\libgcc.a succeeded
attempt to open I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o succeeded
I:\Linux\gcc\x86_64-linux-gnu\4.8.1\crtend.o
attempt to open I:\Linux\lib\x86_64-linux-gnu\crtn.o succeeded
I:\Linux\lib\x86_64-linux-gnu\crtn.o
ld-linux-x86-64.so.2 needed by I:\Linux\libs\lib\x86_64-linux-gnu\libc.so.6
found ld-linux-x86-64.so.2 at I:\Linux\libs\lib\x86_64-linux-gnu\ld-linux-x86-64
.so.2
更新了在文件“Test”上运行的nm

文件上llvm readobj的结果:

I:\LLVM_BUILD\VC12\64\Release\bin>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
以及实际链接的、表面上可执行的文件本身:

https://dl.dropboxusercontent.com/u/1735585/Test
如果文件存在并且是可执行的,“没有这样的文件或目录”错误可能会有点混乱。如果找不到ELF解释器(执行共享库链接的程序),则在执行文件时也会出现该错误

这就是这里发生的事情。
readelf-l测试中的相关行:

INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
               0x000000000000002e 0x000000000000002e  R      1
    [Requesting program interpreter: I:\Linux\libs\lib\x86_64-linux-gnu\ld-2.17.so]
显然,在Linux系统上找不到解释器。出于某种原因,
ldd
显示了一个文件映射到该条目的正确解释器

我无法告诉您如何在Windows构建环境中修复此问题,但使用正确的解释器
ldd
不会显示映射。例如:

$ 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)

该文件是否具有当前用户的执行权限?是的,ls-l:-rwxr-xr-x 1 k k 8594 Apr 23 11:56测试的结果如果要链接到某个特定版本的库(如glibc),则最好根据该版本库附带的标题进行编译。另外,请指定“不会运行”的含义。您是否收到任何错误消息?bash说
/Test:没有这样的文件或目录
,这通常意味着
bash
无法评估名为
/Test
的文件或目录。这并不意味着
/Test
链接不正确或有任何其他错误。将允许作者更改现有ELF文件中的解释器。它可以用于快速检查。安德烈亚斯,谢谢你的回答!很抱歉延迟接受您的答复。你完全正确,修补解释器修复了问题。在修改ld之后,我现在可以完全交叉构建到linux。我非常感谢你花时间回答我的问题,非常感谢!您愿意在github这样的地方发布/发布您的环境吗?
$ 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)