~sergiodj/talks_gdb-intro-kwlug

4b3bbbe2c49a4e5c06099d3597e6aa5a076e4d3f — Sergio Durigan Junior 4 years ago
First version of the slides, with examples.
A  => examples/corefile/1.c +28 -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/points/Makefile +10 -0
@@ 1,10 @@
CC = gcc
CFLAGS = -g3 -O0

all: breakwatch catch hello

%.o: %.c
	$(CC) -o $@ -c $< $(CFLAGS)

clean:
	rm -f breakwatch catch hello

A  => examples/points/breakwatch.c +40 -0
@@ 1,40 @@
/* points.c -- Break and watch examples.  */

#include <stdio.h>

struct sttest
{
  int index;
  char name[15];
  int value;
};

int
test_func (int n)
{
  int r;

  r = n + 10;
  r += 20;

  return r;
}

int
main (int argc, char **argv)
{
  int a, b, i;
  struct sttest example_struct[10];

  a = 5;
  b = test_func (a) / 10;

  for (i = 0; i < 10; i++)
    {
      example_struct[i].index = i;
      sprintf (example_struct[i].name, "element %d", i);
      example_struct[i].value = test_func (i);
    }

  return 0;
}

A  => examples/points/catch.c +31 -0
@@ 1,31 @@
/* catch.c -- Example for 'catch fork' and 'catch syscall'.  */

#include <stdio.h>
#include <unistd.h>

void
test (void)
{
  if (fork () == 0)
    printf ("Child\n");

  fork ();
}

void
another_test (const char *p)
{
  chdir (p);
}

int
main (int argc, char **argv)
{
  int a;

  test ();

  another_test (".");

  return 0;
}

A  => examples/points/hello.c +28 -0
@@ 1,28 @@
/* hello.c -- Segfault example.  */

#include <stdio.h>
#include <string.h>

int
print (char *msg)
{
  printf ("%s\n", msg);
  return 0;
}

int
hello (char *param)
{
  strcpy (param, "Hello World!");
  print (param);
}

int
main (int argc, char **argv)
{
  char *str = "Hi!";

  hello (str);

  return 0;
}

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

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

	return 0;
}

A  => examples/python/pretty-print/str.py +29 -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 +23 -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 +1 -0
@@ 1,1 @@
void foo (int v);

A  => examples/reverse/2.c +17 -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 +3 -0
@@ 1,3 @@
void initialize (void);

void bar (int *v);

A  => examples/stap-probe/1.c +41 -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 +2 -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 +12 -0
@@ 1,12 @@
struct baz
  {
    int a;
    char b;
    union
      {
	int c;
	char d;
      } u;
  };

struct baz blabla;

A  => gdb-intro-kwlug.org +270 -0
@@ 1,270 @@
#+OPTIONS: toc:nil date:nil
#+SELECT_TAGS: export
#+EXCLUDE_TAGS: noexport
#+CREATOR: Emacs 26.1 (Org mode 9.1.9)
#+TITLE: GDB Intro
#+AUTHOR: Sergio Durigan Junior @@latex:\\@@ sergiodj@{sergiodj.net,redhat.com,debian.org}
#+LANGUAGE: en
#+LATEX_HEADER: \usepackage{listings}
#+LATEX_HEADER: \lstdefinestyle{customc}{belowcaptionskip=1\baselineskip,breaklines=true,frame=L,xleftmargin=\parindent,language=C,showstringspaces=false,basicstyle=\footnotesize\ttfamily,keywordstyle=\bfseries\color{green!40!black},commentstyle=\itshape\color{purple!40!black},identifierstyle=\color{blue},stringstyle=\color{orange},}

* License

- License: *Creative Commons Attribution 4.0 International License (CC-BY-4.0)*

- https://creativecommons.org/licenses/by/4.0/

* Agenda

- Blabla

* Introduction

- =GDB=: =GNU= project's Debugger @@latex:\pause@@ (it is *not* a
  /database/...).  Supports several programming languages.

- Started around 1986 by Richard Stallman (after *GNU Emacs*, but
  likely before *GCC*).

* Compiling your program for GDB

- Your program needs to contain *debug information* (also called
  =DWARF=) for GDB to consume.

#+BEAMER: \pause

