A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Informática Numaboa - Referências

O formato PE

Sab

11

Abr

2009


11:01

(10 votos, média 5.00 de 5) 


Nível avançado

O que é que contém estes arquivos de sobrenome .exe que, a um duplo clique do mouse, rodam e efetuam tarefas pre-programadas? Se você não sabe, não se preocupe. A maioria dos programadores, mesmo os bons, também não têm a mínima idéia. Para a maioria dos mortais, um executável não passa de uma sopa de letrinhas que de alguma forma misteriosa acaba fazendo o que se espera dele - beeemmm... quase sempre wink2

Qualquer executável win32 (exceto VxD e DLLs de 16 bits) usa o formato PE de arquivo, ou seja, obedecem a um padrão de armazenamento. É por isso que é interessante conhecê-lo em detalhes. Vamos dar uma olhada como o pequeno executável do tutorial "Janelas" é armazenado em disco. Este tutorial faz parte do "Assembly Numaboa" e você pode fazer o download de tutNB03.zip e usar o tutNB03.exe como exemplo. Usei o mesmo executável como exemplo neste tutorial.

O formato PE

Imagine o formato PE como sendo simplesmente um padrão de armazenamento de dados que o Windows entenda. São regras para guardar "cada coisa em seu lugar" de modo que o sistema possa achá-las quando necessário. Os programas possuem código, dados inicializados, dados não inicializados, etc, etc, etc. Tudo deve ser guardado de acordo com o modelo estabelecido e o resultado é uma imensa fileira de bytes. O objetivo deste tutorial é ir desvendando cada pedaço dessa tripa de bytes.

PE vem de Portable Executable e é um formato de binários executáveis (DLLs e programas) para windows NT, windows 9x e win32s. Também pode ser utilizado para arquivos de objetos e bibliotecas (libraries).

Este formato foi projetado pela Microsoft e padronizado pelo Comitê do TIS (tool interface standart) - Microsoft, Intel, Borland, Watcom, IBM e outros - em 1993. Aparentemente foi baseado no COFF, o "common object file format", usado para arquivos de objetos e executáveis nos vários sabores UNIX e no VMS.

O SDK do win32 inclui um arquivo header que contém os #defines e typedefs para o formato PE. Estes serão mencionados no decorrer do texto.

A DLL "imagehelp.dll" também poderá ser útil. Ela faz parte do windows NT, porém a documentação é escassa. Algumas de suas funções são descritas no "Developer Network".

Layout geral do formato PE

Cabeçalho MZ do DOS
Fragmento (stub) do DOS
Cabeçalho do Arquivo
Cabeçalho Opcional
Diretório de Dados
Cabeçalhos das Seções
Seção 1
Seção 2
...
Seção n

Logo no início de qualquer arquivo no formato PE encontra-se o cabeçalho MZ do DOS seguido por um fragmento (stub) executável MS-DOS. Este stub transforma qualquer arquivo PE num executável MS-DOS válido (apesar disto o tio Bill insiste em afirmar que o windows "baniu" o DOS tongue2).

Depois do stub do DOS existe uma assinatura de 32 bits contendo o número mágico (magic number - é assim mesmo que o pessoal o batizou) de valor 00004550h e identificado como IMAGE_NT_SIGNATURE.

A seguir vem o cabeçalho do arquivo (file header) no formato COFF, que indica em qual máquina o executável deve rodar, o número de seções que contém, a hora em que foi linkado, se é um executável ou uma DLL e assim por diante. (Neste contexto, a diferença entre um executável e uma DLL é a seguinte: uma DLL não pode ser iniciada, somente pode ser utilizada por outro binário e um binário não pode ser linkado a um executável).

Depois do cabeçalho do arquivo vem um cabeçalho opcional ("optional header"). Está sempre presente mas, mesmo assim, é chamado de opcional. É que o COFF utiliza um cabeçalho para bibliotecas, mas não para objetos, que é chamado de opcional. Este cabeçalho indica mais alguns detalhes de como o binário deve ser carregado: o endereço inicial, a quantidade reservada para a pilha (stack), o tamanho do segmento de dados, etc.

Uma parte interessante do cabeçalho opcional é o array indicativo dos diretórios de dados (data directories). Estes diretórios contêm ponteiros para dados residentes nas seções (sections). Se, por exemplo, um binário tiver um diretório de exportação (export directory), existe um ponteiro para este diretório no array, sob a denominação IMAGE_DIRECTORY_ENTRY_EXPORT, que apontará para uma das seções.

Após os cabeçalhos ficam as seções, precedidas pelos cabeçalhos de seções (section headers). Em última análise, o conteúdo das seções é o que realmente é necessário para executar um programa e todos os cabeçalhos e diretórios servem apenas para localizar este conteúdo.

Cada seção possui algumas flags sobre alinhamento, o tipo de dados que contém, se pode ser compartilhada, etc, além dos dados propriamente ditos. A maioria das seções, mas não todas, contêm um ou mais diretórios referenciados através de entradas no array diretório de dados (data directory) do cabeçalho opcional. É o caso do diretório de funções exportadas ou do diretório de base de remanejamento (base relocations). Tipos de conteúdo sem diretório são, por exemplo, código executável ou dados inicializados.

A coisa já complicou? Está querendo desistir por aqui? Não se apavore. Cada um dos tópicos será explicado em detalhes e, se você tiver noções de assembly, vai ter muita coisa boa com que se divertir...

Logo no início de qualquer arquivo no formato PE encontra-se o cabeçalho MZ do DOS seguido por um fragmento (stub) executável MS-DOS. Parece brincadeira, mas não é: o stub é um executável DOS completo dentro do executável win32. O stub pode simplesmente mostrar uma string do tipo "This program cannot be run in DOS mode" ou ser um programa DOS completo. Dependendo da vontade do programador, muita coisa pode rolar antes que o executável win32 comece a ser executado.

Stub significa fragmento. O conceito de fragmento do DOS vem desde o tempo dos executáveis de 16 bits do windows (os quais usam o formato NE). O mesmo fragmento é usado em executáveis OS/2, arquivos "self-extracting" e outros aplicativos de 32 bits. Para arquivos PE, o fragmento é um executável compatível com o MS-DOS 2.0, quase sempre constituído por cerca de 100 bytes, cuja função é dar mensagens de erro do tipo "este programa precisa do windows...".

Informações adicionais