linux调试的一些简单命令

运行下面几行代码时,发现结果有点奇怪,就反汇编看了一下,顺便记录一下在linux中 调试的命令。

#include <stdio.h>
int main()// 数组越界访问
{
	int test[2];
	int i;
	for(i = 0; i < 3; i++)
	{
		test[i] = 1;
		printf("%d\n", test[i]);
	}
	return 0;
}

gcc main.c -o main

./main

运行结果为死循环打印1


lnx@lnx-pc:/mnt/hgfs/share/leetcode/mbstowcs$ gcc -g main2.c
lnx@lnx-pc:/mnt/hgfs/share/leetcode/mbstowcs$ objdump -S a.out > main.s

反汇编代码如下,只看一下main函数部分:

080483e4 <main>:
#include <stdio.h>
int main()// 数组越界访问
{
 80483e4:	55                   	push   %ebp// ebp寄存器内容压栈,即保存main函数的上级调用函数的栈基地址
 80483e5:	89 e5                	mov    %esp,%ebp// esp值赋给ebp,设置main函数的栈基址
 80483e7:	83 e4 f0             	and    $0xfffffff0,%esp// 使栈地址16字节对齐
 80483ea:	83 ec 20             	sub    $0x20,%esp// 通过ESP-8来分配8字节堆栈空间
	int test[2];
	int i;
	for(i = 0; i < 3; i++)
 80483ed:	c7 44 24 1c 00 00 00 	movl   $0x0,0x1c(%esp)
 80483f4:	00 
 80483f5:	eb 2a                	jmp    8048421 <main+0x3d>
	{
		test[i] = 1;
 80483f7:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 80483fb:	c7 44 84 14 01 00 00 	movl   $0x1,0x14(%esp,%eax,4)
 8048402:	00 
		printf("%d\n", test[i]);
 8048403:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 8048407:	8b 54 84 14          	mov    0x14(%esp,%eax,4),%edx
 804840b:	b8 f0 84 04 08       	mov    $0x80484f0,%eax
 8048410:	89 54 24 04          	mov    %edx,0x4(%esp)
 8048414:	89 04 24             	mov    %eax,(%esp)
 8048417:	e8 00 ff ff ff       	call   804831c <printf@plt>
#include <stdio.h>
int main()// 数组越界访问
{
	int test[2];
	int i;
	for(i = 0; i < 3; i++)
 804841c:	83 44 24 1c 01       	addl   $0x1,0x1c(%esp)
 8048421:	83 7c 24 1c 02       	cmpl   $0x2,0x1c(%esp)
 8048426:	7e cf                	jle    80483f7 <main+0x13>
	{
		test[i] = 1;
		printf("%d\n", test[i]);
	}
	return 0;
 8048428:	b8 00 00 00 00       	mov    $0x0,%eax// 设置main函数返回值
 804842d:	c9                   	leave// 撤销Stack Frame(栈框架)  
 804842e:	c3                   	ret// main 函数返回    
 804842f:	90                   	nop

接下来使用gdb调试:

lnx@lnx-pc:/mnt/hgfs/share/leetcode/mbstowcs$ gdb a.out 
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /mnt/hgfs/share/leetcode/mbstowcs/a.out...done.
(gdb) l
1	#include <stdio.h>
2	int main()// 数组越界访问
3	{
4		int test[2];
5		int i;
6		for(i = 0; i < 3; i++)
7		{
8			test[i] = 1;
9			printf("%d\n", test[i]);
10		}
(gdb) b 6// 设置断点
Breakpoint 1 at 0x80483ed: file main2.c, line 6.
(gdb) r
Starting program: /mnt/hgfs/share/leetcode/mbstowcs/a.out 


Breakpoint 1, main () at main2.c:6
6		for(i = 0; i < 3; i++)
(gdb) i r// 显示寄存器当前值
eax            0xbffff3c4	-1073744956
ecx            0x4363b11d	1130606877
edx            0x1	1
ebx            0x283ff4	2637812
esp            0xbffff2f0	0xbffff2f0
ebp            0xbffff318	0xbffff318
esi            0x0	0
edi            0x0	0
eip            0x80483ed	0x80483ed <main+9>
eflags         0x286	[ PF SF IF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb) x/8xw 0xbffff2f0// 使用examine命令(简写是x)来查看内存地址中的值;8个单位;
   		      // x指按十六进制格式显示变量;w指每单位4字节
0xbffff2f0:	0x00284324	0x00283ff4	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x0011e030	0x0804844b	0x00283ff4// esp到ebp的初始值为随机值
(gdb) s// 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数;
       // 这里执行的是i = 0,对应汇编代码为movl   $0x0,0x1c(%esp)
8			test[i] = 1;
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x00284324	0x00283ff4	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x0011e030	0x0804844b	0x00000000// 0x1c(%esp)为0xbffff30c
(gdb) s
9			printf("%d\n", test[i]);// 前面执行的jmp    8048421 <main+0x3d>
						//	     cmpl   $0x2,0x1c(%esp)
						//	     jle    80483f7 <main+0x13>
						// 这里执行  mov    0x1c(%esp),%eax
						//	     movl   $0x1,0x14(%esp,%eax,4)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x00284324	0x00283ff4	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x0804844b	0x00000000
(gdb) s
1// 打印1mov    0x1c(%esp),%eax
 //		 mov    0x14(%esp,%eax,4),%edx 
 //		 mov    $0x80484f0,%eax
 //		 mov    %edx,0x4(%esp)
 //		 mov    %eax,(%esp)
 //		 call   804831c <printf@plt>
6		for(i = 0; i < 3; i++)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x0804844b	0x00000000
(gdb) s
8			test[i] = 1;// addl   $0x1,0x1c(%esp)
				    // cmpl   $0x2,0x1c(%esp)
				    // jle    80483f7 <main+0x13>
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x0804844b	0x00000001
(gdb) s
9			printf("%d\n", test[i]);// mov    0x1c(%esp),%eax
						// movl   $0x1,0x14(%esp,%eax,4)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb) s
1
6		for(i = 0; i < 3; i++)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb) s
8			test[i] = 1;// 直到这里i的值为2
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000002
(gdb) s
9			printf("%d\n", test[i]);// mov    0x1c(%esp),%eax// %eax的值为2
						// movl   $0x1,0x14(%esp,%eax,4)// 0x14(%esp,%eax,4)的值为0xbffff30c
						// 与i的地址相同,所以i的值被修改为1
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb) s
1
6		for(i = 0; i < 3; i++)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb) s
8			test[i] = 1;// i=2,test[2] = 1,i的值再被修改为1,形成死循环
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000002
(gdb) s
9			printf("%d\n", test[i]);
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb) s
1
6		for(i = 0; i < 3; i++)
(gdb) x/8xw 0xbffff2f0
0xbffff2f0:	0x080484f0	0x00000001	0x08048440	0xbffff318
0xbffff300:	0x0015d4a5	0x00000001	0x00000001	0x00000001
(gdb)


references:

LINUX平台可以用GDB进行反汇编和调试。

GDB十分钟教程

使用gdb查看内存和寄存器内容

linux下汇编语言开发总结

Linux 汇编语言开发指南

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值