- The GCC flag to include debug information is =-g=.  We also use
  =-g3=, which includes information about macros (=#define=).

#+BEAMER: \pause

- It's common to *disable optimizations* when building the binary, by
  using the flag =-O0= (it's /dash-oh-zero/).

  #+BEAMER: \pause

  - =# gcc -O0 -g program.c -o program=, /or/

  - ~# CFLAGS='-O0 -g' ./configure && make~

* Running your program using GDB

- In GDB's parlance, the program being debugged is called the
  *inferior*.

#+BEAMER: \pause

- Some ways to start the debugger:

  #+BEAMER: \pause

  - =# gdb ./program=

  #+BEAMER: \pause

  - =# gdb --args ./program arg1 arg2=

  #+BEAMER: \pause

  - =# gdb= @@latex: \\@@
    =(gdb) file ./program= @@latex: \\@@
    =(gdb) run arg1 arg2=

* {Break,Catch,Watch}points

- A *breakpoint* is related to /source code/ (location, function).  A
  *watchpoint* is related to /data/ (read/write of a variable).  A
  *catchpoint* is related to an /event/ (enter/exit a syscall, fork,
  receive a signal).

#+BEAMER: \pause

- Breakpoints (/code/)

  - =break=

  - =tbreak= (temporary)

#+BEAMER: \pause

- Watchpoints (/data/)

  - =watch= (write), =rwatch= (read), =awatch= (access)

  - Conditional watchpoints are supported.

#+BEAMER: \pause

- Catchpoints (/events/)

  - =catch fork=

  - =catch syscall=

* Resuming the execution

- After GDB has stopped the inferior (because a =*point= has been hit,
  for example), you will probably want to resume its execution.

#+BEAMER: \pause

- You may just want to continue the program:

  - =continue=

#+BEAMER: \pause

- Or maybe go to the next statement/instruction:

  - =next= (/statement/), or =nexti= (/instruction/)

#+BEAMER: \pause

- Or step into a function:

  - =step= (/statement/), or =stepi= (/instruction/)

#+BEAMER: \pause

- Or finish executing the current function, but stop at the end:

  - =finish=



* Examining data

- The inferior has stopped...  Now what?

#+BEAMER: \pause

- You may want to print the value of some variable:

  - =print VAR=

#+BEAMER: \pause

- Or examine a memory location:

  - =x ADDRESS=

#+BEAMER: \pause

- The type of a variable?  Easy:

  - =whatis VARIABLE=

#+BEAMER: \pause

- Hint: you may want to enable pretty-printing:

  - =set print pretty on=

* Examining the code

- Yes, we have =ncurses=!  The @@latex:\textbf{T}@@ext
  @@latex:\textbf{U}@@user @@latex:\textbf{I}@@nterface!

  - =C-x a= (that's =CTRL x a=).

#+BEAMER: \pause

- If you want to list the current region, or if you don't want/can't
  to use TUI:

  - =list=

#+BEAMER: \pause

- You can also disassemble code:

  - =disassemble=

#+BEAMER: \pause

- If GDB can't find the source code, you can specify its location
  using the =dir= command.

* Examining the call stack

- If you want to see the call stack (A.K.A. stack trace) that lead to
  the current function:

  - =bt=

#+BEAMER: \pause

- And you can move through it:

  - =up= and =down=

  - You can also go to a specific frame: =frame NUMBER=

* Corefiles

- *Corefiles* are frozen images of the inferior.  You can inspect
  everything that was happening when the process was running (but you
  can't resurrect it).

#+BEAMER: \pause

- You can generate them /outside/ GDB, when a program crashes.  Make
  sure you:

  - =ulimit -c unlimited=

  - Check if =systemd= is handling them
    (=/proc/sys/kernel/core_pattern=).

#+BEAMER: \pause

- You can also generate them /inside/ GDB, at any moment:

  - =generate-core-file=

#+BEAMER: \pause

- You can open a corefile using GDB:

  - =# gdb program -c corefile.PID=

* Other interesting information

- =info breakpoints=

- =info locals=

- =info registers=

- Many others!

* Who you gonna call?

- Our online documentation (=info=) is very good!

- Every command has a =help=.

- You can also use =apropos= when searching for a term.

- =TAB=-completion is also useful.

* Other advanced features

- Python support.

- Reverse debugging.

- Support for /SystemTap SDT probes/.

* End


#+ATTR_LATEX: :options style=customc
#+begin_src c -n
int main ()
{
  const char *c = NULL;

  return 0;
}
#+end_src

A  => gdb-intro-kwlug.tex +411 -0
@@ 1,411 @@
% Created 2019-06-02 Sun 21:20
% Intended LaTeX compiler: pdflatex
\documentclass[presentation]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{grffile}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{textcomp}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usepackage{color}
\usepackage{listings}
\usepackage{listings}
\lstdefinestyle{customc}{belowcaptionskip=1\baselineskip,breaklines=true,frame=L,xleftmargin=\parindent,language=C,showstringspaces=false,basicstyle=\footnotesize\ttfamily,keywordstyle=\bfseries\color{green!40!black},commentstyle=\itshape\color{purple!40!black},identifierstyle=\color{blue},stringstyle=\color{orange},}
\usetheme{default}
\author{Sergio Durigan Junior \\ sergiodj@\{sergiodj.net,redhat.com,debian.org\}}
\date{}
\title{GDB Intro}
\hypersetup{
 pdfauthor={Sergio Durigan Junior \\ sergiodj@\{sergiodj.net,redhat.com,debian.org\}},
 pdftitle={GDB Intro},
 pdfkeywords={},
 pdfsubject={},
 pdfcreator={Emacs 26.1 (Org mode 9.1.9)}, 
 pdflang={English}}
\begin{document}

\maketitle

\begin{frame}[label={sec:orga1f4768}]{License}
\begin{itemize}
\item License: \alert{Creative Commons Attribution 4.0 International License (CC-BY-4.0)}

\item \url{https://creativecommons.org/licenses/by/4.0/}
\end{itemize}
\end{frame}

\begin{frame}[label={sec:org13db7cc}]{Agenda}
\begin{itemize}
\item Blabla
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:orgcb90a6c}]{Introduction}
 \begin{itemize}
\item \texttt{GDB}: \texttt{GNU} project's Debugger \pause (it is \alert{not} a
\emph{database}\ldots{}).  Supports several programming languages.

\item Started around 1986 by Richard Stallman (after \alert{GNU Emacs}, but
likely before \alert{GCC}).
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:orgb03390f}]{Compiling your program for GDB}
 \begin{itemize}
