OLVASSEL.md 2.1 KB

Oktatóanyag 13 - Debugger

Zuzassunk egy nagyot, rakjunk mindjárt egy interaktív debuggert a kivételkezelőbe! :-) Most hogy már van printf(), nem lesz olyan vészes. (Egy kompletebb, többplatformos függvénykönyvtárért, lásd a mini debugger-t.)

$ qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Synchronous: Breakpoint instruction
> x
0007FFF0: 13 60 09 00  00 00 00 00  24 10 20 3F  00 00 00 00  .`......$. ?....
> i x30 x30+64
00080804: D2800000      movz      x0, #0x0
00080808: 94003D1C      bl        0x8FC78
0008080C: 94003ECF      bl        0x90348
00080810: D69F03E0      eret
00080814: D503201F        27 x nop
>

Dbg.h, dbg.c

Egy nagyon minimális és egyszerű debugger (~300 C sor).

breakpoint újonnan definiált C kulcsszó. Ahová beillesztjük a kódba, ott meghívódik a debugger

dbg_decodeexc() hasonló a 11-es oktatóanyagbeli exc_handler-hez, dekódolja a kivételt kiváltó okot és kiírja

dbg_getline() na ja, mégegy hiányzó függvény. Szükségünk van egy módra, amivel a felhasználó szerkesztheti a parancssort és ami sztringként visszaadja amit begépelt, mikor Enter-t üt. Szokásunkhoz híven minimál

dbg_getoffs() ez a funkció a parancs paramétereit értelmezi. Elfogad hexa és decimális számot "regiszter+/-offszet" formátumban

dbg_main() a debugger fő ciklusa.

Disasm.h

Mivel kicsi (~64k), mégis minden ARMv8.2-es utasítást ismer, és az sprintf() az egyetlen függősége (amivel már rendelkezünk), ezért a választásom az Universal Disassembler-re esett ehhez az oktatóanyaghoz. Ha nem szeretnél disassemblert belefordítani a debuggeredbe, akkor a dbg.c fájl elején állítsd a DISASSEMBLER define-t 0-ra.

Start

A _vector táblánk kicsit máshogy fest. Először is el kell mentenünk a regiszterek értékét a dbg_saveregs hívással, majd kiírjuk a kivétel okát és meghívjuk a mini-debuggerünk fő ciklusát.

Main

Leteszteljük az új breakpoint kulcsszavunkat C-ben.