【问题标题】:How to make compiler generate a "elf32-x86-64" format object file?如何让编译器生成“elf32-x86-64”格式的目标文件?
【发布时间】:2023-03-31 01:20:02
【问题描述】:

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

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

问题

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

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

Google 测试格式为elf64-x86-64。我的elf32-x86-64。所以它们不能链接在一起。

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

set(ZEPHYR_LINK_FLAGS "-Wl,--oformat=elf32-x86-64")
set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${ZEPHYR_LINK_FLAGS}")

我希望 linker 标志可以将输出格式更改为elf32-x86-64

但谷歌测试构建失败并出现以下错误:

/usr/lib/gcc/x86_64-linux-gnu/7/libstdc++.so: error adding symbols: File in wrong format

/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 - 2019 年 11 月 1 日下午 3:29

我已通过以下调整将 Google 测试编译为 elf32-x86-64

  • 添加编译标志-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

添加 2 - 2019 年 11 月 1 日下午 3:47

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

/usr/lib/gcc/x86_64-linux-gnu/7/x32/libstdc++.so

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

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

添加 3 - 2019 年 11 月 4 日下午 2:44

感谢 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}")

现在生成的可执行文件是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_FLAGSbuild.ninja 文件中定义如下:

FLAGS = -Wall -Wshadow -Werror  -mx32 ...
LINK_FLAGS = -mx32 ...

所以基本上,$FLAGS $LINK_FLAGS 贡献的 ninja 命令定义中有 2 个-mx32 选项。

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

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

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

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

【问题讨论】:

标签: gcc googletest elf


【解决方案1】:

如果您以gcc -mx32 调用它,GCC 将相应地调整链接器命令行。它不仅仅是一个编译器标志。

【讨论】:

  • 详细说明,添加链接标志-Wl,--oformat=elf32-x86-64,是错误的事情。而是将-mx32 添加到链接行。
  • @EmployedRussian 我尝试为链接器添加-Wl, -mx32。我的最终链接标志是-Wl,-mx32 -rdynamic。它们最终被传递给/usr/bin/x86_64-linux-gnu-g++-7,然后是/usr/bin/x86_64-linux-gnu-ld.bfd。但我收到了这个错误:/usr/bin/ld: unrecognised emulation mode: x32。看来我不应该将-mx32 传递给链接器,因为它被识别为-m 链接选项(sourceware.org/binutils/docs/ld/…)。
  • @FlorianWeimer 如果我只将-mx32 添加到g++ 编译选项,我得到.o 文件为elf32_x86-64,这很好。但是链接器要求 output 格式为elf64_x86-64。所以我收到了这个错误/usr/bin/ld: i386:x64-32 architecture of input file "googletest/CMakeFiles/sample2_unittest.dir/samples/sample2_unittest.cc.o" is incompatible with i386:x86-64 output。所以看来我必须明确地告诉链接器通过-Wl,--oformat=elf32-x86-64 输出为elf32_x86-64 格式。
  • @smwikipedia 你应该传递-mx32 没有 -Wl, 前缀。您必须两个编译和链接命令行上使用-mx32
  • @smwikipedia 仅仅因为-mx32 没有传递给链接器并不意味着它对链接行没有影响。在这种情况下,链接行上存在-mx32 会导致gcc-m elf32_x86_64 传递给ld。此外,选择了不同的动态链接器和不同的crt0.o。就像答案所说:-mx32 不仅仅是一个编译器标志。
猜你喜欢
  • 2011-01-03
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
  • 2021-01-15
  • 1970-01-01
相关资源
最近更新 更多