~sergiodj/talks_gdb-best-friend

dd97dffcfb8e49c611d338fccce898ac65a8f25a — Sergio Durigan Junior 10 years ago 503b3fb
Adding slides in en_US

This commit adds the slides in en_US, and also the examples.
A Makefile => Makefile +12 -0
@@ 0,0 1,12 @@
CC = pdflatex
TARGET = gdb-best-friend
EXTENSION = tex

all:
	set -e ; \
	for i in 1 2 ; do \
		$(CC) $(TARGET).$(EXTENSION) ; \
	done ;

clean:
	rm -f $(TARGET).{aux,log,nav,out,pdf,snm,toc,vrb}

A examples/corefile/1.c => examples/corefile/1.c +28 -0
@@ 0,0 1,28 @@
static void foo_segv (void);

static void
bar (void)
{
  foo_segv ();
}

static void
foo_segv (void)
{
  int *x = 0;

  *x = 5;
}

static void
baz (void)
{
  bar ();
}

int
main (int argc, char *argv[])
{
  baz ();
  return 0;
}

A examples/multi-process/Makefile => examples/multi-process/Makefile +7 -0
@@ 0,0 1,7 @@
all: run

run: segv
	./segv

segv: segv.c
	gcc -g -o segv segv.c

A examples/multi-process/README => examples/multi-process/README +10 -0
@@ 0,0 1,10 @@
Execute:

~/work/src/git/build/gdb/gdb -q make

(gdb) set detach-on-fork off
(gdb) set target-async on
(gdb) set non-stop on
(gdb) set pagination off

inferior 7

A examples/multi-process/segv.c => examples/multi-process/segv.c +9 -0
@@ 0,0 1,9 @@
int
main (int argc, char *argv[])
{
  int *x = 0;

  *x = 52;

  return 0;
}

A examples/python/caller_is/1.c => examples/python/caller_is/1.c +25 -0
@@ 0,0 1,25 @@
static void
foo (void)
{
}

static void
bar (void)
{
  foo ();
}

static void
baz (void)
{
  foo ();
}

int
main (int argc, char *argv[])
{
  baz ();
  bar ();

  return 0;
}

A examples/python/caller_is/README => examples/python/caller_is/README +1 -0
@@ 0,0 1,1 @@
~/work/src/git/build/gdb/gdb -q ./a.out --data-directory ~/work/src/git/build/gdb/data-directory -ex 'source caller_is.py' -ex 'b foo if $caller_is ("bar")' -ex run

A examples/python/caller_is/caller_is.py => examples/python/caller_is/caller_is.py +20 -0
@@ 0,0 1,20 @@
import gdb
class CallerIs (gdb.Function):
    """Return True if the calling function's name is equal to a string.
This function takes one or two arguments.
The first argument is the name of a function; if the calling function's
name is equal to this argument, this function returns True.
The optional second argument tells this function how many stack frames
to traverse to find the calling function.  The default is 1."""

    def __init__ (self):
        super (CallerIs, self).__init__ ("caller_is")

    def invoke (self, name, nframes = 1):
        frame = gdb.selected_frame ()
        while nframes > 0:
            frame = frame.older ()
            nframes = nframes - 1
        return frame.name () == name.string ()

CallerIs()

A examples/python/pretty-print/1.c => examples/python/pretty-print/1.c +42 -0
@@ 0,0 1,42 @@
struct foo
  {
    int a;
    int b;
    char c;
    float d;
    double e;
    struct
      {
	int s1;
	char s2;
	int s3;
	union
	  {
	    int u1;
	    char u2;
	    double u3;
	  } my_union;

	struct
	  {
	    int crazy_1;
	    union
	      {
		struct
		  {
		    int big_field;
		    char my_char;
		  };
		int blabla;
	      } union_2;
	  } my_inner;
      } my_inner2;
  };

int
main (int argc, char *argv[])
{
  struct foo a;

  return 0;
}

A examples/python/pretty-print2/1.cpp => examples/python/pretty-print2/1.cpp +9 -0
@@ 0,0 1,9 @@
#include <string>

int
main ()
{
	std::string x = "Hello Upstream";

	return 0;
}

