compile

gcc -g xxx

start gdb

gdb -q ./out

or

gdb -p xxx

execute

run

(gdb) run
Starting program: /root/hello
this time is : 1
this time is : 2
this time is : 3
this time is : 4
this time is : 5
this time is : 6
this time is : 7
this time is : 8
this time is : 9
this time is : 10
[Inferior 1 (process 20723) exited with code 01]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64

show code

list

(gdb) list
1       # include<stdio.h>
2
3       int main(void) {
4               char* s = "hello world!";
5               int i=1;
6               for (;i<=10;i++) {
7                       printf("this time is : %d\n", i);
8               }
9
10              return 1;
(gdb)
11      }
(gdb)
Line number 12 out of range; hello.c has 11 lines.

break point debuging

break c delete

(gdb) break 7 
Breakpoint 1 at 0x400536: file hello.c, line 7.
(gdb) run
Starting program: /root/hello
 
Breakpoint 1, main () at hello.c:7  
7                       printf("this time is : %d\n", i);
(gdb) c
Continuing.
this time is : 1

Breakpoint 1, main () at hello.c:7
7                       printf("this time is : %d\n", i);
(gdb) c
Continuing.
this time is : 2

(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) print i             
$1 = 1
(gdb) display i
2: i = 2 

nexti 执行下一个machine operation

(gdb) nexti                                    
5    int i=1;

disassemble function (default AT&T syntax )

disassemble(disas)

(gdb) disassemble main
Dump of assembler code for function main:
   0x000000000040051d <+0>:     push   %rbp
   0x000000000040051e <+1>:     mov    %rsp,%rbp 
   0x0000000000400521 <+4>:     sub    $0x10,%rsp 
   0x0000000000400525 <+8>:     movq   $0x4005f0,-0x10(%rbp)        
   0x000000000040052d <+16>:    movl   $0x1,-0x4(%rbp)    
   0x0000000000400534 <+23>:    jmp    0x40054e <main+49>   
=> 0x0000000000400536 <+25>:    mov    -0x4(%rbp),%eax  
   0x0000000000400539 <+28>:    mov    %eax,%esi    
   0x000000000040053b <+30>:    mov    $0x4005fd,%edi  
   0x0000000000400540 <+35>:    mov    $0x0,%eax    
   0x0000000000400545 <+40>:    callq  0x400400 <printf@plt>  
   0x000000000040054a <+45>:    addl   $0x1,-0x4(%rbp)  
   0x000000000040054e <+49>:    cmpl   $0xa,-0x4(%rbp)  
   0x0000000000400552 <+53>:    jle    0x400536 <main+25> 
   0x0000000000400554 <+55>:    mov    $0x1,%eax  
   0x0000000000400559 <+60>:    leaveq   
   0x000000000040055a <+61>:    retq   
End of assembler dump.

disassembly function (intel syntax)

disassembly(disas)

(gdb) set disassembly-flavor intel    
(gdb) disassemble main      
Dump of assembler code for function main:  
   0x000000000040051d <+0>:     push   rbp   
   0x000000000040051e <+1>:     mov    rbp,rsp   
   0x0000000000400521 <+4>:     sub    rsp,0x10                     
   0x0000000000400525 <+8>:     mov    QWORD PTR [rbp-0x10],0x4005f0      
   0x000000000040052d <+16>:    mov    DWORD PTR [rbp-0x4],0x1 
   0x0000000000400534 <+23>:    jmp    0x40054e <main+49>       
=> 0x0000000000400536 <+25>:    mov    eax,DWORD PTR [rbp-0x4]  
   0x0000000000400539 <+28>:    mov    esi,eax              
   0x000000000040053b <+30>:    mov    edi,0x4005fd       
   0x0000000000400540 <+35>:    mov    eax,0x0                
   0x0000000000400545 <+40>:    call   0x400400 <printf@plt>   
   0x000000000040054a <+45>:    add    DWORD PTR [rbp-0x4],0x1 
   0x000000000040054e <+49>:    cmp    DWORD PTR [rbp-0x4],0xa 
   0x0000000000400552 <+53>:    jle    0x400536 <main+25>    
   0x0000000000400554 <+55>:    mov    eax,0x1 
   0x0000000000400559 <+60>:    leave      
   0x000000000040055a <+61>:    ret  