\item Your program needs to contain \alert{debug information} (also called
\texttt{DWARF}) for GDB to consume.
\end{itemize}

\pause

\begin{itemize}
\item The GCC flag to include debug information is \texttt{-g}.  We also use
\texttt{-g3}, which includes information about macros (\texttt{\#define}).
\end{itemize}

\pause

\begin{itemize}
\item It's common to \alert{disable optimizations} when building the binary, by
using the flag \texttt{-O0} (it's \emph{dash-oh-zero}).

\pause

\begin{itemize}
\item \texttt{\# gcc -O0 -g program.c -o program}, \emph{or}

\item \texttt{\# CFLAGS='-O0 -g' ./configure \&\& make}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org71ced54}]{Running your program using GDB}
 \begin{itemize}
\item In GDB's parlance, the program being debugged is called the
\alert{inferior}.
\end{itemize}

\pause

\begin{itemize}
\item Some ways to start the debugger:

\pause

\begin{itemize}
\item \texttt{\# gdb ./program}
\end{itemize}

\pause

\begin{itemize}
\item \texttt{\# gdb -{}-args ./program arg1 arg2}
\end{itemize}

\pause

\begin{itemize}
\item \texttt{\# gdb}  \\
\texttt{(gdb) file ./program}  \\
\texttt{(gdb) run arg1 arg2}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org361654c}]{\{Break,Catch,Watch\}points}
 \begin{itemize}
\item A \alert{breakpoint} is related to \emph{source code} (location, function).  A
\alert{watchpoint} is related to \emph{data} (read/write of a variable).  A
\alert{catchpoint} is related to an \emph{event} (enter/exit a syscall, fork,
receive a signal).
\end{itemize}

\pause

\begin{itemize}
\item Breakpoints (\emph{code})

\begin{itemize}
\item \texttt{break}

\item \texttt{tbreak} (temporary)
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Watchpoints (\emph{data})

\begin{itemize}
\item \texttt{watch} (write), \texttt{rwatch} (read), \texttt{awatch} (access)

\item Conditional watchpoints are supported.
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Catchpoints (\emph{events})

\begin{itemize}
\item \texttt{catch fork}

\item \texttt{catch syscall}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org62a7e28}]{Resuming the execution}
 \begin{itemize}
\item After GDB has stopped the inferior (because a \texttt{*point} has been hit,
for example), you will probably want to resume its execution.
\end{itemize}

\pause

\begin{itemize}
\item You may just want to continue the program:

\begin{itemize}
\item \texttt{continue}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Or maybe go to the next statement/instruction:

\begin{itemize}
\item \texttt{next} (\emph{statement}), or \texttt{nexti} (\emph{instruction})
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Or step into a function:

\begin{itemize}
\item \texttt{step} (\emph{statement}), or \texttt{stepi} (\emph{instruction})
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Or finish executing the current function, but stop at the end:

\begin{itemize}
\item \texttt{finish}
\end{itemize}
\end{itemize}
\end{frame}



\begin{frame}[fragile,label={sec:org717537c}]{Examining data}
 \begin{itemize}
\item The inferior has stopped\ldots{}  Now what?
\end{itemize}

\pause

\begin{itemize}
\item You may want to print the value of some variable:

\begin{itemize}
\item \texttt{print VAR}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Or examine a memory location:

\begin{itemize}
\item \texttt{x ADDRESS}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item The type of a variable?  Easy:

\begin{itemize}
\item \texttt{whatis VARIABLE}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item Hint: you may want to enable pretty-printing:

\begin{itemize}
\item \texttt{set print pretty on}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org71b8f2a}]{Examining the code}
 \begin{itemize}
\item Yes, we have \texttt{ncurses}!  The \textbf{T}ext
\textbf{U}user \textbf{I}nterface!

\begin{itemize}
\item \texttt{C-x a} (that's \texttt{CTRL x a}).
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item If you want to list the current region, or if you don't want/can't
to use TUI:

\begin{itemize}
\item \texttt{list}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item You can also disassemble code:

\begin{itemize}
\item \texttt{disassemble}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item If GDB can't find the source code, you can specify its location
using the \texttt{dir} command.
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org1b45b5a}]{Examining the call stack}
 \begin{itemize}
\item If you want to see the call stack (A.K.A. stack trace) that lead to
the current function:

\begin{itemize}
\item \texttt{bt}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item And you can move through it:

\begin{itemize}
\item \texttt{up} and \texttt{down}

\item You can also go to a specific frame: \texttt{frame NUMBER}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org22c386a}]{Corefiles}
 \begin{itemize}
