Являются ли объектные файлы независимыми от платформы?

Можно ли скомпилировать программу на одной платформе и связать с другой? Что содержит объектный файл? Можем ли мы удалить исполняемый файл для создания объектного файла?


person Xinus    schedule 23.01.2010    source источник


Ответы (9)


Нет. В целом форматы объектных файлов могут быть одинаковыми, например. 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 с использованием соответствующего кросс-компилятора. Я делаю это здесь.

person Richard Pennington    schedule 23.01.2010

Можно ли скомпилировать программу на одной платформе и связать с другой?

В общем, нет. Объектные файлы специфичны для компилятора. Некоторые компиляторы выдают COFF, другие выдают ELF и т. д. Кроме того, вам придется беспокоиться о соглашениях о вызовах, системных вызовах и т. д. Это зависит от платформы.

Что содержит объектный файл?

Таблицы символов, код, перемещение, связывание и отладочная информация.

Если вам нужна переносимость, напишите переносимый C/C++ и позвольте компилятору, совместимому с конкретной платформой, сделать всю работу.

person jason    schedule 23.01.2010
comment
Я не думаю, что зашел бы так далеко, чтобы сказать, что перекрестная компиляция опасна. Очень немногие приложения для iPhone компилируются непосредственно на iPhone. Или приложения Wii. ;-) - person Richard Pennington; 23.01.2010
comment
@Richard, да, но вы используете другой режим компиляции для компиляции приложений для iPhone, чем приложения для OS X. Он компилируется на другой платформе, но предназначен именно для этого. :D - person Gordon Gustafson; 23.01.2010
comment
@CrazyJugglerDrummer: Точно моя точка зрения. Кросс-компиляция — очень распространенная и безопасная вещь. - person Richard Pennington; 23.01.2010

На практике нет. Есть несколько вещей, которые должны быть одинаковыми: - интерфейс ОС (те же системные вызовы) - расположение данных в памяти (порядок байтов, заполнение структур и т. д.) - соглашение о вызовах - формат объектного файла (например, ELF довольно стандартен для Linux)

Посмотрите ABI для получения дополнительной информации.

person abc    schedule 23.01.2010

Нет необходимости повторять еще раз: объектные файлы C/C++ не переносимы.

С другой стороны, ANSI C — один из самых переносимых языков. Возможно, вы не сможете получить свои объектные файлы, но перекомпиляция вашего исходного кода, вероятно, сработает, если вы будете придерживаться стандарта ANSI C. Это также может быть верно и для C++.

Я не знаю, насколько универсален GNU C++, но если вы можете скомпилировать с помощью gcc на одном компьютере, вы можете работать на любой другой машине, на которой также установлен gcc. Почти каждая машина, о которой вы только можете подумать, имеет компилятор C. Это переносимость.

person duffymo    schedule 23.01.2010
comment
Верно... скомпилируй один раз, запускай где угодно... медленно ;-) - person Sam Post; 23.01.2010

Нет. Они не зависят от платформы. Возьмем, к примеру, компилятор GNU C (gcc), который генерирует двоичные файлы ELF. Компиляторы Windows (Borland, Microsoft, Open Watcom) могут создавать формат Windows Binary PE (Portable Executable). Двоичные файлы Novell имеют формат NLM (Netware Loadabable Module).

В приведенных выше примерах различных выходных данных, которые зависят от компилятора, компоновщик на платформе Windows никоим образом не может знать что-либо о формате ELF или формате NLM, поэтому невозможно комбинировать разные форматы для создания исполняемого файла, который может работать на любая платформа.

Возьмите Mac OSX от Apple (до того, как были установлены чипы Intel), они работали на платформе PowerPC, даже если у него есть компилятор GNU C, двоичный файл предназначен специально для платформы PowerPC, если вы возьмете этот двоичный файл и скопируете его на платформу Linux, он не будет работать из-за различий в инструкциях микропроцессора платформы, то есть PowerPC.

Опять же, тот же принцип будет применяться к системе мэйнфреймов OS/390: компилятор GNU C, который создает двоичный файл для этой платформы, не будет работать на Apple Mac OSX до Intel.

Редактировать: Чтобы уточнить, как будет выглядеть формат 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.

Теперь сравните это с форматом 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.

