Sample Debugger Sessions ======================== .. contents:: :local: .. toctree:: :maxdepth: 1 An Extended Debug Session ------------------------- In this session we will go into the debugger initially using the ``--debugger`` or ``-X`` option. We'll use the Makefile from the source code from cd-paranoia_ Basic Information when stopped inside Debugger ++++++++++++++++++++++++++++++++++++++++++++++ .. code:: console $ remake -X Reading makefiles... Updating makefiles... -> (/tmp/libcdio-paranoia/Makefile:428) Makefile: Makefile.in config.status remake<0> The line immediately before the prompt ``remake<0>``, we show the the target name, ``Makefile`` and its dependencies: ``Makefile.in`` and ``config.status``. The line before that has position information ``(/tmp/libcdio-paranoia/Makefile:428)``. But at the beginning of the line is and arrow made up of two characters, ``->``. This indicates that we have not done prerequisite checking for this target yet. Later we will come across other two-character icons like ``++``. See :ref:`icons ` for a complete list. The zero in the prompt ``remake<0>`` is the command history number. If GNU Readline history support has it increments as we enter commands, otherwise it stays zero. For each recursive call to ``remake``, we'll add another pair of angle brackets ``<>`` around the number. Some of the information is given in more verbose format using :ref:`info program `: .. code:: console remake<0> info program Starting directory `/tmp/libcdio-paranoia' Program invocation: remake/make -X Recursion level: 0 Line 428 of "/tmp/libcdio-paranoia/Makefile" Program stopped before rule-prequisite checking. remake<1> Notice that the prompt has incremented to 1 after entering the a command. Stepping ++++++++ We can use the :ref:`step, ` command to progress a little in the interpretation or execution of the makefile: .. code:: console remake<1> step -> (/tmp/libcdio-paranoia/Makefile:415) Makefile.in: Makefile.am m4/ld-version-script.m4 ... remake<2> step -> (/src/external-vcs/github/rocky/libcdio-paranoia/Makefile:443) aclocal.m4: m4/ld-version-script.m4 ... remake<3> I have elided the list of dependencies listed above and substituted ellipses (``...``). There is a slight difference between what you will find in the Makefile and the target output seen above. Below I'll list the what is in the Makefile versus what is line as shown above. For line 415: .. code:: makefile $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) Makefile.in: Makefile.am m4/ld-version-script.m4 ... while line 443: .. code:: makefile $(ACLOCAL_M4): $(am__aclocal_m4_deps) aclocal.m4: m4/ld-version-script.m4 ... In the debugger, variables have been expanded and file paths have been canonicalized. Therefore you see: .. list-table:: :header-rows: 1 * - Makefile - remake output * - `$(srcdir)/Makefile.in` - `Makefile.in` * - `$(ACLOCAL_M4)` - `aclocal.m4 ...` Let's recap where ``remake`` is in the process of running the Makefile. The first thing that seems to be done is that the ``Makefile`` dependencies need to checked. A dependency of ``Makefile`` is ``Makefile.in`` and that in turn depends on target ``aclocal.m4``. We have now stepped into and stopped at that target. At the ``remake<3>`` prompt then before checking for the dependencies of ``aclocal.m4``. You can see this dependency nesting that got us to this state using the :ref:`backtrace ` command: .. code:: console remake<3> backtrace =>#0 aclocal.m4 at /tmp/libcdio-paranoia/Makefile:443 #1 Makefile.in at /tmp/libcdio-paranoia/Makefile:415 #2 Makefile at /tmp/libcdio-paranoia/Makefile:428 remake<4> Stepping through the program can be illuminating as far as what is going on, especially when the Makefile has been derived in some way, as is the case here. This Makefile was created via ``autotools``. I had assumed that when I run ``make`` it looks for a default target and runs that. But as we see here, the first thing that goes on is to check to see if the Makefile is being used is itself out of date. If that is the situation, then the Makefile will get recreated and you start again. However while all of this may be interesting, stepping can be a bit tedious. In the next section, we talk about :ref:`breakpoints ` which can get you to where you want to debug faster. To finish this session though use the :ref:`quit ` command. .. code:: console remake<4> quit remake: That's all, folks... Stopping with Continue ++++++++++++++++++++++ Let's say I am interested in what goes on when ``make dist`` is run. Again, I'll invoke the debugger initially. .. code:: console $ remake -X Reading makefiles... Updating makefiles... -> (/tmp/libcdio-paranoia/Makefile:428) Makefile: Makefile.in config.status remake<0> Instead of stepping we can set a breakpoint on the ``dist`` target and continue running to that point in one command, using :ref:`continue `. .. code:: console remake<0> continue dist Breakpoint 1 on target `dist', mask 0x0f: file Makefile, line 703. Updating goal targets... -> (/src/external-vcs/github/rocky/libcdio-paranoia/Makefile:703) dist: remake<1> Now when I issue a ``step``, I will step into the commands associated with the ``dist`` target: .. code:: console remake<1> step File 'dist' does not exist. Must remake target 'dist'. Makefile:704: target 'dist' does not exist ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> remake dist-bzip2 dist-gzip am__post_remove_distdir='@:' ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ++ (/src/external-vcs/github/rocky/libcdio-paranoia/Makefile:703) dist remake<2> Notice that the event icon above is ``++`` which means I am stepping shell commands, here those associated with the Make target ``dist``. Above the line with the event icon in between the two chevrons is the command that is *about* to be run. To see the entire build commands, there is the :ref:`list ` command. Here is that: .. code:: console remake<2> list /tmp/libcdio-paranoia/Makefile:705 dist: # recipe to execute (from 'Makefile', line 706): $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) A form of the :ref:`target ` command, `target @ command` does about the same thing. Note that in both cases variables are not expanded as the are in the trace output shown above between chevrons. Debugging Make Variables ------------------------- In the above session we have seen that output has variables expanded, while in the ``list`` and ``target`` commands variables were not expanded. You can query any GNU Make variable that has been set in the program *without* variables inside expanded using the :ref:`print ` command. .. code:: console remake<2> print MAKE (origin default) MAKE = $(MAKE_COMMAND) The ``(origin default)`` means this is a built-in definition. Many variables that you will be interested in though, are set somewhere, and the variable is not a default it's location is also shown: .. code:: console remake<3> print DATA Makefile:168 (origin: makefile) DATA := libcdio_paranoia.pc libcdio_cdda.pc The other kind of print which does full expansion of the variables is called ``expand`` or ``x``. Here is an example .. code:: console remake<4> expand MAKE (origin default) MAKE := remake Note that in printing expanded values we use ``:=`` while non-expanded values we use ``=`` This output matches the semantics of these assignment operators. In fact, ``expand`` doesn't need a variable name, it will work with a string. For example: .. code:: console remake<5> x $(MAKE) $(DIST_TARGETS) remake dist-bzip2 dist-gzip No location identification is given here since what I put in isn't a variable. Also note that for ``expand`` I add the dollar sign and parenthesis when there is other stuff. If you just want information about the variable you can leave that off. However for ``print`` you *never* add the dollar sign; printing only prints *variables* not strings. You can change values too using either the :ref:`set `, :ref:`set ` or :ref:`setqx ` commands. Let's see the difference between ``set`` and ``setq``: .. code:: console remake<6> set MAKE $(MAKE_COMMAND) Variable MAKE now has value 'remake' remake<7> setq MAKE $(MAKE_COMMAND) Variable MAKE now has value '$(MAKE_COMMAND)' So with ``set``, the value in the expression ``$(MAKE_COMMAND)`` is expanded before the variable definition is assigned. With ``setq`` the internal variables are kept unexpanded. Which you use or want is up to you. Note the irregular syntax of ``set`` and ``setq``. Don't put an equal sign between the variable and the expression. That is, ``set MAKE = $(MAKE_COMMAND)`` gives: .. code:: console remake<8> set MAKE = $(MAKE_COMMAND) Variable MAKE now has value '= remake' which is probably not what you want. You can optionally put in the word "variable" when using ``set`` and "variable" is ignored. But it won't be if you use ``setq``. Debugging POSIX Shell Commands ------------------------------ Now consider the following sample Makefile ``test2.mk``: .. code:: Makefile PACKAGE=make all: $(PACKAGE).txt $(PACKAGE).txt: ../doc/remake.texi makeinfo --no-headers $< > $@ Running this entering the debugger initially: .. code:: console $ remake -X -f test2.mk ... Reading makefiles... updating makefiles.... Updating goal targets.... /tmp/remake/src/test2.mk:3 File `all' does not exist. -> (/tmp/test2.mk:5) make.txt: ../doc/remake.texi We could use the :ref:`target ` command to show information about the current target, but that returns lots if information. So let us instead narrow the information to just the automatic variables that get set. The following commands do this are all mean the same thing: `target make.txt variables`, `target @ variables`, and `info locals`. .. code:: remake<1> target @ variables @ := all % := * := + := make.txt | := < := all ^ := make.txt ? := There is a ``target`` option to list just the shell commands of the target: .. code:: remake<2> target @ commands make.txt: # commands to execute (from `test2.mk', line 6): makeinfo --no-headers $< > $@ We can see a full expansion of the command that is about to be run: .. code:: remake<5> target @ expand # commands to execute (from `test2.mk', line 6): makeinfo --no-headers $< > $@ # commands to execute (from `test2.mk', line 6): -makeinfo --no-headers ../doc/remake.texi > make.txt Now if we want to write out commands as a shell script which we might want to execute, we can use the :ref:`write ` command: .. code:: console (/tmp/remake/src/test2.mk:6): make.txt remake<6> write File "/tmp/make.txt.sh" written. We can issue a shell command ``cat -n /tmp/make.txt.sh`` to see what was written. See :ref:`shell `. .. code:: console remake<7> shell cat -n /tmp/make.txt.sh #!/bin/sh # cd /tmp/remake/src/ #/tmp/remake/src/test2.mk:5 makeinfo --no-headers ../doc/remake.texi > make.txt If you issue step commands, the debugger runs the each command and stops. In this way, you can inspect the result of running that particular shell command and decide to continue or not. .. code:: console remake<8> step Must remake target `make.txt'. Invoking recipe from test2.mk:6 to update target `make.txt'. ##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> makeinfo --no-headers ../doc/remake.texi > make.txt ##<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ++ (/tmp/test2.mk:5) Notice that we've shown the expansion automatically. One subtle difference in the above output, is that we only show the *single* shell command that is about to be run when there are several commands. In our example though, there is only one command; so there is no a difference. The ``++`` icon means that we are about to run that code. .. code:: console make.txt remake<9> @b{step} Successfully remade target file `make.txt'. <- (/tmp/test2.mk:5) make.txt remake<10> We ran the code, and are still at target ``make.txt``. The ``<-`` icon means that have finished with this target and are about to return. If you are at a target and want to continue to the end of the target you can use the command ``finish`` which is the same as ``finish 0``. Post-Mortem Debug Session ------------------------- In this session we'll go into the debugger on encountering an error. For this the ``--post-mortem`` or ``-!`` option is used. We'll use the Makefile from the source code of this distribution. *to be continued...* .. _cd-paranoia: https://github.com/rocky/libcdio-paranoia