This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!

This article explains some advanced uses of GDB. Debugging is an important skill in your development career, and GDB is the most commonly used debugging tool for Linux development, so here are some advanced uses of GDB to help you with your debugging skills.

Let’s take a look at the mind map:

1. How to debug multithreading in GDB

When GDB debugs multiple threads, by default all threads are executing at the same time, but what if we want only one thread to continue executing while the others are suspended? Let’s take a look at how to do this.

Here is the multithreaded code:

//test.cpp
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *print1_msg(void *arg)
{
	while(1)
	{
		printf("print1_msg\n");
		usleep(100); }}void *print2_msg(void *arg)
{
	while(1)
	{
		printf("print2_msg\n");
		usleep(100); }}int main(a)
{
    pthread_t id1, id2;
    pthread_create(&id1, NULL, print1_msg, NULL);
    pthread_create(&id2, NULL, print2_msg, NULL);
    pthread_join(id1, NULL);  // Cause the main thread to wait until this thread finishes, otherwise the main thread will finish quickly and the thread will not have a chance to execute
    pthread_join(id2, NULL);

    return 0;
}
Copy the code

Suppose we have a problem on the line and then want the program to only execute the thread function print1_msg, but not modify the code?

G ++ -g test. CPP -l pthread -o test = GDB./test = GDB.

(GDB) b test.cpp:28 #b 是break, Breakpoint 1 at 0x40074e: File test. CPP, line 28. (GDB) r #r /root/test [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x40a00940 (LWP 26623)] print1_msg [New Thread 0x41401940 (LWP 26624)] Thread 1 hit Breakpoint 1, main () at test.cpp:28 28 pthread_join(id1, NULL); (GDB) info thread # Display all threads in the current process, Target Id Frame * 1 Thread 0x2AAAAAE794D0 (LWP 26619) main () at test.cpp:28 2 Thread 0x40A00940 (LWP 26623) 0x00000036f289a901 in nanosleep () from /lib64/libc.so.6 3 Thread 0x41401940 (LWP 26624) 0x00000036f28d4971 in Clone () from /lib64/libc.so.6 (GDB) thread 2 [Switching to thread 2 (thread 0x40a00940 (LWP 26623))]#0  0x00000036f289a901 in nanosleep () from /lib64/libc.so.6(GDB) c Continuing. Print1_msg print1_msg print1_msg print1_msgCopy the code

After this, only the first thread is executed. If you run the GDB command set scheduler-locking off, all threads will continue to execute.

Here are some of the more common GDB commands used in multithreaded debugging:

GDB commands Function of command
info thread Display all threads of the current process, the first column represents the thread number, the first thread is the process itself, the serial number preceded by * is the thread currently executing
thread id The ID is the thread id. For example, thread 2 is the entry of thread 2
set scheduler-locking on After this command is set, only the current thread is executed. Other threads are locked and paused
set scheduler-locking off No thread is locked. After this command is set, all threads are executed. This is the default value of GDB
set scheduler-locking step In this mode, the continue, finish, and until commands cannot be executed. Once the commands are executed, all other threads are woken up
show scheduler-locking The current scheduler-locking status is displayed
thread apply 1 2 command Let threads 1 and 2 execute a GDB command where command is a GDB command, such as thread apply 1 2 info local, and let threads 1 and 2 print out all local variables
thread apply all command Command is a GDB command that tells all threads to execute a GDB command

2. How to debug multiple processes in GDB

Two properties are most commonly used by GDB to debug multiple processes: Follow the fork – mode and detach – on – fork, respectively, using the set follow – fork – mode parent child and set | detach – on – fork on | off this form to set up, in general, These two commands work together. Here’s how they work:

follow-fork-mode detach-on-fork instructions
parent on This scenario is the default GDB scenario, which indicates that GDB only debugs the parent process. The interruption point and other functions only on the parent process, and the child process continues to run. In this case, GDB does not control the child process
parent off In this scenario, GDB controls both the parent process and the child process. The parent process can be debugged, but the child process is suspended by GDB and does not continue to execute
child on In this scenario, GDB only controls the child process. All GDB commands are used only for the child process, and the parent process continues to run
child off In this scenario, GDB controls both the parent and child processes. The child processes can be debugged, but the parent process is suspended by GDB and does not continue to execute

There are other commands for debugging multiple processes, such as:

GDB commands Role that
show follow-fork-mode The follow-fork-mode status is displayed
show detach-on-fork The detach-on-fork status is displayed
info inferiors Example Query the current debuggable GDB processes
inferior Switch debugging processes. Infer number is the sequence number of the process displayed by the info inferiors command

Let’s use the following example to illustrate the use of the above command:

//test.cpp
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(a)
{
	if ( fork() > 0)
	{
		while(1)
		{
			printf("this is parent\n");
			sleep(1); }}else
	{
		while(1)
		{
			printf("this is son\n");
			sleep(1); }}return 0;
}
Copy the code

I’m not going to be able to do this in real life, but I’m just going to do it to keep things out of the way, so I’m going to make it very simple.

Let’s use GDB to debug this code using the following basic command:

(gdb) show follow-fork-mode
Debugger response to a program call of fork or vfork is "parent".
(gdb) show detach-on-fork
Whether gdb will detach the child of a fork is on.
Copy the code

Print the default values for both Settings. This is the same as in the GDB default scenario, where we set breakpoints on the parent and child code, and then run them.

(gdb) b test.cpp:11
Breakpoint 1 at 0x40064e: file test.cpp, line 11.
(gdb) b test.cpp:19
Breakpoint 2 at 0x400664: file test.cpp, line 19.
(gdb) r
Starting program: /root/test 
this is son