Надеюсь, это поможет. С уважением, Том.

person t0mm13b    schedule 23.01.2010

Они зависят от платформы. Например, команда file выводит следующее:

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

C++ имеет дополнительную деталь: имена, которые он помещает в объектный файл, обычно «искажаются» для обеспечения безопасности типов для перегруженных имен. Методы, используемые для изменения имен, не являются частью стандарта C++ (на самом деле, изменение имен — это деталь реализации, которая вообще не требуется, если поставщик может придумать другой способ реализации перегрузки). Таким образом, даже для одной и той же целевой платформы вы не можете рассчитывать на возможность связывания объектных файлов от одного поставщика компилятора к другому.

Бывают случаи, когда поставщик компилятора может изменить схему изменения имени от одной версии компилятора к другой. Например, я считаю, что существуют версии MSVC, для которых вы не можете надежно связать объектные файлы C++ из более старой версии в более новую версию.

Некоторые платформы имеют изменение имени, указанное в стандарте ABI для платформы (например, ARM, которая использует изменение имени, указанное в универсальном C++ ABI, изначально разработанном для SVr4 на Itanium), а другие нет (Windows). Даже для ARM я не уверен, насколько интероперабельным стандарт ABI делает связывание объектных файлов C++, созданных разными компиляторами.

person Michael Burr    schedule 23.01.2010
comment
MSVC++6 на самом деле не совместим с MSVC++7; не на уровне ABI и не в искажении имен. Последнее предотвращает несчастные случаи. - person MSalters; 25.01.2010

Я просто хотел сказать, что пока они используют одну и ту же архитектуру процессора и формат объекта, а также соглашение о вызовах (обычно в настоящее время его создает производитель процессора), есть много шансов, что объектные файлы работают взаимозаменяемо.

Однако даже в C компилятор делает некоторые предположения о наличии определенных библиотечных функций, таких как защита стека (о которой я знаю), которые не обязательно должны быть одинаковыми на обеих платформах. в случае создания такого кода объекты не будут напрямую совместимы.

Системные вызовы не имеют особого значения, если системы вообще их разделяют, поскольку обычно они вызываются через C-оболочки в стандартных библиотеках.

В конце концов, это применимо только к C и очень похожим операционным системам, таким как Linux и BSD, но это может случиться.

person Community    schedule 24.01.2010

Можно скомпилировать с помощью GCC и создать объектный файл в формате файла ELF и преобразовать объектный файл для работы в Visual Studio. Я делал это несколько раз.

Для этого вам нужно знать три вещи: соглашение о вызове функции, формат объектного файла и искажение имени функции.

Соглашения о вызовах функций. Для 32-разрядного режима соглашение о вызовах функций простое: они одинаковы для Windows и Unix. Для 64-битного режима Windows и Unix используют разные соглашения о вызовах. Следовательно, в 64-битном режиме вы должны правильно соблюдать соглашение о вызовах. Вы можете сделать это либо при компиляции, либо из самого объектного файла. Это намного проще сделать при компиляции. Чтобы GCC использовал соглашение о вызовах Windows, используйте -mabi=ms. Для этого из объектного файла вам понадобится инструмент. Инструмент Agner Fog objconv может сделать это для некоторых функций.

Формат файла возражения. Чтобы преобразовать формат файла объекта, вам нужен инструмент. Для этого я использую инструмент objconv от Agner Fog. Он может конвертировать из нескольких различных форматов объектных файлов. Например, чтобы преобразовать ELF64 в COFF64 (PE32+), выполните objconv -fcoff64 foo.o foo.obj.

Изменение имени функции: из-за перегрузки функций в компиляторах C++ имена функций искажаются. Подробную информацию о каждом компиляторе можно найти в руководстве Агнера Фога по соглашениям о вызовах. GCC и Visual Studio искажают имена функций по-разному. Чтобы обойти это, перейдите к определениям функций с помощью extern "C"

Если вы правильно поняли все три из них и не делаете никаких специфичных для ОС вызовов, вы можете успешно использовать свои объектные файлы между компиляторами. Конечно, могут возникнуть и другие проблемы. См. руководство в objconv для более подробной информации. Но до сих пор этот метод работал хорошо для меня.

person Z boson    schedule 19.01.2014