Znajdź, która instrukcja montażu spowodowała nielegalny błąd instrukcji bez debugowania

Podczas uruchamiania programu, który napisałem w assembly, dostaję Illegal instruction błąd. Czy istnieje sposób, aby wiedzieć, która Instrukcja powoduje błąd, bez debugowania, to znaczy, ponieważ maszyna, na której pracuję, nie ma debuggera ani żadnego systemu programowania. Innymi słowy, kompiluję na jednej maszynie i uruchamiam na innej. Nie mogę przetestować mojego programu na komputerze, który kompiluję, ponieważ nie obsługują SSE4. 2. Maszyna, na której uruchamiam program, obsługuje instrukcje SSE4. 2 niemniej jednak.

Myślę, że może dlatego, że muszę powiedzieć asemblerowi (YASM), aby rozpoznał instrukcje SSE4.2, tak jak to robimy z gcc, przekazując jej flagę -msse4.2. A może myślisz, że to nie powód? Jakiś pomysł, jak powiedzieć YASM, aby rozpoznał instrukcje SSE4. 2?

Może powinienem przechwycić sygnał SIGILL , a następnie dekodować SA_SIGINFO, aby zobaczyć, jakiego rodzaju nielegalną operację wykonuje program.

6 answers

W rzeczywistości często dostajesz nielegalny błąd instrukcji nie dlatego, że twój program zawiera nielegalny kod opcode, ale dlatego, że w twoim programie jest błąd (np. przepełnienie bufora), który sprawia, że twój program przeskakuje na losowy adres z zwykłymi danymi lub w kodzie, ale nie na początku kodu opcode.

 28
Author: ouah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 16:15:50

Ostatnio doświadczyłem awarii z powodu kodu statusu wyjścia 132 (128 + 4: program przerwany sygnałem + nielegalny sygnał instrukcji). Oto jak zorientowałem się, jaka instrukcja była przyczyną katastrofy.

Najpierw włączyłem core dumps:

$ ulimit -c unlimited

Co ciekawe, folder z którego uruchamiałem binarny zawierał folder o nazwie core. Musiałem powiedzieć Linuksowi, żeby dodał PID do zrzutu pamięci:

$ sudo sysctl -w kernel.core_uses_pid=1

Potem uruchomiłem mój program i dostałem rdzeń o nazwie core.23650. Załadowałem binarny i rdzeń z gdb.

$ gdb program core.23650

Kiedy dostałem się do gdb, pojawiła się następująca informacja:

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

To oznacza, że mój program uległ awarii z powodu nielegalnej instrukcji w pamięci adresowej 0x00007f58e9efd019. Następnie przełączyłem się na układ asm aby sprawdzić ostatnią wykonaną instrukcję:

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

To Instrukcja vpmaskmovd spowodowała błąd. Najwyraźniej próbowałem uruchomić program przeznaczony dla architektury AVX2 na systemie, który nie ma wsparcia dla instrukcji AVX2 gotowi.

$ cat /proc/cpuinfo | grep avx2

Na koniec potwierdziłem vpmaskmovd jest instrukcją tylko AVX2.

 19
Author: Diego Pino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-24 17:01:00

Jeśli możesz włączyć zrzuty pamięci w tym systemie, po prostu uruchom program, pozwól mu się zawiesić, a następnie ściągnij zrzut pamięci z docelowej maszyny na maszynę programistyczną i załaduj go do GDB zbudowanego do debugowania docelowej architektury-to powinno ci dokładnie powiedzieć, gdzie doszło do awarii. Wystarczy użyć komendy core GDB, aby załadować plik core do debuggera.

  • Aby włączyć zrzuty rdzenia na celu:

    ulimit -c unlimited
    
  • Pseudo-pliki, które kontrolują jak plik core będzie nazwane (cat te, aby zobaczyć bieżącą konfigurację, napisz do nich, aby zmienić konfigurację):

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

W moim systemie, gdy zrzuty pamięci są włączone, crashujący program zapisze plik o nazwie po prostu "core" w katalogu roboczym. Prawdopodobnie jest to wystarczająco dobre dla Twoich celów, ale zmiana nazwy pliku zrzutu pamięci pozwala zachować historię zrzutów pamięci, jeśli jest to konieczne (może w przypadku bardziej sporadycznego problemu).

 11
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 18:08:25

W przypadku montaĹźu odrÄ ™ cznego podejrzewaĺ ' bym problem z zarzÄ ... dzaniem stosem powodujÄ ... cy powrĂłt donikąd. Napisz procedurę debugowania wydruku, która zapisuje każdy rejestr i wstaw do niego wywołanie u góry każdej funkcji.

Wtedy zobaczysz, jak daleko zajdziesz...

(BTW, dobry edytor i dobre zrozumienie składni makr asemblera są ratowaniem życia podczas pisania kodu maszynowego.)

 4
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 16:22:42

Cóż ... Można oczywiście wstawiać wydruki śladowe, dzięki czemu można szybko wykluczyć duże obszary kodu. Gdy już to zrobisz, uruchom np.

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

Następnie przejdź do np. funkcji, o której wiesz, że powoduje błąd, i przeczytaj kod, szukając czegokolwiek, co wygląda dziwnie.

Nie jestem do końca pewien, jak objdump wyświetla nielegalne instrukcje, ale powinny się wyróżniać.

 3
Author: unwind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 16:13:09

Brak instrukcji return Na końcu funkcji może to spowodować.

 2
Author: Gabriel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-23 15:07:16