2012-04-27 19 views
20

Durante l'esecuzione di un programma che ho scritto in assembly, ottengo l'errore Illegal instruction. C'è un modo per sapere quale istruzione sta causando l'errore, senza eseguire il debug, perché la macchina su cui sto lavorando non ha un debugger o un sistema di sviluppo. In altre parole, compilo in una macchina e corro su un'altra. Non riesco a testare il mio programma sulla macchina che sto compilando perché non supportano SSE4.2. Il computer su cui sto eseguendo il programma supporta comunque le istruzioni SSE4.2.Trova quale istruzione di montaggio ha causato un errore di istruzione non valida senza debug

Penso che forse perché ho bisogno di dire all'assemblatore (YASM) di riconoscere le istruzioni SSE4.2, proprio come facciamo con gcc passando il flag -msse4.2. O pensi che non sia la ragione? Qualche idea su come dire a YASM di riconoscere le istruzioni SSE4.2?

Forse dovrei intrappolare il segnale SIGILL e quindi decodificare SA_SIGINFO per vedere che tipo di operazione illegale fa il programma.

+1

YASM riconosce le istruzioni SSE4.2, quindi non è questo il problema. Sei sicuro che la tua macchina supporti SSE4.2? Che hardware è esattamente? È possibile eseguire il programma in un emulatore, valgrind (che supporta il sottoinsieme di SSE4.2 utilizzato in glibc e gcc) probabilmente funzionerebbe. – hirschhornsalz

risposta

27

In realtà si verifica un errore di istruzione non valido perché il programma contiene un codice operativo non valido ma perché nel programma è presente un errore (ad esempio un buffer overflow) che fa saltare il programma in un indirizzo casuale con dati semplici o in codice ma non all'inizio dell'opcode.

3

Bene ... È ovviamente possibile inserire stampe di traccia, in modo da poter escludere rapidamente ampie aree del codice. Al termine, esegui per es.

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

Quindi passare a es. la funzione che conosci causa l'errore e legge il codice, cercando qualcosa di strano.

Non sono completamente sicuro di come objdump visualizza istruzioni non valide, ma dovrebbero risaltare.

4

Per assemblaggi scritti a mano, sospetto un problema di gestione dello stack che si traduce in un ritorno al nulla. Scrivi una routine di debugging che salva ogni registro e inserisce una chiamata ad esso nella parte superiore di ogni funzione.

Poi si vedrà quanto lontano si ottiene ...

(a proposito, un buon editor e una buona conoscenza della sintassi della macro assemblatore sono bagnini durante la scrittura di codice macchina.)

+0

Sospetto che l'assemblatore richieda che specifichi espressamente che sto usando l'istruzione SSE4.2, proprio come gcc richiede di passare il flag -msse4.2. – pythonic

+2

Ma abilitare le istruzioni nell'assemblatore cambia solo la sintassi consentita. Non sarebbe la differenza tra intrappolare e non intrappolare, immagino. – DigitalRoss

+0

@ user1018562 No. Se l'assemblatore incontra un'istruzione non consentita per l'architettura di destinazione, si verificherà l'errore, ma solo durante la compilazione. Se esiste un errore in fase di esecuzione, ma non durante la compilazione, è vero il contrario: l'assemblatore emette le istruzioni, che l'architettura di destinazione non comprende. Quindi, semmai, devi dire al compilatore di non emettere istruzioni SSE. – hirschhornsalz

11

Se è possibile abilitare core dump su quel sistema, basta eseguire il programma, lasciarlo andare in crash, quindi estrarre il core dump dalla macchina di destinazione sulla macchina di sviluppo e caricarlo in un GDB creato per eseguire il debug dell'architettura di destinazione, che dovrebbe indicare esattamente dove si è verificato l'arresto anomalo . Basta usare il comando core di GDB per caricare il file core nel debugger.

  • Per abilitare i core dump sul bersaglio:

    ulimit -c unlimited 
    
  • pseudo-file che controllano come il file core si chiamerà (cat questi per vedere la configurazione corrente, scrivere a loro per cambiare il configurazione):

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

Sul mio sistema, discariche una volta fondamentali sono abilitati, un programma di crash sarà scritto e un file semplicemente chiamato "core" nella directory di lavoro.Probabilmente è abbastanza buono per i tuoi scopi, ma cambiare il modo in cui il file di dump di base è denominato ti consente di conservare una cronologia dei dump di core, se necessario (forse per un problema più intermittente).

+0

Scatole di Linux Ho usato tutti i core di rilascio chiamati 'core. $ PID'. –

+0

@Warren: la mia casella Ubuntu (e la build incorporata che abbiamo) è predefinita in un file chiamato semplicemente 'core' per qualche motivo. –

15

Recentemente si è verificato un arresto anomalo a causa di un codice di stato 132 di uscita (128 + 4: programma interrotto da un segnale + segnale di istruzione illegale). Ecco come ho capito quale istruzione stava causando l'incidente.

In primo luogo, ho attivato i core dump:

$ ulimit -c unlimited 

È interessante notare che la cartella da dove stavo correndo il binario conteneva una cartella denominata core. Ho dovuto dire Linux per aggiungere il PID per il core dump:

$ sudo sysctl -w kernel.core_uses_pid=1 

Poi ho eseguito il mio programma e ottenuto un nucleo di nome core.23650. Ho caricato il binario e il core con gdb.

$ gdb program core.23650 

Una volta che sono entrato in gdb, si presentò le seguenti informazioni:

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

Ciò significa che il mio programma si è schiantato a causa di un'istruzione non valida in 0x00007f58e9efd019 memoria indirizzo. Poi sono passato a layout di asm per controllare l'ultima istruzione eseguita:

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

Era istruzioni vpmaskmovd che ha causato l'errore. Apparentemente, stavo cercando di eseguire un programma per l'architettura AVX2 su un sistema che non supporta il set di istruzioni AVX2.

$ cat /proc/cpuinfo | grep avx2 

Infine, ho confermato vpmaskmovd is an AVX2 only instruction.

+0

Mi sono reso conto che la mia risposta non soddisfa pienamente uno dei requisiti della domanda: "determinare le istruzioni di errore senza usare strumenti di debug":/Comunque, penso che la risposta possa essere utile per altri utenti quindi preferisco lasciarla. Inoltre, come ha commentato Michael Burr, potrebbe essere possibile estrarre il core dump dalla macchina di destinazione nella macchina di costruzione e eseguire il debug del core da lì (dove sono disponibili gli strumenti di debug) impostando un'architettura di destinazione diversa "(gdb) set architecture ". –

+0

Vorrei aggiungere, se è il tuo programma che si blocca, compilare con '-ggdb' prima di seguire i passaggi sopra – ComputerSaysNo

+1

Aveva un problema simile con un programma che tentava di usare PMADDUBSW sulla mia VM solo SSE2, grazie :) – Joril