programy s longjmp
programy, ktere pouzivaji longjmp, maji pri debuggu takovou neprijemnou vlastnost, ze pote co se vyvola longjmp debugger zastavi na internim breakpointu a prikaz 'next' (dalsi radka) pak nefunguje. Navic se objevi nejake neprijemne hlasky (nevim to ted presne, nejsem u odpovidajiciho stroje)
Doporucene reseni, - tedy pomoci 'info breakpoints' najit vsechny interni breakpointy (to jsou ty s minusem), ktere adresuji priznak 'siglongjmp' a pomoci 'clear *adress' tento vnitrni breakpoint smazat funguje jen pro prvni longjmp volani. Pote je opet treba proceduru mazani internich breakpointu, ktere adresuji ten siglongjmp opakovat. (protoze se objevi nove interni breakpointy - coz je logicke).
Existuje eventuelne nejaka moznost, jak gdb sdelit, aby trvale ignoroval ty odpovidajici interni breakpointy?
Ale isteze. Napr. encoder x264, x265 ma kopec kodu v asm. Dokonca autor pravidelne organizuje ucast na summer of code, kde sa snazi projekty vylepsit. Poziadavky na vstup do SoC su: assembler - expert.
Takisto som raz stretol cloveka, ktory vytvara ochrany proti piratom do hier. Bez assembleru sa takyto clovek nepohne.
Tak tvorba delších programů pouze v assembleru je na zařízeních, kde běhá linux (což už musí být dost silné stroje, žádné PIC10), asi hodně výjimečná, ale kratší kusy kódu se pořád tvoří. Spousta lidí se například pouští do své zaručeně nejrychlejší :-) implementace FFT či části nějakého kodeku popř. aspoň filtru.
Osobně se však mnohem častěji setkám právě s potřebou odladění kódu, který klidně vznikl překladem kdoví kde nebo v JITu a kde jiná možnost není (třeba změna původního zdrojáku na produkci nebo živém zařízení nehrozí a i kdyby to šlo, tak některé problém s přístupem do paměti "zmizí" ve chvíli, kdy se nový překlad provede s přidáním debug symbolů apod.).
Ale jo. MIPS, ARM.
Zrovna teď píšu něco pro NEON (SIMD jádro) na Cortex-A9 dvoujádře v Zynq7020, Linux 3.14.2.
Jde o rychlost, takže nejdřív to začlo v Cortex-A9 asm, potom pokus o vektorizaci a přepis do NEON intrinsic v C -O3. Ale ani to nedávalo takové výsledky, jakých se mělo podle předpokladů dosáhnout (gcc měl vlastní hlavu, jak instrukce zpřeházet, a bohužel ne příliš efektivně). Takže zpět do asm a ruční práce s každou instrukcí. Vše nad tím samozřejmě už C.
Ono je to tak, že na klasických strojích, když to drhne, tak se koupí lepší stroj, nebo se to rozhodí mezi více strojů. V embedded, když už to máte vyvinuté a osazené a zákazník najednou chce přidat ještě to či ono, tak přechod z C do asm na kritických místech je většinou první volba. Teď jsem třeba věc, která trvala v C -O3 po různých optimalizačních cestách naproti gcc 47 T/bajt srazil na 13 T/bajt (díky NEONu).
Poslední roky ale platí (vyšší verze gcc 4, gcc 5 -O3/-Ofast), že nemá cenu přepisovat C do asm bez nějaké další pomoci, třeba v podobě v C překladači nepodporovaných instrukcích (dosažitelných jen z asm) nebo ještě ne příliš dobře podporovaném hw (třeba právě ty SIMD) apod. Před pár lety jsem míval skóre tak 10 až 25 % na rychlosti C -O3 -> asm, teď jsem tu věc nahoře v ARM asm napsal jen na 47 T/bajt, takže rovná 0. Jo, možná stárnu...
Na AMD64 tenhle příklad skončí na SIGSEGV, takže kdo by si to chtěl vyzkoušet, tak tady je upravená verze (jen sekce .text):
.section .text
.global _start # tento symbol ma byt dostupny i linkeru
_start:
movq rbx, offset buffer # zapis se bude provadet do tohoto bufferu
mov al, 'a' # kod prvniho zapisovaneho znaku
loop:
mov [rbx], al # zapis znaku do bufferu
inc al # ASCII kod dalsiho znaku
inc rbx # uprava ukazatele do bufferu
cmp al, 'z' # ma se smycka ukoncit?
jna loop # pokud jsme neprekrocili kod 'z', opakovat smycku
lwrite:
movq rax, sys_write # cislo syscallu pro funkci "write"
movq rdi, 1 # standardni vystup
movq rsi, offset buffer # adresa retezce, ktery se ma vytisknout
movq rdx, 26 # pocet znaku, ktere se maji vytisknout
syscall # volani Linuxoveho kernelu
lexit:
movq rax, sys_exit # cislo sycallu pro funkci "exit"
movq rdi, 0 # exit code = 0
syscall # volani Linuxoveho kernelu
Pro embedded se mi jinak do gdb dost hodil gdb dashboard: https://github.com/cyrus-and/gdb-dashboard. Chce to mít ale velký monitor nebo velký terminál :-)
Vdaka za clanok.
Velmi dobra vec pri breakpointoch je moznost sputenia preddefinovanych prikazov ak bol breakpoint hitnuty (pripadne dat breakpointu podmienku). Tj. napriklad vypise comment, pripadne cez display zobrazi obsah registra apod.
(gdb) disass $pc, $pc+8
Dump of assembler code from 0x8048074 to 0x804807c:
=> 0x08048074: pop eax
0x08048075: pop edx
0x08048076: mov edx,DWORD PTR [edx]
0x08048078: sub esp,0x1000
End of assembler dump.
(gdb)
(gdb) b *0x08048078
Breakpoint 2 at 0x8048078
(gdb)
(gdb) command
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>print "about to mess up the stack"
>end
(gdb)
(gdb) c
Continuing.
Breakpoint 2, 0x08048078 in ?? ()
=> 0x08048078: 81 ec 00 10 00 00 sub esp,0x1000
$1 = "about to mess up the stack"
(gdb)
Btw tuší někdo, proč se kdysi zvolila zrovna ta prapodivná AT&T syntaxe? Jako chápu, že GNU nevznikl na Intelí platformě, ale AT&T je divná snad pro všechny typy procesorů - na každém je jiný znak pro komentář (například), někde se velikost operandů nemusí do instrukce psát, někde jo, je to dost zmatek. Navíc pokud vím, tak Intel tu svoji syntaxi a instrukční soubor taktéž někde už získal, takže to bylo známé minimálně někdy v roce 1972-73, spíš dřív.
Pro mě to byl kdysi docela blocker, jsem byl zvyklý na TASM, ten byl hrozně fajn :-) A samozřejmě Atari Macro Assembler, pěknej ale snad nejpomalejší na světě :.p
Ovsem v naprostem minumu pripadu, assembler to jinak pozna z druheho operandu. Asi nejcisteji to ma vyreseny NASM, ten jasne odlisuje praci s adresou od prace s obsahem adresy, GAS si pomaha slovem offset, coz je trosku nesikovne (a navic je to nekonzistentni).
Mluvim o tom, ze puvodne AT&T vyzadoval urceni velikosti vsude:
movw %bx, %ax (mov ax, bx)
xorl %eax, %eax (xor eax, eax)
movw $1, %ax (mov ax,1)
movb X, %ah (mov ah, byte ptr X)
movw X, %ax (mov ax, word ptr X)
movl X, %eax (mov eax, X)
Ted je to volnejsi, takze tam, kde je druhej operand registr a tudiz je jasna sirka, nemusime to psat.
este pridam odkaz na zaujimavy projekt:
https://github.com/snare/voltron
zaujimavo sa daju stiepit gdb okna. je pravda, ze nie vzdy to moze vyhovovat .. ale pri niektorych veciach je to fajn. a ked ma clovek 2 monitory tak sa s tym da pekne vyhrat.
vyhoda je, ze ked to nechcem tak to v ~/.gdbinit zahashujem. takze take semi on demand :)
Tak isto je dobry addon
https://github.com/pwndbg/pwndbg
Sice je to zamerane primarne na "pwnables" z wargames, da sa to pekne vyuzit pri akomkolvek debuggingu.
Zaujimavy problem su aj farby v konzole. To by asi bolo na cely samostatny clanok. Pre ludi co poznaju opensolaris (solaris) tie farby nebudu vobec cudzie. Jedna sa o "solarized" temu.