Files
kernel_Notes/Zim/Utils/gdb/gdb_debugging.txt
2012-12-30 14:55:16 +08:00

131 lines
6.5 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Content-Type: text/x-zim-wiki
Wiki-Format: zim 0.4
Creation-Date: 2012-12-25T16:49:56+08:00
====== gdb debugging ======
Created Tuesday 25 December 2012
[geekard@geekard elf]$ **gdb demo**
GNU gdb (GDB) 7.5.1
Copyright (C) 2012 Free Software Foundation, Inc.
**(gdb) info source **//查看当前使用的source file name
**(gdb) info args **
name = 0x80486a3 "geekard"
age = 23
friends = 0xbffff920
**(gdb) info locals**
a = -1209680176
nm = 0xbffff914 "\027"
fr = {0xbffff948 "",
0xb7e5beff <printf+47> "\203\304\030[\303f\220f\220f\220f\220f\220f\220S\203\354\030\215D$,\211D$\f\213D$(讷\r",
0xb7fb5a00 <_IO_2_1_stdout_> "\204*\255", <incomplete sequence \373>, 0x80486b4 "\tThe globalVarStatic is:%d\n"}
//从上面两次的反汇编结果可以得出如下结论:
//1. break function-name 设置的断点并不位于function的入口处而break *function-name才是。
//2. break function-name设置的断点位于function的prologue指令之后auto variable初始化指令之前。
//3. 当执行到前面设置的断点时函数的args已经由caller通过stack传入但是函数的auto variable还没有被初始化
**(gdb) bt **//查看函数调用信息即backtrap。callee的编号小于其caller。
#0 greeting (name=0x80486a3 "geekard", age=23, friends=0xbffff920) at demo.c:13
#1 0x08048578 in main (argc=5, argv=0xbffff9e4) at demo.c:50
**(gdb) info f 1 **//查看stack frame编号为1的函数帧信息
Stack frame at 0xbffff950:
eip = 0x8048578 in main (demo.c:50); saved eip 0xb7e28605
caller of frame at 0xbffff910
source language c.
Arglist at 0xbffff948, args: argc=5, argv=0xbffff9e4
Locals at 0xbffff948, Previous frame's sp is 0xbffff950
Saved registers:
ebp at 0xbffff948, eip at 0xbffff94c
**(gdb) info f 0**
Stack frame at 0xbffff910:
eip = 0x804842c in greeting (demo.c:13); saved eip 0x8048578
called by frame at 0xbffff950
source language c.
Arglist at 0xbffff908, args: name=0x80486a3 "geekard", age=23, friends=0xbffff920
Locals at 0xbffff908, Previous frame's sp is 0xbffff910
Saved registers:
eip at 0xbffff90c
**(gdb) disassemble main **//反汇编main函数
Dump of assembler code for function main:
//从info f 1的输出可知call main前esp的值为 0xbffff950。
0x080484f0 <+0>: push %ebp
0x080484f1 <+1>: mov %esp,%ebp //main函数的prologue指令break main时停止在下一条指令处。
0x080484f3 <+3>: and $0xfffffff0,%esp //SystemV i386 ABI规定esp必须word对齐。
0x080484f6 <+6>: sub $0x30,%esp //为main的auto variables预留空间此后esp的值为0xbffff10。
0x080484f9 <+9>: mov 0x8049918,%eax
0x080484fe <+14>: mov %eax,0x2c(%esp) //int autoVar = globVar;
0x08048502 <+18>: mov 0x8049924,%eax
0x08048507 <+23>: mov %eax,0x28(%esp) //i = externVar;
0x0804850b <+27>: movl $0x80486a3,0x24(%esp) // char *name = "geekard"
0x08048513 <+35>: movl $0x17,0x20(%esp) // int age = 23
0x0804851b <+43>: movl $0x8048639,0x10(%esp) //"Tom"
0x08048523 <+51>: movl $0x804863d,0x14(%esp) //"John"
0x0804852b <+59>: movl $0x8048642,0x18(%esp) //"Pi"
0x08048533 <+67>: movl $0x0,0x1c(%esp) //NULL
//char **friends = {x, x, NUU}friends是一个指向字符指针的指针__变量(占有内存单元)__其指向的数组有4个元素。
//变量friends的地址为0xbffff918即0x8($esp)处可以用print &friends命令打印出。
//变量friends的值为0xbffff920指向栈上"Tom"所在的内参单元地址。对于指针数组变量friends有以下调试信息
**(gdb) p &friends **
$21 = (char ***) 0xbffff918
**(gdb) p friends**
$17 = (char **) 0xbffff920
**(gdb) p friends@4**
$18 = {0xbffff920, 0x80485f2 <__libc_csu_init+82>, 0x8048639, 0x804863d}
**(gdb) p *friends@4**
$19 = {0x8048639 "Tom", 0x804863d "John", 0x8048642 "Pi", 0x0}
**(gdb) x /4wx friends@4**
0xbffff918: 0xbffff920 0x080485f2 0x08048639 0x0804863d
**(gdb) x /4wx *friends@4**
0xbffff920: 0x08048639 0x0804863d 0x08048642 0x00000000
**(gdb) p *friends@4**
$20 = {0x8048639 "Tom", 0x804863d "John", 0x8048642 "Pi", 0x0}
//从main函数的auto variable初始化指令可以得出如下结论
//1. main函数的auto variable是保存在stack中其layourt的顺序与定义的顺序一致即先定义的变量先入栈。
//2.static variable定义在全局数据段(.data section)中而不是stack中(int static staticVar并没有在stack中初始化)。
//3.数组的各元素入栈顺序与定义顺序相反,即索引越大越先入栈; 指针数组变量最后入栈。
//auto variable初始化完成后的main栈分配如下
{{./stack.png?height=544}}
0x0804853b <+75>: movl $0x80486ab,(%esp)
0x08048542 <+82>: call 0x8048300 <puts@plt>
0x08048547 <+87>: mov 0x804991c,%eax
0x0804854c <+92>: mov %eax,0x4(%esp)
0x08048550 <+96>: movl $0x80486b4,(%esp)
0x08048557 <+103>: call 0x80482f0 <printf@plt>
0x0804855c <+108>: lea 0x10(%esp),%eax
0x08048560 <+112>: mov %eax,0x8(%esp)
0x08048564 <+116>: mov 0x20(%esp),%eax
0x08048568 <+120>: mov %eax,0x4(%esp)
0x0804856c <+124>: mov 0x24(%esp),%eax
0x08048570 <+128>: mov %eax,(%esp)
0x08048573 <+131>: call 0x804842c <greeting>
__0x08048578__ <+136>: movl $0x3,0x4(%esp)
0x08048580 <+144>: movl $0x2,(%esp)
0x08048587 <+151>: call 0x8048590 <add>
0x0804858c <+156>: leave
0x0804858d <+157>: ret
End of assembler dump.
//greeting函数的argumets是由main函数通过栈传入的。下面代码节选至main函数的反汇编输出。
//函数的auto variable是保存在其stack中的。下面时main函数的auto variable初始化代码。
0x0804850b <+27>: movl $0x80486a3,0x24(%esp) //name
0x08048513 <+35>: movl $0x17,0x20(%esp) //age
0x0804851b <+43>: movl $0x8048639,0x10(%esp) //friends
//将greeting函数的friends参数圧入栈中注意friends参数的值是main的auto variable所以它保存在main的stack frame中。
0x0804855c <+108>: lea 0x10(%esp),%eax
0x08048560 <+112>: mov %eax,0x8(%esp) //frinnds
0x08048564 <+116>: mov 0x20(%esp),%eax
0x08048568 <+120>: mov %eax,0x4(%esp) //通过栈传入age参数
0x0804856c <+124>: mov 0x24(%esp),%eax
0x08048570 <+128>: mov %eax,(%esp) //通过栈传入name参数
0x08048573 <+131>: call 0x804842c <greeting>