Obsah
1. Trasování a ladění nativních aplikací v Linuxu: použití GDB a jeho nadstaveb
4. Spuštění programu, nastavení breakpointů a krokování
6. Výpis obsahu zásobníkových rámců
7. Ladění aplikací, které zhavarovaly
8. Demonstrační příklady použité v dnešním článku
9. Nadstavby na GNU Debuggerem
11. Data Display Debugger – DDD
1. Trasování a ladění nativních aplikací v Linuxu: použití GDB a jeho nadstaveb
V první části článku o nástrojích, které je možné použít pro trasování a popř. i pro plnohodnotné ladění nativních aplikací běžících v Linuxu, jsme se seznámili s jednoduše použitelnými nástroji nazvanými ltrace a strace. Připomeňme si, že nástroj ltrace slouží k trasování volání knihovních funkcí (s různými možnostmi filtrace, měření atd.) a strace se naopak používá pro trasování volání funkcí jádra (syscalls). Kromě toho jsme si řekli základní informace o pokročilém (a již složitěji ovládaném) nástroji nazvaném SystemTap, s jehož možnostmi se blíže seznámíme v následujícím článku. Připomeňme si též, jak může vypadat použití jednotlivých nástrojů na celém „stacku“, tj. od trasování/ladění samotné uživatelské aplikace až přes řešení problémů přímo v jádře operačního systému:
+----------+ | |..... gdb | aplikace | | |..... SystemTap +----------+ | | |...... ltrace | v +----------+ | |..... gdb | glibc | | |..... SystemTap +----------+ | | |...... strace | v +----------+ | |..... SystemTap | jádro | | |..... KGDB +----------+
Vidíme, že dnes popisovaný GNU Debugger je možné použít jak na úrovni ladění aplikace, tak i knihoven. Kromě toho ho lze využít i pro „pitvu“ těch nativních aplikací, které byly kvůli nějakému problému zabity jádrem systému a byl pro ně vygenerován takzvaný „core dump“.
2. GNU Debugger
Nástroj GNU Debugger, který je taktéž někdy podle své spustitelné (binární) části pojmenováván gdb, primárně používá ke komunikaci s uživatelem příkazový řádek, ale alternativně lze použít i jednoduché TUI (textové uživatelské rozhraní) či protokol pro nepřímé ovládání debuggeru a v případě potřeby je možné k laděné aplikaci přidat relativně krátký „stub“ sloužící pro přímé ladění takové aplikace (touto nepochybně zajímavou problematikou se však dnes nebudeme zabývat). Většina často používaných příkazů zapisovaných na příkazový řádek má i svoji zkrácenou podobu (bt=backtrace, c=continue, f=frame) a navíc je možné používat klávesu [Tab] pro automatické doplnění celého jména příkazu či jeho parametru (doplňování je kontextové). Pokud je správně nastavený terminál, bude fungovat i historie příkazového řádku, a to stejným způsobem, jaký známe ze shellu. Alternativně je možné využít gdbtui s celoobrazovkovým výstupem a alespoň částečně se tak přiblížit možnostem debuggerů s plnohodnotným grafickým uživatelským rozhraním.
Podívejme se nyní na způsob spuštění GNU Debuggeru a práce s ním. Nejprve si připravíme testovací aplikaci, kterou pro jednoduchost naprogramujeme v céčku (a nikoli v C++ – to kvůli jménům funkcí):
#include <stdio.h> void print_hello() { puts("Hello world!"); } int main(int argc, char **argv) { print_hello(); return 0; }
Zdrojový kód uložíme do souboru nazvaného hello.c a přeložíme s volbou -g, která zajistí vložení potřebných ladicích symbolů do výsledného binárního (spustitelného) souboru:
gcc -g -ansi -pedantic -Wall -o hello hello.c
Následně již můžeme spustit GNU Debugger:
gdb hello GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 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. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from hello...done.
Povšimněte si především posledního řádku, ve kterém debugger potvrzuje načtení ladicích symbolů. Pokud se v tomto řádku zobrazí text:
(no debugging symbols found)
znamená to, že jste pravděpodobně při překladu zapomněli použít volbu -g, popř. se na již přeložený soubor použila utilita strip, která symboly odstranila.
GNU Debugger obsahuje i poměrně rozsáhlý systém nápovědy, který si můžeme vyzkoušet:
(gdb) help List of classes of commands: aliases -- Aliases of other commands breakpoints -- Making program stop at certain points data -- Examining data files -- Specifying and examining files internals -- Maintenance commands obscure -- Obscure features running -- Running the program stack -- Examining the stack status -- Status inquiries support -- Support facilities tracepoints -- Tracing of program execution without stopping the program user-defined -- User-defined commands Type "help" followed by a class name for a list of commands in that class. Type "help all" for the list of all commands. Type "help" followed by command name for full documentation. Type "apropos word" to search for commands related to "word". Command name abbreviations are allowed if unambiguous.
Ukončení GNU Debuggeru zajišťuje příkaz quit zkracovaný na pouhé q:
(gdb) q
Pro úplnost se ještě podívejme, jak vypadá TUI (textové uživatelské rozhraní) zabudované do GNU Debuggeru:
gdbtui hello +--hello.c-----------------------------------------------------------------------------+ |1 #include <stdio.h> | |2 | |3 void print_hello() | |4 { | |5 puts("Hello world!"); | |6 } | |7 | |8 int main(int argc, char **argv) | |9 { | |10 print_hello(); | |11 return 0; | |12 } | |13 | |14 | |15 | |16 | +--------------------------------------------------------------------------------------+ exec No process In: Line: ?? PC: ?? <http://www.gnu.org/software/gdb/documentation/> For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from hello...done.
V základním nastavení je terminál rozdělen do dvou oken – první okno obsahuje zdrojový kód, druhé pak klasické rozhraní příkazového řádku. Ve skutečnosti je však možné zobrazit i další okna, například speciální okno s registry atd. V okně se zdrojovým kódem se navíc zobrazují breakpointy a další důležité informace, takže „režim TUI“ může být pro mnohé vývojáře velmi užitečný (dokonce si dovolím říct, že je časově výhodnější se naučit pracovat v tomto režimu, než řešit problémy s různými GUI nadstavbami).
3. Orientace v laděném kódu
Pokud jsou do binárního souboru laděné aplikace přiloženy i ladicí symboly, lze v GNU Debuggeru relativně snadno pracovat přímo se zdrojovým kódem a využívat jména funkcí, jména proměnných atd. Základním příkazem, který se může hodit například při nastavování breakpointů, je příkaz info functions, který vypíše jak všechny funkce z aplikace, tak i přímo či nepřímo volané funkce (pro zápis tohoto příkazu použijte klávesu [Tab] pro kontextové doplňování):
(gdb) info functions All defined functions: File hello.c: int main(int, char **); void print_hello(); Non-debugging symbols: 0x00000000004003e0 _init 0x0000000000400410 puts@plt 0x0000000000400420 __libc_start_main@plt 0x0000000000400430 __gmon_start__@plt 0x0000000000400440 _start 0x0000000000400470 deregister_tm_clones 0x00000000004004a0 register_tm_clones 0x00000000004004e0 __do_global_dtors_aux 0x0000000000400500 frame_dummy 0x0000000000400560 __libc_csu_init 0x00000000004005d0 __libc_csu_fini 0x00000000004005d4 _fini
Dalším užitečným příkazem je příkaz list, který vypíše deset řádků zdrojového kódu. Opakováním příkazu (či pouhým stlačením klávesy Enter, což má stejný význam, jako explicitní opakování posledního příkazu) se zobrazí dalších deset řádků atd.:
(gdb) list 1 #include <stdio.h> 2 3 void print_hello() 4 { 5 puts("Hello world!"); 6 } 7 8 int main(int argc, char **argv) 9 { 10 print_hello();
K příkazu list je možné explicitně přidat i číslo prvního a posledního vypisovaného řádku, což je výhodné v případě, že z nějakého chybového hlášení víte, na kterém řádku k chybě došlo:
(gdb) list 1,12 1 #include <stdio.h> 2 3 void print_hello() 4 { 5 puts("Hello world!"); 6 } 7 8 int main(int argc, char **argv) 9 { 10 print_hello(); 11 return 0; 12 }
Užitečnější je však použití příkazu list společně se jménem funkce, protože nemusíte složitě zjišťovat, na jakém řádku je hledaná funkce zapsána (ani v jakém je souboru):
(gdb) list main 4 { 5 puts("Hello world!"); 6 } 7 8 int main(int argc, char **argv) 9 { 10 print_hello(); 11 return 0; 12 } 13
Pokud chcete jméno funkce vybrat ze seznamu, stačí napsat jen příkaz list, mezeru a potom stlačit klávesu [Tab]:
_IO_stdin_used __JCR_END__ __JCR_LIST__ __libc_csu_fini __libc_csu_init __libc_start_main __libc_start_main@got.plt __libc_start_main@plt long int long unsigned int main print_hello puts puts@got.plt puts@plt register_tm_clones short int short unsigned int signed char sizetype _start __TMC_END__ unsigned char unsigned int (gdb) list
Samozřejmě funguje i vyhledávání na základě částečně zapsaného jména funkce:
__libc_csu_fini __libc_start_main@got.plt __libc_csu_init __libc_start_main@plt __libc_start_main (gdb) list __libc_
Užitečné mohou být i další varianty příkazu info:
(gdb) info sources Source files for which symbols have been read in: /home/tester/temp/presentations/tracing/hello.c Source files for which symbols will be read in on demand:
(gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00007ffff7ddaae0 0x00007ffff7df54e0 Yes (*) /lib64/ld-linux-x86-64.so.2 (*): Shared library is missing debugging information.
4. Spuštění programu, nastavení breakpointů a krokování
Nyní se podíváme na způsob spuštění laděné aplikace přímo v GNU Debuggeru. To je ve skutečnosti velmi jednoduché a přímočaré, protože postačuje zadat příkaz run či jen r:
(gdb) run Starting program: /home/tester/temp/presentations/tracing/hello Hello world! [Inferior 1 (process 6977) exited normally]
Na libovolnou funkci, řádek či dokonce jednotlivou strojovou instrukci je možné zaregistrovat breakpoint. Pokud se běh programu dostane na breakpoint, je jeho běh přerušen a řízení se vrátí zpět uživateli do debuggeru. Nejjednodušeji se nastavuje breakpoint na vstupním bodě funkce. V tomto případě postačuje zadat příkaz break se jménem funkce:
(gdb) break main Breakpoint 1 at 0x40054c: file hello.c, line 10.
Pokud nyní program znovu spustíme, zastaví se na právě nastaveném breakpointu:
(gdb) run Starting program: /home/tester/temp/presentations/tracing/hello Breakpoint 1, main (argc=1, argv=0x7fffffffe158) at hello.c:10 10 print_hello();
Nyní máme možnost pokračovat v běhu (c/continue), ale zajímavější je použít příkaz n/next, který vykoná pouze jediný programový řádek a posléze se běh programu opět zastaví:
(gdb) n Hello world! 11 return 0; (gdb) c Continuing. [Inferior 1 (process 7040) exited normally]
O tom, že GNU Debugger není žádné ořezávátko, možná svědčí i to, že se v průběhu ladění může použít mj. i příkaz print akceptující různé typy výrazů, lokální i globální proměnné, formátování atd.:
(gdb) print(i) $1 = 30 (gdb) print(argc>0) $2 = 1 (gdb) print(atoi("42")) $3 = 42 (gdb) print(isdigit('4')) $4 = 2048 (gdb) print(isdigit('a')) $5 = 0
Všechny doposud popsané příkazy si otestujme na jiném (nepatrně složitějším) zdrojovém kódu, v němž se nachází funkce pro výpočet faktoriálu:
#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; }
Výpis části zdrojového kódu:
(gdb) list 2 3 short factorial(short n) 4 { 5 if (n==0 || n==1) return 1; 6 return n*factorial(n-1); 7 } 8 9 int main(int argc, char **argv) 10 { 11 printf("%d\n", factorial(8));
Nastavení breakpointu:
(gdb) break factorial Breakpoint 1 at 0x40053b: file factorial.c, line 5.
Spuštění programu a výpis parametru funkce po zastavení na breakpointu:
(gdb) run Starting program: /home/tester/temp/presentations/tracing/factorial Breakpoint 1, factorial (n=8) at factorial.c:5 5 if (n==0 || n==1) return 1; (gdb) print(n) $1 = 8
Pokračování v běhu programu a opětovný výpis parametru funkce:
(gdb) continue Continuing. Breakpoint 1, factorial (n=7) at factorial.c:5 5 if (n==0 || n==1) return 1; (gdb) print(n) $2 = 7
Odstranění breakpointu:
(gdb) clear main Deleted breakpoint 1 (gdb) run Starting program: /home/tester/temp/presentations/tracing/a.out Hello world! [Inferior 1 (process 7876) exited normally]
5. Parametry breakpointů
U breakpointů je možné nastavovat různé parametry a především podmínky ovlivňující, za jakých okolností se breakpoint projeví a za jakých nikoli. Nejprve si opět nastavme breakpoint na vstupní bod funkce nazvané factorial:
(gdb) break factorial Breakpoint 1 at 0x40053b: file factorial.c, line 5.
Informaci o všech breakpointech získáme příkazem info breakpoints:
(gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x000000000040053b in factorial at factorial.c:5
Vidíme, že náš breakpoint je uložen na indexu 1. Nastavme nyní tento breakpoint takovým způsobem, aby ignoroval prvních pět průchodů, tedy část „winding“ fáze rekurzivní funkce factorial:
(gdb) ignore 1 5 Will ignore next 5 crossings of breakpoint 1. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x000000000040053b in factorial at factorial.c:5 ignore next 5 hits
Pozor: pokud se breakpoint zobrazil pod jiným číslem, je nutné příkaz ignore n 5 upravit tak, aby se použilo správné n.
Pokud aplikaci nyní spustíme, bude se chovat odlišně, protože se zastaví až ve chvíli, kdy je hodnota n rovna třem a nikoli osmi:
(gdb) r Starting program: /home/tester/temp/presentations/tracing/factorial Breakpoint 1, factorial (n=3) at factorial.c:5 5 if (n==0 || n==1) return 1;
6. Výpis obsahu zásobníkových rámců
V tomto okamžiku si můžeme vypsat historii volání, a to příkazem backtrace popř. jeho zkrácenou variantou bt:
(gdb) bt #0 factorial (n=3) at factorial.c:5 #1 0x000000000040055f in factorial (n=4) at factorial.c:6 #2 0x000000000040055f in factorial (n=5) at factorial.c:6 #3 0x000000000040055f in factorial (n=6) at factorial.c:6 #4 0x000000000040055f in factorial (n=7) at factorial.c:6 #5 0x000000000040055f in factorial (n=8) at factorial.c:6 #6 0x0000000000400583 in main (argc=1, argv=0x7fffffffe158) at factorial.c:11
Vidíme, že se skutečně ještě nacházíme ve „winding“ fázi funkce factorial. Historii je nutné číst odspodu, což je logické, protože bt získává informace z obsahu zásobníkových rámců vytvářených pro každou volanou funkci.
Pokud nepotřebujete zobrazit celou historii, ale jen posledních n volání, stačí zadat bt s požadovaným počtem řádků:
(gdb) bt 4 #0 factorial (n=3) at factorial.c:5 #1 0x000000000040055f in factorial (n=4) at factorial.c:6 #2 0x000000000040055f in factorial (n=5) at factorial.c:6 #3 0x000000000040055f in factorial (n=6) at factorial.c:6 (More stack frames follow...)
Začátek historie se naopak zobrazí po zadání záporného čísla:
(gdb) bt -4 #3 0x000000000040055f in factorial (n=6) at factorial.c:6 #4 0x000000000040055f in factorial (n=7) at factorial.c:6 #5 0x000000000040055f in factorial (n=8) at factorial.c:6 #6 0x0000000000400583 in main (argc=1, argv=0x7fffffffe1c8) at factorial.c:11
Pro zobrazení zásobníkových rámců společně s lokálními proměnnými použijte bt full (to však u naší jednoduchoučké funkce postrádá význam).
7. Ladění aplikací, které zhavarovaly
GNU Debugger může být velmi užitečný i v těch případech, kdy je zapotřebí zjistit příčinu havárie nějakého programu. Jádro operačního systému totiž může ještě před úplným ukončením procesu uložit do speciálního souboru nazvaného core dump jak obsah paměti přiřazené procesu, tak i další údaje související s jeho aktuálním stavem – obsahy pracovních registrů, stav otevřených souborů apod. (tyto informace jsou do značné míry závislé na architektuře i na použitém operačním systému). Mimochodem termín „core dump“ vznikl v dobách používání feritových pamětí, protože jadérka v těchto pamětech si pamatovala svůj obsah tak dlouho, že po pádu aplikace (žádný skutečný operační systém ještě neexistoval, většinou se jednalo o pouhý loader uživatelského kódu) bylo možné její obsah v klidu prozkoumat. Nicméně se vraťme k současným core dumpům. Jeden si vytvoříme, a to tímto jednoduchým (zabugovaným) prográmkem:
void set_mem(int *address, int value) { *address = value; } int main(int argc, char **argv) { set_mem((int*)0, 42); return 0; }
Program přeložíme běžným způsobem:
gcc -g -Wall -ansi -pedantic npe.c
A pokusíme se ho spustit běžným způsobem z příkazové řádky:
./npe Segmentation fault
Pokud se vypíše pouze „Segmentation fault“, znamená to, že se core dump ve skutečnosti nevytvořil. Zkusíme tedy systému pomoci povolením vytváření core dumpů o neomezené velikosti:
ulimit -c unlimited ./npe Segmentation fault (core dumped)
Teď už je to lepší (viz text v závorce) – vytvořil se core dump, který můžeme prozkoumat. GNU Debugger je nutné spustit takovým způsobem, že se specifikuje jak jméno spustitelného souboru, tak i jméno souboru s core dumpem (v uvedeném pořadí):
gdb npe core
Zajímavé je, že se při spouštění GNU Debuggeru vypíšou odlišné informace, které však poměrně přesně říkají, co se stalo. Proč se to stalo, to je již otázkou na samotného programátora:
Reading symbols from npe...done. [New LWP 7703] Core was generated by `./npe'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00000000004004ff in set_mem (address=0x0, value=42) at npe.c:3 3 *address = value;
GNU Debugger se nyní chová, jakoby byl program již spuštěný (což není náhoda), takže si můžeme nechat vypsat obsah zásobníkových rámců:
(gdb) bt #0 0x00000000004004ff in set_mem (address=0x0, value=42) at npe.c:3 #1 0x0000000000400521 in main (argc=1, argv=0x7fff07ba7798) at npe.c:8
Můžeme nastavit breakpoint na začátek té funkce, v níž došlo k pádu. Jedná se o funkci nazvanou set_mem:
(gdb) b set_mem Breakpoint 1 at 0x4004f8: file npe.c, line 3.
A program můžeme znovu spustit:
(gdb) r Starting program: /home/tester/temp/presentations/tracing/npe
Běh laděné aplikace se podle očekávání zastaví na breakpointu:
Breakpoint 1, set_mem (address=0x0, value=42) at npe.c:3 3 *address = value;
Takže znovu prozkoumáme obsah zásobníkových rámců:
(gdb) bt #0 set_mem (address=0x0, value=42) at npe.c:3 #1 0x0000000000400521 in main (argc=1, argv=0x7fffffffe168) at npe.c:8
Aha, adresa je nastavená nějak divně – zápis na adresu 0 skutečně povede k pádu (to je většinou ošetřeno na hardwarové úrovni, například nastavením práv k celé první stránce paměti přidělené aplikaci atd.):
(gdb) print address $1 = (int *) 0x0
Skutečně, nyní již víme (což bylo v tomto případě velmi jednoduché), že chyba je ve funkci main, resp. v předání špatné adresy. Bez opuštění debuggeru si můžeme kód prohlédnout (osmý řádek):
(gdb) list main 2 { 3 *address = value; 4 } 5 6 int main(int argc, char **argv) 7 { 8 set_mem((int*)0, 42); 9 return 0; 10 } 11
Poznámka: ke složitějším situacím, stejně jako k ladění programů napsaných v C++ (kde je někdy nutné se zabývat překladem jmen funkcí a metod), se dostaneme příště.
8. Demonstrační příklady použité v dnešním článku
Všechny tři demonstrační příklady, které jsme používali při popisu GNU Debuggeru, byly opět uloženy do GIT repositáře nazvaného https://github.com/tisnik/presentations:
# | Program | URL do GITu |
---|---|---|
1 | test.c | https://github.com/tisnik/presentations/blob/master/tracing/test.c |
2 | factorial.c | https://github.com/tisnik/presentations/blob/master/tracing/factorial.c |
3 | npe.c | https://github.com/tisnik/presentations/blob/master/tracing/npe.c |
9. Nadstavby na GNU Debuggerem
Práce s příkazovým řádkem GNU Debuggeru sice programátorům přináší velkou flexibilitu (a to jsme se prozatím seznámili pouze s nepatrnou částí celkové funkcionality), ovšem je pochopitelné, že některým uživatelům příkazová řádka nemusí vyhovovat. To však – alespoň teoreticky – nemusí být nepřekonatelným problémem, protože GDB je navržen takovým způsobem, aby se nad ním daly vytvářet různé nadstavby vybavené více či méně konformním textovým či grafickým uživatelským rozhraním. O nadstavbách vytvořených nad GNU Debuggerem jsem již napsal krátký seriál na „konkurenčním“ webu http://www.mojefedora.cz, takže si dnes o každé nadstavbě řekneme pouze základní informace (nejdůležitější informací je v době Googlu samozřejmě jméno nadstavby :-), zbytek se již dá dohledat na stránkách vývojářů toho kterého nástroje).

Obrázek 1: 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. Rozhraní a možnosti Turbo Debuggeru je stále možné považovat za etalon toho, jak by mohl vypadat moderní debugger s TUI či GUI.
10. cgdb
Nástroj nazvaný cgdb, o němž jsem se zmínil zde, je založený na knihovně curses resp. ncurses, tudíž ho je možné využít v terminálu, na 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, které již známe. 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 jen v 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 2: 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.
11. Data Display Debugger – DDD
O nástroji nazvaném Data Display Debugger, který je známý i pod svojí zkratkou DDD, vznikl článek na serveru mojefedora.cz, takže si zde pouze ve stručnosti řekněme, že Data Display Debugger je nadstavbou nad GNU Debuggerem, která 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). Příkladem flexibility GUI 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 používajícími programovací jazyk Python

Obrázek 3: Ukázka grafického uživatelského rozhraní programu Data Display Debugger. V horní části můžeme vidět okno se zdrojovým kódem, v prostřední části pak výpis odpovídajícího strojového kódu a spodní třetina GUI obsahuje klasický příkazový řádek GNU Debuggeru. K dispozici je i dialogové okno se základními a často používanými příkazy.
12. Nemiver
I o dalším nástroji pojmenovaném Nemiver již vyšel samostatný článek. 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 dobrým řešením.

Obrázek 4: Ukázka grafického uživatelského rozhraní nástroje Nemiver při ladění uživatelské aplikace. V dolní části si povšimněte „oušek“ jednotlivých podoken.
13. 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 5: Ukázka grafického uživatelského rozhraní nástroje KDbg, opět při ladění uživatelské aplikace. Obsah levého spodního podokna je opět volitelný.
14. 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 6: Nám již známý program nazvaný npe v průběhu jeho krokování a ladění v Emacsu (v režimu GNU Debuggeru).
15. Odkazy na Internetu
- 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/ - Tracing (software)
https://en.wikipedia.org/wiki/Tracing_%28software%29 - ltrace(1) – Linux man page
http://linux.die.net/man/1/ltrace - ltrace (Wikipedia)
https://en.wikipedia.org/wiki/Ltrace - strace(1) – Linux man page
http://linux.die.net/man/1/strace - strace (stránka projektu na SourceForge)
https://sourceforge.net/projects/strace/ - strace (Wikipedia)
https://en.wikipedia.org/wiki/Strace - SystemTap (stránka projektu)
https://sourceware.org/systemtap/ - SystemTap (Wiki projektu)
https://sourceware.org/systemtap/wiki - SystemTap (Wikipedia)
https://en.wikipedia.org/wiki/SystemTap - Dynamic Tracing with DTrace & SystemTap
http://myaut.github.io/dtrace-stap-book/ - DTrace (Wikipedia)
https://en.wikipedia.org/wiki/DTrace - 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 - Getting started with ltrace: how does it do that?
https://www.ellexus.com/getting-started-with-ltrace-how-does-it-do-that/ - Reverse Engineering Tools in Linux – strings, nm, ltrace, strace, LD_PRELOAD
http://www.thegeekstuff.com/2012/03/reverse-engineering-tools/ - 7 Strace Examples to Debug the Execution of a Program in Linux
http://www.thegeekstuff.com/2011/11/strace-examples/ - Oracle® Solaris 11.3 DTrace (Dynamic Tracing) Guide
http://docs.oracle.com/cd/E53394_01/html/E53395/gkwpo.html#scrolltoc - 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 - 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/ - Insight
http://www.sourceware.org/insight/ - Supported Languages (GNU Debugger)
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 - Clewn
http://clewn.sourceforge.net/ - Clewn installation
http://clewn.sourceforge.net/install.html - Clewn – soubory ke stažení
http://sourceforge.net/projects/clewn/files/OldFiles/ - Pyclewn installation notes
http://pyclewn.sourceforge.net/install.html - Debugging
http://janus.uclan.ac.uk/pagray/labs/debug.htm