diff options
| author | Jan Altenberg <jan@jan-laptop.(none)> | 2010-04-23 15:41:59 +0200 |
|---|---|---|
| committer | Jan Altenberg <jan@jan-laptop.(none)> | 2010-04-23 15:41:59 +0200 |
| commit | ae303294cc741b9498816a0c6d1540074c364ded (patch) | |
| tree | 8e36efe0bdf2201c32946dd3e00895b0723d2b80 /application-devel | |
| parent | a27c72e072813081e79798db5e54deaa5b7ad5d5 (diff) | |
Started debugging chapter.
Diffstat (limited to 'application-devel')
3 files changed, 66 insertions, 299 deletions
diff --git a/application-devel/app-debugging/handout_app-debugging_de.tex b/application-devel/app-debugging/handout_app-debugging_de.tex index 89c71c2..b6e7158 100644 --- a/application-devel/app-debugging/handout_app-debugging_de.tex +++ b/application-devel/app-debugging/handout_app-debugging_de.tex @@ -6,290 +6,14 @@ \begin{document} -\section*{Debugging} +\section*{Titel} -Beim Debugging geht es darum, Fehler in einem System zu finden. +\subsection*{Abschnitt1} -Es gibt zwei grundlegend verschiedene Fehlerarten: +Text -\begin{enumerate} -\item die Anwendung beendet sich unerwartet - \begin{description} - \item[auf Grund von Fehlern bei der Speicherveraltung] z.B. durch freigeben - eines Speicherbereichs, welcher zuvor nicht alloziert wurde: - \begin{lstlisting} -mem = malloc(5); -free(((char*)mem)+6000); - \end{lstlisting} - Die Programmausf\"uhrung wird abgebrochen, die glibc liefert alle - Informationen, welche n\"otig sind, um den Fehler zu decodieren: - \begin{lstlisting} -bash-4.0$ ./test -*** glibc detected *** ./test: free(): invalid pointer: 0x083c9778 *** -======= Backtrace: ========= -/lib/libc.so.6[0x57c231] -./test[0x804841e] -/lib/libc.so.6(__libc_start_main+0xe6)[0x522a66] -./test[0x8048361] -======= Memory map: ======== -0048e000-0048f000 r-xp 0048e000 00:00 0 [vdso] -004e8000-00508000 r-xp 00000000 fd:00 66065 /lib/ld-2.10.1.so -00508000-00509000 r--p 0001f000 fd:00 66065 /lib/ld-2.10.1.so -... - \end{lstlisting} - Mit folgendem Befehl kann festgestellt werden, von wo aus der Fehler - getriggered wurde: - - \cmd{addr2line -e test 0x804841e} +\subsection*{Abschnitt2} - /home/linutronix/test.c:16 - - \item[Speicherzugriffsfehler] z.B. durch Zugriff auf nicht allozierten - Speicher. Die Programmausf\"uhrung wird abgebrochen: - \begin{lstlisting} -bash-4.0$ ./test -Speicherzugriffsfehler - \end{lstlisting} - Solche Fehler lassen sich am Besten mit einer gdb Backtrace Ausgabe (siehe - unten) finden. - \end{description} -\item die Anwendung verh\"alt sich anders als erwartet. - - In einem solchen Fall sollte man sich zu erst Gedanken dar\"uber machen, - durch was das Fehlverhalten getriggered werden k\"onnte. Sofort mit einem - Debugger durch den Code zu steppen ist kein guter Ansatz, da so evt. ein - Fehler gefunden und behoben wird der aber nicht zwangsl\"aufig die Ursache - f\"ur das Problem war. Dies kann dazu f\"uhren, dass die Fehlersuche eines - sp\"ater entdeckten Bugs um so komplexer und schwieriger wird. - - Hat man sich Gedanken \"uber die Ursachen gemacht, kann man gezielt mit den - nachfolgend beschriebenen Techniken dem Fehler auf den Grund gehen. -\end{enumerate} - -\subsection*{Einfach aber wirkungsvoll: \cmd{printf}, \cmd{fprintf}} - -Da Ausgaben auf die \cmd{stdout} gecached werden, ist es zuverl\"assiger f\"ur -Debugging \cmd{stderr} zu verwenden und nach jeder Ausgabe noch den cash flush -zu triggern. Ein Debug konstrukt k\"onnte z.B. folgenderma\ss en aussehen: - -\begin{lstlisting} -fprintf(stderr, "debug test\n"); -fflush(stderr); -\end{lstlisting} - -F\"ur gew\"ohnlich wird \cmd{(f)printf} beim Debuggen f\"ur drei Zwecke -verwendet: - -\begin{enumerate} -\item Tracing: -\begin{lstlisting} -fprintf(stderr, "%s, called\n", __FUNCTION__); -fflush(stderr); -\end{lstlisting} -\item Ausgabe von Variablenwerten: -\begin{lstlisting} -fprintf(stderr, "Wert: %d, Wert (hex): %x\n", wert, wert); -fflush(stderr); -\end{lstlisting} -\item Ausgabe von Adressen: -\begin{lstlisting} -fprintf(stderr, "Adresse: %p, Wert: %x\n", wert, wert); -fflush(stderr); -\end{lstlisting} -\end{enumerate} - -Nat\"urlich k\"onnen die Methoden kombiniert werden. - -Soll das Debugging zur Compilezeit zu- und abschaltbar sein, kann z.B. folgendes -Pr\"aprozessor konstrukt hilfreich sein: - -\begin{lstlisting} -#ifdef DEBUG -#define debug(...) fprintf(stderr, "%s:%d - ", __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__); fflush(stderr) -#else -#define debug(...) ((void)0) -#endif - -int main(int argc, char **argv) -{ - int val = 3; - debug("addr: %p - val: %d\n", &val, val); - return 0; -} -\end{lstlisting} - -Resultat: -\begin{lstlisting} -bash-4.0$ gcc -o test test.c -bash-4.0$ ./test -bash-4.0$ -bash-4.0$ gcc -o test -DDEBUG test.c -bash-4.0$ ./test -test.c:22 - test: 0xbfef8694 - val: 3 -bash-4.0$ -\end{lstlisting} - -\subsubsection*{deutlich flexibler: Logging Frameworks} - -Wird f\"ur Debugging oder Logging mehr Flexibilit\"at ben\"otigt, sollte ein -Logging Framework verwendet werden. Prominente Vertretter f\"ur verschiedene -Programmiersprachen sind zum Beispiel: - -\begin{itemize} -\item Log for C++ (http://log4cpp.sourceforge.net) -\item log4c (http://log4c.sourceforge.net) -\item log4j (http://logging.apache.org/log4j) - f\"ur JAVA -\end{itemize} - -Diese Frameworks bieten die M\"oglichkeit das Loggingverhalten zum Startpunkt -der Anwendung, oder teilweise sogar, w\"ahrend der Laufzeit zu ver\"andern. - -Es wird beim Loggen mindestens zwischen den Kategorien Debug, Error und Info -unteschieden, welche jeweils an verschiedene Ziele geleitet werden k\"onnen: -Datei, syslog, \dots - -\subsubsection*{Backtraces ausgeben} - -Die glibc bietet auch die M\"oglichkeit an einer beliebigen Stelle in der -Applikation die Ausgabe eines Function Call Traces (Backtrace) aus zu geben. - -Dies ist hilfreich, wenn man herausfinden will, \"uber welche Funktionsaufrufe -die aktuelle Codezeile aufgerufen wurde. - -Beispiel: -\begin{lstlisting} -#include <stdio.h> -#include <stdlib.h> -#define DEFAULT_BT_DEPTH 16 - -void btrace(int depth) { - const void *trace[depth]; - char **messages = (char **) NULL; - unsigned int i = 0; - int trace_size = backtrace(trace, depth); - messages = backtrace_symbols(trace, trace_size); - fprintf(stderr, "***BACKTRACE***\n"); - for(; i < trace_size; i++) - fprintf(stderr, "%s\n", messages[i]); - fprintf(stderr, "***************\n"); - fflush(stderr); -} -void pong() { -#ifdef DEBUG - btrace(DEFAULT_BT_DEPTH); -#endif -} -void ping() { - pong(); -} -int main(int argc, char **argv) { - ping(); - return 0; -} -\end{lstlisting} - -Anwendung: -\begin{lstlisting} -bash-4.0$ gcc -g -o test -DDEBUG test.c -bash-4.0$ ./test -***BACKTRACE*** -./test [0x804859b] -./test [0x8048663] -./test [0x8048670] -./test [0x804867d] -/lib/libc.so.6(__libc_start_main+0xe6) [0x522a66] -./test [0x8048441] -*************** -bash-4.0$ addr2line -e test 0x804867d -/home/linutronix/test.c:27 -bash-4.0$ addr2line -e test 0x8048670 -/home/linutronix/test.c:24 -\end{lstlisting} - -\subsection*{Tracing mit strace} - -Mit \cmd{strace} k\"onnen Systemaufrufe getraced werden. Es kann ermittelt -werden welche Systemaufrufe von der Applikation zu welchem Zeitpunkt aufgerufen -wurden und wieviel Zeit der Kernel ben\"otigt um den Aufruf ab zu arbeiten. - -Ein \cmd{strace} ist folgenderma\ss en zu interpretieren: - -\begin{lstlisting} -bash-4.0$ strace -ftttT ./test -1245687387.873813 execve("./test", ["./test"], [/* 18 vars */]) = 0 <0.000233> -^ ^ ^ ^ ^ -| | | | | -| | +- Argumente | +- Dauer -+- Zeitstempel +- syscall +- Rueckgabewert -\end{lstlisting} - -Die Option -\begin{itemize} -\item \cmd{-f} sorgt daf\"ur, dass auch Kindprozesse mit getraced werden, -\item \cmd{-ttt} blendet den pr\"azisen Zeitstempel ein, -\item \cmd{-T} gibt die Dauer des Systemaufrufs mit an. -\end{itemize} - -\subsection*{Debugging mit gdb} - -gdb ist ein textbasierter Debugger. Eine Applikation kann z.B mit dem Befehl -\cmd{gdb ./test} in gdb geladen werden und anschliessend mit dem Befehl -\cmd{run} ausgef\"uhrt werden. - -Die 'gdb Reference Card' listet viele n\"utzliche Befehle, z.B. zum Setzen von -Breakpoints und zum Steppen durch die Applikation. - -Es gibt auch grafische Frontends f\"ur gdb, wie z.B. \cmd{ddd} -(http://www.gnu.org/software/ddd). - -\subsubsection*{Core Dumps analysieren} - -\cmd{gdb} eignet sich au\ss erdem hervorragend zur Analyse von so genannten -'core dumps'. Ein 'core dump' entsteht, wenn eine Applikation unerwartet beendet -wird. Gegebenenfalls mu\ss mit \cmd{ulimit -c unlimited} vor dem -Applikationsstart das Limit f\"ur maximal zul\"assige core dumps erh\"oht -werden. - -Beispiel: -\begin{lstlisting} -bash-4.0$ ulimit -c unlimited -bash-4.0$ ./test -Speicherzugriffsfehler (Speicherabzug geschrieben) -bash-4.0$ gdb ./test core.12371 -GNU gdb 6.8-debian -Copyright (C) 2008 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"... -Reading symbols from /lib/libc.so.6...done. -Loaded symbols for /lib/libc.so.6 -Reading symbols from /lib/ld-linux.so.2...done. -Loaded symbols for /lib/ld-linux.so.2 -Core was generated by `./test'. -Program terminated with signal 11, Segmentation fault. -[New process 12371] -#0 0x08048661 in pong () at test.c:22 -22 *null_ptr = 3; -(gdb) -(gdb) bt -#0 0x08048661 in pong () at test.c:22 -#1 0x08048671 in ping () at test.c:26 -#2 0x0804867b in main (argc=1, argv=0xbf9921f4) at test.c:29 -(gdb) -\end{lstlisting} - -Der Befehl \cmd{bt} steht f\"ur Backtrace. Die zuletzt aufgerufene Funktion -steht an Position \#0. Zeigt \#0 nicht auf die eigene Applikationen sondern z.B. -in die glibc ist es eher warscheinlich, dass der Fehler durch eine nicht -spezifiezierte Verwendung einer glibc Funktion getriggered wurde. Man sollte in -diesem Fall zuerst untersuchen, ob die erste Funktion in der eigenen Software, -einen korrekten glibc call absetzt, bevor die glibc gedebugged wird. - -%\subsubsection*{Remote-Debuggging mit gdbserver} - -%Text +Text \end{document} diff --git a/application-devel/app-debugging/hints_app-debugging_de.tex b/application-devel/app-debugging/hints_app-debugging_de.tex index e17f921..11c5c34 100644 --- a/application-devel/app-debugging/hints_app-debugging_de.tex +++ b/application-devel/app-debugging/hints_app-debugging_de.tex @@ -1,17 +1,18 @@ -\documentclass{article} +\documentclass{lxarticle} \usepackage{german} \usepackage[utf8]{inputenc} +\usepackage{lxheaders} +\usepackage{lxextras} \begin{document} -\section*{Block \lq Debugging von Applikationen\rq} +\section*{Block \lq Was ist Linux?\rq} \subsection*{Lernziele} \begin{itemize} -\item Einfach aber wirkungsvoll: printf -\item Kennenlernen von strace -\item Debugging mit gdb -\item Remote-Debugging mit gdbserver +\item Lernziel 1 +\item Lernziel 2 +\item Lernziel 3 \end{itemize} \subsection*{Unterrichts-Ablauf} diff --git a/application-devel/app-debugging/pres_app-debugging_de.tex b/application-devel/app-debugging/pres_app-debugging_de.tex index 07db328..1c912b9 100644 --- a/application-devel/app-debugging/pres_app-debugging_de.tex +++ b/application-devel/app-debugging/pres_app-debugging_de.tex @@ -1,24 +1,66 @@ -\documentclass{article} +\documentclass{beamer} +\usetheme{linutronix} \usepackage{german} \usepackage[utf8]{inputenc} +\usepackage{pgf} +\usepackage{graphicx} +\usepackage{lxextras} + +\title{Block \lq Was ist Linux?\rq} +\institute{Linutronix GmbH} + +\lstset{keywordstyle=\color{blue},commentstyle=\color{orange}} \begin{document} -\section*{Block \lq Was ist Linux?\rq} +\maketitle +\begin{frame} +\frametitle{Übersicht} +\tableofcontents +\end{frame} -\subsection*{Lernziele} -\begin{itemize} -\item Lernziel 1 -\item Lernziel 2 -\item Lernziel 3 -\end{itemize} +\section{Einfache Debugging Werkzeuge} +\subsection{System calls tracen mit STRACE} +\begin{frame} +\frametitle{STRACE} +\begin{alertblock}{Was ist STRACE?} +STRACE ist ein mächtiges Diagnosewerkzeug, mit dem sich System Calls und Signale +tracen lassen. +\end{alertblock} +\end{frame} -\subsection*{Unterrichts-Ablauf} +\begin{frame}[containsverbatim] +\frametitle{Anwendungsbeispiel} +\begin{lstlisting}[language=bash] +$ strace /bin/ls +execve("/bin/ls", ["/bin/ls"], [/* 38 vars */]) = 0 +brk(0) = 0x8061000 +access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) +mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = +0xb7f03000 +access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +open("/etc/ld.so.cache", O_RDONLY) = 3 +fstat64(3, {st_mode=S_IFREG|0644, st_size=113431, ...}) = 0 +[...] +\end{lstlisting} +\end{frame} -Hinweise zur Präsentation, Zeitplanung, etc. +\begin{frame}[containsverbatim] +\frametitle{Wichtige STRACE Optionen} +\begin{itemize} +\item \textbf{-f}: Follow Forks +\item \textbf{-v}: Verbose mode +\item \textbf{-T}: Print out time which is spent in each syscall +\item \textbf{-p PID}: Attach to PID +\end{itemize} +\end{frame} -\subsection*{Übungen bei vorhandener Hardware} +\subsection{Memory debugging} +\subsubsection{MTrace} +\subsubsection{libDUMA (aka electric fence)} +\section{Der GNU Debugger: GDB} +\subsection{Post mortem Analyse mit GDB} +\subsection{Interaktives Debugging mit GDB} -Hinweise zu Übungen, Zeitlimit dazu. \end{document} |