End of assembler dump.

显而易见,Intel语法更加适合人看。

上面充斥了各种汇编指令以及一些register

mov : move, copy various from one place to another place. jmp : jump, CPU switch context. call : subroutine jle : if <= then jump ret : return subroutine cmp : compare

show off register

(gdb) info register 
rax            0x11     17 
rbx            0x0      0    
rcx            0x10     16   
rdx            0x7ffff7dd6a00   140737351870976   
rsi            0x7fffffef       2147483631      
rdi            0x0      0                        
rbp            0x7fffffffe320   0x7fffffffe320  
rsp            0x7fffffffe310   0x7fffffffe310   
r8             0x0      0                         
r9             0x7ffff7a5b16d   140737348219245   
r10            0x22     34                        
r11            0x246    582                        
r12            0x400430 4195376                    
r13            0x7fffffffe400   140737488348160    
r14            0x0      0                          
r15            0x0      0                         
rip            0x400536 0x400536 <main+25>       
eflags         0x297    [ CF PF AF SF IF ]       
cs             0x33     51   
ss             0x2b     43   
ds             0x0      0   
es             0x0      0   
fs             0x0      0   
gs             0x0      0   
(gdb) 

or brief command

(gdb) i r rax
rax            0x11     17

what the register do?

(gdb) disassemble main      
Dump of assembler code for function main:  
0x000000000040051d <+0>:     push   rbp   
0x000000000040051e <+1>:     mov    rbp,rsp   
0x0000000000400521 <+4>:     sub    rsp,0x10                     
0x0000000000400525 <+8>:     mov    QWORD PTR [rbp-0x10],0x4005f0
0x000000000040052d <+16>:    mov    DWORD PTR [rbp-0x4],0x1 
0x0000000000400534 <+23>:    jmp    0x40054e <main+49>       
0x0000000000400536 <+25>:    mov    eax,DWORD PTR [rbp-0x4]  
0x0000000000400539 <+28>:    mov    esi,eax             
0x000000000040053b <+30>:    mov    edi,0x4005fd      
0x0000000000400540 <+35>:    mov    eax,0x0                
0x0000000000400545 <+40>:    call   0x400400 <printf@plt>
0x000000000040054a <+45>:    add    DWORD PTR [rbp-0x4],0x1  
0x000000000040054e <+49>:    cmp    DWORD PTR [rbp-0x4],0xa
0x0000000000400552 <+53>:    jle    0x400536 <main+25>    
0x0000000000400554 <+55>:    mov    eax,0x1 
0x0000000000400559 <+60>:    leave      
0x000000000040055a <+61>:    ret  
  • push rbp: rbp将是main()的起始栈地址。The rsp (stack pointer) register tell us where the top of the stack currently is.
  • 前3行指令: 会创建一个 Call Stack Frame
  • ESI/EDI分别叫做”源/目标索引寄存器”(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串. 如下edi 存储着printf中的 “this time is : %d\n”,而 esi 中存储的是此次的 %d 的值 i.
    (gdb) i r eax esi edi         
    eax            0x2      2     
    esi            0x2      2     
    edi            0x4005fd 4195837  
    (gdb) x/ls 0x4005fd 
    0x4005fd:       "this time is : %d\n"
    
  • mov esi,eax EAX 是”累加器”(accumulator), 它是很多加法乘法指令的缺省寄存器。所以这里在循环结束之后,mov eax,0x1 eax会执行累加,然后做 **esi=eax ** 这样的操作

  • mov edi,0x4005fd 因为0x4005fd这个地址上存储的是我们的常量字符串 this time is: %d\n,所以在此次循环中将此edi这个寄存器指向这个地址。

  • jle 0x400536 <main+25> 如果依旧满足条件,跳回循环开始位置

cheatsheet

http://img.xuwenzhi.com/gdb-cheatsheet1.png

http://img.xuwenzhi.com/gdb-cheatsheet2.png

refer

汇编语言里 eax, ebx, ecx, edx, esi, edi, ebp, esp这些都是什么意思啊?

debugging with gdb part 1

Comparing C to machine language