Unter Linux /proc/cpuinfo
können Sie auf einfache Weise alle CPU-Flags des Computers überprüfen.
Wenn ein Programm eine Obermenge des Befehlssatzes einer Maschine benötigt, können Sie dies am einfachsten feststellen, indem Sie es ausführen und prüfen, ob es ein SIGILLSignal auslöst.
Aber in meinem Fall unterstützen alle meine Prozessoren mindestens SSE4.1 und AVX.
Gibt es also eine einfache Möglichkeit zu überprüfen, ob eine Binärdatei spezielle Anweisungen enthält?
objdump --disassemble
führt eine Demontage durch. Mit können Sieobjdump
eine Liste mit Mnemonics erstellen. Es ist Teil von Binutils und daher auf GNU Linux-Systemen verfügbar. Die zusätzlichen Anweisungen sind möglicherweise vorhanden, werden jedoch möglicherweise nicht ausgeführt. Das Programm könnte Laufzeitwächter haben.-mavx
um sicherzustellen, dass der Compiler nur aus dem AVX ISA auswählt, aber es gibt Möglichkeiten, ihn zu umgehen. Beispielsweise kann der Inline-Assembler die ISA-Prüfungen des Compilers normalerweise umgehen.Antworten:
Ich habe ein Programm in Rust rausgeschmissen, das dies versucht. Ich denke, es funktioniert, obwohl es undokumentiert und furchtbar zerbrechlich ist:
https://github.com/pkgw/elfx86exts
Anwendungsbeispiel:
quelle
Ich bin auf dasselbe Problem gestoßen, als ich versuchte, die GCC-Optimierungsprozesse zu verstehen und herauszufinden, welche Anweisungen während dieses Prozesses verwendet wurden oder nicht. Da ich mit der enormen Anzahl von Operationscodes nicht einverstanden bin, habe ich nach einer Möglichkeit gesucht, bestimmte Anweisungen (z. B. SSE3) innerhalb des zerlegten Codes zu visualisieren oder zumindest einige minimale Statistiken auszudrucken, z. B. ob und wie viele diese Anweisungen vorhanden sind in der binären.
Ich habe keine existierende Lösung gefunden, aber die Antwort von Jonathan Ben-Avraham erwies sich als sehr nützlich, da sie auf eine großartige (und sogar teilweise strukturierte) Quelle von Operationscodes hinweist. Basierend auf diesen Daten habe ich ein Bash-Skript geschrieben, mit dem bestimmte Anweisungssätze visualisiert oder Statistiken darüber gedruckt werden können,
grep
wenn die Ausgabe von eingespeist wirdobjdump
.Die Liste der Operationscodes wurde in ein eigenständiges Bash-Skript konvertiert, das dann (zur besseren Lesbarkeit) in der Hauptdatei enthalten ist, die ich einfach benannt habe
opcode
. Da Opcodes ingas.vim
( Shirk'svim
Syntaxdefinitionen , aus Jonathans Antwort) systematisch (scheinbar) nach verschiedenen CPU-Architekturen gruppiert wurden, habe ich versucht, diese Unterteilung beizubehalten und eine Architektur-> Befehlssatzzuordnung vorzunehmen . Ich bin mir jetzt nicht sicher, ob das eine gute Idee war. Die Zuordnung ist nicht korrekt und ich musste sogar einige Änderungen am Original vornehmengas.vim
Gruppierung. Da architekturbezogene Befehlssätze nicht meine ursprüngliche Absicht waren, habe ich versucht, nur Befehlssätze der im Internet beschriebenen Hauptarchitekturen zu erstellen, ohne die Dokumentationen der Hersteller zu konsultieren. AMD-Architekturen erscheinen mir überhaupt nicht zuverlässig (mit Ausnahme von Befehlssätzen wie 3DNow! Und SSE5). Ich habe mich jedoch entschlossen, den Code für Befehlssätze verschiedener Architekturen hier zu belassen, damit andere ihn untersuchen und korrigieren / verbessern und anderen vorläufige Ergebnisse liefern können.Anfang der Hauptdatei mit dem Namen
opcode
:Ein Beispiel für eine
Opcode_list
Datei, die gemäß den Anweisungenopcode
vom 27. Oktober 2014 erstellt und geändert wurde, finden Sie unter http://pastebin.com/yx4rCxqs . Sie können diese Datei direktopcode
anstelle dersource Opcode_list
Zeile einfügen . Ich habe diesen Code ausgegeben, weil Stack Exchange nicht zulässt, dass ich eine so große Antwort sende.Schließlich der Rest der
opcode
Datei mit der eigentlichen Logik:Beachten Sie, dass
-r
die Berechnung bei zu großen Suchanfragen (z. B. mit Haswell-Befehlssatz und Switch - dazu gehören Hunderte von Anweisungen) möglicherweise langsam vonstatten geht und bei großen Eingaben, für die dieses einfache Skript nicht vorgesehen war, viel Zeit in Anspruch nimmt .Ausführliche Informationen zur Verwendung finden Sie unter
Das gesamte
opcode
Skript (einschließlich Opcode-Liste) finden Sie unter http://pastebin.com/A8bAuHAP .Fühlen Sie sich frei, das Tool zu verbessern und eventuelle Fehler zu korrigieren. Zuletzt möchte ich Jonathan Ben-Avraham für seine großartige Idee danken, die
gas.vim
Datei von Shirk zu verwenden.BEARBEITEN: Das Skript kann jetzt feststellen, zu welchem Befehlssatz ein Operationscode gehört (regulärer Ausdruck kann verwendet werden).
quelle
Dekompilieren Sie zunächst Ihre Binärdatei:
Dann finden Sie alle SSE4-Anweisungen in der Assembly-Datei:
(Hinweis: CRC32 stimmt möglicherweise mit Kommentaren überein.)
Hier finden Sie die gebräuchlichsten AVX-Anweisungen (einschließlich Skalar, einschließlich AVX2, AVX-512-Familie und einiger FMA-ähnlicher Anweisungen
vfmadd132pd
):HINWEIS: getestet mit
gawk
undnawk
.quelle
Leider scheint es zum jetzigen Zeitpunkt kein bekanntes Hilfsprogramm zu geben, das den erforderlichen Befehlssatz einer bestimmten ausführbaren Datei erkennt.
Das Beste, was ich für x86 vorschlagen kann, ist die Verwendung
objdump -d
der ELF-Binärdatei, um die ausführbaren Abschnitte in die Sprache Gnu Assemply (gas
) zu zerlegen . Verwenden Sie dann Shirk dievim
Syntaxdefinitionen entwedergrep
durch die Assembler - Code - Datei oder visuell scannen Sie den Assembler - Code für eine dergasOpcode_SSE41
odergasOpcode_SANDYBRIDGE_AVX
Anweisungen, die Sie in Shirk sehengas.vim
Datei.Die Assemblersprachendatei enthält die Anweisungen ("Opcodes") auf Maschinenebene, die der Compiler beim Kompilieren des Programms generiert hat. Wenn das Programm mit Kompilierungszeit-Flags für SSE- oder AVX-Anweisungen kompiliert wurde und der Compiler SSE- oder AVX-Anweisungen ausgegeben hat, sollten Sie einen oder mehrere SSE- oder AVX-Opcodes in der Disassembly-Liste von sehen
objdump -d
.Wenn Sie beispielsweise
grep vroundsdb
in der Assemblycodedatei eine Übereinstimmung finden, wissen Sie, dass für die Ausführung der Binärdatei AVX-Funktionen erforderlich sind.Es gibt einige unterarchitekturspezifische Anweisungen für x86, wie Sie aus der
gas.vim
Datei von Shirkgrep
ersehen können. Es wäre also zugegebenermaßen mühsam , für alle Opcodes für jede Unterarchitektur zu pingen. Das Schreiben eines C-, Perl- oder Python-Programms, um dies zu tun, könnte eine hervorragende Idee für ein Open Source-Projekt sein, insbesondere wenn Sie jemanden finden, der es für ARM, PPC und andere Architekturen erweitert.quelle
gas.vim
. OTOH Wenn dies ein One-Shot-Problem ist, können Sie die Muster der Opcodes, die zwischen den Unterarchitekturen unterscheiden, leicht lernen.Ich habe versucht, ein Python-Hilfsprogramm zu schreiben, das auf Jonathan Ben-Avrahams basiert, und Kyselejsyrečeks antwortet. Es ist ein grobes Drehbuch, aber es erledigt den Job.
https://gist.github.com/SleepProgger/d4f5e0a0ea2b9456e6c7ecf256629396 Die gas.vim-Datei wird automatisch heruntergeladen und konvertiert, und es werden alle verwendeten (optionalen, nicht grundlegenden) Vorgänge einschließlich des Funktionsumfangs, von dem sie stammen, gespeichert. Außerdem unterstützt es die Suche nach Funktionssätzen mit op.
quelle