stringtranslate.com

Ejecutable portátil

El formato Portable Executable ( PE ) es un formato de archivo para ejecutables , código objeto , DLL y otros utilizados en versiones de 32 y 64 bits de los sistemas operativos Windows , y en entornos UEFI . [2] El formato PE es una estructura de datos que encapsula la información necesaria para que el cargador del sistema operativo Windows administre el código ejecutable empaquetado . Esto incluye referencias de bibliotecas dinámicas para vincular tablas de exportación e importación de API , datos de administración de recursos y datos de almacenamiento local de subprocesos (TLS). En los sistemas operativos NT , el formato PE se utiliza para EXE , DLL , SYS ( controlador de dispositivo ), MUI y otros tipos de archivos. La especificación Unified Extensible Firmware Interface (UEFI) establece que PE es el formato ejecutable estándar en entornos EFI. [3]

En los sistemas operativos Windows NT, PE actualmente admite las arquitecturas de conjunto de instrucciones (ISA) x86-32 , x86-64 (AMD64/Intel 64), IA-64 , ARM y ARM64 . Antes de Windows 2000 , Windows NT (y por lo tanto PE) admitía las ISA MIPS , Alpha y PowerPC . Debido a que PE se usa en Windows CE , continúa admitiendo varias variantes de MIPS, ARM (incluido Thumb ) y SuperH ISA. [4]

Los formatos análogos a PE son ELF (usado en Linux y la mayoría de las otras versiones de Unix ) y Mach-O (usado en macOS e iOS ).

Historia

Microsoft migró al formato PE desde los formatos NE de 16 bits con la introducción del sistema operativo Windows NT 3.1 . Todas las versiones posteriores de Windows, incluido Windows 95/98/ME y la adición de Win32 a Windows 3.1x, admiten la estructura de archivos. El formato ha conservado un soporte heredado limitado para cerrar la brecha entre los sistemas basados ​​en DOS y NT. Por ejemplo, los encabezados PE/COFF todavía incluyen un programa ejecutable de DOS , que por defecto es un código auxiliar de DOS que muestra un mensaje como "Este programa no se puede ejecutar en modo DOS" (o similar), aunque puede ser un DOS completo. versión del programa (un caso notable posterior es el instalador de Windows 98 SE). [5] Esto constituye una forma de binario gordo . PE también continúa sirviendo a la cambiante plataforma Windows. Algunas extensiones incluyen el formato .NET PE (ver más abajo), una versión con soporte de espacio de direcciones de 64 bits llamada PE32+, [6] y una especificación para Windows CE.

Detalles técnicos

Disposición

Estructura de un ejecutable portátil de 32 bits

Un archivo PE consta de una serie de encabezados y secciones que le indican al vinculador dinámico cómo asignar el archivo a la memoria. Una imagen ejecutable consta de varias regiones diferentes, cada una de las cuales requiere una protección de memoria diferente; por lo que el inicio de cada sección debe estar alineado con el límite de una página. [7] Por ejemplo, normalmente la sección .text (que contiene el código del programa) se asigna como ejecución/solo lectura, y la sección .data (que contiene variables globales) se asigna como escritura sin ejecución/lectura. Sin embargo, para evitar desperdiciar espacio, las diferentes secciones no están alineadas en las páginas del disco. Parte del trabajo del vinculador dinámico es asignar cada sección a la memoria individualmente y asignar los permisos correctos a las regiones resultantes, de acuerdo con las instrucciones que se encuentran en los encabezados. [8]

tabla de importación

Una sección a tener en cuenta es la tabla de direcciones de importación (IAT), que se utiliza como tabla de búsqueda cuando la aplicación llama a una función en un módulo diferente. Puede tener la forma tanto de importación por ordinal como de importación por nombre . Debido a que un programa compilado no puede conocer la ubicación de memoria de las bibliotecas de las que depende, se requiere un salto indirecto cada vez que se realiza una llamada API. A medida que el enlazador dinámico carga módulos y los une, escribe direcciones reales en las ranuras IAT, de modo que apunten a las ubicaciones de memoria de las funciones de biblioteca correspondientes. Aunque esto agrega un salto adicional sobre el costo de una llamada dentro del módulo, lo que resulta en una penalización en el rendimiento, proporciona un beneficio clave: se minimiza la cantidad de páginas de memoria que el cargador debe cambiar mediante copia en escritura , lo que ahorra memoria. y tiempo de E/S del disco. Si el compilador sabe de antemano que una llamada será entre módulos (a través de un atributo dllimport), puede producir un código más optimizado que simplemente resulte en un código de operación de llamada indirecta . [8]

Mudanzas

Los archivos PE normalmente no contienen código independiente de la posición . En su lugar, se compilan en una dirección base preferida y todas las direcciones emitidas por el compilador/enlazador se fijan de antemano. Si un archivo PE no se puede cargar en su dirección preferida (porque ya está ocupado por otra cosa), el sistema operativo lo modificará . Esto implica volver a calcular cada dirección absoluta y modificar el código para usar los nuevos valores. El cargador hace esto comparando las direcciones de carga preferidas y reales y calculando un valor delta . Luego se agrega a la dirección preferida para obtener la nueva dirección de la ubicación de memoria. Las reubicaciones de bases se almacenan en una lista y se agregan, según sea necesario, a una ubicación de memoria existente. El código resultante ahora es privado para el proceso y ya no se puede compartir , por lo que muchos de los beneficios de ahorro de memoria de las DLL se pierden en este escenario. También ralentiza significativamente la carga del módulo. Por esta razón, se debe evitar el cambio de base siempre que sea posible, y las DLL enviadas por Microsoft tienen direcciones base precalculadas para no superponerse. Por lo tanto, en el caso de no rebase, PE tiene la ventaja de un código muy eficiente, pero en presencia de rebase, el impacto en el uso de memoria puede ser costoso. Esto contrasta con ELF , donde generalmente se prefiere el código totalmente independiente de la posición a la reubicación del tiempo de carga, compensando así el tiempo de ejecución a favor de un menor uso de memoria.

