Какая часть (в частности) собственного исполняемого файла делает его непереносимым? - PullRequest
6 голосов
/ 31 мая 2009

Поначалу это звучит глупо, но потерпите меня.

Общеизвестно, что двоичные файлы для одной архитектуры ЦП не работают на других. Так, например, невозможно запустить (без какого-либо уровня совместимости) двоичный файл x86 на чипе sparc64. Наборы инструкций различны, поэтому ясно, что они не будут работать.

Но когда двоичный файл предназначен для того же процессора, но для другой операционной системы, какая часть кода препятствует выполнению. Например, запуск бинарного файла x86 Solaris на Linux-компьютере x86. Я предполагаю, что есть какая-то заглушка для конкретной платформы, которая относится к компоновщику времени выполнения или планировщику процесса?

Мне было бы интересно узнать. Спасибо.

Ответы [ 8 ]

12 голосов
/ 31 мая 2009

Есть несколько причин. Основные из них, заказанные на «расстоянии от металла»:

  1. Операционные системы могут иметь разные двоичные форматы для исполняемых файлов. В этом случае вы не сможете загрузить двоичный файл.
  2. Программа может использовать другой метод, чтобы указать, что они хотят выполнить системный вызов (например, INT21 против INT80).
  3. Программа может полагаться на системные вызовы, которых нет в других ОС (например, dlopen ())
  4. Программа может использовать стандартную библиотеку, отсутствующую в других ОС.
  5. Программа может полагаться на другие библиотеки, которые недоступны в других ОС.

Конечно, есть много других способов, с помощью которых программа, работающая в неожиданной среде, может неожиданно завершиться сбоем.

5 голосов
/ 31 мая 2009

Есть четыре проблемы:

  1. Различные операционные системы по-разному упаковывают свои двоичные исполняемые файлы (например, формат Linux ELF или Windows);
  2. Различные наборы команд для разных архитектур ЦП;
  3. Различные операционные системы имеют разные системные вызовы (например, CreateProcess () в Win32 против fork () в Linux / Unix);
  4. Различия, такие как пути, допустимые символы, разделители каталогов и т. Д.

Предполагается, что в обоих случаях присутствуют несистемные библиотеки, в противном случае это еще одно отличие.

3 голосов
/ 31 мая 2009

В основном это API. Например, Win32 API не доступны в Linux. Однако обойти это можно, см. Wine . Формат исполняемого файла также может быть другим (ELF / PE), но это можно исправить довольно легко (это делает Wine; он позволяет выполнять исполняемые файлы PE в Linux).

Кроме того, ваш пример смешивания исполняемых файлов Solaris и Linux будет довольно легко реализовать, поскольку ОС очень похожи (ELF для исполняемого формата, API POSIX, система X Window и т. Д.). FreeBSD уже может запускать исполняемые файлы Linux. Причина, по которой это не так часто, заключается в том, что спрос на него невелик. Windows-программ гораздо больше, чем * NIX, поэтому Wine был создан. Linux-программ намного больше, чем FreeBSD, поэтому FreeBSD реализовала уровень совместимости с Linux. Солярис может со временем реализовать нечто подобное. Однако не стоит ожидать обратного (исполняемые файлы Solaris / BSD в Linux), поскольку на это просто нет спроса.

2 голосов
/ 06 июня 2009

Помимо двоичного формата и других «упаковочных» функций (которые тоже могут быть не совсем тривиальными) Есть также последствия, которые вы обнаружите почти во всех фрагментах кода. Вещи как

  1. PIC может заставить каждый глобальный доступ полагаться на специфические для системы допущения при перезагрузке указателя GOT и допущения на дополнительные смещения.
  2. Многие системы имеют определенный ABI, передавая небольшие структуры в регистрах, пропуская регистры для выравнивания, резервируя регистры для специальных целей. Некоторые имеют несколько (например, ARM EABI и OABI)
  3. проблемы, связанные с локальным хранением потока, переменные, которые создаются для каждого потока, тесно связаны со средствами, указанными ОС. Выбор регистра, смещения и т. Д.
  4. Некоторые окна ОС (в первую очередь) имеют поддержку определенного формата обработки исключений, чтобы разрешить обработку исключений между языками и даже между компьютерами (через DCOM).
  5. Кросс-программные системы более высокого уровня (такие как COM, но также, например, совместимость с Objective C на Mac или совместимость с определенной версией KDE-gcc) также могут иметь определенные требования к компоновке VMT.
  6. Некоторые компоновщики и форматы поддерживают смещения, отрицательные для раздела, некоторые нет.

Обратите внимание, что это просто мозговая штучка, которую интересно изучить. Это, вероятно, не завершено, и не все могут применяться. Некоторые из приведенных выше пунктов могут перекрываться (например, резервирование регистра для TLS или PIC также является изменением ABI)

1 голос
/ 31 мая 2009

В дополнение к тому, что сказали другие, фактический формат исполняемого файла может отличаться. Поэтому, когда ОС загружает ее, она не находит ожидаемых значений кода, сегментов данных и т. Д. В нужных местах файла.

1 голос
/ 31 мая 2009

Системные библиотеки и API. На самом деле простой код должен работать. Вот почему такие слои, как Wine, не выполняют никакой эмуляции процессора, они просто заново реализуют Windows API.

1 голос
/ 31 мая 2009

Это системные библиотеки, которые не всегда переносимы. Например, вы не можете использовать api окна win32 на vanilla linux (и да, я понимаю, что для этого есть обходные пути, например wine, это не лучший пример).

0 голосов
/ 31 мая 2009

Как уже указывалось, несовместимость меньше связана с самими исполняемыми форматами, чем с библиотеками, на которые ссылается исполняемый файл.

Я считаю, что Linux на самом деле совместим с рядом различных исполняемых форматов, хотя я могу ошибаться

...