代码之家  ›  专栏  ›  技术社区  ›  Xinus

对象文件是否独立于平台?

  •  24
  • Xinus  · 技术社区  · 15 年前

    是否可以在一个平台上编译程序并与另一个平台链接?对象文件包含什么?我们可以取消可执行文件的链接以生成对象文件吗?

    9 回复  |  直到 11 年前
        1
  •  22
  •   Richard Pennington    15 年前

    不。在一般情况下,对象文件格式可能相同,例如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
    

    对象代码通常不仅特定于处理器,而且还特定于操作系统,例如,如果它包含系统调用。


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

    当然。如果使用交叉编译器。此编译器专门针对平台并生成与目标平台兼容的对象文件(和程序)。因此,您可以使用x86 Linux系统,例如,使用适当的交叉编译器为基于PowerPC或ARM的系统生成程序。我做到了 here .

        2
  •  17
  •   jason    13 年前

    是否可以在一个平台上编译程序并与另一个平台链接?

    一般来说,没有对象文件是特定于编译器的。一些编译器会吐出 COFF ,其他人吐出来 ELF 除此之外,您还需要担心调用约定、系统调用等。这取决于平台。

    对象文件包含什么?

    符号表、代码、重定位、链接和调试信息。

    如果你所追求的是便携性,那么编写可移植的C/C++,让一个特定于平台的兼容编译器完成这项工作。

        3
  •  5
  •   abc    15 年前

    实际上,没有。有几件事必须是相同的: -操作系统接口(相同的系统调用) -数据的内存布局(endianness、结构填充等) -呼叫约定 -对象文件格式(例如,ELF在Linux上相当标准)

    有关详细信息,请查阅ABI。

        4
  •  4
  •   duffymo    15 年前

    它不需要再说一遍:C/C++对象文件是不可移植的。

    另一方面,ANSIC是目前最可移植的语言之一。您可能无法获取对象文件,但如果您坚持使用ANSIC标准,则重新编译源文件可能会起作用。这也同样适用于C++。

    我不知道通用的GNU C++是怎样的,但是如果你可以在一台计算机上用GCC编译,那么你就可以去安装GCC的任何其他机器。几乎每台你能想到的机器都有一个C编译器。 那是 便携性。

        5
  •  4
  •   t0mm13b    15 年前

    不,它们不是平台独立的。例如,生成ELF二进制文件的GNUC编译器(gcc)。Windows编译器(Borland、Microsoft、OpenWatcom)可以生成Windows二进制PE(可移植可执行文件)格式。Novell二进制文件是NLM(Netware可加载模块)格式。

    以上这些例子说明了不同的输出是编译器依赖的,在Windows平台上的链接器不可能知道任何关于ELF格式或NLM格式的信息,因此不可能组合不同的格式来生成一个可以在任何平台上运行的可执行文件。

    以苹果的Mac OSX(在英特尔芯片投入使用之前)为例,它们是在PowerPC平台上运行的,即使它有GNU C编译器,二进制文件也是专门针对PowerPC平台的,如果您要将该二进制文件复制到Linux平台上,它也不会因为平台MIC指令的不同而运行。RoProcessor,即PowerPC。

    同样,同样的原则也适用于OS/390大型机系统,一个为该平台生成二进制文件的GNU C编译器不会在英特尔苹果Mac OSX之前的版本上运行。

    编辑: 为了进一步澄清ELF格式的外观,可以通过运行 objdump -s main.o 在Linux下。

    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.
    

    现在将其与简单dll的PE格式进行比较

    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 ,是i386处理器的ELF格式。

    希望这有帮助, 最好的问候, 汤姆。

        6
  •  3
  •   Ahe    15 年前

    它们依赖于平台。例如,“文件”命令打印出以下内容:

    $ file foo.o
    foo.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
    
        7
  •  2
  •   Michael Burr    15 年前

    C++有另外的细节,即将其放入对象文件的名称通常是“MangLED”,以对重载的名称处理类型安全性。用于命名的方法不是C++标准的一部分(事实上,名称Mangle是一个实现细节,如果供应商可以想出一种不同的方法来实现重载,则根本不需要实现细节)。因此,即使对于同一个平台目标,也不能指望能够将对象文件从一个编译器供应商链接到另一个。

    有时编译器供应商可能会将名称管理方案从一个编译器版本更改为另一个。例如,我相信有MSVC版本,您不能将C++对象文件从旧版本可靠地链接到较新版本。

    一些平台的名称在平台的ABI标准中指定了名称(例如ARM,该名称使用了最初在ItnIn上针对SVR4开发的通用C++ ABI中指定的名称),但其他一些则没有(Windows)。即使对于ARM,我也不知道ABI标准如何使由不同编译器创建的C++对象文件链接起来。

        8
  •  2
  •   jbcreix    15 年前

    我只是想说,只要他们使用相同的 处理器体系结构 对象格式,以及调用约定(通常现在,处理器制造商创建了一个),对象文件有很多机会可以互换工作。

    但是,即使在C语言中,编译器也会对某些库函数(如堆栈保护(我知道的))进行一些假设,这两个平台上的函数不必相同。在生成此类代码的情况下,对象将不直接兼容。

    系统调用并不真正相关,只要系统像通常那样共享它们,它们是通过标准库中的C包装器调用的。

    最后,这只适用于C和非常类似的操作系统,如Linux和BSD,但也可能发生。

        9
  •  1
  •   Z boson    11 年前

    可以使用gcc编译并以elf文件格式创建对象文件,然后将对象文件转换为在Visual Studio中工作。我已经做了很多次了。

    要做到这一点,您需要知道三件事: 函数调用约定、对象文件格式和函数名管理。

    函数调用约定: 对于32位模式,函数调用约定很简单:对于Windows和Unix,它们是相同的。对于64位模式,Windows和Unix使用不同的调用约定。因此,在64位模式下,您必须使调用约定正确。您可以在编译时执行此操作,也可以从对象文件本身执行此操作。编译时这样做容易得多。要让GCC使用Windows调用约定,请使用 -mabi=ms . 要从对象文件执行此操作,需要一个工具。Agner Fog objconv 工具可以为某些功能执行此操作。

    异议文件格式: 要转换对象文件格式,需要一个工具。我用Agner Fog的objconv工具来做这个。它可以从几个不同的对象文件格式转换。例如,将ELF64转换为COFF64(PE32+)do objconv -fcoff64 foo.o foo.obj .

    函数名管理: 在C++编译器中,由于函数重载,函数名称就变模糊了。每个编译器的详细信息可以在Agner Fog的手册中找到。 calling convetions . gcc和Visual Studio的mangle函数名称不同。要解决此问题,请使用 extern "C"

    如果所有这三个都正确,并且没有进行任何特定于操作系统的调用,则可能无法在编译器之间成功地使用对象文件。当然还有其他问题。有关更多详细信息,请参阅objconv中的手册。但到目前为止,这种方法对我很有效。