.NET, metadatos y formato PE

En un ejecutable .NET, la sección de código PE contiene un código auxiliar que invoca la entrada de inicio de la máquina virtual CLR , _CorExeMaino _CorDllMainen mscoree.dll, muy parecido a lo que ocurría en los ejecutables de Visual Basic . Luego, la máquina virtual hace uso de los metadatos .NET presentes, cuya raíz IMAGE_COR20_HEADER(también llamada "encabezado CLR") es señalada por la entrada IMAGE_DIRECTORY_ENTRY_COMHEADER[9] en el directorio de datos del encabezado PE. IMAGE_COR20_HEADERSe parece mucho al encabezado opcional de PE y esencialmente desempeña su función para el cargador CLR. [4]

Los datos relacionados con CLR, incluida la propia estructura raíz, suelen estar contenidos en la sección de código común, .text. Se compone de algunos directorios: metadatos, recursos integrados, nombres seguros y algunos para la interoperabilidad del código nativo. El directorio de metadatos es un conjunto de tablas que enumeran todas las distintas entidades .NET en el ensamblado, incluidos tipos, métodos, campos, constantes, eventos, así como referencias entre ellos y a otros ensamblados.

Uso en otros sistemas operativos

ReactOS también utiliza el formato PE , ya que ReactOS está diseñado para ser compatible binariamente con Windows. Históricamente, también ha sido utilizado por otros sistemas operativos, incluidos SkyOS y BeOS R3. Sin embargo, tanto SkyOS como BeOS finalmente se trasladaron a ELF . [ cita necesaria ]

Como la plataforma de desarrollo Mono pretende ser compatible binariamente con Microsoft .NET Framework , utiliza el mismo formato PE que la implementación de Microsoft. Lo mismo ocurre con el .NET Core multiplataforma de Microsoft .

En sistemas operativos tipo Unix x86 (-64) , los archivos binarios de Windows (en formato PE) se pueden ejecutar con Wine . El HX DOS Extender también utiliza el formato PE para archivos binarios nativos de DOS de 32 bits y, además, puede, hasta cierto punto, ejecutar archivos binarios de Windows existentes en DOS, actuando así como un equivalente de Wine para DOS.

En Linux IA-32 y x86-64 también se pueden ejecutar archivos DLL de Windows bajo la biblioteca de carga. [10]

Mac OS X 10.5 tiene la capacidad de cargar y analizar archivos PE, pero no es compatible binariamente con Windows. [11]

El firmware UEFI y EFI utiliza archivos ejecutables portátiles, así como la convención de llamada ABI x64 de Windows para aplicaciones .

Ver también

Referencias

  1. ^ Andersson, Henrik (23 de abril de 2015). "aplicación/vnd.microsoft.portable-executable". IANA . Consultado el 26 de marzo de 2017 .
  2. ^ "Ejecutable portátil (PE) - Definición - Trend Micro IN". www.trendmicro.com . Consultado el 10 de noviembre de 2022 .
  3. ^ "Especificación UEFI, versión 2.8B" (PDF) ., una nota en la página 15, establece que "este tipo de imagen se elige para permitir que las imágenes UEFI contengan instrucciones Thumb y Thumb2 mientras se definen las interfaces EFI para que estén en modo ARM".
  4. ^ ab "Formato PE (Windows)" . Consultado el 21 de octubre de 2017 .
  5. ^ Por ejemplo, el vinculador de Microsoft tiene el modificador /STUB para adjuntar uno
  6. ^ Para saber si el código ejecutable es de 32 o 64 bits, verifique el campo Máquina en IMAGE_FILE_HEADER. (Truco de PE explicado: diferenciar 32 y 64 bits a simple vista por Karsten Hahn)
    Para ver si las direcciones en el ejecutable son de 32 o 64 bits, verifique el campo Magic en IMAGE_OPTIONAL_HEADER. 10B 16 indica un archivo PE32, mientras que 20B 16 indica un archivo PE32+. (Formato PE en Microsoft.com)
  7. ^ "El archivo ejecutable portátil de arriba a abajo" . Consultado el 21 de octubre de 2017 .
  8. ^ ab "Mirando dentro del PE: un recorrido por el archivo ejecutable portátil Win32" . Consultado el 21 de octubre de 2017 .
  9. ^ La entrada se usó anteriormente para metadatos COM+ en aplicaciones COM+, de ahí el nombre
  10. ^ "GitHub - taviso/Loadlibrary: migración de bibliotecas de vínculos dinámicos de Windows a Linux". GitHub .
  11. ^ Chartier, David (30 de noviembre de 2007). "Descubierto: evidencia de que Mac OS X pronto podría ejecutar aplicaciones de Windows". Ars Técnica . Consultado el 3 de diciembre de 2007 . ... Steven Edwards describe el descubrimiento de que Leopard aparentemente contiene un cargador indocumentado para ejecutables portátiles, un tipo de archivo utilizado en las versiones de Windows de 32 y 64 bits. Más investigaciones revelaron que el propio cargador de Leopard intenta encontrar archivos DLL de Windows cuando intenta cargar un binario de Windows.

enlaces externos