2010-01-23 90 views

回答

18

否。一般來說,目標文件格式可能是相同的,例如, ELF,但目標文件的內容因系統而異。

目標文件包含的東西,如:

Object code that implements the desired functionality 
A symbol table that can be used to resolve references 
Relocation information to allow the linker to locate the object code in memory 
Debugging information 

目標代碼通常不僅是處理器特有的,但也OS特定如果,例如,它包含了系統調用。


編輯:

Is it possible to compile program on one platform and link with other ? 

絕對。如果你使用交叉編譯器。該編譯器專門針對平臺並生成與目標平臺兼容的目標文件(和程序)。因此,例如,您可以使用X86 Linux系統,使用適當的交叉編譯器爲基於powerpc或ARM的系統製作程序。我這樣做here

16

是否有可能編譯在一個平臺上,並鏈接與其他計劃?

一般來說,沒有。對象文件是編譯器特定的。一些編譯器吐出COFF,其他吐出ELF等。最重要的是,你不得不擔心調用約定,系統調用等。這是平臺依賴的。

什麼是目標文件包含哪些內容?

符號表,代碼,搬遷,鏈接和調試信息。

如果你是後是便攜性,那麼編寫可移植的C/C++,讓特定於平臺的兼容性的編譯器做的工作。

+4

我不認爲我竟然說交叉編譯是危險的。很少iPhone應用程序直接在iPhone上編譯。或Wii應用程序。 ;-) – 2010-01-23 15:13:53

+0

@Richard,是的,但是您使用不同的編譯「模式」來編譯OS X應用程序的Iphone應用程序。它正在被編譯在不同的平臺上,但它的具體目的是爲了做到這一點。 :D – 2010-01-23 15:52:20

+4

@CrazyJugglerDrummer:我的確切點。交叉編譯是一件非常常見而且安全的事情。 – 2010-01-23 15:58:51

3

它們依賴於平臺。例如文件命令輸出如下:

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

在實踐中,沒有。有幾件事情必須是相同的: - 操作系統接口(相同的系統調用) - 數據的內存佈局(字節序,結構填充等) - 調用約定 - 目標文件格式(例如ELF很漂亮標準在Linux上)

查找ABI瞭解更多信息。

4

它不需要再說一遍:C/C++目標文件不可移植。

另一方面,ANSI C是最便攜的語言之一。你可能無法拿起你的目標文件,但如果你堅持ANSI C標準,重新編譯源代碼很可能會起作用。 C++也是如此。

我不知道GNU C++如何萬能是的,但如果你可以用一臺計算機上的gcc編譯,你是好去任何其他機器也已安裝GCC上。幾乎所有你能想到的機器都有一個C編譯器。 這就是的便攜性。

+1

Java更好! :p – abc 2010-01-23 14:49:19

+5

正確...編譯一次,在任何地方運行......慢慢地;-) – 2010-01-23 15:00:25

+2

幾乎所有你能想到的機器都有一個Java VM? Nah ... – Frunsi 2010-01-23 15:55:47

4

不。他們不是平臺獨立的。以GNU C編譯器(gcc)爲例,它生成ELF二進制文件。 Windows編譯器(Borland,Microsoft,Open Watcom)可以生成Windows Binary PE(可移植可執行文件)格式。 Novell二進制文件是NLM(Netware Loadabable模塊)格式。

上面這些依賴於編譯器的不同輸出的例子,Windows平臺上的鏈接器無法知道ELF格式和NLM格式的任何內容,因此不可能將不同的格式組合起來以生成可執行文件可以在任何平臺上運行。

拿蘋果的Mac OSX(在Intel芯片投入使用之前),他們在PowerPC平臺上運行,即使它有GNU C編譯器,該二進制文件專門用於PowerPC平臺,如果你要該二進制文件並將其複製到Linux平臺上,它不會因平臺的微處理器(即PowerPC)的指令差異而運行。

同樣的原理也適用於OS/390大型機系統,爲該平臺生成二進制文件的GNU C編譯器不能在英特爾之前的Apple Mac OSX上運行。

編輯:爲了進一步闡明ELF格式的外觀如下,這是通過在Linux下運行objdump -s main.o獲得的。

 
main.o:  file format elf32-i386 

