2012-04-27 14 views
20

Al ejecutar un programa que he escrito en ensamblado, recibo el error Illegal instruction. ¿Hay alguna manera de saber qué instrucción está causando el error, sin depuración, porque la máquina en la que estoy ejecutando no tiene un depurador ni ningún sistema de desarrollo? En otras palabras, compilo en una máquina y corro en otra. No puedo probar mi programa en la máquina que estoy compilando porque no son compatibles con SSE4.2. La máquina en la que ejecuto el programa sí admite las instrucciones de SSE4.2.Buscar qué instrucción de ensamblado provocó un error de instrucción ilegal sin depurar

Creo que tal vez porque necesito decirle al ensamblador (YASM) que reconozca las instrucciones SSE4.2, al igual que hacemos con gcc pasándole la bandera -msse4.2. ¿O crees que no es la razón? ¿Alguna idea de cómo decirle a YASM que reconozca las instrucciones de SSE4.2?

Quizás debería atrapar la señal SIGILL y luego decodificar el SA_SIGINFO para ver qué tipo de operación ilegal hace el programa.

+1

YASM reconoce las instrucciones SSE4.2, por lo que este no es el problema. ¿Estás seguro de que tu máquina es compatible con SSE4.2? ¿Qué hardware es exactamente? Podrías ejecutar el programa en un emulador, valgrind (que admite el subconjunto de SSE4.2 que se usa en glibc y gcc) probablemente funcionaría. – hirschhornsalz

Respuesta

27

En realidad, recibe un error de instrucción ilegal no porque su programa contenga un código de operación ilegal sino porque hay un error en su programa (por ejemplo, un desbordamiento del búfer) que hace que su programa salte en una dirección aleatoria con datos simples o en código pero no en el inicio del código de operación.

3

Bien ... Por supuesto, puede insertar impresiones de trazas, para que pueda descartar rápidamente grandes áreas del código. Una vez que hayas hecho eso, ejecuta, p.

$ objdump --disassemble my-crashing-program | less 

Luego salta a, p. la función que usted sabe está causando el error, y lea el código, buscando cualquier cosa que parezca extraña.

No estoy del todo seguro de cómo objdump muestra instrucciones ilegales, pero deben destacarse.

4

Para el ensamblaje escrito a mano sospecho que hay un problema de administración de la pila que da como resultado un retorno a la nada. Escriba una rutina de impresión de depuración que guarda cada registro e inserte una llamada en la parte superior de cada función.

A continuación podrá ver hasta qué punto se obtiene ...

(Por cierto, un buen editor y una buena comprensión de la sintaxis macro del ensamblador son salvavidas al escribir código de máquina.)

+0

Sospecho que el ensamblador requiere que especifique explícitamente que estoy usando la instrucción SSE4.2, al igual que gcc requiere pasar el indicador -msse4.2. – pythonic

+2

Pero las instrucciones de habilitación en el ensamblador solo cambian la sintaxis permitida. No sería la diferencia entre atrapar y no atrapar, imagino. – DigitalRoss

+0

@ user1018562 No. Si el ensamblador encuentra una instrucción no permitida para la arquitectura de destino, se equivocaría, pero solo durante el tiempo de compilación. Si existe un error en el tiempo de ejecución, pero no durante el tiempo de compilación, ocurre lo contrario: el ensamblador emite instrucciones que la arquitectura de destino no comprende. Entonces, si algo necesita, debe decirle al compilador que no emita instrucciones SSE. – hirschhornsalz

11

Si puede permitir en el sistema, simplemente ejecute el programa, déjelo colapsar, luego extraiga el volcado del núcleo de la máquina de destino en su máquina de desarrollo y cárguelo en un GDB construido para depurar la arquitectura de destino; esto debería indicar exactamente dónde ocurrió el bloqueo. . Simplemente use el comando core de GDB para cargar el archivo central en el depurador.

  • Para habilitar los volcados de memoria en el objetivo:

    ulimit -c unlimited 
    
  • pseudo-archivos que controlan la forma en el archivo central será nombrado (cat estos para ver la configuración actual, escriba que se cambie el configuración):

    /proc/sys/kernel/core_pattern 
    /proc/sys/kernel/core_uses_pid 
    

En mi sistema, una vez vertederos centrales están habilitadas, un programa de estrellarse se decreto judicial e un archivo simplemente llamado "core" en el directorio de trabajo.Probablemente sea lo suficientemente bueno para sus propósitos, pero cambiar la forma en que se nombra el archivo de volcado del núcleo le permite mantener un historial de volcados del núcleo si es necesario (tal vez para un problema más intermitente).

+0

Linux boxes He utilizado todos los núcleos de extracción llamados 'core. $ PID'. –

+0

@Warren: mi caja Ubuntu (y la versión incorporada que tenemos) por defecto a un archivo simplemente llamado 'core' por alguna razón. –

15

Recientemente experimenté un bloqueo debido a un código de estado de salida 132 (128 + 4: programa interrumpido por una señal + señal de instrucción ilegal). Así es como descubrí qué instrucción estaba causando el bloqueo. núcleo

En primer lugar, Habilité vertederos:

$ ulimit -c unlimited 

Curiosamente, la carpeta de donde yo estaba corriendo el binario contiene una carpeta con el nombre core. Tenía que decirle a Linux para añadir el PID para el vaciado de memoria:

$ sudo sysctl -w kernel.core_uses_pid=1 

Luego ejecutar mi programa y tengo un núcleo llamado core.23650. Cargué el binario y el núcleo con gdb.

$ gdb program core.23650 

Una vez que entré en GDB, que se presentó la siguiente información:

Program terminated with signal SIGILL, Illegal instruction. 
#0 0x00007f58e9efd019 in ??() 

Eso significa que mi programa bloqueado debido a una instrucción ilegal en 0x00007f58e9efd019 memoria de direcciones. Entonces me pasa a diseño asm para comprobar la última instrucción ejecutada:

(gdb) layout asm 
>|0x7f58e9efd019 vpmaskmovd (%r8),%ymm15,%ymm0 
|0x7f58e9efd01e vpmaskmovd %ymm0,%ymm15,(%rdi) 
|0x7f58e9efd023 add $0x4,%rdi 
|0x7f58e9efd027 add $0x0,%rdi 

Fue instrucción vpmaskmovd que provocó el error. Aparentemente, estaba tratando de ejecutar un programa dirigido a la arquitectura AVX2 en un sistema que carece de soporte para el conjunto de instrucciones AVX2.

$ cat /proc/cpuinfo | grep avx2 

Por último, confirmé vpmaskmovd is an AVX2 only instruction.

+0

Me di cuenta de que mi respuesta no cumplía uno de los requisitos de la pregunta: "determinar la instrucción de fallas sin usar herramientas de depuración":/Aún así, creo que la respuesta puede ser útil para otros usuarios, así que prefiero abandonarla. Además, como comentó Michael Burr, podría ser posible extraer el volcado del núcleo de la máquina objetivo en la máquina de construcción y depurar el núcleo desde allí (donde las herramientas de depuración están disponibles) configurando una arquitectura de destino diferente "(gdb) set architecture ". –

+0

Añadiría, si es tu programa el que falla, compila con '-ggdb' antes de seguir los pasos anteriores – ComputerSaysNo

+1

Tuve un problema similar con un programa que intentó usar PMADDUBSW en mi máquina virtual solo SSE2, gracias :) – Joril

Cuestiones relacionadas