Como posso testar um arquivo DLL do Windows para determinar se é de 32 ou 64 bits?

Eu gostaria de escrever um script de teste ou programa que afirma que todos os arquivos DLL em um determinado diretório são de um determinado tipo de compilation.

Eu usaria isso como uma verificação de sanidade no final de um processo de compilation em um SDK para garantir que a versão de 64 bits não tenha, de alguma forma, alguns arquivos DLL de 32 bits e vice-versa.

Existe uma maneira fácil de olhar para um arquivo DLL e determinar o seu tipo?

A solução deve funcionar tanto no xp32 quanto no xp64.

Detalhes sangrentos

Uma DLL usa o formato executável PE, e não é muito difícil ler essas informações fora do arquivo.

Consulte este artigo do MSDN sobre o formato de arquivo PE para obter uma visão geral. Você precisa ler o header do MS-DOS e, em seguida, leia a estrutura IMAGE_NT_HEADERS . Contém a estrutura IMAGE_FILE_HEADER que contém as informações que você precisa no membro Machine que contém um dos seguintes valores

  • IMAGE_FILE_MACHINE_I386 (0x014c)
  • IMAGE_FILE_MACHINE_IA64 (0x0200)
  • IMAGE_FILE_MACHINE_AMD64 (0x8664)

Essa informação deve estar em um deslocamento fixo no arquivo, mas eu ainda recomendaria atravessar o arquivo e verificar a assinatura do header do MS-DOS e o IMAGE_NT_HEADERS para ter certeza de lidar com quaisquer alterações futuras.

Use o ImageHelp para ler os headers …

Você também pode usar a API ImageHelp para fazer isso – carregar a DLL com LoadImage e você terá uma estrutura LOADED_IMAGE que conterá um ponteiro para uma estrutura IMAGE_NT_HEADERS. Desaloque LOADED_IMAGE com ImageUnload.

… ou adaptar este script áspero Perl

Aqui está o script áspero do Perl que faz o trabalho. Ele verifica se o arquivo tem um header DOS e, em seguida, lê o deslocamento PE dos IMAGE_DOS_HEADER 60 bytes no arquivo.

Em seguida, ele procura o início da parte PE, lê a assinatura e a verifica e, em seguida, extrai o valor em que estamos interessados.

#!/usr/bin/perl # # usage: petype  # $exe = $ARGV[0]; open(EXE, $exe) or die "can't open $exe: $!"; binmode(EXE); if (read(EXE, $doshdr, 64)) { ($magic,$skip,$offset)=unpack('a2a58l', $doshdr); die("Not an executable") if ($magic ne 'MZ'); seek(EXE,$offset,SEEK_SET); if (read(EXE, $pehdr, 6)){ ($sig,$skip,$machine)=unpack('a2a2v', $pehdr); die("No a PE Executable") if ($sig ne 'PE'); if ($machine == 0x014c){ print "i386\n"; } elsif ($machine == 0x0200){ print "IA64\n"; } elsif ($machine == 0x8664){ print "AMD64\n"; } else{ printf("Unknown machine type 0x%lx\n", $machine); } } } close(EXE); 

Uma maneira bruta seria chamar dumpbin com a opção de headers das ferramentas do Visual Studio em cada DLL e procurar a saída apropriada:

 dumpbin / headers my32bit.dll

 Assinatura PE encontrada

 Tipo de arquivo: DLL

 VALORES DE CABEÇALHO DE ARQUIVO
              Máquina 14C (x86)
                1 número de seções
         45499E0A data e hora marcadas Qui Nov 02 03:28:10 2006
                0 ponteiro de arquivo para a tabela de símbolos
                0 número de símbolos
               Tamanho E0 do header opcional
             2102 características
                    Executável
                    Máquina de 32 bits
                    DLL

 VALORES OPCIONAIS DE CABEÇALHO
              10B magic # (PE32)

Você pode ver algumas dicas nessa saída que é uma DLL de 32 bits, incluindo o valor 14C mencionado por Paul. Deve ser fácil procurar em um script.

Se você tem o Cygwin instalado (o que eu recomendo fortemente por uma variedade de razões), você pode usar o utilitário ‘arquivo’ na DLL

 file  

o que daria uma saída como esta:

 icuuc36.dll: MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit 

Dependência Walker diz tudo (bem quase). http://www.dependencywalker.com/

Ele não “instala” – basta obtê-lo, extraí-lo e executar o exec. Funciona para qualquer aplicação de módulo de janelas x32 ou x64.

Pelo que me lembro, é bastante simples de ver todas as dependencies, ou seja, os módulos de dll e desde o appl. é uma sum das dependencies que se pode verificar se está cheio x64, x32 (x86) ou um pouco de cada.

O tipo de CPU para o qual o módulo foi construído está na coluna “CPU”. A maioria dos aps de 64 bits ainda é um pouco de cada, exceto de 32 bits ap / b todos os x86.

Belo programa para geeks / programadores e é grátis …

Eu escrevi uma ferramenta muito simples que faz exatamente isso – é chamado PE Deconstructor.

Basta ativá-lo e carregar seu arquivo DLL:

insira a descrição da imagem aqui

No exemplo acima, a DLL carregada é de 32 bits.

Você pode baixá-lo aqui (eu só tenho a versão 64-bit compilada ATM):
http://files.quickmediasolutions.com/exe/pedeconstructor_0.1_amd64.exe

Uma versão anterior de 32 bits está disponível aqui:
http://dl.dropbox.com/u/31080052/pedeconstructor.zip