Executável Portátil
| Executável Portátil | ||
|---|---|---|
| desenvolvedor | ||
| Microsoft | ||
| Informações gerais | ||
| extensão de arquivo |
.cpl, .exe, .dll, .ocx, .sys, .scr, .drv | |
| tipo mime | application/vnd.microsoft.portable-executable, application/x-msdownload e application/efi | |
| Identificador de tipo uniforme | com.microsoft.windows-executable | |
| número mágico |
MZ | |
| tipo de formato | Binário , executável , código objeto , bibliotecas compartilhadas | |
| estendido de |
Executável DOS MZ , COFF | |
| Padrões) | Especificação Microsoft PE e COFF (ver. 8) | |
| formato aberto | ? | |
O formato Portable Executable (PE) é um formato de arquivo para arquivos executáveis, arquivos de código de objeto, bibliotecas de links dinâmicos (DLLs), arquivos de fonte FON, [ 1 ] e outros usados em versões de 32 e 64 bits do sistema . Sistema operacional Windows . O termo "portátil" refere-se à versatilidade do formato em diversos ambientes de arquiteturas de software de sistema operacional. [ 2 ] O formato PE é uma estrutura de dados que encapsula as informações necessárias para que o carregador do Windows gerencie o código executável que o envolve. Isso inclui referências a bibliotecas de links dinâmicos para vinculação, importação e exportação de tabelas de API , gerenciamento de dados de recursos e dados de armazenamento local de thread (dados TLS). Em sistemas operacionais baseados no Windows NT , o formato PE é usado para EXE , DLL , SYS ( drivers de dispositivo) e outros tipos de arquivo. A especificação Extensible Firmware Interface (EFI) indica que PE é o formato padrão para executáveis em ambientes EFI.
PE é uma versão modificada do formato Unix COFF . Além disso, PE/COFF é um nome alternativo no desenvolvimento do Windows.
Nos sistemas operacionais Windows NT, o PE atualmente suporta os conjuntos de instruções (ISA ) IA - 32 , IA-64 e x86-64 (AMD/Intel64 ). Antes do Windows 2000 , o Windows NT (e, portanto, o PE) suportava os conjuntos de instruções MIPS , DEC Alpha e PowerPC . Como o PE é usado no Windows CE , ele continua a oferecer suporte a várias variantes das arquiteturas MIPS, ARM (incluindo Thumb) e SuperH .
Os principais concorrentes do PE são o ELF (usado no Linux e muitos outros sistemas do tipo Unix ) e o Mach-O (usado no Mac OS X ).
História
A Microsoft migrou para o formato PE com a introdução do sistema operacional Windows NT 3.1 . Todas as versões posteriores do Windows, incluindo Windows 95, 98 e ME, oferecem suporte à estrutura de arquivos PE. O formato manteve suporte legado limitado para preencher a lacuna entre sistemas baseados em DOS e sistemas baseados em NT. Por exemplo, os cabeçalhos PE/COFF ainda incluem um programa MS-DOS executável, que por padrão é um trecho que exibe a mensagem simples "Este programa não pode ser executado no modo DOS" (ou similar). [ 2 ] Além disso, o PE continua a atender às mudanças na plataforma Windows. As extensões incluem o formato PE .NET ( veja abaixo ), uma versão para binários de 64 bits chamada PE32+ (ou às vezes PE+) e uma especificação para Windows CE.
Detalhes técnicos
Projeto
Um arquivo PE consiste em uma série de cabeçalhos e seções que informam ao vinculador dinâmico como alocar o arquivo na memória. Uma imagem executável consiste em várias zonas diferentes, cada uma exigindo proteção de memória diferente, portanto, o início de cada seção deve ser alinhado a um limite de página. Por exemplo, normalmente a seção .text (que contém o código do programa) é mapeada como "executar/somente leitura" e a seção .data (que contém as variáveis globais) é mapeada como "não executar/ler-escrever". No entanto, para evitar desperdício de espaço, as diferentes seções não são alinhadas à página no disco. Parte do trabalho do vinculador dinâmico é mapear cada seção individualmente na memória e atribuir as permissões corretas às regiões resultantes, de acordo com as instruções encontradas nos cabeçalhos.
Tabela de seções
A tabela de seção está localizada logo atrás do cabeçalho PE. Esta é uma tabela que contém várias estruturas IMAGE_SECTION_HEADER . Essas estruturas contêm informações sobre as seções dos binários a serem carregados na memória.
O campo NumberOfSections da estrutura IMAGE_FILE_HEADER indica quantas entradas existem na tabela. O máximo suportado pelo Windows é de 96 seções.
Um protótipo de uma tabela de seção se parece com isso:
typedef struct _IMAGE_SECTION_HEADER {
Nome BYTE [ IMAGE_SIZEOF_SHORT_NAME ];
união {
Endereço Físico DWORD ;
Tamanho Virtual DWORD ;
} Diversos ;
Endereço Virtual DWORD ;
DWORD SizeOfRawData ;
DWORD PointerToRawData ;
DWORD PointerToRelocations ;
DWORD PointerToLinenumbers ;
WORD NumberOfRelocations ;
WORD NumberOfLinenumbers ;
Características DWORD ;
} IMAGE_SECTION_HEADER , * PIMAGE_SECTION_HEADER ;
Cada seção tem um nome de 8 caracteres; esse nome não é significativo, mas geralmente você pode encontrar o seguinte:
| Nome | Descrição |
|---|---|
| .texto | O código (instruções) do programa |
| .bss | Variáveis não inicializadas |
| .relógio | A tabela de recolocação |
| .dados | Variáveis inicializadas |
| .rsrc | Os recursos do arquivo (cursores, sons, menus...) |
| .rdata | dados somente leitura |
| .idata | A tabela de importação |
| .upx | Assinatura de uma compressão UPX, típica de software UPX |
| .aspack | Assinatura de um pacote ASPACK, típico do software ASPACK |
| .adata | Assinatura de um pacote ASPACK, típico do software ASPACK |
IMPORT tabela
Uma seção a ser mencionada é a tabela de endereços de importação (IAT), que é usada como uma tabela de pesquisa quando o aplicativo chama uma função em um módulo diferente. Isso pode ser na forma de importação por ordinal ou importação por nome. Como um programa compilado não pode saber a localização na memória das bibliotecas das quais depende diretamente, um salto indireto é necessário toda vez que uma chamada de API é feita. À medida que o vinculador dinâmico carrega os módulos e os une, ele grava o endereço atual nos slots IAT para que eles apontem para os locais de memória correspondentes na biblioteca de funções. Embora isso adicione um salto extra no custo de uma chamada intramódulo que resulta em uma penalidade de desempenho, ele oferece uma vantagem importante: minimiza o número de páginas de memória que precisam ser alteradas copy-on-write pelo carregador. , economizando memória e tempo de E/S de disco. Se o compilador souber de antemão que será uma chamada entre módulos (através do atributo dllimport ) ele pode produzir um código mais otimizado que simplesmente se traduz em uma chamada indireta de opcode .
Mudanças
Os arquivos PE não contêm código independente de posição . Em vez disso, eles são compilados para um endereço base preferencial e todos os endereços emitidos pelo compilador/vinculador são prefixados. Se um arquivo PE não puder ser carregado em seu endereço preferencial (porque já foi usado por outra coisa), o sistema operacional o redefinirá. Isso envolve recalcular cada endereço absoluto e modificar o código para usar os novos valores. O carregador faz isso comparando os endereços de carregamento atuais e preferenciais e calculando um valor delta . Este é então adicionado ao endereço preferencial para chegar ao novo endereço de localização de memória. As realocações de base são armazenadas em uma lista e adicionadas, quando necessário, a um local de memória existente. O código resultante agora é privado para o processo e não é mais compartilhado, portanto, muitos dos benefícios de economia de memória das DLLs são perdidos nesse cenário. Também diminui significativamente o carregamento do módulo. Por esse motivo, o realinhamento é evitado sempre que possível, e as DLLs fornecidas pela Microsoft têm endereços de base pré-computados para que não se sobreponham. Assim, no caso de não reinicialização, o PE oferece a vantagem de um código muito eficiente, mas na presença de reinicialização, o sucesso no uso da memória pode ser caro. Isso contrasta com o ELF, que usa código totalmente independente de posição e uma tabela de compensação global, que troca o tempo de execução versus o uso de memória em favor do último.
.NET, metadados e o formato PE
O .NET Framework da Microsoft estendeu o formato PE com recursos que suportam o Common Language Runtime (CLR). Entre os recursos adicionados estão o cabeçalho CLR e as seções de dados CLR. Ao carregar um binário, o carregador do SO entrega a execução ao CLR fazendo uma referência à tabela PE/COFF IMPORT. O CLR então carrega o cabeçalho CLR e as seções de dados.
A seção de dados CLR contém dois segmentos importantes, código de metadados e código de linguagem intermediária (IL):
- Os metadados contêm informações relevantes para o assembly, incluindo o manifesto do assembly. Um manifesto descreve o assembly em detalhes, incluindo identificação exclusiva (usando um hash , número de versão etc.), dados em componentes exportados, informações de tipo abrangentes (suportadas pelo Common Type System (CTS)), referências externas e uma lista de arquivos dentro da montagem. O ambiente CLR faz uso extensivo de metadados. [ 3 ]
- O código IL é um código abstrato e independente de linguagem que atende aos requisitos de linguagem intermediária comum (CIL) do CLR . O termo " intermediário " refere-se à natureza compatível entre linguagens e plataformas cruzadas do código IL . Essa linguagem intermediária , semelhante ao bytecode Java , permite que plataformas e linguagens suportem o CLR comum . IL suporta programação orientada a objetos (polimorfismo, herança, tipos abstratos, etc.), exceções, eventos e várias estruturas de dados.
Uso em outros sistemas operacionais
O formato PE também é usado pelo ReactOS , pois este sistema operacional deve ser compatível com o binário do Windows. O formato PE também tem sido usado historicamente por alguns sistemas operacionais, incluindo SkyOS e BeOS R3. No entanto, tanto o SkyOS quanto o BeOS foram portados para o formato ELF .
Como a plataforma de desenvolvimento Mono foi projetada para ser compatível com o binário do Microsoft .NET , ela usa o mesmo formato PE que a implementação da Microsoft.
Em sistemas operacionais do tipo Unix de 32 bits , alguns binários do Windows (no formato PE) podem ser executados com o Wine . O HX DOS Extender também usa o formato PE para binários nativos do DOS de 32 bits, além de poder, até certo ponto, executar binários do Windows existentes no DOS, agindo assim como se fosse o Wine para DOS.
O Mac OS X 10.5 tem a capacidade de carregar e analisar arquivos PE, mas não é compatível com binários do Windows. [ 4 ]
Referências
- ↑ Tatam, Simon. "mkwinfont" (em inglês) . Recuperado em 31 de outubro de 2012 .
- ↑ a b Microsoft , ed. (1 de novembro de 2006). "Formato de arquivo de objeto comum (formato COFF)" . Suporte Microsoft . Recuperado em 5 de abril de 2013 .
- ↑ Microsoft (ed.). "Metadados e a estrutura do arquivo PE" . MSDNLibrary . Recuperado em 5 de abril de 2013 .
- ^ Chartier, David (30 de novembro de 2007). "Descoberto: Evidência de que o Mac OS X poderá executar aplicativos do Windows em breve" . Ars Technica . Recuperado em 3 de dezembro de 2007 . «... Steven Edwards descreve a descoberta de que o Leopard aparentemente contém um carregador não documentado para Portable Executables, um tipo de arquivo usado nas versões de 32 e 64 bits do Windows. Mais pesquisas revelaram que o próprio carregador do Leopard tenta encontrar arquivos DLL do Windows ao tentar carregar um binário do Windows. »
Veja também
- Adendo: Comparação de formatos de arquivos executáveis
- exe
Links externos
- Especificação de formato de arquivo de objeto comum e executável portátil da Microsoft ( link quebrado disponível no Internet Archive ; consulte o histórico , primeira e última versão ). (em inglês). Rede de Desenvolvimento Microsoft.
- Peering dentro do PE: um tour do formato de arquivo executável portátil Win32 . Rede de Desenvolvimento Microsoft.