Debugging Octave: Difference between revisions

From Octave
Jump to navigation Jump to search
No edit summary
(→‎Tools for debugging: __debug_octave__ is in released versions now)
 
(25 intermediate revisions by 8 users not shown)
Line 1: Line 1:
= Preliminaries =
= Preliminaries =
Since compilation of all the source from scratch can take long it is good to have a source folder where most of the source has been compiled. To do this ...


== Workflow ==
Since compilation of all the source from scratch can take long it is good to have a source folder where most of the source has been compiled. To do this, you can create a parallel build:
# Clone the repository.
# Regenerate the scripts.
# Configure.
# Compile the code.
# Start debugging.


= Basic debugging processes =
<syntaxhighlight lang="bash">
== Error & trace the stack ==
mkdir dbg-octave
cd dbg-octave
/path/to/octave/source/configure FFLAGS=-g CFLAGS=-g CXXFLAGS=-g --enable-address-sanitizer-flags --prefix=/opt/dbg-octave
make # or make -jN where N is the number of CPU cores
</syntaxhighlight>
 
This will create a new build of Octave in a different directory without optimizations (no -O2 gcc parameter) and with debug symbols compiled in. This build is useful for debugging Octave itself.
 
= Tools for debugging =
 
There are different tools for debugging. This article concentrates on describing how to use <code>gdb</code>.


= Debugging oct-files =
If you run Octave from a build tree, execute <code>./run-octave -g</code> to start a gdb session that is prepared to run Octave (with the necessary environment correctly set up).  Note that when Octave runs in GUI mode, it forks at startup on Linux and MacOS systems, so this method will only work if <code>gdb</code> correctly follows the process across the <code>fork</code> and <code>exec</code> system calls.
 
Alternatively, you can attach a debugger to a running Octave session.  Current versions of Octave include the command <code>__debug_octave__</code> to manage the details.  Executing this command at the Octave prompt should open a separate window for a debugger session attached to the current Octave process.  On Linux systems, the default terminal window is <code>gnome-terminal</code>.  On MacOS systems, the default debugger is <code>lldb</code>.
 
For some kinds of errors on some OS, the last approach might not be useful. The OS might kill the shell that runs gdb as soon as the spawning process (i.e. Octave) crashes. In that case, you can attach to Octave from an "independent" shell. Execute <code>getpid ()</code> in Octave and take note of the displayed *PID*. Open a shell and execute <code>gdb -p *PID*</code> (replace <code>*PID*</code> with the actual PID). On Windows, use the msys2 shell that can be started with the file <code>cmdshell.bat</code> in Octave's installation folder.
 