\item \alert{Corefiles} are frozen images of the inferior.  You can inspect
everything that was happening when the process was running (but you
can't resurrect it).
\end{itemize}

\pause

\begin{itemize}
\item You can generate them \emph{outside} GDB, when a program crashes.  Make
sure you:

\begin{itemize}
\item \texttt{ulimit -c unlimited}

\item Check if \texttt{systemd} is handling them
(\texttt{/proc/sys/kernel/core\_pattern}).
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item You can also generate them \emph{inside} GDB, at any moment:

\begin{itemize}
\item \texttt{generate-core-file}
\end{itemize}
\end{itemize}

\pause

\begin{itemize}
\item You can open a corefile using GDB:

\begin{itemize}
\item \texttt{\# gdb program -c corefile.PID}
\end{itemize}
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org7b2681d}]{Other interesting information}
 \begin{itemize}
\item \texttt{info breakpoints}

\item \texttt{info locals}

\item \texttt{info registers}

\item Many others!
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org73ead26}]{Who you gonna call?}
 \begin{itemize}
\item Our online documentation (\texttt{info}) is very good!

\item Every command has a \texttt{help}.

\item You can also use \texttt{apropos} when searching for a term.

\item \texttt{TAB}-completion is also useful.
\end{itemize}
\end{frame}

\begin{frame}[label={sec:orgf6ce0ab}]{Other advanced features}
\begin{itemize}
\item Python support.

\item Reverse debugging.

\item Support for \emph{SystemTap SDT probes}.
\end{itemize}
\end{frame}

\begin{frame}[fragile,label={sec:org0d39b0e}]{End}
 \lstset{language=C,label= ,caption= ,captionpos=b,firstnumber=1,numbers=left,style=customc}
\begin{lstlisting}
int main ()
{
  const char *c = NULL;

  return 0;
}
\end{lstlisting}
\end{frame}
\end{document}