= *Experimental and Advanced Debugging Techniques*

=== Set a variable value

To set or change the value of a variable in a program in current GDB session
we can use command `(gdb)set var <variable>=<value>`.

This can help us to see the behavior of the program under different circumstances and this feature avoid the need to do the explicit changes to the source code and compile it again.


=== Reverse Debugging

To go back to the previous instruction and revert the execution of
current instruction w.r.t the source code, we can achieve this in GDB
using on command `(gdb)target record-full`. This will record the
execution of the commands and the changes in program from the instance
when the above command was executed.

This is helpful when we want to inspect something which has already happened in program execution. Due to this, we don't have to rerun the execution of the program under inspection from the start.

We can go to the previous instruction using 

`(gdb)reverse-next`

command.

=== Debugging Multithreaded programs

We can use GDB to debug multi-threaded program as well.

In GDB, as the new thread are generated in program the output in GDB is somewhat look as shown below:
[source,]
----
Temporary breakpoint 2, main () at thread.cpp:26
26      int main() {
(gdb) n
34          std::vector< std::thread > threads;
(gdb) n
35          for( int i = 0 ; i < 10 ; i++ ) {
(gdb) n
36              threads.push_back( std::thread( lamda, i ) );
(gdb) n
[New Thread 0x7ffff77ff6c0 (LWP 16236)]
Hello from thread!140737345746624
Argument passed in: 0
35          for( int i = 0 ; i < 10 ; i++ ) {
(gdb) n
36              threads.push_back( std::thread( lamda, i ) );
(gdb) n
[New Thread 0x7ffff6ffe6c0 (LWP 16243)]
Hello from thread!140737337353920
Argument passed in: 1
35          for( int i = 0 ; i < 10 ; i++ ) {
(gdb) n
36              threads.push_back( std::thread( lamda, i ) );
(gdb) n
[Thread 0x7ffff77ff6c0 (LWP 16236) exited]
[New Thread 0x7ffff67fd6c0 (LWP 16256)]
Hello from thread!140737328961216
Argument passed in: 2
35          for( int i = 0 ; i < 10 ; i++ ) {
(gdb) info threads
  Id   Target Id                                   Frame
* 1    Thread 0x7ffff7e9a740 (LWP 16198) "threads" main () at thread.cpp:35
  3    Thread 0x7ffff6ffe6c0 (LWP 16243) "threads" 0x00007ffff78ecadf in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0,
    req=0x7ffff6ffdd60, rem=0x7ffff6ffdd60) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
  4    Thread 0x7ffff67fd6c0 (LWP 16256) "threads" 0x00007ffff78ecadf in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0,
    req=0x7ffff67fcd60, rem=0x7ffff67fcd60) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
(gdb)
----
[NOTE]
====
1. To toogle between TUI mode and cmd mode, use `CTRL+x a`
2. Command to disable tui `tui disable`.
3. Command to enable tui `tui enable`.
====



To view the current thread that are in execution, use command `info threads`.

To switch to particular thread execution in GDB use command `thread <thread-number>`


*Locking the current thread*

Although we can change the current state of execution in GDB to a particular thread execution, however, the spawning of new thread can disrupt our focus from the current thread in GDB.

To avoid such case, we can use the below command:

`set scheduler-locking on`

This allow us to work on the current thread of interest.

Note that this prevent the program from new thread as our current execution pointer is in the thread, instead of the parent thread which is spawning new child threads.

For this we need to switch of the scheduler-locking using command:

`set scheduler-locking off`

And move our current execution pointer to the parent thread which spawning the new thread.


*See all the threads*

To watch every thread instance (by watch we mean the current state), we can use the command:

`thread apply all <command>`

For example, `<command>` here can be `bt` to see the backtrace of all the threads.


=== Bookmarks and checkpoints (Save a snapshot of your program)

Sometimes we might want to save a point the execution of the program at certain point and later we might want to return to that same exact point.

This feat can using the command called `checkpoint`

Use this command when you are on the line where you want to create the checkpoint in the program.

*What does this command do?*

This command internally in GDB, fork the process and save a snapshot of the whole process where the line where the checkpoint command got executed is also saved with the forked process and saved in GDB.

To check the active checkpoints, use command:

`info checkpoint`

*Loading the checkpoint*

Before the termination of current program under execution, we can go the checkpoint using below command:

`restart <checkpoint-index>`

Once the execution of the checkpoint loaded is finished, it is deleted from the GDB.