无法将共享库与 -mx32 和 gcc 4.7 或 gcc 4.8 链接 [英] Can't link shared library with -mx32 and gcc 4.7 or gcc 4.8

查看:24
本文介绍了无法将共享库与 -mx32 和 gcc 4.7 或 gcc 4.8 链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编译为 32 位嵌入式处理器编写的大型代码库,以便在 64 位桌面处理器上运行以进行模拟/单元测试.我需要生成的对象是一个共享库.这在 Windows 中不是问题,我可以构建这样的 dll (/DWIN32) 并且它运行良好.

I'm trying to compile a large codebase written for a 32 bit embedded processor to run on a 64 bit desktop processor for simulation/unit testing. I need the resulting object to be a shared library. This is not an issue in Windows, I can build a dll like this (/DWIN32) and it runs fine.

在 Linux 中,我能够编译和链接给 gcc 和链接器的 -m32 选项,并得到一个共享库.问题是,这个库是(就像我用 -m32 指定的)一个 32 位库,不会在我的 64 位架构上运行.使用 Python,我尝试加载库(使用 ctypes.cdll.LoadLibrary())

In Linux, I'm able to compile and link with the -m32 option given to both gcc and the linker and get a shared library out. The problem is, this library is (just like I specified with -m32) a 32 bit library and will not run on my 64 bit arch. With Python, I try to load the library (using ctypes.cdll.LoadLibrary())

OSError: out.so: wrong ELF class: ELFCLASS32

我发现了 -mx32 选项,并且根据 docs 这正是我想要的:

I discovered the -mx32 option, and according to the docs this is exactly what I want:

-mx32 选项将 int、long 和指针类型设置为 32 位,并且为 x86-64 架构生成代码.

The -mx32 option sets int, long, and pointer types to 32 bits, and generates code for the x86-64 architecture.

因此,我将 -mx32 传递给编译器和链接器(替换我的 -m32 选项)并获得以下内容(截断输出):

So, I pass -mx32 to the compiler and the linker (replacing my -m32 option) and get the following (snipped the output):

/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/32/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/32/libstdc++.a when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so when searching for -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a when searching for -lstdc++
/usr/bin/ld: cannot find -lstdc++
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.so when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm

我在 gcc 4.7 和 gcc 4.8 上得到了相同的结果.以上输出来自 gcc 4.8.

I get the same results with gcc 4.7 and gcc 4.8. The above output is from gcc 4.8.

我安装了 gcc-4.8-multilib 和 g++-4.8-multilib.

I have gcc-4.8-multilib and g++-4.8-multilib installed.

我的库路径是:

LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu/4.8/32:/usr/lib/gcc/x86_64-linux-gnu/4.8/

从 .bashrc 开始,我像这样(如下)指定了它,在阅读链接器只会与有效的库绑定后绝望地添加/4.8/和/4.8/32/内容.

From .bashrc I've specified it like this (below), in despair adding the /4.8/ and /4.8/32/ stuff after reading that the linker would only bind with the libraries that work.

export LIBRARY_PATH=/usr/lib/$(gcc -print-multiarch):/usr/lib/gcc/x86_64-linux-gnu/4.8/32:/usr/lib/gcc/x86_64-linux-gnu/4.8/

正如我所提到的,这在 Windows 上作为 dll 已经很好用了,我不得不相信我只是遗漏了一些东西.指针应该是 32 位,long 应该是 32 位,整个过程应该在 x86_64 上运行.-mx32 说它会做到这一点(对吧?).

As I mention, this works quite well already on Windows as a dll, I have to believe I'm just missing something. Pointers should be 32 bits and longs should be 32 bits, the whole thing should run on x86_64. -mx32 says it will do exactly that (right?).

在 -m32 中编译后检查其中一个对象:

Checking one of the objects after compiling in -m32:

$:~/project$ file foo.o
foo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped

并在使用 -mx32 编译后检查相同的对象:

And checking the same object after compiling with -mx32:

$:~/project$ file foo.o
foo.o: ELF 32-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

我是不是用错了方法?我还可以使用带有某种兼容层的 32 位共享库吗?

Am I going about this the wrong way? Can I still use my 32-bit shared library with some sort of compatibility layer?

我看到了针对 gcc 4.7 的错误报告关于这些链接错误......但我没有从中看到太多结论.此页面说 gcc 4.8 是 x32 的推荐最低要求,所以我安装了它.仍然 - 我无法将其链接.-m32 链接正常.

I saw a bug report against gcc 4.7 regarding these link errors... But I didn't see much conclusion from it. This page says that gcc 4.8 is the recommended minimum for x32, so I installed it. Still -- I can't get it to link. -m32 links fine.

推荐答案

-m32 是正常的 32 位模式,是的,大多数 x86-64 GNU/Linux 系统都支持 32 位的多架构如果尚未安装,您可以安装这些库.

-m32 is normal 32-bit mode, and yes most x86-64 GNU/Linux systems have multiarch support with 32-bit libraries that you can install if not already installed.

-mx32 选项根本不是您想要的.它为 x32 ABI 编译代码,它使用带有 64 位寄存器的 32 位地址和指示.生成的代码与 32 位处理器不兼容(因为它使用 64 位指令),但与 64 位代码(将使用 64 位地址)不兼容.所以用户空间中的所有东西都必须在编译时考虑到它,包括 libc,甚至内核也需要支持 x32 用户空间和系统调用:https://unix.stackexchange.com/questions/121424/linux-and-x32-abi-how-to-use(即只是就像支持 32 位二进制文​​件一样,x32 实际上是一个独立的架构.)

The -mx32 option is not what you want at all. It compiles code for the x32 ABI, which uses 32-bit addresses with 64-bit registers and instructions. The resulting code is not compatible with 32-bit processors (as it uses 64-bit instructions), but is also not compatible with 64-bit code (which will use 64-bit addresses). So everything in user-space has to be compiled with it in mind, including libc, and even the kernel needs to support x32 user-space and syscalls: https://unix.stackexchange.com/questions/121424/linux-and-x32-abi-how-to-use (i.e. just like supporting 32-bit binaries, x32 is effectively a separate architecture.)

更复杂的是,您在 Windows 上所做的测试根本没有按照您的想法进行.将 /DWIN32 传递给 Visual C++ 编译器只定义了一个名为 WIN32 的宏(就像 -DWIN32 用于 GCC);它不会让编译器生成 32 位二进制文​​件.64 位 Windows 可执行文件无法加载 32 位库;您一直在测试的库实际上是 64 位的.

Complicating matters further, the testing you've been doing on Windows hasn't been doing what you think at all. Passing /DWIN32 to the Visual C++ compiler only defines a macro called WIN32 (like -DWIN32 would for GCC); it doesn't make the compiler generate 32-bit binaries. 64-bit Windows executables cannot load 32-bit libraries; the libraries you've been testing with have actually been 64-bit.

如果您想对 32 位代码进行单元测试,则需要在像 -m32 这样的完整 32 位目标架构上进行测试.x32 不是这样的系统.(不过,64 位内核下的 32 位代码很好,除非您担心嵌入式系统中的用户空间只能使用 2G 或 3GiB 的地址空间,而不是 64 位内核下的 4GiB.)

If you want to unit-test 32-bit code, you'll need to test it on a fully 32-bit target architecture like -m32. x32 is not such a system. (32-bit code under a 64-bit kernel is fine, though, unless you're worried about only having 2G or 3GiB of address-space usable by user-space in your embedded system, instead of 4GiB under a 64-bit kernel.)

这篇关于无法将共享库与 -mx32 和 gcc 4.7 或 gcc 4.8 链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