2009-05-31 7 views
6

Esto suena como una pregunta tonta al principio, pero tengan paciencia conmigo.¿Qué parte (específicamente) de un ejecutable nativo lo hace no portátil?

Es de conocimiento común que los binarios para una arquitectura de CPU no se ejecutan en otros. Entonces, por ejemplo, es imposible ejecutar (sin una capa de compatibilidad de algún tipo), un binario x86 en un chip sparc64. Los conjuntos de instrucciones son diferentes, por lo que claramente no funcionará.

Pero cuando el binario es para la misma CPU, pero para un sistema operativo diferente, qué parte del código impide que la ejecución sea posible. Por ejemplo, ejecutando un binario Solaris x86 en una caja Linux x86. ¿Asumo que hay algún tipo de código auxiliar específico de la plataforma que se relaciona con el enlazador en tiempo de ejecución o el planificador de procesos?

Me gustaría saber. Gracias.

Respuesta

12

Hay una serie de razones. Los principales, ordenados en "distancia del metal" son:

  1. Los sistemas operativos pueden tener diferentes formatos binarios para archivos ejecutables. En este caso, no podrá cargar el binario en primer lugar.
  2. El programa puede usar otro método para indicar que desean realizar una llamada al sistema (por ejemplo, INT21 vs INT80).
  3. El programa puede depender de llamadas al sistema que no están presentes en el otro sistema operativo (por ejemplo, dlopen())
  4. El programa puede confiar en la biblioteca estándar no presente en el otro sistema operativo.
  5. El programa puede depender de otras bibliotecas que no están disponibles en el otro sistema operativo.

Por supuesto, hay muchas más maneras en que un programa que se ejecuta en un entorno inesperado puede fallar espectacularmente.

+1

Las razones 1, 2 y 3 son muy fáciles de corregir. Linux ya es compatible con una gran cantidad de formatos ejecutables. Se podrían crear nuevas interrupciones con un módulo de kernel cargable. Y las llamadas al sistema generalmente se corresponden bastante bien entre diferentes sistemas operativos. – Zifre

+0

Debería haber dicho que estamos asumiendo ELF :) Gracias por la respuesta. –

1

Es bibliotecas específicas del sistema que no son siempre portátiles. Por ejemplo, no puede usar la ventana win32 de api en vanilla linux (y sí, me doy cuenta de que hay campos de trabajo para esto, como el vino, no es el mejor ejemplo).

3

Principalmente son las API. Por ejemplo, las API de Win32 no están realmente disponibles en Linux. Sin embargo, es posible evitar esto, ver Wine. El formato ejecutable también puede ser diferente (ELF/PE), pero se puede arreglar con bastante facilidad (Wine hace esto, permite ejecutar ejecutables PE en Linux).

Además, su ejemplo de mezcla de ejecutables de Solaris y Linux sería bastante fácil de implementar, ya que los sistemas operativos son muy similares (ELF para formato ejecutable, API POSIX, sistema de ventanas X, etc.). FreeBSD ya puede ejecutar ejecutables de Linux. La razón por la que esto no es tan común es simplemente que no hay mucha demanda para ello. Hay muchos más programas de Windows que * programas NIX, por lo que se creó Wine. Hay muchos más programas de Linux que FreeBSD, por lo que FreeBSD implementó la capa de compatibilidad de Linux. Solaris podría eventualmente implementar algo similar también. Sin embargo, no espere lo contrario (ejecutables de Solaris/BSD en Linux), ya que simplemente no hay demanda.

1

Bibliotecas del sistema y API. El código simple real debería funcionar. Esta es la razón por la cual capas como Wine no hacen ninguna emulación de CPU, solo implementan de nuevo la API de Windows.

0

Como ya se ha señalado, la incompatibilidad tiene menos que ver con los propios formatos ejecutables que con las bibliotecas a las que hace referencia un ejecutable.

creo que Linux es realmente compatible con un número de diferentes formatos ejecutables aunque podría estar equivocado aquí

5

Hay cuatro problemas:

  1. diferentes sistemas operativos paquete sus ejecutables binarios de forma diferente (por ejemplo, Linux ELF vs formato Windows);
  2. Diferentes conjuntos de instrucciones en diferentes arquitecturas de CPU;
  3. Los diferentes sistemas operativos tienen diferentes llamadas al sistema (por ejemplo, CreateProcess() en Win32 frente a fork() en Linux/Unix);
  4. Diferencias tales como rutas, caracteres legales, separadores de directorios, etc.

Se supone que las bibliotecas que no son del sistema están presentes en ambas, de lo contrario, esa es otra diferencia.

1

Además de lo que otros han dicho, el formato real del ejecutable puede ser diferente. Entonces, cuando el sistema operativo viene a cargarlo, no encuentra los valores que espera para el código, los segmentos de datos, etc. en los lugares correctos en el archivo.

+1

Una vez más, eso podría solucionarse con bastante facilidad. Linux ya es compatible con muchos formatos ejecutables. Wine hace esto también. Las bibliotecas son * mucho * factor más grande que el formato ejecutable. – Zifre

2

Además del formato binario y otras características de "empaquetado" (que pueden no ser exactamente triviales tampoco) También existen consecuencias que puede encontrar en casi todos los fragmentos de código. Cosas como

  1. PIC pueden hacer que cada acceso global dependa de supuestos específicos del sistema al volver a cargar el puntero GOT, y suposiciones sobre compensaciones adicionales.
  2. Muchos sistemas tienen un ABI específico, pasando pequeñas estructuras en registros, saltando registros encontrados para fines de alineación, la reserva de registros para fines especiales Algunos tienen varios (como ARM EABI y OABI) cuestiones relacionadas
  3. hilo de almacenamiento local, las variables que se crea una instancia por hilo están estrechamente vinculados a las instalaciones que especifica el sistema operativo. Opciones de registro, compensaciones, etc.
  4. Algunos sistemas operativos (más notablemente) Windows tienen soporte para un cierto formato de manejo de excepciones para permitir el manejo de excepciones entre idiomas e incluso a través de la máquina (a través de DCOM).
  5. Los sistemas de programa cruzado de nivel más alto (como COM, pero también, por ejemplo, la interoperabilidad de Objective C en Mac o la compatibilidad con una cierta combinación de versiones de KDE-gcc) también pueden tener ciertos requisitos en el diseño de VMT.
  6. Algunos enlazadores y formatos admiten compensaciones negativas a una sección, otras no.

Tenga en cuenta que esto es solo un braindump de cosas que podrían ser interesantes de examinar. Probablemente no esté completo, y no todos podrían aplicarse. Algunos de los puntos anteriores pueden superponerse (por ejemplo, reservar un registro para TLS o PIC también es un cambio de ABI)

Cuestiones relacionadas