Как я могу протестировать DLL файл Windows, чтобы определить, 32 бит или 64 бит?

Я бы хотел написать тестовый script или программу, которая утверждает, что все DLL файлы в заданном каталоге имеют определенный тип сборки.

Я бы использовал это как проверку работоспособности в конце процесса сборки на SDK, чтобы убедиться, что 64-разрядная версия каким-то образом не имеет в ней 32-разрядных DLL файлов и наоборот.

Есть ли простой способ взглянуть на DLL файл и определить его тип?

Решение должно работать как на xp32, так и на xp64.

Ответ 1

Сведения о горах

DLL использует исполняемый формат PE, и это не слишком сложно прочитать эту информацию из файла.

См. статью MSDN в формате файла PE для обзора. Вам нужно прочитать заголовок MS-DOS, а затем прочитать структуру IMAGE_NT_HEADERS. Это содержит структуру IMAGE_FILE_HEADER, которая содержит информацию, которая вам нужна в члене Machine, который содержит одно из следующих значений

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

Эта информация должна иметь фиксированное смещение в файле, но я по-прежнему рекомендую обходить файл и проверять подпись заголовка MS-DOS и IMAGE_NT_HEADERS, чтобы быть уверенным, что вы справитесь с любыми будущими изменениями.

Используйте ImageHelp для чтения заголовков...

Вы также можете использовать ImageHelp API - загрузите DLL с помощью LoadImage, и вы получите структуру LOADED_IMAGE, которая будет содержать указатель на структуру IMAGE_NT_HEADERS. Отмените LOADED_IMAGE с помощью ImageUnload.

... или адаптировать этот грубый Perl script

Здесь грубый Perl script, который выполняет свою работу. Он проверяет, что файл имеет заголовок DOS, затем считывает смещение PE из IMAGE_DOS_HEADER 60 байтов в файл.

Затем он ищет начало части PE, считывает подпись и проверяет ее, а затем извлекает интересующее нас значение.

#!/usr/bin/perl
#
# usage: petype <exefile>
#
$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);

Ответ 2

Грубым способом было бы назвать дамббин с опцией заголовков из инструментов Visual Studio в каждой DLL и искать соответствующий вывод:

dumpbin /headers my32bit.dll

PE signature found

File Type: DLL

FILE HEADER VALUES
             14C machine (x86)
               1 number of sections
        45499E0A time date stamp Thu Nov 02 03:28:10 2006
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
            2102 characteristics
                   Executable
                   32 bit word machine
                   DLL

OPTIONAL HEADER VALUES
             10B magic # (PE32)

Вы можете увидеть пару подсказок в этом выпуске, что это 32-битная DLL, включая значение 14C, которое Павел упоминает. Должно быть легко искать в script.

Ответ 3

Если у вас установлен Cygwin (который я настоятельно рекомендую по целому ряду причин), вы можете использовать утилиту 'file' DLL

file <filename>

который даст такой вывод:

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

Ответ 4

Зависимость Уокер рассказывает все (ну почти). http://www.dependencywalker.com/

Он не "устанавливает" - просто достаньте его, извлеките и запустите exec. Он работает для любого приложения x32 или x64 windows.

Насколько я помню, довольно просто увидеть все зависимости, т.е. модули dll, и после приложения. представляет собой сумму зависимостей, которые можно определить, если они полны x64, x32 (x86) или бит каждого.

Тип процессора, для которого был построен модуль, находится в столбце "ЦП". Большинство 64-битных aps по-прежнему немного, но 32-разрядные ap w/b все x86.

Красивая программа для разработчиков/программистов и бесплатна...

Ответ 5

Я написал очень простой инструмент, который делает именно это - он называется PE Deconstructor.

Просто запустите его и загрузите DLL файл:

enter image description here

В приведенном выше примере загруженная DLL 32-разрядная.

Вы можете скачать его здесь (у меня есть только 64-битная версия скомпилированного банкомата):
http://files.quickmediasolutions.com/exe/pedeconstructor_0.1_amd64.exe

Более старая 32-разрядная версия доступна здесь:
http://dl.dropbox.com/u/31080052/pedeconstructor.zip