2015-10-19 395 views
0

我試圖編譯一個大的代碼庫編寫的32位嵌入式處理器在64位桌面處理器上運行,以進行仿真/單元測試。我需要生成的對象成爲共享庫。這在Windows中不是問題,我可以像這樣構建一個dll(/ DWIN32)並且運行良好。無法鏈接共享庫與-mx32和gcc 4.7或gcc 4.8

在Linux中,我可以使用給予gcc和鏈接器的-m32選項進行編譯和鏈接,並獲得共享庫。問題是,這個庫(就像我用-m32指定的那樣)是一個32位庫,並且不會在我的64位版本庫上運行。使用Python,我嘗試加載庫(使用ctypes.cdll.LoadLibrary())

OSError: out.so: wrong ELF class: ELFCLASS32 

我發現了-mx32選項,並根據docs這正是我想要的:

-mx32選項將int,long和指針類型設置爲32位, 爲x86-64體系結構生成代碼。

所以,我通過-mx32到編譯器和鏈接(更換我-m32選項),並得到以下(剪斷輸出):

/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。

我已經安裝了gcc-4.8-multilib和g ++ - 4.8-multilib。

我的庫路徑是:

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/東西,鏈接器會只與工作的庫綁定。

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位,長整型應該是32位,整個事情應該在x86_64上運行。 -mx32表示它會做到這一點(對吧?)。

檢查對象之一-m32編譯後:

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

而且隨着-mx32編譯後檢查相同的對象:

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

我要對這個錯誤的方式?我還可以使用我的32位共享庫和某種兼容層嗎?

我看到一個針對gcc 4.7的bug report關於這些鏈接錯誤......但我沒有看到太多的結論。 This page說gcc 4.8是x32的推薦最小值,所以我安裝了它。仍然 - 我無法把它鏈接起來。 -m32鏈接正常。

+0

假設您確實需要一個ELF 64位,它看起來像鏈接器無法找到由glibc提供的libm.so。你可以在庫路徑中加入'/ usr/lib64'嗎? – alvits

+0

感謝您的回覆@alvits,但我沒有這個目錄:'$ cd/usr/lib64 bash:cd:/ usr/lib64:沒有這樣的文件或目錄' – skelliam

回答

1

-mx32選項不是你想要的。它編譯代碼爲the x32 ABI,它使用帶有64位寄存器和指令的32位地址。由此產生的代碼與32位處理器(因爲它使用64位指令)不兼容,但是與64位代碼(將使用64位地址)不兼容。

使問題變得更加複雜,您在Windows上進行的測試一直沒有按照您的想法進行。將/DWIN32傳遞給Visual C++編譯器只定義了一個名爲WIN32的宏(如-DWIN32對於GCC);它不會使編譯器生成32位二進制文​​件。 64位Windows可執行文件不能加載32位庫的;你一直在測試的庫實際上是64位的。

如果要單元測試32位代碼,則需要在完全32位系統上進行測試。 X32不是這樣一個系統。

+0

Thanks @duskwuff。你能解釋一下Visual Studio如何完成我想要的任務嗎?是否有某種允許32位dll運行的抽象層? – skelliam

+0

它不;您在Windows上的測試方法存在缺陷。 '/ DWIN32'只是定義了一個名爲「WIN32」的宏;它實際上並沒有使Visual Studio構建32位代碼。 – duskwuff

+0

任何爲什麼它會在Windows中編譯和鏈接?我想真正的問題是爲什麼我不能與mx32鏈接?我會弄清楚之後會發生什麼。或者,我應該採取的下一步方法是什麼? @duskwuff – skelliam

0

您最初的錯誤,試圖加載您成功構建的庫,表明您沒有使用32位版本的Python,因此無法構建32位共享庫。

如果您安裝了一個i386(32位)版本的Python,它應該能夠加載該庫。更重要的是,這是您需要在嵌入式i386目標上運行的Python版本。

請注意,以上所有假設您的「32位嵌入式處理器」是i386兼容的。如果不是(它是一個ARM或MIPS或其他一些32位嵌入式處理器),那麼您需要爲該目標安裝交叉編譯器來構建庫和模擬器(例如QEMU)來運行可執行文件。

+0

最終目標是從64位版本的Matlab中加載它。我不需要完全模仿目標。我已經對eeprom讀取等目標特定位進行了抽象。我可以在Windows中做我想做的事情。我以爲我可以在Linux中構建相同的代碼......聽起來好像答案是,將其正確移植或忘記它。 – skelliam