如何让编译器生成一个"elf32-x86-64"格式的目标文件?
How to make compiler generate a "elf32-x86-64" format object file?
首先,关于 elf32-x86-64 格式的一些背景信息。
这是一种在强制使用 32 位指针的同时利用 64 位硬件的格式。 Ref1 and Ref2.
问题
我正在尝试将 link Google 测试框架二进制文件添加到我的项目中。
我使用 objdump -f
检查 Google 测试二进制文件和我的二进制文件的格式。
Google 测试格式为 elf64-x86-64
。我的 elf32-x86-64
。所以他们不能link一起编辑。
然后我将以下内容添加到 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
.
但是 google 测试构建失败并出现以下错误:
/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
.
因此 linker 标志似乎不影响目标文件格式。
我记得 linker ld
会根据第一次遇到的目标文件来选择输出格式。所以我想我需要告诉 编译器 输出 elf32-x86-64
格式。
如何让编译器输出一个elf32-x86-64
目标文件?
添加 1 - 3:29 下午 11/1/2019
我已经通过以下调整将 Google 测试编译为 elf32-x86-64
:
- 添加编译标志
-mx32
- 并添加link标志
-Wl,--oformat=elf32-x86-64
现在输出二进制文件 libgtest.a
、libgtest_main.a
是 elf32-x86-64
。但它们需要 linked 到 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 - 3:47 2019 年 11 月 1 日下午
安装 sudo apt-get install gcc-multilib g++-multilib
(ref) 后,我在以下位置获得了 libstdc++.so
的 elf32-x86-64
版本:
/usr/lib/gcc/x86_64-linux-gnu/7/x32/libstdc++.so
最终指向/usr/libx32/libstdc++.so.6.0.25
现在看来我只需要找到一种方法告诉 link 用户使用它...非常接近!
添加 3 - 2:44 2019 年 11 月 4 日下午
感谢 Florian 和 EmployedRussian,我更改 Google 测试的 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
添加到 两个 编译和 link 标志。
并且在生成的 rules.ninja
文件中,link 规则如下:
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 ...
基本上,$FLAGS $LINK_FLAGS
贡献的 ninja 命令定义中有 2 个 -mx32
选项。
那么为什么我需要指定两次-mx32
?
而且我不明白为什么我可以为CMAKE_EXE_LINKER_FLAGS
指定-mx32
。
首先,-mx32
只是一个编译选项(ref),不是一个linker选项。
其次,根据 link 规则定义,$LINK_FLAGS
被传递给 usr/bin/c++
而没有 -Wl,
前缀,因此即使是选项也可以被 linker,不会传给linker。
如果您将其作为 gcc -mx32
调用,GCC 将相应地调整链接器命令行。它不仅仅是一个编译器标志。
首先,关于 elf32-x86-64 格式的一些背景信息。
这是一种在强制使用 32 位指针的同时利用 64 位硬件的格式。 Ref1 and Ref2.
问题
我正在尝试将 link Google 测试框架二进制文件添加到我的项目中。
我使用 objdump -f
检查 Google 测试二进制文件和我的二进制文件的格式。
Google 测试格式为 elf64-x86-64
。我的 elf32-x86-64
。所以他们不能link一起编辑。
然后我将以下内容添加到 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
.
但是 google 测试构建失败并出现以下错误:
/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
.
因此 linker 标志似乎不影响目标文件格式。
我记得 linker ld
会根据第一次遇到的目标文件来选择输出格式。所以我想我需要告诉 编译器 输出 elf32-x86-64
格式。
如何让编译器输出一个elf32-x86-64
目标文件?
添加 1 - 3:29 下午 11/1/2019
我已经通过以下调整将 Google 测试编译为 elf32-x86-64
:
- 添加编译标志
-mx32
- 并添加link标志
-Wl,--oformat=elf32-x86-64
现在输出二进制文件 libgtest.a
、libgtest_main.a
是 elf32-x86-64
。但它们需要 linked 到 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 - 3:47 2019 年 11 月 1 日下午
安装 sudo apt-get install gcc-multilib g++-multilib
(ref) 后,我在以下位置获得了 libstdc++.so
的 elf32-x86-64
版本:
/usr/lib/gcc/x86_64-linux-gnu/7/x32/libstdc++.so
最终指向/usr/libx32/libstdc++.so.6.0.25
现在看来我只需要找到一种方法告诉 link 用户使用它...非常接近!
添加 3 - 2:44 2019 年 11 月 4 日下午
感谢 Florian 和 EmployedRussian,我更改 Google 测试的 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
添加到 两个 编译和 link 标志。
并且在生成的 rules.ninja
文件中,link 规则如下:
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 ...
基本上,$FLAGS $LINK_FLAGS
贡献的 ninja 命令定义中有 2 个 -mx32
选项。
那么为什么我需要指定两次-mx32
?
而且我不明白为什么我可以为CMAKE_EXE_LINKER_FLAGS
指定-mx32
。
首先,-mx32
只是一个编译选项(ref),不是一个linker选项。
其次,根据 link 规则定义,$LINK_FLAGS
被传递给 usr/bin/c++
而没有 -Wl,
前缀,因此即使是选项也可以被 linker,不会传给linker。
如果您将其作为 gcc -mx32
调用,GCC 将相应地调整链接器命令行。它不仅仅是一个编译器标志。