SO 2023

ASM

Nieoficjalny spis instrukcji asemblera x86 (nie jest idealny, ale za to podany w dość czytelnej postaci): https://www.felixcloutier.com/x86/index.html.

Poradnik o asemblerze na wikibooks: https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture.

GDB

Rozszerzenie PEDA do gdb: https://github.com/longld/peda.

Jak używać gdb (wersja bardzo skompresowana):

  1. Uruchamiamy gdb i podajemy ścieżkę do programu, który będziemy debugować: $ gdb ./nasz_program.
  2. Stawiamy breakpoint w miejscu, od którego chcemy zacząć debugowanie: b nazwa_funkcji (b to skrót od breakpoint).
  3. Uruchamiamy program: r (skrót od run).
  4. Teraz program powinien zacząć działać i dotrzeć aż do pierwszego wystąpienia breakpointu. W tym momencie przydadzą się 3 komendy gdb:
    1. s (skrót od step) - wykonuje jedną instrukcję, jeśli jest to wywołanie funkcji, to wchodzi do niej.
    2. n (skrót od next) - wykonuje jedną instrukcję, ale omija wywołania funkcji.
    3. c (skrót od continue) - kontynuuje wykonanie programu aż do ponownego natrafienia na breakpoint.
  5. gdb zamykamy podając komendę q (skrót od quit).

MINIX

Konfiguracja środowiska do pracy z kodem źródłowym Minixa może wyglądać następująco:

  1. Pobieramy obraz qemu ze studentsa:

    $ scp <login>@students.mimuw.edu.pl:/home/students/inf/PUBLIC/SO/scenariusze/4/minix.img minix_original.img
  2. Tworzymy obraz copy-on-write:

    $ qemu-img create -f qcow2 -F raw -o backing_file=minix_original.img minix.img
  3. Tworzymy skrypt uruchamiający obraz run_minix.sh:

    qemu-system-x86_64 -curses -drive file=minix.img -enable-kvm -machine kernel_irqchip=off -rtc base=localtime -net user,hostfwd=tcp::10022-:22 -net nic,model=virtio -m 1024M

    Na systemie Mac OS X być może zadziała coś takiego:

    qemu-system-x86_64 -display curses -drive file=minix.img -machine accel=hvf -rtc base=localtime -net user,hostfwd=tcp::10022-:22 -net nic,model=virtio -m 1024M
  4. Uruchamiamy obraz:

    $ ./run_minix.sh
  5. Kopiujemy nasz klucz publiczny na minix:

    $ ssh-copy-id root@localhost -p 10022
  6. Dodajemy minixa do .ssh/config:

    Host minix
     HostName localhost
     Port 10022
     User root
  7. Teraz możemy zalogować się na minixa:

    $ ssh minix
  8. Instalujemy nano i rsync na minixie:

    $ pkgin install nano
    $ pkgin install rsync
  9. Kopiujemy kod źródłowy z minixa na hosta i inicjalizujemy repozytorium gita:

    $ mkdir minix_source
    $ rsync -vrazh minix:/usr/src minix_source
    $ cd minix_source
    $ git init .
  10. Dodajemy plik .gitignore:

    */*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*/*.*
    */*/*/*/*/*/*/*.*
    */*/*/*/*/*/*.*
    */*/*/*/*/*.*
    */*/*/*/*.*
    */*/*/*.*
    */*/*.*
    */*.*
    *.*
    !/**/*.c
    !/**/*.h
    !/**/Makefile
    !/**/makefile
    !/**/Makefile.inc
    !/**/makefile.inc
    !.gitignore
  1. Commitujemy:
    • .gitignore
    • src/include
    • src/lib/libc
    • src/minix/servers
    • src/minix/kernel
    • src/minix/lib/libsys
  1. Tworzymy skrypt kopiujący kod źródłowy z hosta na minixa sync.sh:
    rsync -vrazh src minix:/usr/
  1. Tworzymy skrypt do backupowania obrazu minixa backup.sh (przed wykonaniem backupu należy wyłączyć qemu):
    month=$( date +%m )
    day=$( date +%d )
    hour=$( date +%H )
    minute=$( date +%M )
    cp minix.img minix_${month}.${day}T${hour}:${minute}.img
  1. Teraz możemy edytować kod źródłowy na hoście (na przykład CLionem lub VSCode) i kompilować go na minixie. Wszystkie zmiany powinny być widoczne w git status. Przykładowe flow edycji kodu może wyglądać tak:
    • Edytujemy kod w IDE
    • Przysyłamy zmiany za pomocą rsync (uwaga, rsync wysyła też pliki *.o, także nadpisze Wam wszystkie wcześniej skompilowane pliki)
    • W minixie uruchamiamy skrypt do kompilowania, wyglądający mniej więcej tak:
      cd /usr/src; make includes || exit 1
      cd /usr/src/minix/kernel; make clean && make || exit 1
      make install || exit 1
      cd /usr/src/minix/lib/libsys; make clean && make || exit 1
      make install || exit 1
      cd /usr/src/minix/servers/sched; make clean && make || exit 1
      make install || exit 1
      cd /usr/src/minix/servers/pm; make clean && make || exit 1
      make install || exit 1
      cd /usr/src/lib/libc; make clean && make || exit 1
      make install || exit 1
      cd /usr/src/releasetools; make hdboot
    • Jeśli wszystkie polecenia się udały, to wykonujemy $ reboot, a w oknie wyboru wersji jądra wybieramy 2.
    • Jeśli system się nie uruchomi, możemy zamknąć qemu i uruchomić minixa ponownie, ale wybierając 1 - uruchomi się wtedy poprzednia wersja jądra.