Breakpoint 1, main () at test.cpp:11
11				printf("this is parent\n");
(gdb) this is son
this is son
this is son
this is son
Copy the code

You can see that only the parent’s breakpoint is hit, but the child continues to run.

Then, assuming THAT I only want to debug the child process and don’t want the parent process to continue running, the GDB command is:

(gdb) set follow-fork-mode child (gdb) set detach-on-fork off (gdb) b test.cpp:11 Breakpoint 1 at 0x40064e: file test.cpp, line 11. (gdb) b test.cpp:19 Breakpoint 2 at 0x400664: file test.cpp, line 19. (gdb) r Starting program: /root/test [New process 29409] Reading symbols from /root/test... done. Reading symbols from /usr/lib64/libstdc++.so.6... Done. [Switching to process 29409] Thread 2.1 hit Breakpoint 2, main () at test.cpp:19 19 printf("this is son\n"); (GDB) c Continuing. This is son Thread 2.1 hit Breakpoint 2, main () at test.cpp:19 19 printf("this is son\n"); (GDB) c Continuing. This is son Thread 2.1 hit Breakpoint 2, main () at test.cpp:19 19 printf("this is son\n");Copy the code

At this point, both the parent and child processes are controlled by GDB, and only the child process will hit the breakpoint. The parent process is suspended, so neither the breakpoint is hit nor execution continues.

3. How can GDB debug a running process

There are many scenarios in which we need to debug a running process. There are two ways to do this:

  • GDB PID or GDB -p PID. Program is the process name and PID is the process id in the operating system. Run the ps command to view the process id.
  • After GDB, attach PID can also play the same role in GDB mode, that is, attach a process to GDB.

If you do not want to continue debugging, run the detach command in GDB mode to cancel the GDB mounted process.

To illustrate this, consider the following code:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(a)
{
	int i = 0;
	while(1)
	{
		i++;
		sleep(1);
	}
	return 0;
}
Copy the code

The process ID is 29549, and the process ID is 29549. The process ID is 29549. The process ID is 29549, and the process ID is 29549.

(gdb) b test.cpp:10
Breakpoint 1 at 0x4005bb: file test.cpp, line 10.
(gdb) c
Continuing.

Breakpoint 1, main () at test.cpp:10
10			i++;
(gdb) p i
$1 = 165,
Copy the code

4. How can GDB debug generated core files

For example, if you use the ulimit command on Linux, you can use the ulimit -c command. If you do not use the ulimit -c command, you can use the ulimit -c command. If you do not use the ulimit -c command, you can use the ulimit -c command. Use ulimit -c unlimited to set the ulimit command.

My machine has now turned on the core file generation switch, so I now have the following code:

#include <stdio.h>

int main(a)
{
	char *str = NULL;
	printf("%s\n", str);
	return 0;
}
Copy the code

Then, sure enough, the output error (core dumped) such a statement, visible is to produce the core file, here I called core. The core file 29626, GDB core.29626 = GDB core.29626

(gdb) bt
#0  0x00000036f2879ba0 in strlen () from /lib64/libc.so.6
#1  0x00000036f28631cb in puts () from /lib64/libc.so.6
#2  0x00000000004005c8 in main () at test.cpp:6
Copy the code

Use the BT command to check the error in the end is which function, which line of code.

How can GDB view the details of class objects in c++

Suppose you have c++ code like this:

class CPeople
{
public:
	int age;
public:
	virtual void print(a){}};class CBigPeople : public CPeople
{
public:
	int height;
};

int main(a)
{
	CPeople *people = new CBigPeople;
	delete people;
	return 0;
}
Copy the code

We use GDB to see what type people points to, as follows:

(gdb) p *people
$2 = {_vptr.CPeople = 0x4008b0 <vtable for CBigPeople+16>, age = 0}
Copy the code

Obviously GDB does not display the true type by default, so let’s turn on a switch like this:

(gdb) set print object on
(gdb) p *people
$3 = (CBigPeople) {<CPeople> = {_vptr.CPeople = 0x4008b0 <vtable for CBigPeople+16>, age = 0}, height = 0}
Copy the code

If the type is simple, this is fine. If the type is complex, this is very ugly. So we can make GDB show the tree structure, as follows:

(gdb) set print pretty on
(gdb) p *people
$5 = (CBigPeople) {
  <CPeople> = {
    _vptr.CPeople = 0x4008c0 <vtable for CBigPeople+16>, 
    age = 0
  }, 
  members of CBigPeople: 
  height = 0
}
Copy the code

6. Summary

It’s a very powerful command to debug GDB in Linux. If you look at it carefully, you’ll find that GDB can do almost anything you can think of. Meanwhile, make good use of GDB’s help command, which prints out all the GDB commands and their functions. You can print a single command or a class of commands, such as:

(GDB) help shell (GDB) help shell (GDB) Execute the rest of the line as a shell command. With no arguments Generic Command for showing things about the program being run an inferior shell. (GDB) help info debugged. List of info subcommands: info address -- Describe where symbol SYM is stored info all-registers -- List of all registers and their contents info args -- Argument variables of current stack frame info auto-load -- Print current status of auto-loaded files info auxv -- Display the inferior's auxiliary vector info bookmarks -- Status of user-settable bookmarks info breakpoints -- Status of specified breakpoints (all user-settable breakpoints if no argument) info checkpoints -- IDs of currently known checkpoints info classes -- All Objective-C classes info common -- Print out the values contained in a Fortran COMMON block info copying -- Conditions for redistributing copies of GDB info dcache -- Print information on the dcache performance info display -- Expressions to display when program stops ...... # Space is limited, so it is omittedCopy the code

Well, this article for you to introduce here, feel content useful to you, remember to click a like oh ~