如何让编译器生成“elf32-x86-64”格式的目标文件?

smw*_*dia 2 gcc elf googletest

首先,关于 elf32-x86-64 格式的一些背景信息。

它是一种利用 64 位硬件同时强制执行 32 位指针的格式。Ref1Ref2

我正在尝试将 Google Test 框架二进制文件链接到我的项目。

objdump -f用来检查 Google Test 二进制文件和我的二进制文件的格式。

谷歌测试格式是elf64-x86-64. 我的elf32-x86-64。所以它们不能连接在一起。

然后我将以下内容添加到谷歌测试的 internal_utils.cmake 文件中:

set(ZEPHYR_LINK_FLAGS "-Wl,--oformat=elf32-x86-64")
set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${ZEPHYR_LINK_FLAGS}")
Run Code Online (Sandbox Code Playgroud)

我希望链接器标志可以将输出格式更改为elf32-x86-64.

但是谷歌测试构建失败,错误如下:

/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so: error adding symbols: File in wrong format
Run Code Online (Sandbox Code Playgroud)

/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so也是一种elf64-x86-64格式。

我检查了生成的目标文件,例如: ./googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o

仍然elf64-x86-64

所以看起来链接器标志不影响目标文件格式。

我记得链接器ld会根据它第一个遇到的目标文件来选择输出格式。所以我想我需要告诉编译器输出elf32-x86-64格式。

如何要求编译器输出elf32-x86-64目标文件?

添加 1 - 3:29 PM 11/1/2019

我已经设法elf32-x86-64通过以下调整编译了 Google 测试:

  • 添加编译标志 -mx32
  • 并添加链接标志 -Wl,--oformat=elf32-x86-64

现在,输出二进制文件libgtest.alibgtest_main.aelf32-x86-64。但它们需要链接到libstdc++.so. 到目前为止,它elf64-x86-64在我的系统上。而且我还没有找到elf32-x86-64。因此以下错误:

/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so: error adding symbols: File in wrong format
Run Code Online (Sandbox Code Playgroud)

添加 2 - 3:47 PM 11/1/2019

安装sudo apt-get install gcc-multilib g++-multilibref)后,我在以下位置获得了一个elf32-x86-64版本libstdc++.so

/usr/lib/gcc/x86_64-linux-gnu/7/x32/libstdc++.so
Run Code Online (Sandbox Code Playgroud)

它最终指向 /usr/libx32/libstdc++.so.6.0.25

现在看来我只需要找到一种方法来告诉链接器使用它......太接近了!

添加 3 - 2:44 PM 11/4/2019

感谢FlorianEmployedRussian,我更改了 Google Test 的internal_utils.cmake文件以添加以下 4 行:

set(MY_COMPILE_FLAGS "-mx32")
set(cxx_base_flags "${cxx_base_flags} ${MY_COMPILE_FLAGS}") 
set(MY_LINK_FLAGS "-mx32")
set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${MY_LINK_FLAGS}")
Run Code Online (Sandbox Code Playgroud)

现在生成的可执行文件是elf32_x86-64格式。

所以基本上,我加入-mx32这两个编译和链接标志。

在生成的rules.ninja文件中,链接规则是这样的:

command = $PRE_LINK && /usr/bin/c++ $FLAGS $LINK_FLAGS $in -o $TARGET_FILE $LINK_PATH $LINK_LIBRARIES && $POST_BUILD

$FLAGS$LINK_FLAGS是在定义build.ninja文件,如下:

FLAGS = -Wall -Wshadow -Werror  -mx32 ...
LINK_FLAGS = -mx32 ...
Run Code Online (Sandbox Code Playgroud)

因此,本质上,分别-mx32由 ninja 命令定义提供了2 个选项$FLAGS $LINK_FLAGS

那么为什么我需要指定-mx32两次?

我不明白为什么我可以指定-mx32CMAKE_EXE_LINKER_FLAGS

首先,-mx32只是一个编译选项(ref),而不是链接器选项。

其次,从链接规则定义来看,$LINK_FLAGS传递给usr/bin/c++没有-Wl,前缀,因此即使链接器可以理解该选项,它也不会传递给链接器。

Flo*_*mer 5

如果您将其作为gcc -mx32. 它不仅仅是一个编译器标志。