A examples/python/pretty-print2/str.py => examples/python/pretty-print2/str.py +29 -0
@@ 0,0 1,29 @@
import gdb.printing
import re

class StdStringPrinter:

	def __init__ (self, val):
		self.val = val

	def to_string (self):
		return self.val['_M_dataplus']['_M_p']

	def display_hint (self):
		return 'string'

def str_lookup_function(val):
	bbb = {}
	try:
		bbb = val.type.fields ()
	except:
		pass
	found = 0
	for x in bbb:
		if x.name == '_M_dataplus':
			found = 1
	if found == 1:
		return StdStringPrinter(val)
	return None

gdb.printing.register_pretty_printer (gdb, str_lookup_function)

A examples/reverse/1.c => examples/reverse/1.c +23 -0
@@ 0,0 1,23 @@
#include "2.h"

void
foo (int v)
{
  int a = 0;

  a = 10 + 20;
  a += v;

  bar (&a);
  bar (0);

  a = 0;
}

int
main (int argc, char *argv[])
{
  initialize ();

  return 0;
}

A examples/reverse/1.h => examples/reverse/1.h +1 -0
@@ 0,0 1,1 @@
void foo (int v);

A examples/reverse/2.c => examples/reverse/2.c +17 -0
@@ 0,0 1,17 @@
#include "1.h"

void
initialize (void)
{
  int n = 0;

  n = 12314314 % 453;
  foo (n);
}

void
bar (int *v)
{
  if (v != 0)
    *v += 12314314 % 453;
}

A examples/reverse/2.h => examples/reverse/2.h +3 -0
@@ 0,0 1,3 @@
void initialize (void);

void bar (int *v);

A examples/stap-probe/1.c => examples/stap-probe/1.c +41 -0
@@ 0,0 1,41 @@
#include <sys/sdt.h>

struct baz
  {
    int a;
    char b;
    union
      {
	int c;
	char d;
      } u;
  };

static void
foo (int a, const char *b)
{
  STAP_PROBE2 (test, probefoo, a, b);
}

static void
bar (const struct baz *a)
{
  STAP_PROBE1 (test, probebar, a);
}

int
main (int argc, char *argv[])
{
  int i1 = 1;
  const char *s = "String test";
  struct baz b;

  b.a = 49;
  b.b = 'y';
  b.u.d = 'a';

  foo (i1, s);
  bar (&b);

  return 0;
}

A examples/stap-probe/README => examples/stap-probe/README +2 -0
@@ 0,0 1,2 @@
Compiling with -Ox (x > 0) changes the layout of the symbols in the memory.
If you want to access a structure field, refer to it explicitly in the probe argument.

A examples/stap-probe/baz.c => examples/stap-probe/baz.c +12 -0
@@ 0,0 1,12 @@
struct baz
  {
    int a;
    char b;
    union
      {
	int c;
	char d;
      } u;
  };

struct baz blabla;

A gdb-best-friend.tex => gdb-best-friend.tex +413 -0
@@ 0,0 1,413 @@
\documentclass[slidestop,compress,blue]{beamer}
%\usetheme{default}
%\usetheme{Malmoe}
%\usetheme{Boadilla}
%\usetheme{umbc2}
%\usetheme{Antibes}
%\usetheme{Berlin}
%\usetheme{Madrid}

% Pacotes úteis
\usepackage[utf8]{inputenc}
% Fonte bonita!
\usepackage{ae,aecompl}
\usepackage[english]{babel}
\usepackage[T1]{fontenc}
\usepackage{listings}

\title{GDB, Your New Best Friend}
\author{Sergio Durigan Junior \\
	\texttt{sergiodj@\{redhat.com,sergiodj.net\}}}
\date{\today}

