Obsah
1. Grafická nadstavba nad GNU Debuggerem gdbgui a její alternativy
2. Existující nadstavby pro GNU Debugger
4. DDD (Data Display Debugger)
10. Nová nadstavba na GNU Debuggerem: gdbgui
11. Technologie, na nichž je nástroj gdbgui postaven
12. Instalace a první spuštění
13. Zobrazení zdrojového kódu a disassemblovaného strojového kódu
14. Krokování a sledování hodnot lokálních proměnných
15. Výrazy, zobrazení grafů historie vyhodnocených výrazů
17. Výpis složitějších datových struktur (pole, struktury, stromy)
18. Ladění programů napsaných v programovacím jazyku Rust
1. Grafická nadstavba nad GNU Debuggerem gdbgui a její alternativy
S nástrojem GNU Debugger jsme se již na stránkách Roota několikrát setkali. Ostatně se ani není čemu divit, protože se jedná o skutečně velmi dobrý nástroj, který je navíc skriptovatelný, podporuje ladění aplikací psaných v různých programovacích jazycích (nejenom tedy v C a C++), vzdálené ladění, tvorbu nadstaveb komunikujících s GNU Debuggerem s využitím standardního protokolu atd. Ovšem univerzálnost GNU Debuggeru a velké množství dostupných příkazů do značné míry komplikuje jeho ovládání, především těm vývojářům, kteří debugger nepoužívají tak často, aby se jim vyplatilo věnovat velké množství času pro zjištění všech možností a triků, které jim GNU Debugger nabízí.
Obrázek 1: Klasické rozhraní GNU Debuggeru ovládaného z příkazového řádku.
Právě z tohoto důvodu vznikly různé nadstavby nad GNU Debuggerem, které se snaží alespoň ty nejčastěji používané operace a příkazy uživatelům nabídnout z prostředí s plnohodnotným celoobrazovkovým textovým či přímo grafickým uživatelským rozhraním. Zde je nutné připomenout, že prakticky všechny existující nadstavby nad GNU Debuggerem skutečně nabízí pouze podmnožinu všech jeho funkcí; ty pokročilejší funkce je nutné stále volat s využitím příkazového řádku (ostatně i proto ho nadstavby většinou taktéž nabízí).
Obrázek 2: GNU Debugger samozřejmě podporuje i disassembling strojového kódu.
GNU Assembler byl sice původně nástrojem ovládaným čistě z příkazového řádku nebo vzdáleně pomocí síťového protokolu (RSP), ovšem později byl rozšířen o jednoduché textové uživatelské rozhraní (TUI). To se zapíná a konfiguruje příkazem layout.
Obrázek 3: GDB s jeho textovým uživatelským rozhraním.
2. Existující nadstavby pro GNU Debugger
Tvůrci nadstaveb nad GNU Debuggerem zvolili hned několik různých technologií. Některé nadstavby, zejména se to týká Data Display Debuggeru (DDD), Nemiveru a KDbg, jsou samostatně běžící aplikace s plnohodnotným grafickým uživatelským rozhraním, které si samy GNU Debugger spouští a komunikují s ním. Alternativní cgdb používá textové uživatelské rozhraní, ale v ostatních ohledech se podobá trojici předchozích nástrojů. Grand Unified Debugger, Clewn a PyClewn jsou nadstavby nad programátorskými textovými editory Emacs a Vim.
Obrázek 3: V minulosti velmi populární nástroj Turbo Debugger je vybaven celoobrazovkovým textovým uživatelským rozhraním (TUI) připomínajícím další produkty vytvořené společností Borland.
A konečně gdbgui je postavena na webových technologiích, konkrétně na serveru komunikujícím s GNU Debuggerem a klientským kódem běžícím ve webovém prohlížeči, který zajišťuje GUI. Každé z těchto řešení samozřejmě má své výhody ale i zápory; o některých z nich se stručně zmíníme v navazujících kapitolách.
Obrázek 4: Jedno ze speciálních oken Turbo Debuggeru, v němž se zobrazuje stav mikroprocesoru (obsahy pracovních registrů i příznakových bitů), obsah vybrané části operační paměti a taktéž zdrojový kód proložený disassemblovaným strojovým kódem (v této části okna je zvýrazněn právě prováděný řádek).
3. cgdb (curses debugger)
Nástroj nazvaný cgdb je založený na knihovně curses resp. ncurses, tudíž ho je možné využít v terminálu, na vzdáleném stroji připojeném přes SSH atd. Ve svém základním nastavení nástroj cgdb rozděluje okno terminálu (konzole) na dvě části. V horní části je zobrazen zdrojový kód laděné aplikace a v části dolní pak rozhraní samotného GNU Debuggeru. Mezi oběma částmi je možné se s využitím několika klávesových zkratek přepínat, přičemž je nutné poznamenat, že většinu složitějších příkazů je možné zadávat pouze v rozhraní GNU Debuggeru.
Obrázek 5: Takto vypadá textové uživatelské rozhraní nástroje cgbd po spuštění. V horním okně můžeme vidět zdrojový kód se zeleně zvýrazněným aktivním řádkem, v dolní polovině terminálu se pak nachází rozhraní GNU Debuggeru.
Horní část slouží zejména pro dobrou orientaci v laděném programu, pro zobrazení nastavených breakpointů (v základním nastavení je použita červená barva) a taktéž pro zobrazení místa, v němž se právě nachází laděný program (v základním nastavení je tento řádek zobrazen zeleně).
Obrázek 6: Ladění programu v cgdb. Na řádku 21 je nastaven breakpoint, proto je tento řádek zvýrazněn červeně. Řízení programu přešlo na řádek číslo 23 (zvýrazněno zeleně) a v dolní části si vývojář s využitím příkazu print vypsal obsah dvou lokálních proměnných.
V nástroji cgdb se využívají klávesové zkratky známé především z textových editorů Vi a Vim, ovšem i ti uživatelé, kteří tyto editory nepoužívají (a tudíž dané zkratky neznají), nebudou ztraceni, protože se například ve zdrojovém textu mohou pro přesun kurzoru používat i kurzorové klávesy atd. cgdb obsahuje i vestavěnou nápovědu dostupnou po stisku klávesy F1.
Obrázek 7: Další pohled na nástroj cgdb, tentokrát při ladění kódu pro mikroprocesor s architekturou AArch64.
4. DDD (Data Display Debugger)
Další nadstavba nad GNU Debuggerem se jmenuje Data Display Debugger. Tato nadstavba nabízí uživatelům při ladění aplikací plnohodnotné grafické uživatelské rozhraní, jehož jednotlivé ovládací prvky a jejich chování sice mohou působit zastarale (což je způsobeno použitou GUI knihovnou), ve skutečnosti je však celé uživatelské rozhraní Data Display Debuggeru velmi flexibilní, což vynikne především při použití dvou a více monitorů (to je dnes pro vývojáře asi standardní konfigurace).
Obrázek 7: Pokud se nastaví breakpointy, jsou viditelné jak ve zdrojovém kódu (pokud je samozřejmě k dispozici), tak i v okně s disassemblovaným strojovým kódem.
Příkladem flexibility grafického uživatelského rozhraní Data Display Debuggeru jsou například „odtrhávací“ menu (tear off menu), které je možné velmi snadno změnit na nemodální dialogy s nabídkou příkazů. Data Display Debugger lze využít i pro komunikaci s dalšími debuggery, například s debuggerem jazyka Perl, debuggerem skriptů psaných v BASHi a v neposlední řadě taktéž pro ovládání pydb, což je jeden z debuggerů používaných vývojáři, kteří pro tvorbu programů používají jazyk Python
Obrázek 8: V průběhu ladění nativních aplikací může být užitečné si zobrazit obsahy všech pracovních registrů mikroprocesoru. I tuto možnost Data Display Debugger samozřejmě programátorům nabízí.
Při ladění prakticky jakékoli složitější aplikace je nutné sledovat jak vlastní programový kód (ať již na úrovni zdrojového programového kódu či na úrovni assembleru, tj. jednotlivých strojových instrukcí), tak i datové struktury používané tímto kódem. Tyto struktury mohou být velmi komplikované, zejména pak ve chvíli, kdy je laděn program vytvořený v C či C++, kdy je mnohdy nutné používat lineárně vázané seznamy, různé typy stromů, pole struktur atd. Právě z tohoto důvodu dostala aplikace Data Display Debugger svoje jméno, protože prohlížení a analýza dat je zde poměrně propracovaná.
Obrázek 9: Zobrazení několika prvků binárního stromu v Data Display Debuggeru. Povšimněte si, jakým způsobem se pracuje s ukazateli nastavenými na hodnotu NULL.
Obrázek 10: Alternativní pohled na data, se kterými aplikace pracuje.
5. Nemiver
O dalším nástroji pojmenovaném Nemiver již vyšel samostatný článek na „konkurenčním“ webu. Tento nástroj opět komunikuje s GNU Debuggerem, ovšem na rozdíl od DDD postaveného nad postarší GUI knihovnou je Nemiver primárně určený pro desktopové prostředí GNOME se všemi přednostmi a zápory, které to přináší. Nemiver tak uživatelům nabízí přehledné prostředí, které ovšem není tak flexibilní jako DDD a taktéž například možnosti zobrazení složitějších datových struktur (různých lineárně vázaných seznamů, stromů či obecnějších grafových struktur) jsou v Nemiveru omezené. Pokud ale někdo pouze potřebuje odkrokovat několik funkcí a neprovádět žádné složitější operace, může být tento nástroj pro takového uživatele velmi dobrým řešením.
Obrázek 11: Nastavení breakpointu ve zdrojovém kódu laděné aplikace. V dolní části okna Nemiveru můžeme vidět aktuální hodnoty lokálních proměnných.
Velmi užitečnou vlastností je podpora takzvaných „sezení“ (session). Kdykoli je totiž Nemiver ukončen, zapamatuje si, která aplikace byla laděna, na kterých řádcích byly nastaveny breakpointy atd. K ladění této aplikace se lze kdykoli k budoucnu vrátit a to bez nutnosti explicitně vytvářet projekty či se nějak dále o uložená sezení starat. Mimochodem – veškerá nastavení naleznete v souboru ~/.nemiver/nemivercommon.db a jak již koncovka tohoto souboru napovídá, jedná se o SQLite databázi (obsah této databáze je jednoduché exportovat do textového souboru, takže uživatelé nemusí nutně ztratit všechny výhody textových souborů a nástrojů pro jejich zpracování).
Obrázek 12: „Rozbalení“dalších elementů binárního stromu.
Na rozdíl od DDD je způsob zobrazení složitějších datových struktur pojat odlišným způsobem a může být méně přehledný, což je ostatně patrné ze screenshotů číslo 12 a 13.
Obrázek 13: Způsob zobrazení obsahu jednorozměrného a dvourozměrného pole.
6. KDbg
Pro „konkurenční“ desktopové prostředí KDE vznikl projekt nazvaný KDbg, který byl podrobněji zmíněn v tomto článku. KDbg vývojářům nabízí prakticky veškeré základní funkce, které jsou od debuggerů očekávány: nastavování breakpointů, nastavování watchpointů, krokování po jednotlivých příkazech, vstup do volaných funkcí, prohlížení obsahu operační paměti, prohlížení složitějších datových struktur apod. KDbg je ve skutečnosti opět nadstavbou nad klasickým GNU Debuggerem, což mj. znamená, že KDbg je možné v současné verzi použít pro ladění nativních aplikací naprogramovaných v jazycích Ada, C, C++, Go, Objective-C, D, Fortran, Modula-2, Pascal a Java (zde ovšem pouze při překladu do nativního strojového kódu). Nejpoužívanějšími jazyky laděných aplikací pravděpodobně zůstanou C a C++.
Obrázek 14: Laděný program bez nastaveného breakpointu podle očekávání zhavaroval na řádku číslo 5 (viz zpráva zobrazená v pravém dolním rohu). Aby bylo možné debuggerem odhalit, kde chyba vznikla, je nutné nastavit breakpoint před tento řádek.
Nástroj KDbg dokáže přehledně zobrazit obsah zásobníku, resp. přesněji řečeno obsah zásobníkových rámců platných pro aktivní vlákno (ladění vícevláknových aplikací je ovšem funkční pouze v případě, že tuto funkci podporuje GNU Debugger!). Informace o zásobníkových rámcích je rozdělena do dvou podoken. V podoknu nazvaném Stack je možné sledovat pořadí volání funkcí a taktéž hodnoty předávaných parametrů. V podoknu nazvaném Locals naproti tomu můžeme vidět názvy a hodnoty všech lokálních proměnných a současně i názvy a hodnoty předávaných parametrů (jak nestatické lokální proměnné, tak i parametry se ostatně nachází ve stejném zásobníkovém rámci).
Obrázek 15: Prohlížení obsahu zásobníku (podokno vlevo dole) a lokálních proměnných (podokno vpravo nahoře).
KDbg používá pro zobrazení rekurzivních datových struktur podobný způsob, jako výše zmíněný program Nemiver:
Obrázek 16: Zobrazení prvků stromové datové struktury.
7. Emacs
Rozhraní pro GNU Debugger může být zabudováno i do různých pokročilejších programátorských editorů. Pravděpodobně nejlepší propojení s debuggerem nabízí textový editor Emacs. Používá se v něm knihovna Grand Unified Debugger, která mj. zajišťuje i propojení mezi textovým editorem GNU Emacs a debuggerem GNU Debugger. V tomto režimu je možné si v okně Emacsu zobrazit zdrojový kód a současně i několik bufferů obsahujících jak textové uživatelské rozhraní debuggeru (konzoli, která je aktivní, tj. lze do ní zapisovat příkazy), tak i speciální buffer s hodnotami pracovních registrů procesoru, další buffer se seznamem breakpointů, buffer se seznamem vláken atd. Kromě toho je možné (minimálně ve chvíli, kdy je Emacs spuštěn v prostředí grafického desktopu) otevřít další specializovaná okna, zejména okno s výpisem obsahu vybraných proměnných, obsahem bloku paměti, disassemblovaným kódem apod.
Obrázek 17: Nastavení breakpointu ve zdrojovém kódu laděné aplikace. Informace o nastaveném breakpointu se současně zobrazí i v interaktivním okně GNU Debuggeru.
Propojení mezi textovým editorem GNU Emacs a debuggerem GNU Debugger zajišťuje knihovna Grand Unified Debugger neboli zkráceně gud. V tomto režimu je možné si v okně Emacsu zobrazit zdrojový kód a současně i několik bufferů obsahujících jak textové uživatelské rozhraní debuggeru (konzoli, která je aktivní, tj. lze do ní zapisovat příkazy), tak i speciální buffer s hodnotami pracovních registrů procesoru, další buffer se seznamem breakpointů, buffer se seznamem vláken atd. Kromě toho je možné (minimálně ve chvíli, kdy je Emacs spuštěn v prostředí grafického desktopu) otevřít další specializovaná okna, zejména okno s výpisem obsahu vybraných proměnných, obsahem bloku paměti, disassemblovaným kódem apod.Obrázek 18: Disassembler.
Nabízené příkazy a operace jsou umístěny ve vlastním menu nazvaném Gud, některé příkazy mají vlastní klávesovou zkratku a ostatní příkazy lze zavolat i jako funkce Emacs Lispu (viz též navazující kapitoly). Důležité přitom je, že vývojář stále může zdrojový kód vyvíjené aplikace editovat, překládat, commitovat atd. bez nutnosti opuštění Emacsu (a tím pádem i debuggeru, jen je v některých případech nutné do něj znovu nahrát laděnou aplikaci). Celý vývojový cyklus se tak může poměrně výrazným způsobem urychlit.
Obrázek 19: Obsah pracovních registrů mikroprocesoru.
8. Clewn
Když už se zmiňujeme o (nejenom) editoru Emacs, nesmíme samozřejmě zapomenout ani na programátorský textový editor Vim. Pro něj vznikl plugin nazvaný Clewn sloužící taktéž pro propojení s GNU Debuggerem. Tento plugin umožňuje volat většinu základních příkazů GNU Debuggeru, ovšem způsob kooperace mezi Vimem a debuggerem, který je v pluginu Clewn implementován, nemusí všem uživatelům vyhovovat – v tomto případě je dobré se podívat na možnosti alternativního pluginu Pyclewn zmíněného v navazující kapitole.
Obrázek 20: Bez podpory této technologie (viz červený obdélník) nebudou mnohé pluginy pracovat korektně! To se týká i pluginu Clewn popisovaného v dnešním článku. Název této technologie vychází z toho, že se kdysi skutečně jednalo o rozhraní používané výhradně pluginem nazvaným NetBeans pro komunikaci se známým integrovaným vývojovým prostředím NetBeans. Tento plugin již v současnosti není vyvíjen, ovšem samotný „Vim NetBeans Protocol“ je podporován a taktéž používán mnoha dalšími pluginy, a to nikoli pro komunikaci s IDE NetBeans, ale právě i při ovládání debuggerů.
Jakým způsobem vlastně přídavný modul Clewn funguje? Tento plugin obsahuje kromě části psané ve VimScriptu i binární (nativní) část, konkrétně spustitelný program nazvaný clewn, který je nainstalován v adresáři dostupném přes proměnnou prostředí PATH (v případě lokální instalace se většinou jedná o adresář ~/bin). Tento binární program po svém spuštění provede inicializaci debuggeru a následně i spuštění Gvimu, tj. Vimu s grafickým uživatelským rozhraním. Tyto dvě aplikace pak spolu mohou přes nativní program clewn oboustranně komunikovat.
Obrázek 21: Ladění aplikace naprogramované v jazyku C: připojení Vimu k debuggeru a nastavení breakpointu na začátek funkce main.
9. Pyclewn
Dalším pluginem určeným pro propojení populárního textového editoru Vim s debuggerem je přídavný modul nazvaný Pyclewn. Tento plugin umožňuje práci s debuggerem GNU Debugger (použijí ho céčkači, vývojáři pracující v C++, Fortranu, Rustu, Go atd. atd.) a taktéž s debuggerem pdb používaném při ladění aplikací naprogramovaných v Pythonu. Tento plugin nepotřebuje pro svoji práci Gvim spuštěný s grafickým uživatelským rozhraním, protože veškerá činnost se odehrává v jediném terminálu a navíc se tento plugin spouští přímo z Vimu (u výše popsaného nástroje to bylo naopak – nejprve se spustil clewn, který následně otevřel nové okno s Gvimem, což mě osobně připadá poněkud nešikovné řešení).
Obrázek 22: Integrovaná nápověda k pluginu Pyclewn.
Samotné textové uživatelské prostředí připravené tímto pluginem (viz oba dva přiložené screenshoty) je snadno pochopitelné – jedno okno se používá pro zobrazení konzole debuggeru, další menší okna slouží pro výpis nastavených breakpointů, sledovaných proměnných atd. a poslední část plochy Vimu ukazuje laděný zdrojový kód, v němž jsou s využitím značek zvýrazněny breakpointy, zakázané breakpointy a ve chvíli krokování i právě prováděný prováděný řádek. Plugin mapuje i klávesové zkratky, další zkratky je samozřejmě možné v případě potřeby přidat.
Obrázek 23: Ladění programu napsaného v céčku: nastavení breakpointů, sledování proměnných atd. Povšimněte si, že tento plugin bez problémů pracuje i v terminálu, ovšem je zapotřebí použít větší okno (zde 80×25 znaků je nedostatečných, což je ovšem pochopitelné)
Poznámka: Vim je sice omezen na použití jediného okna konzole, ve skutečnosti je však možné toho okno roztáhnout přes větší počet monitorů a pomocí Ctrl+W S či příkazu :vsplit rozdělit plochu okna přesně na společné hraně monitorů.10. Nová nadstavba na GNU Debuggerem: gdbgui
Konečně se dostáváme k nástroji, který je nazvaný jednoduše gdbgui. Jedná se o poměrně nový projekt postavený na jazycích Python a JavaScript, což je v ostrém kontrastu s většinou nástrojů popsaných v předchozích kapitolách, neboť ty jsou naprogramovány v jazyku C++ (cgdb, DDD, Nemiver i KDbg). Pro zobrazení grafického uživatelského rozhraní gdbgui se používá webový prohlížeč, což s sebou přináší některé výhody (při vzdáleném ladění není zapotřebí na klientské straně nic instalovat, změna layoutu je velmi jednoduchá i pro neprogramátory atd.), ale i zápory (v současnosti jen omezená historie mezi sezeními, L&F odlišná od „pravých“ systémových utilit, …). Autoři gdbgui si ovšem uvědomují, že u debuggeru je důležité, aby ho bylo možné rychle ovládat z klávesnice, takže pro několik základních příkazů byly vytvořeny klávesové zkratky – Run, Continue, Next (Step Over), Step (Step Into) a Up (Next a Step navíc zvlášť pro krokování po příkazech či po strojových instrukcích).
Obrázek 24: Takto vypadá základní (a jediná) stránka nástroje gdbgui po jeho spuštění. U prohlížeče Chrome/Chromium se navíc ve spodní části zobrazuje konzole GNU Debuggeru.
gdbgui lze použít pro ladění programů napsaných v jazycích C, C++, Rust i Go, ovšem u Rustu a Go je nutné ručně zvolit vstupní bod do programu a nastavit na něj breakpoint, protože gdbgui u těchto jazyků nedokáže přesně zjistit, kde je umístěna funkce main. Bližší informace si řekneme v dalších kapitolách.
Obrázek 25: Úpravou CSS lze docílit zobrazení konzole GNU Debuggeru i ve Firefoxu.
Na tomto místě je vhodné upozornit na fakt zmíněný už v úvodu článku – gdbgui totiž uživatelům nabízí pouze zlomek funkcionality GNU Debuggeru, ovšem v případě potřeby je možné si přímo v okně prohlížeče otevřít konzoli zajišťující přístup k příkazové řádce GNU Debuggeru. Z této konzole je pak možné volat jakýkoli příkaz, který bude přenesen klient → server → GNU Debugger, tam spuštěn a výsledek vrácen zpět do prohlížeče.
11. Technologie, na nichž je nástroj gdbgui postaven
Na rozdíl od předchozích nástrojů je gdbgui postaven na webových technologiích, v nichž se kombinuje serverová část a část klientská. Úkolem serverové části, která je založena na mikroframeworku Flask a knihovně pygdbmi , je zabezpečení komunikace s GNU Debuggerem (ostatně server si debugger sám spustí) popř. lldb a s klientskou částí. Na klientskou část naprogramovanou v JavaScriptu s využitím knihoven jQuery, Lodash, Awescomplete, šablonovacího systému PugJS atd. pak zbylo zajištění vlastního grafické uživatelského rozhraní. To lze použít z jakéhokoli moderního webového prohlížeče, navíc je možné, aby laděná aplikace, GNU Debugger i serverová část běžely na jiném počítači, než část klientská, což může být v některých situacích poměrně užitečná vlastnost.
Poznámka: screenshoty pro dnešní článek byly vytvořeny ve Firefoxu, v něm je však nutné upravit CSS, aby se zobrazila konzole GNU Debuggeru (viz předchozí kapitolu se screenshoty původní verze a verze upravené).
12. Instalace a první spuštění
Instalace nástroje gdbgui je dobře zdokumentována na stránce s popisem balíčku, takže jen stručně. Na svém systému byste měli mít nainstalován GNU Debugger a samozřejmě i překladač a linker některého podporovaného programovacího jazyka, tj. GCC (C a/nebo C++), Rustu či Go. GNU Debugger by měl mít verzi 7.x:
$ gdb --version GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1 Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. ... ... ...
Dále je nutné si nainstalovat pip, manažer balíčků pro Python, a to minimálně verzi 8:
$ pip --version pip 9.0.1 from /usr/local/lib/python2.7/dist-packages (python 2.7)
Nesmíme zapomenout ani na interpret Pythonu. Ten je taktéž vyžadován, ovšem může se jednat jak o Python 2.7, tak i o Python 3.4 či vyšší, takže jedna z těchto závislostí bude s velkou pravděpodobností na všech systémech splněna:
$ python --version Python 2.7.9
Poznámka: pokud budete chtít použít Python 3.4+, použijte pip3, ne pip.
Pokud máte k dispozici všechny závislé balíčky a nástroje, je samotná instalace snadná:
$ sudo pip install gdbgui --upgrade
Následně gdbgui spusťte příkazem (v okně prohlížeče se otevře nové okno s GUI):
gdbgui
Pokud chcete použít vzdálené ladění, provede se spuštění takto:
gdbgui -r
V tomto případě ovšem bude zvolený port (implicitně 5000) dostupný i z dalších počítačů (!), což většinou znamená nutnost správné konfigurace firewallu. Při použití volby -r se můžete ke GUI připojit na URL http://hostname_stroje:5000
13. Zobrazení zdrojového kódu a disassemblovaného strojového kódu
Pro načtení programu přeloženého s ladicími informacemi (prakticky univerzální volba -g) je nutné napsat cestu ke spustitelnému souboru do horního řádku nadepsaného „Load this Binary and Args“ a volbu potvrdit Enterem (zde se ukazuje jeden z nedostatků webového UI). Současně se načte i seznam objektových souborů a knihoven, ze kterého je možné si vybírat („Enter source file path…“):
Obrázek 26: Po zápisu cesty k binárnímu souboru, který se má debugovat, se automaticky zobrazí příslušný zdrojový kód, samozřejmě ovšem za předpokladu, že se při překladu použila volba -g.
Dále je možné tlačítkem „fetch disassembly“ načíst a zobrazit disassemblovaný zdrojový kód:
Obrázek 27: Tlačítkem „fetch disassembly“ je možné zajistit zobrazení strojových instrukcí, které odpovídají příslušnému příkazu. Tato volba bude fungovat v pořádku jen ve chvíli, kdy se při překladu nepoužívá optimalizace.
Standardně je nastaveno, že se při načtení spustitelného souboru automaticky nastaví breakpoint na první příkaz ve funkci main, ovšem tato volba pracuje dobře pouze u programů napsaných v jazycích C a C++. Automatické nastavení breakpointu je možné vypnout v dialogu s nastavením projektu.
Obrázek 28: Po načtení programu do debuggeru se automaticky nastaví breakpoint na první řádek ve funkci main. Tato možnost však pracuje správně jen u jazyků C a C++, nikoli u Rustu či Go a v případě potřeby je možné ji zcela vypnout v dialogu pro nastavení gdbgui (tlačítko ozubeného kola vpravo nahoře).
14. Krokování a sledování hodnot lokálních proměnných
Vlastní ladění je velmi jednoduché, protože pouze postačuje nastavit breakpointy kliknutím myší na příslušný zdrojový řádek a spustit program tlačítkem Run (kupodivu jeho ikona obsahuje šipku v kruhu, nenechte se zmást sousedním tlačítkem). V této chvíli se automaticky zobrazí aktivní zásobníkové rámce i obsah lokálních proměnných. Ke krokování slouží tlačítka Next (Step Over), Step (Step Into), Up a znovuspuštění programu zajistí tlačítko Continue.
Obrázek 29: V pravé části stránky se při ladění (krokování) automaticky vypisují jména a hodnoty lokálních proměnných. Také je možné nastavit kurzor myši nad jméno proměnné ve zdrojovém kódu se stejným výsledkem.
Příkaz Step slouží pro vstup do volané funkce či metody, rychlý návrat (bez nutnosti krokovat až do konce kódu) z funkce/metody zajišťuje příkaz Up. Pro urychlení krokování je samozřejmě možné použít i klávesové zkratky r, n, s, u a c. Pro krokování na úrovni jednotlivých strojových instrukcí slouží tlačítka Next Instruction (NI) a Step Instruction (SI).
Obrázek 30: Při ladění je možné vybrat si binární (objektový) soubor, který se má krokovat.
15. Výrazy, zobrazení grafů historie vyhodnocených výrazů
Jednou z nejužitečnějších vlastností nástroje gdbgui je jeho schopnost zobrazit hodnoty prakticky libovolných výrazů (podporovaných GNU Debuggerem), a taktéž historické hodnoty výrazů zobrazených ve formě jednoduchého grafu. Představme si například následující program pro výpočet číselné řady, v níž jsou jednotlivé členy postupně reprezentovány aktuální hodnotou proměnné y:
int main(void) { float x, y; int i; x = 1.0f; y = 0.0f; for (i=0; i<20; i++) { y += x; x = x / 2.0; } }
Pokud začneme program (smyčku) krokovat a přidáme do části Expressions výrazy x a y, můžeme u každého výrazu stlačit tlačítko s ikonou grafu a získáme tak přibližně následující výstup:
Obrázek 31: Začátek ladění se sledováním výrazů x a y.
Při každé další změně hodnot proměnných x či y se příslušný graf překreslí:
Obrázek 32: Ladění smyčky (další iterace) se sledováním výrazů x a y.
V případě, že potřebujete znát přesnou hodnotu výrazu v historii ladění, stačí najet kurzorem myši na graf (na „kolečko“) a příslušná hodnota se automaticky zobrazí v bublinkové nápovědě:
Obrázek 33: Zobrazení hodnoty v grafu.
16. Obsah zásobníkových rámců
Pro otestování, jak je možné sledovat obsah zásobníkových rámců, nejlépe poslouží nějaká rekurzivní funkce, například následující příklad na výpočet faktoriálu (je schválně napsán pro hodnoty short):
#include <stdio.h> short factorial(short n) { if (n==0 || n==1) return 1; return n*factorial(n-1); } int main(int argc, char **argv) { printf("%d\n", factorial(8)); return 0; }
Obrázek 34: Průběh laděni programu, povšimněte si sekce call stack.
Obrázek 35: V zásobníkovém rámci lze samozřejmě sledovat i kód „nad“ funkcí main.
Obrázek 36: Zobrazení disassemblovaného zdrojového kódu.
17. Výpis složitějších datových struktur (pole, struktury, stromy)
Nástroj gdbgui samozřejmě podporuje i zobrazení hodnot uložených do složitějších datových struktur, zejména do polí, záznamů i struktur s ukazateli. Nejdříve si ukažme, jakým způsobem se zobrazují prvky polí a záznamů:
Obrázek 37: Zobrazení hodnot všech prvků pole a taktéž prvků datové struktury var_x.
Dále se můžeme pokusit odladit následující příklad s implementací binárního stromu, do něhož postupně ukládáme různé řetězce:
#include <stdlib.h> #include <stdio.h> #include <string.h> typedef struct Node { struct Node *left; struct Node *right; char *value; } Node; void insert_new_node(Node **root, char *value) { int cmp; if (*root == NULL) { *root = (Node *)malloc(sizeof(Node)); (*root)->value = (char*)calloc(strlen(value), sizeof(char)); strcpy((*root)->value, value); (*root)->left = NULL; (*root)->right = NULL; return; } cmp = strcmp(value, (*root)->value); if (cmp < 0) { insert_new_node(&(*root)->left, value); } else { insert_new_node(&(*root)->right, value); } } void traverse_tree(Node *root, void (*callback_function)(char *)) { if (root == NULL) { return; } traverse_tree(root->left, callback_function); callback_function(root->value); traverse_tree(root->right, callback_function); } void callback_function(char *value) { printf("%s\n", value); } int main(void) { static Node *root = NULL; insert_new_node(&root, "xxx"); insert_new_node(&root, "aaa"); insert_new_node(&root, "bbb"); insert_new_node(&root, "ccc"); insert_new_node(&root, "yyy"); insert_new_node(&root, "yyy"); traverse_tree(root, callback_function); return 0; }
Do sekce expressions postačuje v průběhu ladění přidat novou položku root reprezentující kořen binárního stromu:
Obrázek 38: Na začátku je binární strom prázdný – viz sekce expressions.
Při postupném přidávání prvků do binárního stromu vznikají uzly a listy, což se v gdbgui zobrazuje takto:
Obrázek 39: Před ukončením programu je již binární strom částečně zaplněn.
18. Ladění programů napsaných v programovacím jazyku Rust
V desáté kapitole jsme si mj. řekli, že gdbgui podporuje ladění aplikací naprogramovaných v Rustu. Můžeme si to ostatně jednoduše vyzkoušet na příkladu, který se opět počítá členy číselné řady:
fn main() { let mut x:f32 = 1.0; let mut y:f32 = 0.0; for _ in 0..20 { y += x; x = x / 2.0; } println!("{}", y); }
Překlad je nutné provést příkazem:
rustc -g test.rs -o test.a
Vytvořený binární soubor test.a se načte stejným způsobem, jako je tomu u programů psaných v C a C++, ovšem navíc musíme v listboxu se všemi objektovými soubory ručně vybrat, kde se nachází funkce main (to je jeden z nedostatků současné verze gdbgui):
Obrázek 40: Načtení binárního souboru obsahujícího ladicí informace a nastavení breakpointu na prvním příkazu ve funkci main (je nutné provést ručně). Povšimněte si, že funkce main je již poměrně hluboce „zanořeno“ v zásobníkovém rámci.
Ladění probíhá naprosto stejně, jako je tomu u programů psaných v jazycích C a C++. Na dalším obrázku můžeme vidět způsob vyhodnocování výrazů, zobrazení historie hodnot atd.:
Obrázek 41: Historie hodnot výrazů samozřejmě pracuje korektně i při ladění aplikací v Rustu.
Obrázek 42: Zde můžeme vidět, že překlad bez optimalizací vede k vygenerování dosti rozsáhlého strojového kódu.
19. Odkazy na Internetu
- gdbgui 0.7.8.3: browser-based gdb frontend using Flask and JavaScript to visually debug C, C++, Go, or Rust
https://pypi.python.org/pypi/gdbgui - Repositář projektu gdbgui
https://github.com/cs01/gdbgui - gdbgui – examples
https://github.com/cs01/gdbgui/tree/master/examples - Debuggery a jejich nadstavby v Linuxu
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/ - Debuggery a jejich nadstavby v Linuxu (2. část)
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/ - Debuggery a jejich nadstavby v Linuxu (3): Nemiver
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/ - Debuggery a jejich nadstavby v Linuxu (4): KDbg
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/ - Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-5-ladeni-aplikaci-v-editorech-emacs-a-vim/ - GDB – Dokumentace
http://sourceware.org/gdb/current/onlinedocs/gdb/ - GDB – Supported Languages
http://sourceware.org/gdb/current/onlinedocs/gdb/Supported-Languages.html#Supported-Languages - GNU Debugger (Wikipedia)
https://en.wikipedia.org/wiki/GNU_Debugger - The LLDB Debugger
http://lldb.llvm.org/ - Debugger (Wikipedia)
https://en.wikipedia.org/wiki/Debugger - 13 Linux Debuggers for C++ Reviewed
http://www.drdobbs.com/testing/13-linux-debuggers-for-c-reviewed/240156817 - Reverse Engineering Tools in Linux – strings, nm, ltrace, strace, LD_PRELOAD
http://www.thegeekstuff.com/2012/03/reverse-engineering-tools/ - An Introduction To Using GDB Under Emacs
http://tedlab.mit.edu/~dr/gdbintro.html - GNU Emacs
https://www.gnu.org/software/emacs/emacs.html - The Emacs Editor
https://www.gnu.org/software/emacs/manual/html_node/emacs/index.html - Emacs Lisp
https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html - An Introduction to Programming in Emacs Lisp
https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html - 27.6 Running Debuggers Under Emacs
https://www.gnu.org/software/emacs/manual/html_node/emacs/Debuggers.html - GdbMode
http://www.emacswiki.org/emacs/GdbMode - Emacs (Wikipedia)
https://en.wikipedia.org/wiki/Emacs - Emacs Lisp (Wikipedia)
https://en.wikipedia.org/wiki/Emacs_Lisp - Pyclewn installation notes
http://pyclewn.sourceforge.net/install.html - pip Installation
https://pip.pypa.io/en/latest/installing.html - Clewn
http://clewn.sourceforge.net/ - Clewn installation
http://clewn.sourceforge.net/install.html - Clewn – soubory
http://sourceforge.net/projects/clewn/files/OldFiles/ - KDbg: úvodní stránka
http://www.kdbg.org/ - Nemiver (stránky projektu)
https://wiki.gnome.org/Apps/Nemiver - Basic Assembler Debugging with GDB
http://dbp-consulting.com/tutorials/debugging/basicAsmDebuggingGDB.html - Nemiver FAQ
https://wiki.gnome.org/Apps/Nemiver/FAQ - Nemiver (Wikipedia)
https://en.wikipedia.org/wiki/Nemiver - Data Display Debugger
https://www.gnu.org/software/ddd/ - GDB – Dokumentace
http://sourceware.org/gdb/current/onlinedocs/gdb/ - BASH Debugger
http://bashdb.sourceforge.net/ - The Perl Debugger(s)
http://debugger.perl.org/ - Visual Debugging with DDD
http://www.drdobbs.com/tools/visual-debugging-with-ddd/184404519 - Pydb – Extended Python Debugger
http://bashdb.sourceforge.net/pydb/ - Debugging
http://janus.uclan.ac.uk/pagray/labs/debug.htm - Insight
http://www.sourceware.org/insight/