Ejecutable portátil - Portable Executable

Ejecutable portátil
Extensión de nombre de archivo
.acm, .ax, .cpl, .dll, .drv, .efi, .exe, .mui, .ocx, .scr, .sys,.tsp
Tipo de medio de Internet
aplicación / vnd.microsoft.portable-ejecutable
Desarrollado por Actualmente: Microsoft
Tipo de formato Bibliotecas binarias , ejecutables , de objetos y compartidas
Extendido desde DOS MZ ejecutable
COFF

El formato Portable Executable (PE) es un formato de archivo para ejecutables , código objeto , DLL y otros que se utilizan en las versiones de 32 y 64 bits de los sistemas operativos Windows . 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 , exportar e importar tablas 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.

En los sistemas operativos Windows NT, PE admite actualmente las arquitecturas de conjuntos 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.

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 Win32s 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 stub 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). Esto constituye una forma de binario gordo . PE también continúa sirviendo a la cambiante plataforma de Windows. Algunas extensiones incluyen el formato .NET PE (ver más abajo), una versión de 64 bits llamada PE32 + (a veces PE +) y una especificación para Windows CE.

Detalles técnicos

Diseño

Estructura de un ejecutable portátil de 32 bits

Un archivo PE consta de varios 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. 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 no-ejecutar / leer y escribir. Sin embargo, para evitar desperdiciar espacio, las diferentes secciones no están alineadas en el disco. Parte del trabajo del enlazador dinámico es mapear 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.

Importar tabla

Una sección a destacar 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 de importar por ordinal e importar por nombre . Debido a que un programa compilado no puede conocer la ubicación de la memoria de las bibliotecas de las que depende, se requiere un salto indirecto cada vez que se realiza una llamada a la 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 que resulta en una penalización del rendimiento, brinda un beneficio clave: la cantidad de páginas de memoria que deben ser modificadas por copia en escritura por el cargador se minimiza, 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 da como resultado un código de operación de llamada indirecta .

Reubicaciones

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 reorganizará . Esto implica recalcular 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 . Esto luego se agrega a la dirección preferida para generar la nueva dirección de la ubicación de la 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 rebase siempre que sea posible, y las DLL enviadas por Microsoft tienen direcciones base precalculadas para que no se superpongan. En el caso de no rebase, PE tiene la ventaja de un código muy eficiente, pero en presencia de rebase, el uso de memoria puede resultar costoso. Esto contrasta con ELF, que utiliza un código totalmente independiente de la posición y una tabla de compensación global, que intercambia 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, de forma muy similar a como estaba 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") se señala mediante una IMAGE_DIRECTORY_ENTRY_COMHEADERentrada 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.

Los datos relacionados con CLR, incluyendo la estructura de la raíz sí mismo, es típicamente 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 entidades .NET distintas en el ensamblaje, incluidos tipos, métodos, campos, constantes, eventos, así como referencias entre ellos y otros ensamblados.

Usar en otros sistemas operativos

ReactOS también usa el formato PE , ya que ReactOS está diseñado para ser compatible con Windows en formato binario . También ha sido utilizado históricamente por varios otros sistemas operativos, incluidos SkyOS y BeOS R3. Sin embargo, tanto SkyOS como BeOS finalmente se trasladaron a ELF .

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

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

En IA-32 y x86-64 Linux también se pueden ejecutar las DLL de Windows en loadlibrary.

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

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

Ver también

Referencias

enlaces externos