Independent of how <code>gdb</code> was started and Octave was attached to it, it is now possible to issue gdb commands on the <code>(gdb)</code> prompt. See e.g. the [https://sourceware.org/gdb/download/onlinedocs/gdb/index.html gdb documentation]. To return to Octave while gdb is still attached to it, execute <code>continue</code> (or <code>c</code>) at the <code>(gdb)</code> prompt.


To debug oct-files, avoid making any optimization during compilation. Use <code>export CXXFLAGS="-ggdb -Wall -O0"</code> for C++ code or <code>export CFLAGS="-ggdb -Wall -O0"</code> for C code to suppress optimization. Compile the oct-file with the debug flag <code>-g</code> which enables debug symbols
*NOTE:  Ubuntu introduced a patch to disallow ptracing of non-child processes by non-root users - i.e. only a process which is a parent of another process can ptrace it for normal users - whilst root can still ptrace every process.
That's why gdb won't be able to link to the octave process if you start gdb from within an Octave session using the <code>__debug_octave__</code> command.


You can temporarily disable this restriction by doing:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
mkoctfile -g file.cpp
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
</syntaxhighlight>
and then reopen <code>gdb</code> using the command mentioned above from within an Octave session or if you have admin rights you can simply do:
<syntaxhighlight lang="bash">
__debug_octave__ ("gnome-terminal --command 'sudo gdb -p %d'")
</syntaxhighlight>
</syntaxhighlight>


start now the GNU debugger with octave
= Debugging oct-files =
 
To debug oct-files, avoid making any optimization during compilation. Use <code>export CXXFLAGS="-ggdb -Wall -O0"</code> for C++ code or <code>export CFLAGS="-ggdb -Wall -O0"</code> for C code to suppress optimization. Compile the oct-file with the debug flag <code>-g</code> which enables debug symbols


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
gdb octave
mkoctfile -g file.cpp
</syntaxhighlight>
</syntaxhighlight>


and run it
In next step you will use GNU debugger or gdb. The symbols from your oct-file will only be available to gdb once the oct-file is loaded in Octave.  To do that without executing any functions from the oct-file, you can ask Octave to display the help for the oct-file:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
(gdb) run
octave> help file
</syntaxhighlight>
</syntaxhighlight>


Octave will start up. To load the symbol table the function needs to be executed, for example by invoking the help function
start now the GNU debugger with octave by following the instructions above.


<syntaxhighlight lang="octave">
Now you can set a breakpoint in the line of interest of your oct-file in gdb prompt:
octave:1> help file
</syntaxhighlight>
 
Now halt execution of Octave by typing ctrl+c, you'll see again the gdb prompt. Set now a breakpoint in the line of interest


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 47: Line 61:


<syntaxhighlight lang="octave">
<syntaxhighlight lang="octave">
octave:1> x = file(y)
octave> x = file(y)
</syntaxhighlight>  
</syntaxhighlight>  


the debugger will stop on the above defined line and you can start debugging according to the manual of GNU debugger.
the debugger will stop on the above defined line and you can start debugging according to the manual of GNU debugger.


If you encounter problem with interrupting octave (i.e. "^C" is only
== Producing a stack trace ==
printed when you press ctrl+c and control is not transferred to gdb)
 
then you might follow following steps (which should work always).
Sometimes Octave might crash, meaning, it terminates abruptly and returns control to the operating system shell. In these cases, it is very helpful to produce a stack trace to diagnose the problem. For this, it can be useful to (re)compile Octave with debugging symbols. Otherwise, the stack trace can be harder to read and optimizations might make debugging more difficult. (But it is also possible to produce a stack trace with a "standard" build.)
# Start gdb<br/><syntaxhighlight lang="bash">> gdb octave</syntaxhighlight>
 
# Catch loading of your oct-file ("file" below is a regex matching name of your oct-file)<br/><syntaxhighlight lang="bash">(gdb) catch load file</syntaxhighlight>
Attach <code>gdb</code> to Octave as described before and return execution to Octave. Then, execute whatever commands are necessary to cause Octave to crash. At that point, you will be back in the gdb session. Type <code>where</code> or <code>bt</code> at the gdb prompt to obtain a stack trace.
# Run octave<br/><syntaxhighlight lang="bash">(gdb) r</syntaxhighlight>
 
# From octave request loading of your oct-file by calling function<br/><syntaxhighlight lang="octave">octave> x = file(y)</syntaxhighlight>
When running in GUI mode or debugging threading issues, it is usually useful to get information about all the execution threads at the point of the crash.  To do that, use the gdb command <code>thread apply all bt</code>.
# Control will switch to gdb just after oct-file is loaded and at this point all symbols from oct-file are available so you can either set up a breakpoint at particular line or at function entry.<br/><syntaxhighlight lang="bash">(gdb) b file.cpp:40</syntaxhighlight>
# Resume execution of octave by<br/><syntaxhighlight lang="bash">(gdb) c</syntaxhighlight>
and debugger will stop at the breakpoint defined.


= Tools for debugging =
You could also get some help from your system tools. In most GNU/Linux systems whenever a crash happens in a software, a <i>core dump</i> will be generated. These core dumps are handled by a registered component of the system and finally might be stored somewhere in the directory tree. You should find them, view them and inspect them.
== GBD ==
To start Octave under gdb use the script <code> run-octave </code> at the top level of the source tree and run it with the command-line option <code> -g </code>like this


    cd /octave/build/tree
=== Where are core dumps stored? ===
    ./run-octave -g


== Producing a stack trace ==
It differs on each system. First you should see how core dumps are handled on your system. To do so, type this in a shell terminal:
<syntaxhighlight lang="bash">
$ cat /proc/sys/kernel/core_pattern
</syntaxhighlight>
This may print a file name pattern along with a path where all core dumps will be saved <b>ONLY</b> if it does not start by a pipe or '|'. If it does, <i>the kernel will treat the rest of the pattern as a command to run.  The core dump will be written to the standard input of that program instead of to a file</i>, and you need to consult that program's help or manual.


Sometimes Octave will crash, meaning, it terminates abruptly and returns control to the operating system shell. In these cases, it is very helpful to produce a stack trace to reproduce the problem. To do so, you need to (re)compile Octave with debugging symbols as explained above and run the debugger, as explained above. Then, run Octave:
=== How to view a core dump? ===


To do this you should use gdb. Core dumps are saved under root user, so you may need to change owner of the core dump you are interested in if you are not logged in as root. After that type in the terminal:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
gdb> run
gdb octave -c <Path to core dump>
</syntaxhighlight>
</syntaxhighlight>


execute whatever commands you think are necessary to produce the crash. When Octave crashes, you will be back in a gdb session. Type <code>bt</code> here to obtain a stack trace.
Always expect some warnings from gdb in a few first times of doing this. Most likely gdb will tell you that:


=== Most used commands ===
1. The core dump file is not in the correct format. It is the case if the core dump handler of your system compresses core dumps before storing them, and you need to decompress the core dump first.
[http://www.gnu.org/software/gdb/documentation gdb documentation]
 
2. Core dump was generated by a-path-to/octave-gui. Then quit gdb and start it again by:
<syntaxhighlight lang="bash">
gdb octave-gui -c <Path to core dump>
</syntaxhighlight>


== Emacs ==
3. Some debug info are missing. In this case gdb itself will tell you how to install them. Install them and start gdb again.


In short:
If everything worked fine, you can use <code>where</code> command in gdb prompt to see a full stack trace of the crash.


To start Octave in debug mode within emacs type
=== Helpful gdb commands ===


<code>
[http://www.gnu.org/software/gdb/documentation gdb documentation]
M-x gud-gdb
<code>


then change the command in the minibuffer to
The following command shows the back trace of all threads belonging to the Octave process:
<syntaxhighlight lang="bash">
(gdb) thread apply all bt
</syntaxhighlight>


<code>
For debugging octave_value variables (e.g. <code>my_octave_value</code>) to find out what the variable actually is (instead of just it's base class):
Run gud-gdb (like this): /path/to/octave/build/tree/run-octave -gud
<syntaxhighlight lang="bash">
</code>
(gdb) print *(my_octave_value.rep)
</syntaxhighlight>


For more info use this
The file <code>etc/gdbinit</code> in the Octave repository contains some macros that can be helpful:
[http://www.gnu.org/software/emacs/manual/html_node/emacs/Debuggers.html#Debuggers link]
* <code>display-dims DIM_VECTOR</code>: Display the contents of an Octave dimension vector.
to the emacs manual section on debuggers operation
* <code>display-dense-array ARRAY</code>: Display the contents of an ordinary, i.e., dense Octave array.
* <code>display-sparse-array SPARSE_ARRAY</code>: Display the contents of a sparse Octave array.
* <code>show-octave-dbstack</code>: Display the contents of the current Octave debugging stack.


== ddd ==
== ddd ==
[http://www.gnu.org/software/ddd gui for gdb]
 
[http://www.gnu.org/software/ddd GUI for gdb]


[[Category:Development]]
[[Category:Development]]

Latest revision as of 15:25, 22 December 2022

Preliminaries[edit]

Since compilation of all the source from scratch can take long it is good to have a source folder where most of the source has been compiled. To do this, you can create a parallel build:

mkdir dbg-octave
cd dbg-octave
/path/to/octave/source/configure FFLAGS=-g CFLAGS=-g CXXFLAGS=-g --enable-address-sanitizer-flags --prefix=/opt/dbg-octave
make # or make -jN where N is the number of CPU cores

This will create a new build of Octave in a different directory without optimizations (no -O2 gcc parameter) and with debug symbols compiled in. This build is useful for debugging Octave itself.

Tools for debugging[edit]

There are different tools for debugging. This article concentrates on describing how to use gdb.

If you run Octave from a build tree, execute ./run-octave -g to start a gdb session that is prepared to run Octave (with the necessary environment correctly set up). Note that when Octave runs in GUI mode, it forks at startup on Linux and MacOS systems, so this method will only work if gdb correctly follows the process across the fork and exec system calls.

Alternatively, you can attach a debugger to a running Octave session. Current versions of Octave include the command __debug_octave__ to manage the details. Executing this command at the Octave prompt should open a separate window for a debugger session attached to the current Octave process. On Linux systems, the default terminal window is gnome-terminal. On MacOS systems, the default debugger is lldb.

For some kinds of errors on some OS, the last approach might not be useful. The OS might kill the shell that runs gdb as soon as the spawning process (i.e. Octave) crashes. In that case, you can attach to Octave from an "independent" shell. Execute getpid () in Octave and take note of the displayed *PID*. Open a shell and execute gdb -p *PID* (replace *PID* with the actual PID). On Windows, use the msys2 shell that can be started with the file cmdshell.bat in Octave's installation folder.

Independent of how gdb was started and Octave was attached to it, it is now possible to issue gdb commands on the (gdb) prompt. See e.g. the gdb documentation. To return to Octave while gdb is still attached to it, execute continue (or c) at the (gdb) prompt.

  • NOTE: Ubuntu introduced a patch to disallow ptracing of non-child processes by non-root users - i.e. only a process which is a parent of another process can ptrace it for normal users - whilst root can still ptrace every process.

That's why gdb won't be able to link to the octave process if you start gdb from within an Octave session using the __debug_octave__ command.

You can temporarily disable this restriction by doing:

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

and then reopen gdb using the command mentioned above from within an Octave session or if you have admin rights you can simply do:

__debug_octave__ ("gnome-terminal --command 'sudo gdb -p %d'")

Debugging oct-files[edit]

To debug oct-files, avoid making any optimization during compilation. Use export CXXFLAGS="-ggdb -Wall -O0" for C++ code or export CFLAGS="-ggdb -Wall -O0" for C code to suppress optimization. Compile the oct-file with the debug flag -g which enables debug symbols

mkoctfile -g file.cpp

In next step you will use GNU debugger or gdb. The symbols from your oct-file will only be available to gdb once the oct-file is loaded in Octave. To do that without executing any functions from the oct-file, you can ask Octave to display the help for the oct-file:

octave> help file

start now the GNU debugger with octave by following the instructions above.

Now you can set a breakpoint in the line of interest of your oct-file in gdb prompt:

(gdb) b file.cpp:40

by typing c the execution of octave will continue and you can run your oct-file directly or via an m-script.

octave> x = file(y)

the debugger will stop on the above defined line and you can start debugging according to the manual of GNU debugger.

Producing a stack trace[edit]

Sometimes Octave might crash, meaning, it terminates abruptly and returns control to the operating system shell. In these cases, it is very helpful to produce a stack trace to diagnose the problem. For this, it can be useful to (re)compile Octave with debugging symbols. Otherwise, the stack trace can be harder to read and optimizations might make debugging more difficult. (But it is also possible to produce a stack trace with a "standard" build.)

Attach gdb to Octave as described before and return execution to Octave. Then, execute whatever commands are necessary to cause Octave to crash. At that point, you will be back in the gdb session. Type where or bt at the gdb prompt to obtain a stack trace.

When running in GUI mode or debugging threading issues, it is usually useful to get information about all the execution threads at the point of the crash. To do that, use the gdb command thread apply all bt.

You could also get some help from your system tools. In most GNU/Linux systems whenever a crash happens in a software, a core dump will be generated. These core dumps are handled by a registered component of the system and finally might be stored somewhere in the directory tree. You should find them, view them and inspect them.

Where are core dumps stored?[edit]

It differs on each system. First you should see how core dumps are handled on your system. To do so, type this in a shell terminal:

$ cat /proc/sys/kernel/core_pattern

This may print a file name pattern along with a path where all core dumps will be saved ONLY if it does not start by a pipe or '|'. If it does, the kernel will treat the rest of the pattern as a command to run. The core dump will be written to the standard input of that program instead of to a file, and you need to consult that program's help or manual.

How to view a core dump?[edit]

To do this you should use gdb. Core dumps are saved under root user, so you may need to change owner of the core dump you are interested in if you are not logged in as root. After that type in the terminal:

gdb octave -c <Path to core dump>

Always expect some warnings from gdb in a few first times of doing this. Most likely gdb will tell you that:

1. The core dump file is not in the correct format. It is the case if the core dump handler of your system compresses core dumps before storing them, and you need to decompress the core dump first.

2. Core dump was generated by a-path-to/octave-gui. Then quit gdb and start it again by:

gdb octave-gui -c <Path to core dump>

3. Some debug info are missing. In this case gdb itself will tell you how to install them. Install them and start gdb again.

If everything worked fine, you can use where command in gdb prompt to see a full stack trace of the crash.

Helpful gdb commands[edit]

gdb documentation

The following command shows the back trace of all threads belonging to the Octave process:

(gdb) thread apply all bt

For debugging octave_value variables (e.g. my_octave_value) to find out what the variable actually is (instead of just it's base class):

(gdb) print *(my_octave_value.rep)

The file etc/gdbinit in the Octave repository contains some macros that can be helpful:

  • display-dims DIM_VECTOR: Display the contents of an Octave dimension vector.
  • display-dense-array ARRAY: Display the contents of an ordinary, i.e., dense Octave array.
  • display-sparse-array SPARSE_ARRAY: Display the contents of a sparse Octave array.
  • show-octave-dbstack: Display the contents of the current Octave debugging stack.

ddd[edit]

GUI for gdb