GDB installation 【 source code compile GDB 】

  1. Download the source code

    Address: ftp.gnu.org/gnu/gdb

    Download the GDB source package

    Download the wget

    Web site:

    Ftp.gnu.org/gnu/gdb/gdb…

    Decompress: tar -zxvf gdb-8.0.1.tar.gz/

  2. configuration

    Find configure in the unzip directory and execute./configure

    Waiting for the configuration to complete

  3. Make && make install Wait

  4. View: GDB -v. Check whether it is successful.

** II. GDB basic debugging

(I) GDB debugging started

1. Start core to collect the state of program crash

First you follow me to enable core crash state collection, which can be viewed through ulimit -c. If the value is 0, it is not enabled.

After opening, perform the following operations:

su root vi /etc/profileShift + Gi# No core files by default 0, unlimited is ooulimit -S -c unlimited > /dev/null 2>&1wq! source /etc/profile
Copy the code

The shell operation above is added in the last line of /etc/profile. It is set to enable debugging of core file globally. The size is unlimited.

Follow my lead, because the core file with the same name will be overwritten. Add a core naming convention to make it [core.pid].

su root vi /etc/sysctl.confShift + Gi # open, add core.pid kernel.core_pattern = ./core_%t_%p_%ekernel.core_uses_pid = 1 wq! sysctl -p /etc/sysctl.conf
Copy the code

Add system configuration to /etc/sysctl.conf file and enable it immediately.

Kernel. core_pattern mode parameters:

%% A single % character

%p Indicates the process ID of the dump process

%u Indicates the actual user ID of the dump process

%g The actual group ID of the dump process

%s causes the core dump signal

%t Time of core dump (seconds from 1 January 1970)

% h host name

%e File name of the program

2, simple contact with GDB, start debugging r n P:

The first demo code is monkey.c

#include <stdio.h> int g_var = 0; static int _add(int a, int b) { printf("_add callad, a:%d, b:%d\n", a, b); return a+b; } int main(void) { int n = 1; printf("one n=%d, g_var=%d\n", n, g_var); ++n; --n; g_var += 20; g_var -= 10; n = _add(1, g_var); printf("two n=%d, g_var=%d\n", n, g_var); return 0; }Copy the code

GCC -g-wall -o monkey.out monkey.c

The first command, GDB monk. out, indicates that GDB loads monk. out to start debugging. If you want to debug using GDB, you need to add -g to GCC when compiling.

The L command indicates: View the loaded source code content.

Here’s how to add a breakpoint:

R indicates that the debugged program is running.

P command indicates print value, n indicates process debugging, go to the next step; No tube process how do not enter, directly a skip.

The s used above represents single step debugging. When encountering a sub-function, it will enter the internal debugging of the function.

To sum up:

L looks at the source, BR adds a breakpoint, R starts debugging, N goes next, S goes next but goes into subfunctions, p outputs data.

Here, GDB basic can use, is it also very easy, straightforward? Small code can be debugged at will.

Seeing that, the basics are over, so let’s talk about it.

(2) other commands used in GDB development

Compile command:

gcc -g -Wall monkey.c -o monkey.out
Copy the code

1, GDB other common command usage c q b info

Let’s start with the debug file king.c

#include <stdio.h>#include <stdlib.h>#include <time.h> /* * arr can only be array */#define LEN(arr) (sizeof(arr)/sizeof(*arr)) static void _parrs(int a[], int len) {int I = -1; Puts (" Current array content values are as follows :"); while(++i < len) printf("%d ", a[i]); putchar('\n'); } #define PARRS(arr) \ _parrs(arr, LEN(arr)) #define _INT_OLD (23) */int main(void) {int I; int a[_INT_OLD]; int* ptr = NULL; Srand ((unsigned)time(NULL)); for(i=0; i<LEN(a); ++i) a[i] = rand()%222; PARRS(a); // double for(I =1; i<=LEN(a); ++i) a[i] <<= 1; PARRS(a); PTR = 0; return 0; }Copy the code

In King.c we start debugging. A runtime error occurred in our core.pid file

Start debugging through GDB core.18605.king.out, and immediately locate the cause of the error.

2. Debug memory stack information

In the _add function, a is the address of a parameter group.

See info args to view current function parameter values.

Info locals views the value information on the function stack. Info Registers indicates the value of a register.

Then check the memory information.

You need to remember more. Look at the picture first:

X /23dw a means: view 23 4-byte, signed decimal numbers from address A, output.

For more details on x, see the following steps:

View memory format with GDB:

x /nfu ptr

Description:

X is short for examine

N indicates the number of memory units to be displayed

F indicates the display mode. The value can be

X displays variables in hexadecimal format

D Displays variables in decimal format

U Displays an unsigned integer in decimal format

O Displays variables in octal format

T Displays variables in binary format

A Displays variables in hexadecimal format

I instruction address format

C Displays variables in character format

F Displays variables in floating-point format

U represents the length of an address unit

B represents a single byte

H stands for double bytes

W stands for four bytes

G stands for eight bytes

Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),

t(binary), f(float), a(address), i(instruction), c(char) and s(string).

Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes)

PTR means start at that address

This command is often used to monitor memory changes, especially during debugging.

3. GDB sets conditional breakpoints

Simple: **b 17 if I == 8. ** sets a breakpoint at line 17 and only fires if I ==8.

GDB deletes breakpoints

GDB deletes d followed by breakpoint indexes 1,2,3

Clear line number or name, which line breakpoint to delete, see the following demonstration:

At this point, the GDB debugging tips are basically enough. Feel using a graphical IDE, such as VS debugging, is also useful.

Three, GDB advanced debugging – debugging multithreading

First look at the test case FightSaintBuddha.c

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <sys/syscall.h>#include <sys/types.h> #define MAX_NUM 1000// thread callbackstatic void* _run(void* arg) { int piyo = 10; char* name = (char*)arg; int i; for(i = 0; i < MAX_NUM; ++i) { printf("[thread %u]: <%d, hi! > from %s\n", syscall(SYS_gettid), i, name); sleep(1); } return NULL; }#define _INT_PTX (3)char* thread_name[] = {"A", "B", "C", "D", "E", "F", "G", "H"}; int main(void) { int i; pthread_t tx[_INT_PTX]; puts("main beign"); printf("main thread id :%u\n",/*syscall(SYS_gettid)*/getpid()); for(i=0; i<_INT_PTX; ++i) { //create threads rt = pthread_create(tx+i, NULL, _run, thread_name[i]); if(rt < 0) { printf("pthread_create create error! rt = %d, i=%d\n", rt, i); break; } } for(i=0; i<_INT_PTX; ++i) { pthread_join(tx[i], NULL); } puts("end"); return 0; }Copy the code

Compile command

gcc -Wall -g -o FightingSaintBuddha.out FightingSaintBuddha.c -lpthread
Copy the code

Take a look at the chart below:

Info Threads looks at all running threads. * indicates the thread being debugged.

After that, l _run means look at the code around _run. And, of course, l 16 look at the contents of the file near line 16.

GDB multithreading switch, the tests are as follows:

Info Threads the id of the first column is the ID of the thread to be switched.

We use the following command to make only the threads to be debugged run and the other threads block.

Set Scheduler-locking on Starts multi-threaded debugging alone.

If no, set scheduler-locking off to disable the scheduler-locking off function. It’s going to go back to the one you’re debugging, and the other thread is not blocking.

GDB multithreaded debugging, commonly used is the following three practical commands:

info threads

thread id

set scheduler-locking on/off

They are: View, switch, and set synchronous debugging. Here, multithreading debugging is basically finished.