GDB basic ZT

Source: Internet
Author: User
You can use GDB to debug the local executable files (that is, not Java * or Perl. GDB can be used for source code-level debugging, as well as tracking programs without source code or checking the core files left by a terminated program. Unfortunately, it may be difficult to use it when you have never used it or have not used it for a while. Figure 1 shows each command required for debugging using GDB.

Command description
File Load Program
B set breakpoint
R run
C continue
S step (line)
Si step (machine instruction)
N next (step over function call)
Finish run until function returns
I r show all registers
I r show specific register
L list source
P display value
Set ARGs set command line arguments

Figure 1

To use GDB as a source code-level debugger, make sure to compile the program when debugging symbols are included. This is the-G option of GCC. To start GDB, you can enter GDB programname (in this example, GDB simple), or run GDB itself and use the file command to load executable files.

To set a basic breakpoint, You can interrupt a function name or a row number. For example, B 27 sets a breakpoint on Row 27th of the current file. There are two ways to use the function name: B Main is interrupted in the first line of executable code in the function main, B * main sets a breakpoint on the main entry address (this is useful if you plan to debug each instruction of the function in one step ).

Once the first breakpoint is set, run or R can be used to start the program and run to the first breakpoint. You can run the program without any breakpoint. It is helpful if you do not know where the program crashed. When you hit a breakpoint C or continue, the program resumes execution until it hits the next breakpoint.

Step: Debug source code lines in one step. Step instruction (SI) One-Step debugging of machine code lines (SI commands may be particularly useful when you debug optimized code in one step, which will be described later ). Next works like a step, but it does not trace the function call. (If it does mistakenly track the function call, you can use finish to complete the function, and then interrupt in the place it returns ).

The independent info register (I r) itself displays the values of all registers (except floating point values), but you can specify a register name. On a 31-bit system, General registers are named as upl0, GPRS 1, and GPRS 2. on 64-bit systems, General registers are named as r0, R1, R2, and so on. Floating-point registers follow the same naming conventions: fpr0, fpr1, and fpr2 on 31-bit systems; F0, F1, and F2 on 64-bit systems.

"L" lists the source code around the current stop position of the program. You can also specify the row number or function name to start listing the code. Print allows you to print the value of any variable in the program. One of the best advantages of print is that it will retrieve all values in a structure for you, or allow you to directly reference a part of this structure:

Breakpoint 1, main () at simple. C: 30
30 boink. boik = & R1;
(GDB) print boink
$3 = {boik = 0x0}
(GDB) print boink. boik
$4 = (int *) 0x0

Finally, set ARGs to set command line parameters for the program. You can also specify the command line parameter when executing run, but set ARGs will make the parameter valid for multiple run operations.

GDB post mortem

When the program terminates unexpectedly, the kernel will try to generate a core file to determine what went wrong. However, core files are not usually generated under the default value. This can be changed using the ulimit command. Ulimit-C unlimited helps ensure that you obtain the complete core file of the application.

Although the core file currently only provides a limited value in multi-threaded applications, the development kernel of Version 2.5 has begun to handle this problem. It is expected that some ideal thread improvements will be provided in the 2.6 kernel.

Command description
File Load Program
Core load Core File
BT back trace
Where same as back trace
I f frame information
Up move up stack
Down move down stack
Frame jump to frame
Disassem display function's machine code
I locals display local variable values

Figure 2

Figure 2 highlights a series of convenient post mortem commands.

(GDB) file simple
Reading symbols from simple... done.
(GDB) core
Core was generated by './simple '.
Program terminated with signal 11, segmentation fault.
Reading symbols from/lib/libc. so.6...... done.
Loaded symbols for/lib/libc. so.6
Reading symbols from/lib/lD. so.1. .. Done.
Loaded symbols for/lib/lD. so.1
#0 0x400ab738 in memcpy () from/lib/libc. so.6
(GDB) Where
#0 0x400ab738 in memcpy () from/lib/libc. so.6
#1 0x40066e in main () at simple. C: 34
#2 0x40041eb8 in _ libc_start_main () from/lib/libc. so.6
#3 0x4004ac in _ start ()
(GDB) I f
Stack level 0, frame at 0x7ffff7a0:
Pswa = 0x400ab738 in memcpy; saved pswa 0x0
(Frameless), called by frame at 0x7ffff7a0
Arglist at 0x7ffff7a0, argS:
Locals at 0x7ffff7a0, previous frame's SP is 0x0
(GDB) Up
#1 0x40066e in main () at simple. C: 34
34 memcpy (doink. boik, boink. boik, sizeof (boink. boik ));
(GDB) I locals
Doink = {boik = 0x4019a0}
Boink = {boik = 0x0}
(GDB) ptype boink. boik
Type = int *
(GDB) print * boink. boik
Cannot access memory at address 0x0
(GDB) print * doink. boik
$1 = 4

Figure 3

Figure 3 briefly shows the complete running process of a core program. Similarly, we use the simple program. Instead of manually loading programs and core files, you can call the following commands:

GDB simple core

After the symbol is loaded, GDB indicates where the program is terminated. Note that the current frame #0 contains the address calculated in the previous section. GDB removes the high position from the 31-bit system and only displays the command address. Also note that frame #1 contains the return address in upl14.

Next, I f provides information about the current stack frame. Move the stack frame up to main, which is the place where we leave the frame (that is, the place where memcpy is called ). Simple I locals provides the value of the variable passed to memcpy. The value of boink. boik is 0x0. Use ptype to check the variable type. This will confirm that it is an integer pointer, and it should not be 0x0 if it is used to copy the content to it. The last option is print, which removes the pointer reference through an asterisk (*) to receive the value.

Process Optimized Code

Previously, I mentioned that GDB may become a little tricky when you debug optimized code at the source code level. The compiler optimizes the execution sequence of some code to maximize performance. Figure 4 shows an example. You can see how to switch the row number from 32 to 30 and then switch back to 32.

(GDB) Break main
Breakpoint 1 at 0x800007a8: file simple. C, line 32.
(GDB) r
Starting program:/home/grundym/Foo/simple
Breakpoint 1, main () at simple. C: 32
32 do_one_thing (& doink );
(GDB) S
30 doink. boik = & R1;
(GDB)
32 do_one_thing (& doink );
(GDB)
Do_one_thing (pnum_times = 0x1fffffff690) at simple. C: 47
47 for (I = 0; I <4; I ++ ){

Figure 4

How can this problem be solved? It is very helpful to use Si AND Ni (next instruction; it is similar to Si, but will skip the subroutine call. At this level, a good understanding of zarchitecture is helpful.

(GDB) break * Main
Breakpoint 1 at 0x80000794: file simple. C, line 27.
(GDB) display/I $ pswa
(GDB) r
Starting program:/home/grundym/Foo/simple

Breakpoint 1, main () at simple. C: 27
27 {
1: X/I $ pswa 0x80000794: EB af F0 50 00 24 stmg % R10, % R15, 80 (% R15)
(GDB) Si
0x8000079a 27 {
1: X/I $ pswa 0x8000079a: B9 04 00 1f lgr % R1, % R15
(GDB)
0x8000079e 27 {
1: X/I $ pswa 0x8000079e: A7 FB FF 58 aghi % R15,-168
(GDB)
0x800007a2 in main () at simple. C: 27
27 {
1: X/I $ pswa 0x800007a2: E3 10 F0 00 00 24 STG % R1, 0 (% R15)
(GDB)
32 do_one_thing (& doink );
1: X/I $ pswa 0x800007a8: 41 C0 F0 A0 la % R12, 160 (% R15)
(GDB)
30 doink. boik = & R1;
1: X/I $ pswa 0x800007ac: C0 10 00 00 08 C2 larl % R1, 0x80001930
(GDB)
0x800007b2 30 doink. boik = & R1;
1: X/I $ pswa 0x800007b2: E3 10 F0 A0 00 24 STG % R1, 160 (% R15)
(GDB)
32 do_one_thing (& doink );
1: X/I $ pswa 0x800007b8: B9 04 00 2C lgr % R2, % R12
(GDB)
0x800007bc 32 do_one_thing (& doink );
1: X/I $ pswa 0x800007bc: C0 E5 FF 68 brasl % R14, 0x8000068c
(GDB)
Do_one_thing (pnum_times = 0x1fffffff7f8) at simple. C: 44
44 {
1: X/I $ pswa 0x8000068c: EB BF F0 58 00 24 stmg % R11, % R15, 88 (% R15)
(GDB)

Figure 5

Figure 5 shows the settings for the Program for debugging. First, set a breakpoint at the address of main (), and then set a display. Display is an expression that prints information when the code is stopped. In this example, display is set to display the commands at the current command address. /I is printed as the format of the disassembly code, and the current instruction pointer is in the value/register (value/register) $ pswa.

One-step code debugging shows that each machine command is associated with a line of C code. The first four rows are associated with the first 27th rows (beginning with the function main. The first four rows are typical function introduction operations. They save registers, stack pointers, and adjust stacks. When the associated row number changes to 32, we have set the function call for do_one_thing.

When display is working, it displays x/I as the command before the actual data is displayed. X is the command to check the memory. /I is formatted in command format;/X is formatted in hexadecimal format; And/A is formatted in hexadecimal format. However, you should think of this value as an address and parse the symbol name whenever possible.

Display/I $ pswa
Display/x $ pswm
Display/A $ R0
Display/A $ r1
Display/A $ r2
Display/A $ r3
Display/A $ r4
Display/A $ R5
Display/A $ R6
Display/A $ r7
Display/A $ R8
Display/A $ R9
Display/A $ R10
Display/A $ R11
Display/A $ R12
Display/A $ R13
Display/A $ R12
Display/A $ R14
Display/A $ R15
Display/10i $ pswa

Figure 6

It may be helpful to set some display items when working at the command level. You can place all the display commands in a file and use the-x option on the command line to specify it. Figure 6 contains the display command that is commonly used to work at the assembler level.

Breakpoint 1, main () at simple. C: 27
27 {
20: X/10i $ pswa
0x80000794: EB af F0 50 00 24 stmg % R10, % R15, 80 (% R15)
0x8000079a: B9 04 00 1f lgr % R1, % R15
0x8000079e: A7 fb ff 58 aghi % R15,-168
0x800007a2: E3 10 F0 00 00 24 STG % R1, 0 (% R15)
0x800007a8: 41 C0 F0 A0 la % R12, 160 (% R15)
0x800007ac: C0 10 00 00 08 C2 larl % R1, 0x80001930
0x800007b2: E3 10 F0 A0 00 24 STG % R1, 160 (% R15)
0x800007b8: B9 04 00 2C lgr % R2, % R12
0x800007bc: C0 E5 FF 68 brasl % R14, 0x8000068c
0x800007c2: E3 10 F0 A0 00 04 LG % R1, 160 (% R15)
19:/a $ R15 = 0x1fffffff698
18:/a $ R14 = 0x10000057b04 <__libc_start_main + 260>
17:/a $ R12 = 0x10000019108 <__curbrk + 280>
16:/a $ R13 = 0x8006c9be
15:/a $ R12 = 0x10000019108 <__curbrk + 280>
14:/a $ R11 = 0x1fffffff7f8
13:/a $ R10 = 0x80000418 <_ init>
12:/a $ R9 = 0x100000198f8 <_ dl_debug_mask>
11:/a $ R8 = 0x000017bee0
10:/a $ R7 = 0x1
9:/a $ R6 = 0x2
8:/a $ R5 = 0x00001803d8
7:/a $ r4 = 0x1fffffff808
6:/a $ R3 = 0x1fffffff7f8
5:/a $ r2 = 0x1
4:/a $ R1 = 0x80000794
3:/a $ R0 = 0x1ff00000000
2:/x $ pswm = 0x705c00180000000
1: X/I $ pswa 0x80000794: EB af F0 50 00 24 stmg % R10, % R15, 80 (% R15)
(GDB)

Figure 7

This command prints all psw values, all general registers, and the next 10 lines of machine code starting from the current command address. Figure 7 shows the result when we interrupt at main. As you can see, in some of the registers, the/A Format Parsing makes it easier to understand what is happening.

Conclusion

For some basic tools that can be used for Linux application debugging and the debugging process itself, the information in this article should provide you with useful entry information.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.