Contents of section .text: 
0000 8d4c2404 83e4f0ff 71fc5589 e55183ec .L$.....q.U..Q.. 
0010 14894df4 a1000000 00a30000 0000a100 ..M............. 
0020 000000a3 00000000 8b45f483 38010f8e .........E..8... 
0030 9c000000 8b55f48b 420483c0 048b0083 .....U..B....... 
0040 ec086800 00000050 e8fcffff ff83c410 ..h....P........ 
0050 a3000000 00a10000 000085c0 7520a100 ............u .. 
0060 00000050 6a1f6a01 68040000 00e8fcff ...Pj.j.h....... 
0070 ffff83c4 10c745f8 01000000 eb5a8b45 ......E......Z.E 
0080 f4833802 7e218b55 f48b4204 83c0088b ..8.~!.U..B..... 
0090 0083ec08 68240000 0050e8fc ffffff83 ....h$...P...... 
00a0 c410a300 000000a1 00000000 85c07520 ..............u 
00b0 a1000000 00506a20 6a016828 000000e8 .....Pj j.h(.... 
00c0 fcffffff 83c410c7 45f80100 0000eb08 ........E....... 
00d0 e8fcffff ff8945f8 8b45f88b 4dfcc98d ......E..E..M... 
00e0 61fcc3        a.. 
Contents of section .rodata: 
0000 72000000 4552524f 52202d20 63616e6e r...ERROR - cann 
0010 6f74206f 70656e20 696e7075 74206669 ot open input fi 
0020 6c650a00 77000000 4552524f 52202d20 le..w...ERROR - 
0030 63616e6e 6f74206f 70656e20 6f757470 cannot open outp 
0040 75742066 696c650a 00     ut file.. 
Contents of section .comment: 
0000 00474343 3a202847 4e552920 342e322e .GCC: (GNU) 4.2. 
0010 3400         4. 

現在比較,給PE格式簡單的DLL

 
C:\Program Files\Microsoft Visual Studio 9.0\VC\bin>dumpbin /summary "C:\Documents and Settings\Tom\My Documents\Visual Studio 2008\Projects\SimpleLib\Release\SimpleLib.dll" 
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01 
Copyright (C) Microsoft Corporation. All rights reserved. 


Dump of file C:\Documents and Settings\Tom\My Documents\Visual Studio 2008\Projects\SimpleLib\Release\SimpleLib.dll 

File Type: DLL 

    Summary 

     1000 .data 
     1000 .rdata 
     1000 .reloc 
     1000 .rsrc 
     1000 .text 

請注意,在部分的差異,ELF下,有.bss.text.rodata.comment,並且是一個ELF格式爲i386處理器。

希望這會有所幫助, 最好的問候, 湯姆。

2

C++有額外的細節,它放入一個對象文件的名稱通常會被「破壞」以處理重載名稱的類型安全。用於修改名稱的方法不是C++標準的一部分(事實上,如果供應商可以採用不同的方式來實現重載,名稱修改就是一個根本不需要的實現細節)。因此,即使對於相同的平臺目標,也不能指望能夠將來自一個編譯器供應商的對象文件鏈接到另一個編譯器供應商。

有時編譯器供應商可能會將名稱修改方案從一個編譯器版本更改爲另一個。例如,我相信有些MSVC版本無法將C++對象文件從較舊版本可靠地鏈接到較新版本。

某些平臺在平臺的ABI標準中指定了名稱mangling(例如ARM,它使用在最初爲Itanium上的SVr4開發的通用C++ ABI中指定的名稱修改),但其他平臺不支持(Windows )。即使對於ARM,我也不確定ABI標準如何實現互連,從而鏈接由不同編譯器創建的C++對象文件。

+0

MSVC++ 6與MSVC++ 7並不真正兼容;不在ABI水平,也不在名義上。後者可防止事故發生。 – MSalters 2010-01-25 13:36:44

2

我只是想,只要他們使用相同的處理器架構和對象格式,以及調用約定說,(通常如今,處理器製造商創建一個),有目標文件的工作很多機會互換。

但是,即使在C語言中,編譯器也會對某些庫函數(如我所知)存在的某些庫函數做出一些假設,而這些函數在兩個平臺上都不必相同。在生成這種代碼的情況下,這些對象不會直接兼容。

只要系統共享它們,系統調用並不真正相關,因爲通常它們是通過標準庫中的C封裝器調用的。

最後,這隻適用於C和非常類似的操作系統,如Linux和BSD,但它可能會發生。

1

可以使用GCC進行編譯並以ELF文件格式創建目標文件並將目標文件轉換爲在Visual Studio中工作。我現在已經多次這樣做了。

要做到這一點,您需要知道三件事:函數調用約定,對象文件格式和函數名稱修改。

函數調用約定:對於32位模式下的功能調用約定很簡單:他們是爲Windows和Unix一樣。對於64位模式,Windows和Unix使用不同的調用約定。因此,在64位模式下,您必須使調用約定正確。您可以在編譯時執行此操作,也可以從對象文件本身執行此操作。編譯時做這件事更容易。要讓GCC使用Windows調用約定,請使用-mabi=ms。要從目標文件中執行此操作,您需要一個工具。 Agner Fog的objconv工具可以爲一些功能做到這一點。

異議文件格式:要轉換目標文件格式,您需要一個工具。我使用Agner Fog的objconv工具。它可以從幾種不同的目標文件格式轉換而來。例如,要將ELF64轉換爲COFF64(PE32 +),請執行objconv -fcoff64 foo.o foo.obj

函數名稱修改:由於C++編譯器中的函數重載,會調用函數名稱。每個編譯器的細節可以在Agner Fog的手冊calling convetions中找到。 GCC和Visual Studio的mangle函數名稱不同。要解決此問題,請執行以下操作:extern "C"

如果您將所有這三項都正確,並且未進行任何操作系統特定調用,則可能會成功在編譯器之間使用對象文件。當然還有其他問題可能發生。有關更多詳細信息,請參閱objconv手冊。但到目前爲止,這種方法對我來說效果很好。