En Linux, /proc/cpuinfo
permite verificar todos los indicadores de CPU que tiene la máquina de una manera simple.
Por lo general, si un programa requiere un superconjunto del conjunto de instrucciones de una máquina, la forma más fácil de determinarlo es ejecutarlo y ver si genera una SIGILLseñal.
Pero en mi caso, todos mis procesadores admiten al menos SSE4.1 y AVX.
Entonces, ¿hay una manera simple de verificar si un binario tiene instrucciones especiales dentro?
objdump --disassemble
realiza un desmontaje Puede usarobjdump
para generar una lista de mnemotécnicos. Es parte de Binutils, por lo que está disponible en sistemas GNU Linux. Además, las instrucciones adicionales pueden estar presentes pero no pueden ejecutarse. El programa podría tener guardias de tiempo de ejecución.-mavx
para asegurarse de que el compilador solo seleccione desde AVX ISA, pero hay formas de evitarlo. Por ejemplo, el ensamblador en línea generalmente puede eludir las verificaciones ISA del compilador.Respuestas:
Expulsé un programa en Rust que intenta hacer esto. Creo que funciona, aunque es indocumentado y terriblemente frágil:
https://github.com/pkgw/elfx86exts
Ejemplo de uso:
fuente
Me encontré con el mismo problema cuando intentaba comprender los procesos de optimización de GCC y averiguar qué instrucciones se usaron o no durante este proceso. Como no soy amigable con la enorme cantidad de códigos de operación, estaba buscando una manera de visualizar instrucciones específicas (digamos SSE3) dentro del código desensamblado, o al menos imprimir algunas estadísticas mínimas como si y cuántas instrucciones hay allí en el binario
No he encontrado ninguna solución existente, pero la respuesta de Jonathan Ben-Avraham resultó muy útil, ya que señala una gran fuente (e incluso parcialmente estructurada) de códigos de operación. En base a estos datos, he escrito un script Bash que puede visualizar conjuntos de instrucciones específicos o imprimir estadísticas sobre ellos utilizando
grep
cuando se alimenta con salida deobjdump
.La lista de códigos de operación se ha convertido en una secuencia de comandos Bash independiente que luego se incluye (con el fin de una mejor legibilidad) en el archivo principal que he nombrado simplemente
opcode
. Dado que los códigos de operación engas.vim
( definiciones de sintaxis de Shirkvim
, de la respuesta de Jonathan) se agruparon sistemáticamente (aparentemente) de acuerdo con diferentes arquitecturas de CPU, traté de preservar esta división y hacer una asignación de arquitectura-> conjunto de instrucciones ; Ahora no estoy seguro de si fue una buena idea. El mapeo no es exacto e incluso tuve que hacer algunos cambios en el originalgas.vim
agrupamiento. Dado que los conjuntos de instrucciones relacionados con la arquitectura no eran mi intención original, traté de construir solo conjuntos de instrucciones de las principales arquitecturas descritas en Internet, pero sin consultar las documentaciones de los fabricantes. Las arquitecturas de AMD no me parecen confiables (excepto conjuntos de instrucciones como 3DNow! Y SSE5). Sin embargo, decidí dejar el código para los conjuntos de instrucciones de varias arquitecturas aquí para que otra persona lo examine y corrija / mejore y para dar a otros algunos resultados tentativos.Comienzo del archivo principal llamado
opcode
:Puede encontrar un ejemplo de un
Opcode_list
archivo generado y modificado utilizando las instruccionesopcode
del 27 de octubre de 2014 en http://pastebin.com/yx4rCxqs . Puede insertar este archivo directamenteopcode
en lugar de lasource Opcode_list
línea. He publicado este código porque Stack Exchange no me permitió enviar una respuesta tan grande.Finalmente, el resto del
opcode
archivo con la lógica real:Tenga en cuenta que si su consulta de búsqueda es demasiado grande (p. Ej., Con el conjunto de instrucciones de Haswell y el
-r
interruptor, esto incluye cientos de instrucciones), el cálculo puede continuar lentamente y tomar mucho tiempo en entradas grandes para las que este simple script no estaba destinado .Para obtener información detallada sobre el uso, consulte
El
opcode
script completo (con Opcode_list incluido) se puede encontrar en http://pastebin.com/A8bAuHAP .Siéntase libre de mejorar la herramienta y corregir cualquier error que pueda haber cometido. Por último, me gustaría agradecer a Jonathan Ben-Avraham por su gran idea de usar el
gas.vim
archivo de Shirk .EDITAR: El script ahora puede encontrar a qué conjunto de instrucciones pertenece un código de operación (se puede usar la expresión regular).
fuente
Primero, descompila tu binario:
Luego encuentre todas las instrucciones SSE4 en el archivo de ensamblaje:
(Nota: CRC32 podría coincidir con los comentarios).
Encuentre las instrucciones AVX más comunes (incluyendo escalar, incluyendo AVX2, familia AVX-512 y algunos como FMA
vfmadd132pd
):NOTA: probado con
gawk
ynawk
.fuente
Desafortunadamente, no parece haber ninguna utilidad conocida a partir de esta fecha que detecte el conjunto de instrucciones requerido de un ejecutable dado.
Lo mejor que puedo sugerir para x86 es usarlo
objdump -d
en el binario ELF para desarmar las secciones ejecutables en el lenguaje Gnu Assemply (gas
). A continuación, utilice de Shirkvim
definiciones de sintaxis ya sea agrep
través del archivo de código ensamblador o escanear visualmente el código ensamblador para cualquiera de losgasOpcode_SSE41
ogasOpcode_SANDYBRIDGE_AVX
las instrucciones que se ven en el Shirk degas.vim
archivo.El archivo de lenguaje ensamblador contiene las instrucciones a nivel de máquina ("códigos de operación") que el compilador generó cuando se compiló el programa. Si el programa se compiló con marcas de tiempo de compilación para instrucciones SSE o AVX, y el compilador emitió instrucciones SSE o AVX, entonces debería ver uno o más códigos opcionales SSE o AVX en la lista de desmontaje producida por
objdump -d
.Por ejemplo, si lo hace
grep vroundsdb
en el archivo de código de ensamblaje y encuentra una coincidencia, entonces sabe que el archivo binario requiere capacidades AVX para ejecutarse.Hay bastantes instrucciones específicas de la subarquitectura para x86, como puede ver en el
gas.vim
archivo de Shirk , por lo que hacergrep
ping para todos los códigos de operación para cada subarquitectura sería tedioso. Escribir un programa en C, Perl o Python para hacer esto podría ser una excelente idea para un proyecto de código abierto, especialmente si puede encontrar a alguien que lo extienda para ARM, PPC y otras arquitecturas.fuente
gas.vim
. OTOH, si este es un problema único, puede aprender fácilmente los patrones de los códigos de operación que diferencian las subarquitecturas.Le di a escribir un script de utilidad de Python basado en las respuestas de Jonathan Ben-Avrahams y Kyselejsyrečeks. Es un guión grosero pero hace el trabajo.
https://gist.github.com/SleepProgger/d4f5e0a0ea2b9456e6c7ecf256629396 Descarga y convierte automáticamente el archivo gas.vim y admite el volcado de todas las operaciones usadas (opcionales no básicas), incluido el conjunto de características de donde provienen. Además, admite operaciones de búsqueda de conjunto de características.
fuente