\usetheme[secheader]{Madrid}
\setbeamertemplate{navigation symbols}{}
\defbeamertemplate*{footline}{infolines theme without institution}
{
  \leavevmode%
  \hbox{%
  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,center]{author in head/foot}%
    \usebeamerfont{author in head/foot}\insertshortauthor
  \end{beamercolorbox}%
  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,center]{title in head/foot}%
    \usebeamerfont{title in head/foot}\insertshorttitle
  \end{beamercolorbox}%
  \begin{beamercolorbox}[wd=.333333\paperwidth,ht=2.25ex,dp=1ex,right]{date in head/foot}%
    \usebeamerfont{date in head/foot}\insertshortdate{}\hspace*{2em}
    \insertframenumber{} / \inserttotalframenumber\hspace*{2ex}
  \end{beamercolorbox}}%
  \vskip0pt%
}

\newcommand{\aspas}[1]{``#1''}
\newcommand{\gnu}{\texttt{GNU}}
\newcommand{\gdb}{\texttt{GDB}}
\newcommand{\gcc}{\texttt{GCC}}
\newcommand{\stap}{\texttt{SystemTap}}
\newcommand{\python}{\texttt{Python}}
\newcommand{\glibc}{\texttt{GLIBC}}
\newcommand{\kernel}{\textit{kernel}}
\newcommand{\probe}{\textit{probe}}
\newtheorem{sourcecode}{Source Code}

\begin{document}

\lstset{escapeinside={(*}{*)}}

\begin{frame}
	\titlepage
\end{frame}

\begin{frame}
	\frametitle{License}
	\begin{itemize}
		\item{License: \textbf{Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)}}
		\item{\url{http://creativecommons.org/licenses/by-sa/3.0/}}
	\end{itemize}
\end{frame}

\section{Tópicos}
\begin{frame}
	\frametitle{Agenda}

\begin{itemize}
	\item{Introduction}

% corefile
	\item{The core of the file}

% Falar de multiprocess
	\item{Multiprocess}

% Falar de probes, stap
	\item{\stap{} \texttt{SDT} probes}

% Falar de catchpoints?  catch syscall
%	\item{Análise de uma \probe{}}

% Falar de depuração reversa
	\item{gniggubeD esreveR}

% Falar de Python
	\item{\python{}}

	\item{Conclusion}
\end{itemize}
\end{frame}

\section{Introduction}
\begin{frame}[fragile]
	\frametitle{Introduction}
	\begin{itemize}
		\item{\gdb{}: \gnu{} project's Debugger \pause{} (it is \textbf{not} a \textit{database}...).  Supports several programming languages.}
		\begin{itemize}
			\item{\verb|#> gcc -g program.c -o program|}
			\item{\verb|#> gdb ./program|}
		\end{itemize}
		\pause
		\item{Before anything else!  \verb|C-x a|}
	\end{itemize}
\end{frame}

\section{The core of the file}
\begin{frame}[fragile]
	\frametitle{The core of the file}
	\begin{itemize}
		\item{\texttt{corefile}s are ``frozen images'' of a certain point of execution inside a program.}
		\pause
		\item{To generate one on \gdb{}, at any time:}
		\begin{itemize}
			\item{\verb|(gdb) generate-core-file|}
		\end{itemize}
		\pause
		\item{If you are seeing a segmentation fault, enable the \texttt{corefile} generation in your \texttt{shell}:}
		\begin{itemize}
			\item{\verb|#> ulimit -c unlimited|}
		\end{itemize}
		\pause
		\item{And then open the \texttt{corefile} on \gdb{}:}
		\begin{itemize}
			\item{\verb|#> gdb program core.12345|}
		\end{itemize}
		\pause
		\item{Inside \gdb{}, almost everything works.  You can print variables, request a \texttt{backtrace}, change the current \texttt{frame}.  You just cannot ``resurrect'' the program (i.e., execute it from that point) \verb|:-)|.}
	\end{itemize}
\end{frame}

\section{Multiprocess}
\begin{frame}[fragile]
	\frametitle{Multiprocess}
	\begin{itemize}
		\item{Given:}
		\begin{block}{Makefile}
		\tiny
		\begin{lstlisting}[language=sh,showstringspaces=false]
all: run

run: segv
        ./segv

segv: segv.c
        gcc -g -o segv segv.c
		\end{lstlisting}
		\end{block}
		\begin{block}{segv.c}
		\tiny
		\begin{lstlisting}[language=c,showstringspaces=false]
int
main (int argc, char *argv[])
{
  int *x = 0;

  *x = 52;

  return 0;
}
		\end{lstlisting}
		\end{block}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{Multiprocess$^2$}
	\begin{itemize}
		\item{How do you debug the program from the example, which has a segmentation fault?}
		\pause
		\item{Multiprocess!}
		\pause
		\item{On \gdb{}:}
		\begin{itemize}
			\item{\verb|(gdb) set detach-on-fork off|}
			\item{\verb|(gdb) set target-async on|}
			\item{\verb|(gdb) set non-stop on|}
			\item{\verb|(gdb) run|}
			\item{(...)}
			\item{\verb|(gdb) info inferiors|}
		\end{itemize}
		\item{(Yes, it is boring to type.  Yes, we will improve it.)}
		\pause
		\item{Time for a hands-on!}
	\end{itemize}
\end{frame}

\section{SystemTap SDT probes}
\begin{frame}[fragile]
	\frametitle{\stap{} \texttt{SDT} probes}
	\begin{itemize}
		\item{Pre-req for \gdb{}:  \probe{} v3, \verb|systemtap-sdt-devel >= 1.4|.}
		\begin{block}{Example code -- \texttt{exemplo-stap.c}}
		\tiny
		\begin{lstlisting}[language=c,showstringspaces=false]
(*\textcolor{red}{\#\textbf{include}} \textcolor{red}{\textless{}sys/sdt.h\textgreater{}}*)

void foo (int a)
{
  (*\textcolor{red}{STAP\_PROBE1 (}\textcolor{red}{example-stap, my\_probe, a}\textcolor{red}{);}*)
}

int main (int argc, char *argv[])
{
  foo (10);
  return 0;
}
		\end{lstlisting}
		\end{block}
		\pause
		\begin{block}{Compiling and verifying the \probe{}}
		\tiny
		\begin{lstlisting}[language=sh,showstringspaces=false]
$> gcc exemplo-stap.c -o exemplo-stap
$> stap -L '(*\textcolor{red}{process("./example-stap").mark("*")}*)'
process("./example-stap").mark("my_probe") $arg1:long
		\end{lstlisting}
		\end{block}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\stap{} \texttt{SDT} probes$^2$}
	\begin{itemize}
		\item{Available since \gdb{} 7.5, release in August, 2012.}
		\pause
		\item{Integrated with the \textit{breakpoint} system.  Support for printing a \probe{}'s argument value.}
		\pause
		\item{Supports \textit{tracepoints}.}
		\pause
		\item{Not necessary to include debug information in your binary (\texttt{-g} flag); arguments are encoded directly in the asm.}
		\pause
		\item{Also possible to use optmization flags (\texttt{-O}).}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\stap{} \texttt{SDT} probes$^3$}
	\begin{itemize}
		\item{Command \texttt{info probes}, list information about available \textit{probes}.}
		\pause
		\item{Command \texttt{break -probe-stap <probe\_name>}.}
		\pause
		\begin{itemize}
			\item{Also possible to use \texttt{-probe} or \texttt{-p}.}
		\end{itemize}
		\pause
		\item{Printing arguments for each \probe{}:  internal \gdb{} variables.}
		\begin{itemize}
			\item{\texttt{\$\_probe\_argc}: number of arguments of the \probe{} (max: 12).}
			\item{\texttt{\$\_probe\_arg$\{$0..11$\}$}:  print argument \{0..11\}.}
		\end{itemize}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\stap{} \texttt{SDT} probes$^4$}
	\begin{itemize}
		\item{After compiling your program (as shown previously):}
		\begin{block}{Debugging \stap{} \texttt{SDT} probes}
		\tiny
		\begin{lstlisting}[language=sh,showstringspaces=false]
\$> gdb /tmp/example-stap
...
(gdb) info probes
Provider   Name       Where               Semaphore           Object
example-stap my_probe   0x000000000040047b                    /tmp/example-stap
(gdb) break -probe-stap my_probe
Breakpoint 1 at 0x40047b
(gdb) run
Starting program: /tmp/example-stap 

Breakpoint 1, 0x000000000040047b in foo ()
(gdb) print $_probe_argc
$1 = 1
(gdb) print $_probe_arg0
$2 = 10
		\end{lstlisting}
		\end{block}
	\end{itemize}
\end{frame}

\section{gniggubeD esreveR}
\begin{frame}[fragile]
	\frametitle{gniggubeD esreveR}
	\begin{itemize}
		\item{Available since \gdb{} 7.0, released on September, 2009!}
		\pause
		\item{Implementation is kind of messy, but works in most cases...}
		\pause
		\item{Just works on x86/x86\_64 (patch for PowerPC is being made).}
		\pause
		\item{The hacker who did almost everything passed away.  \verb|:-(|}
		\begin{itemize}
			\item{Old story: ``... if I die, who is going to maintain this code?''}
		\end{itemize}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{gniggubeD esreveR$^2$}
	\begin{itemize}
		\item{\verb|(gdb) start|}
		\item{\verb|(gdb) target record-full|}
		\item{Or, with a recent \gdb{}: \verb|(gdb) record|}
		\item{(...)}
		\item{Use the commands with the prefix \texttt{reverse}.  \verb|reverse-next, reverse-step, reverse-nexti, reverse-stepi, set exec-direction reverse|...}
	\end{itemize}
\end{frame}


\section{Python}
\begin{frame}[fragile]
	\frametitle{\python{}}
	\begin{itemize}
		\item{Available since \gdb{} 7.0, too.}
		\pause
		\item{Motivation: make it easy to extend \gdb{} without having to mess with its internals.}
		\pause
		\item{Very well maintained, several extensions implemented.}
		\pause
		\item{Several projects already make use of it.  Yours can be the next!  \verb|:-)|}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\python{}$^2$}
	\begin{itemize}
		\item{Problem: \gdb{} knows about the \texttt{call stack}.  \gdb{} also has conditional \texttt{breakpoints}.}
		\pause
		\item{\emph{However, you cannot use information from the \texttt{stack} in the condition of a \texttt{breakpoint}.}}
		\pause
		\item{Solution?  Python!}
	\end{itemize}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\python{}$^3$}
%	\begin{itemize}
		\begin{block}{caller\_is.py}
		\tiny
		\begin{lstlisting}[language=python,showstringspaces=false]
import gdb
class CallerIs (gdb.Function):
    """Return True if the calling function's name is equal to a string.
This function takes one or two arguments.
The first argument is the name of a function; if the calling function's
name is equal to this argument, this function returns True.
The optional second argument tells this function how many stack frames
to traverse to find the calling function.  The default is 1."""

    def __init__ (self):
        super (CallerIs, self).__init__ ("caller_is")

    def invoke (self, name, nframes = 1):
        frame = gdb.selected_frame ()
        while nframes > 0:
            frame = frame.older ()
            nframes = nframes - 1
        return frame.name () == name.string ()

CallerIs()
		\end{lstlisting}
		\end{block}
\end{frame}

\begin{frame}[fragile]
	\frametitle{\python{}$^4$}
	\begin{itemize}
		\item{\verb|(gdb) source caller_is.py|}
		\item{\verb|(gdb) break foo if $caller_is ("bar")|}
	\end{itemize}
\end{frame}

\section{Conclusion}
\begin{frame}[fragile]
	\frametitle{Conclusion}
	\begin{itemize}
		\item{The debugger you knew has changed for the better.}
		\pause
		\item{Things that are coming:}
		\begin{itemize}
			\item{Improvements in the multiprocess feature.}
			\item{Scalability}
			\item{Improvements for \texttt{C++}.}
		\end{itemize}
	\end{itemize}
\end{frame}

\section{Thank you's}
\begin{frame}[fragile]
	\frametitle{Thank you's}
	\begin{itemize}
		\item{Red Hat}
		\item{FSOSS}
		\item{You guys and girls \verb|:-)|}
	\end{itemize}
\end{frame}

\section{Questions}
\begin{frame}
	\frametitle{Questions?}
	\begin{center}
		Shoot!  Or send e-mail!
	\end{center}
\end{frame}

\end{document}