\documentclass[10pt]{beamer}

\usetheme{CambridgeUS}
\usecolortheme{rose}
\usepackage[polish]{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{listings}
\usepackage{wasysym}
\lstset{language=C++,
	basicstyle=\ttfamily,
	keywordstyle=\color{blue}\ttfamily,
	stringstyle=\color{red}\ttfamily,
	commentstyle=\color{magenta}\ttfamily,
}

\title{Proste i użyteczne kawałki \texttt{gdb}}
\author{Bartosz Szreder}
\date{}

\begin{document}

\frame{\maketitle}

\begin{frame}{Przechlapane}
	\begin{block}{}
		\texttt{gdb} to jeden z tych programów, którym przydałby się manpage do spisu treści jego manpage'a.
	\end{block}
	\pause
	\begin{center}
		\includegraphics[height=2.5cm]{yo_dawg.jpg}
	\end{center}
\end{frame}

\begin{frame}{\ldots{}no może nie do końca}
	\begin{alertblock}{Flagi kompilacji}
		Kompilujemy program z \texttt{-O0 -ggdb}, chyba, że chcemy co chwila czytać \textit{value optimized out}.
	\end{alertblock}

	\pause
	\begin{itemize}
		\item Uruchamianie debuggera: \texttt{gdb ./program}. To jeszcze nie uruchamia śledzonego programu, ale da konsolę debuggera.
		\pause
		\item Ustawianie argumentów dla śledzonego programu: \texttt{set args \ldots}. Coś takiego nie zadziała: \texttt{gdb ./program < argumenty}
		\pause
		\item Uruchomienie programu: \texttt{run}. Można też tutaj podać argumenty do programu.
	\end{itemize}
\end{frame}

\begin{frame}{Ogólnie}
	\begin{itemize}
		\item \texttt{set} ustawia różne parametry debuggera, \texttt{show} je wyświetla.
		\pause
		\item \texttt{info} wyświetla informacje o~śledzonym programie i~różnych rzeczach, które podczas tego śledzenia ustawiamy (np. breakpointy).
		\pause
		\item \texttt{help <polecenie>} pomaga.
		\pause
		\item Wyjście: \texttt{quit}.
		\pause
		\item W konsoli \texttt{gdb} działa uzupełnianie tabulacją.
		\pause
		\item Większość poleceń ma krótszą wersję, np. \texttt{backtrace} można wołać \texttt{bt}.
		\pause
		\item Jeśli chcemy rozpocząć od~nowa uruchomienie, wystarczy użyć polecenia \texttt{run}.
	\end{itemize}
\end{frame}

\begin{frame}{Przebieg}
	\begin{itemize}
		\item \texttt{stdout} i \texttt{stderr} śledzonego programu będzie widoczne w konsoli \texttt{gdb}.
		\pause
		\item Program może normalnie zakończyć swoje działanie albo zostać przerwany z jakiegoś powodu.
		\pause
		\item Powód przerwania jest wypisywany, zwykle jest to jakiś sygnał (np. \texttt{SIGSEGV}).
		\pause
		\item Można też klepnąć na klawiaturze \texttt{Ctrl+c}, czyli wysłać sygnał \texttt{SIGINT}.
		\pause
		\item Wznowienie działania zatrzymanego programu: \texttt{continue}.
		\pause
		\item Powrót z bieżącej ramki stosu: \texttt{return}. Można w~argumencie przekazać wartość, która ma być zwrócona z~tej ramki.
	\end{itemize}
\end{frame}

\begin{frame}[fragile]{Gdy już się wywali}
	\ldots{}fajnie byłoby wiedzieć dlaczego.
	\begin{verbatim}
	Program received signal SIGSEGV, Segmentation fault.
	0x00007fffe0000158 in ?? ()
	\end{verbatim}
\end{frame}

\begin{frame}[fragile]{Stos wywołań}
	\begin{verbatim}
	(gdb) backtrace
	#0  0x00007fffe0000158 in ?? ()
	#1  0x000000000043d311 in ClientThread::cleanup (this=0x87a430)
	    at .../src/networking/ClientThread.cpp:212
	...
	\end{verbatim}
	\pause
	\begin{block}{}
		W moim roboczym przykładzie jest dużo tekstu, który się tu nie zmieści, ale mogę pokazać pełen backtrace.
	\end{block}
	\pause
	\begin{itemize}
		\item Numerek po lewej (\texttt{\#0} i dalsze) to numer ramki stosu. Potem mamy adres w pamięci i~informacja o~miejscu wykonania (wraz z~argumentami funkcji), która powinna być czytelna dla człowieka (a~przynajmniej programisty).
		\pause
		\item Znaki zapytania się niefortunnie zdarzają -- może nie mamy symboli debugowych na tym poziomie stosu, a~może wykonanie programu poleciało w kosmos?
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\begin{block}{}
		Jak widać ramka \texttt{\#0} jest nieużyteczna, ale przeskoczmy do kolejnej i~zobaczmy na czym się wywala.
	\end{block}
	\pause
	\begin{verbatim}
	(gdb) frame 1
	(gdb) list
	207     }
	208
	209     void ClientThread::cleanup()
	210     {
	211             if (udpSocket != NULL) {
	212                     udpSocket->close();
	213                     delete udpSocket;
	214             }
	215     }
	\end{verbatim}
\end{frame}

\begin{frame}[fragile]
	\begin{verbatim}
	212                     udpSocket->close();
	\end{verbatim}
	\begin{block}{}
		Ciekawe co jest nie tak z tym socketem.
	\end{block}
	\pause
	\begin{verbatim}
	(gdb) print udpSocket
	     (QUdpSocket *) 0x7fffe00013d0
	\end{verbatim}
	\pause
	To nie było zbyt pomocne. Ale widać, że \texttt{gdb} kuma typy z bibliotek.
	\pause
	\begin{verbatim}
	(gdb) print *udpSocket
	     <incomplete type>
	\end{verbatim}
	\pause
	\ldots{}jak mamy dobry dzień.
\end{frame}

\begin{frame}[fragile]
	\begin{block}{}
		Nie wszystkie typy są zdefiniowane w miejscu wywołania metody (forward declarations).
	\end{block}
	\pause
	\begin{verbatim}
	(gdb) print this
	     (ClientThread * const) 0x87a430
	\end{verbatim}
	\pause
	Przynajmniej moje typy kuma.
	\pause
	\begin{verbatim}
	(gdb) print *this
	     {<AbstractThread> = {<QThread> = {<No data fields>},
	     static staticMetaObject = {d =
	     {superdata = 0x659140 <QThread::staticMetaObject> ...
	\end{verbatim}
\end{frame}

\begin{frame}[fragile]{Zatrzymywanie ręczne}
	\begin{itemize}
		\item \texttt{break} ustawia breakpoint na~wskazanej linii kodu (format: \texttt{plik:numer}) albo funkcji.
		\begin{verbatim}
		(gdb) break ClientThread::cleanup()
		Breakpoint 1 at 0x43d2e5:
		    file .../src/networking/ClientThread.cpp, line 211.
		\end{verbatim}
		\pause
		\item \texttt{step} przenosi do następnej linii kodu.
		\pause
		\item \texttt{stepi} przenosi do następnej instrukcji procesora. Przydatne przy grzebaniu w~assemblerze.
		\pause
		\item \texttt{skip} przeskakuje wywołania funkcji (nie zagłębia się w~nie).
		\pause
		\item \texttt{print} już się pojawiło, a~\texttt{continue} było wspomniane, ale to dobre miejsce na~przypomnienie.
		\pause
		\item \texttt{print} wypisuje podane wyrażenie raz, \texttt{display} wypisuje przy każdym zatrzymaniu programu.
		\pause
		\item Jest też \texttt{printf} do ładniejszego formatowania. Przydaje się, jeśli definiujemy własne funkcje.
	\end{itemize}
\end{frame}

\begin{frame}[fragile]{Mój \texttt{\textasciitilde/.gdbinit} z~czasów programowania w assemblerze}
	\begin{verbatim}
	set disassembly-flavor intel
	set disassemble-next-line on

	define pxd
	        display $xmm8.v16_int8
	        display $xmm7.v16_int8
	        display $xmm6.v16_int8
	        display $xmm5.v16_int8
	        display $xmm4.v16_int8
	        display $xmm3.v16_int8
	        display $xmm2.v16_int8
	        display $xmm1.v16_int8
	        display $xmm0.v16_int8
	end
	\end{verbatim}
\end{frame}

\begin{frame}
	Przerwania są bardzo silne i~elastyczne. Kilka zachęcających linijek z~\texttt{help breakpoints}:
	\begin{itemize}
		\item \texttt{watch} -- Set a watchpoint for an expression
		\item Podobne: \texttt{awatch}, \texttt{rwatch}
		\item \texttt{commands} -- Set commands to be executed when a breakpoint is hit
		\item \texttt{condition} -- Specify breakpoint number N to break only if COND is true
	\end{itemize}
\end{frame}

\begin{frame}{Krwawe detale}
	\begin{itemize}
		\item Własny debugger? \texttt{man 2 ptrace}
		\pause
		\item Pouczająca lektura, warto wiedzieć co potrafi ten syscall.
		\pause
		\item Tak są robione np. ograniczone środowiska wywołana na konkursach programistycznych.
		\pause
		\item Przydatne narzędzie śledzące program pod kątem używanych syscalli: \texttt{strace}.
		\pause
		\item Debugging gruboziarnisty, ale czasami szybko można namierzyć problem, np. zawieszenie na \texttt{select} albo \texttt{poll}.
		\pause
		\item Nie trzeba programu kompilować jakoś szczególnie (nie musi być \texttt{-ggdb}).
	\end{itemize}
\end{frame}

\begin{frame}{Co ułatwia \texttt{gdb}?}
	\begin{itemize}
		\item Śledzenie i~badanie programu: breakpointy są mocne.
		\pause
		\item Szybkie łapanie głupich błędów (null-pointer dereference, off-by-one), o~ile te błędy wcześnie powodują wysypkę zamiast mazać po~pamięci.
		\pause
		\item \ldots{}coś jeszcze?
	\end{itemize}
\end{frame}

\begin{frame}{Na co nie pomaga \texttt{gdb}?}
	\begin{itemize}
		\item Heisenbugs.
		\pause
		\item Głupotę/nieznajomość języka/nieuważność (undefined behavior).
		\pause
		\item Nie jest kryształową kulą, która zastąpi asercje i~logowanie ostrzeżeń, błędów czy zwykłych informacji diagnostycznych.
	\end{itemize}
\end{frame}

\end{document}
