J'aimerais écrire un script de test ou un programme qui affirme que tous les fichiers DLL d'un répertoire donné sont d'un type de construction particulier.
J'utiliserais cela comme vérification de validité à la fin du processus de génération d'un SDK pour m'assurer que la version 64 bits ne contient pas de fichiers DLL 32 bits et inversement.
Existe-t-il un moyen simple d’examiner un fichier DLL et de déterminer son type?
La solution devrait fonctionner à la fois sur xp32 et xp64.
Un DLL utilise le format exécutable PE et il n'est pas trop difficile de lire ces informations dans le fichier.
Voir ceci article MSDN sur le format de fichier PE pour un aperçu. Vous devez lire l'en-tête MS-DOS, puis la structure IMAGE_NT_HEADERS . Cela contient la structure IMAGE_FILE_HEADER qui contient les informations dont vous avez besoin dans le membre Machine et qui contient l'une des valeurs suivantes.
Cette information devrait se trouver à un décalage fixe dans le fichier, mais je recommanderais quand même de parcourir le fichier et de vérifier la signature de l'en-tête MS-DOS et de IMAGE_NT_HEADERS pour vous assurer de faire face aux modifications futures.
Vous pouvez également utiliser ImageHelp API pour cela. Chargez le DLL avec LoadImage et vous obtiendrez un LOADED_IMAGE structure qui contiendra un pointeur sur une structure IMAGE_NT_HEADERS. Libérez LOADED_IMAGE avec ImageUnload.
Voici un script approximatif en Perl qui fait le travail. Il vérifie que le fichier a un en-tête DOS, puis lit le décalage PE à partir des 60 octets IMAGE_DOS_HEADER dans le fichier.
Il cherche ensuite au début de la partie PE, lit la signature et la vérifie, puis extrait la valeur qui nous intéresse.
#!/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);
Une méthode grossière consiste à appeler dumpbin avec l'option d'en-têtes à partir des outils Visual Studio sur chaque DLL et à rechercher le résultat approprié:
dumpbin/headers my32bit.dll La signature PE a été trouvée Type de fichier: DLL EN-FICHIER VALEURS Machine 14C (x86) 1 nombre de sections 45499E0U heure horodatage jeu. Nov. 02 03:28:10 2006 0 pointeur de fichier sur la table des symboles 0 nombre de symboles E0 taille de l’en-tête facultatif Caractéristiques 2102 Exécutable Machine Word 32 bits DLL VALEURS EN-TÊTE FACULTATIVES 10B numéro magique (PE32)
Vous pouvez voir quelques indices dans cette sortie qu'il s'agit d'une DLL 32 bits, y compris la valeur 14C mentionnée par Paul. Devrait être facile à rechercher dans un script.
Si Cygwin est installé (ce que je recommande vivement pour diverses raisons), vous pouvez utiliser l'utilitaire 'fichier' de la DLL.
file <filename>
ce qui donnerait une sortie comme celle-ci:
icuuc36.dll: MS-DOS executable PE for MS Windows (DLL) (GUI) Intel 80386 32-bit
Dependency Walker dit tout (enfin presque). http://www.dependencywalker.com/
Il ne "installe" pas - il suffit de l'obtenir, de l'extraire et de lancer l'exécutif. Cela fonctionne pour n'importe quelle application de module Windows x32 ou x64.
Si je me souviens bien, il est assez simple de voir toutes les dépendances, c’est-à-dire les modules dll, et depuis l’appl. est la somme des dépendances que l’on peut vérifier s’il s’agit de x64 complet, x32 (x86) ou un peu de chacun.
Le type de CPU pour lequel le module a été créé est dans la colonne "CPU". La plupart des APS 64 bits sont encore un peu de chacun, mais des 32 bits avec tous les x86.
Beau programme pour les geeks/programmeurs et c'est gratuit ...
J'ai écrit un outil très simple qui fait exactement cela - il s'appelle PE Deconstructor.
Il suffit de le lancer et de charger votre fichier DLL:
Dans l'exemple ci-dessus, le DLL chargé est 32 bits.
Vous pouvez le télécharger ici (je n'ai que la version 64 bits de l'ATM compilé):
http://files.quickmediasolutions.com/exe/pedeconstructor_0.1_AMD64.exe
Une version 32 bits plus ancienne est disponible ici:
http://dl.dropbox.com/u/31080052/pedeconstructor.Zip