gdb调试命令----小话c语言(15)

[Mac-10.7.1  Lion  Intel-based  x64  gcc4.2.1  GNU gdb 6.3.50-20050815 (Apple version gdb-1708)]


Q: 给个简单的代码,然后进入调试状态。

A: 如下代码,保存为hello.c:

#include <stdio.h>

int main()
{
    int i = 2;
    printf("%d\n", i);
    return 0;
}
gcc编译,需要有-g参数:gcc  -g  hello.c  -o  hello得到带调试信息的hello可执行文件,gdb  hello进入调试状态,输入list查看源代码信息:

可以看到hello.c源代码被打印出来了。输入run命令运行程序,

可以看到程序开始运行,且输出了结果。


Q: 如何能够看到调试信息?

A: 可以通过源代码编译后的汇编代码得到信息。gcc  -S  -g  hello.c得到hello.s文件:

	.section	__TEXT,__text,regular,pure_instructions
	.section	__DWARF,__debug_frame,regular,debug
Lsection_debug_frame:
	.section	__DWARF,__debug_info,regular,debug
Lsection_info:
	.section	__DWARF,__debug_abbrev,regular,debug
Lsection_abbrev:
	.section	__DWARF,__debug_aranges,regular,debug
Lsection_aranges:
	.section	__DWARF,__debug_macinfo,regular,debug
Lsection_macinfo:
Lsection_line:
	.section	__DWARF,__debug_loc,regular,debug
Lsection_loc:
	.section	__DWARF,__debug_pubnames,regular,debug
Lsection_pubnames:
	.section	__DWARF,__debug_pubtypes,regular,debug
Lsection_pubtypes:
	.section	__DWARF,__debug_str,regular,debug
Lsection_str:
	.section	__DWARF,__debug_ranges,regular,debug
Lsection_ranges:
	.section	__TEXT,__text,regular,pure_instructions
Ltext_begin:
	.section	__DATA,__data
Ldata_begin:
	.section	__TEXT,__text,regular,pure_instructions
	.globl	_main
	.align	4, 0x90
_main:
Leh_func_begin1:
Lfunc_begin1:
Ltmp3:
	pushq	%rbp
Ltmp0:
	movq	%rsp, %rbp
Ltmp1:
Ltmp4:
	subq	$16, %rsp
Ltmp2:
	movl	$2, -12(%rbp)
Ltmp5:
	movl	-12(%rbp), %eax
	xorb	%cl, %cl
	leaq	L_.str(%rip), %rdx
	movq	%rdx, %rdi
	movl	%eax, %esi
	movb	%cl, %al
	callq	_printf
Ltmp6:
	movl	$0, -8(%rbp)
	movl	-8(%rbp), %eax
	movl	%eax, -4(%rbp)
	movl	-4(%rbp), %eax
	addq	$16, %rsp
	popq	%rbp
	ret
Ltmp7:
Lfunc_end1:
Leh_func_end1:

	.section	__TEXT,__cstring,cstring_literals
L_.str:
	.asciz	 "%d\n"

	.section	__TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame0:
Lsection_eh_frame:
Leh_frame_common:
Lset0 = Leh_frame_common_end-Leh_frame_common_begin
	.long	Lset0
Leh_frame_common_begin:
	.long	0
	.byte	1
	.asciz	 "zR"
	.byte	1
	.byte	120
	.byte	16
	.byte	1
	.byte	16
	.byte	12
	.byte	7
	.byte	8
	.byte	144
	.byte	1
	.align	3
Leh_frame_common_end:
	.globl	_main.eh
_main.eh:
Lset1 = Leh_frame_end1-Leh_frame_begin1
	.long	Lset1
Leh_frame_begin1:
Lset2 = Leh_frame_begin1-Leh_frame_common
	.long	Lset2
Ltmp8:
	.quad	Leh_func_begin1-Ltmp8
Lset3 = Leh_func_end1-Leh_func_begin1
	.quad	Lset3
	.byte	0
	.byte	4
Lset4 = Ltmp0-Leh_func_begin1
	.long	Lset4
	.byte	14
	.byte	16
	.byte	134
	.byte	2
	.byte	4
Lset5 = Ltmp1-Ltmp0
	.long	Lset5
	.byte	13
	.byte	6
	.align	3
Leh_frame_end1:

	.section	__TEXT,__text,regular,pure_instructions
Ltext_end:
	.section	__DATA,__data
Ldata_end:
	.section	__TEXT,__text,regular,pure_instructions
Lsection_end1:
	.section	__DWARF,__debug_frame,regular,debug
Ldebug_frame_common:
Lset6 = Ldebug_frame_common_end-Ldebug_frame_common_begin
	.long	Lset6
Ldebug_frame_common_begin:
	.long	4294967295
	.byte	1
	.byte	0
	.byte	1
	.byte	120
	.byte	16
	.byte	12
	.byte	7
	.byte	8
	.byte	144
	.byte	1
	.align	2
Ldebug_frame_common_end:
Lset7 = Ldebug_frame_end1-Ldebug_frame_begin1
	.long	Lset7
Ldebug_frame_begin1:
Lset8 = Ldebug_frame_common-Lsection_debug_frame
	.long	Lset8
	.quad	Lfunc_begin1
Lset9 = Lfunc_end1-Lfunc_begin1
	.quad	Lset9
	.byte	4
Lset10 = Ltmp0-Lfunc_begin1
	.long	Lset10
	.byte	14
	.byte	16
	.byte	134
	.byte	2
	.byte	4
Lset11 = Ltmp1-Ltmp0
	.long	Lset11
	.byte	13
	.byte	6
	.align	2
Ldebug_frame_end1:
	.section	__DWARF,__debug_info,regular,debug
Linfo_begin1:
	.long	201
	.short	2
Lset12 = Labbrev_begin-Lsection_abbrev
	.long	Lset12
	.byte	8
	.byte	1
	.ascii	 "4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)"
	.byte	0
	.byte	1
	.ascii	 "hello.c"
	.byte	0
	.quad	0
	.long	0
	.ascii	 "/Users/xichen/codes/c_simple/"
	.byte	0
	.byte	2
	.byte	5
	.ascii	 "int"
	.byte	0
	.byte	4
	.byte	3
	.ascii	 "main"
	.byte	0
	.ascii	 "main"
	.byte	0
	.byte	1
	.byte	4
	.byte	1
	.long	125
	.byte	1
	.quad	Lfunc_begin1
	.quad	Lfunc_end1
	.byte	1
	.byte	86
	.byte	4
	.quad	Ltmp4
	.quad	Ltmp7
	.byte	5
	.byte	105
	.byte	0
	.byte	1
	.byte	5
	.long	125
	.byte	2
	.byte	145
	.byte	116
	.byte	0
	.byte	0
	.byte	0
	.byte	0
	.byte	0
	.byte	0
	.byte	0
Linfo_end1:
	.section	__DWARF,__debug_abbrev,regular,debug
Labbrev_begin:
	.byte	1
	.byte	17
	.byte	1
	.byte	37
	.byte	8
	.byte	19
	.byte	11
	.byte	3
	.byte	8
	.byte	82
	.byte	1
	.byte	16
	.byte	6
	.byte	27
	.byte	8
	.byte	0
	.byte	0
	.byte	2
	.byte	36
	.byte	0
	.byte	62
	.byte	11
	.byte	3
	.byte	8
	.byte	11
	.byte	11
	.byte	0
	.byte	0
	.byte	3
	.byte	46
	.byte	1
	.byte	3
	.byte	8
	.byte	135
	.byte	64
	.byte	8
	.byte	58
	.byte	11
	.byte	59
	.byte	11
	.byte	39
	.byte	12
	.byte	73
	.byte	19
	.byte	63
	.byte	12
	.byte	17
	.byte	1
	.byte	18
	.byte	1
	.byte	64
	.byte	10
	.byte	0
	.byte	0
	.byte	4
	.byte	11
	.byte	1
	.byte	17
	.byte	1
	.byte	18
	.byte	1
	.byte	0
	.byte	0
	.byte	5
	.byte	52
	.byte	0
	.byte	3
	.byte	8
	.byte	58
	.byte	11
	.byte	59
	.byte	11
	.byte	73
	.byte	19
	.byte	2
	.byte	10
	.byte	0
	.byte	0
	.byte	0
Labbrev_end:
	.section	__DWARF,__debug_line,regular,debug
Lset13 = Lline_end-Lline_begin
	.long	Lset13
Lline_begin:
	.short	2
Lset14 = Lline_prolog_end-Lline_prolog_begin
	.long	Lset14
Lline_prolog_begin:
	.byte	1
	.byte	1
	.byte	246
	.byte	245
	.byte	10
	.byte	0
	.byte	1
	.byte	1
	.byte	1
	.byte	1
	.byte	0
	.byte	0
	.byte	0
	.byte	1
	.asciz	 "/Users/xichen/codes/c_simple/"
	.byte	0
	.asciz	 "hello.c"
	.byte	1
	.byte	0
	.byte	0
	.byte	0
Lline_prolog_end:
	.byte	0
	.byte	9
	.byte	2
	.quad	Ltmp3
	.byte	23
	.byte	0
	.byte	9
	.byte	2
	.quad	Ltmp4
	.byte	21
	.byte	0
	.byte	9
	.byte	2
	.quad	Ltmp5
	.byte	21
	.byte	0
	.byte	9
	.byte	2
	.quad	Ltmp6
	.byte	21
	.byte	0
	.byte	9
	.byte	2
	.quad	Lsection_end1
	.byte	0
	.byte	1
	.byte	1
Lline_end:
	.section	__DWARF,__debug_pubnames,regular,debug
Lset15 = Lpubnames_end1-Lpubnames_begin1
	.long	Lset15
Lpubnames_begin1:
	.short	2
Lset16 = Linfo_begin1-Lsection_info
	.long	Lset16
Lset17 = Linfo_end1-Linfo_begin1
	.long	Lset17
	.long	132
	.asciz	 "main"
	.long	0
Lpubnames_end1:
	.section	__DWARF,__debug_pubtypes,regular,debug
Lset18 = Lpubtypes_end1-Lpubtypes_begin1
	.long	Lset18
Lpubtypes_begin1:
	.short	2
Lset19 = Linfo_begin1-Lsection_info
	.long	Lset19
Lset20 = Linfo_end1-Linfo_begin1
	.long	Lset20
	.long	0
Lpubtypes_end1:
	.section	__DWARF,__debug_aranges,regular,debug
	.section	__DWARF,__debug_ranges,regular,debug
	.section	__DWARF,__debug_macinfo,regular,debug
	.section	__DWARF,__debug_inlined,regular,debug
Lset21 = Ldebug_inlined_end1-Ldebug_inlined_begin1
	.long	Lset21
Ldebug_inlined_begin1:
	.short	2
	.byte	8
Ldebug_inlined_end1:

.subsections_via_symbols

可以看到里面有很多关于debug的信息,使用MachOView工具也可以看到对应的可执行文件中的调试信息。


Q: 如何调试core文件?

A: 可以使用gdb  可执行文件  core文件 的方式来调试。如下,写个可以导致崩溃的代码invalid_ptr.c:

#include <stdio.h>

int main()
{
    int *p = (int *)0;
    *p = 1;
    return 0;
}
使用-g参数编译成可执行文件invalid_ptr.先查看下系统是否支持生成core文件,

如果是0,那说明不能生成core文件。做如下修改:

接着运行invalid_ptr文件:

注意上面的这个过程可能很慢,因为mac下生成的core文件异常的大,就这个代码,在笔者的机器上core文件有340MB,有点费解。

然后使用gdb调试此core文件(命令行中的/cores/core.13890是刚刚生成的core文件,不同平台可能不同,需要根据时间自行判断):

可以看到,它正确地定位到了错误代码的位置。


Q: 如何能够得到一个变量的类型?

A: 使用whatis命令即可。如下代码保存为mem.c:

#include <stdio.h>

int main()
{
    int arr[] = {1, 2, 3, 4};
    arr[0] = 100;
    return 0;
}
使用gdb调试:


Q: 在gdb环境,需要调用外部shell命令,如何不退出gdb来执行?

A: 使用shell命令即可。

上面是在gdb环境输出hello.c文件的内容。


Q: 有的时候,调试外部代码,为了给外部代码返回正确的数值,强制让一个函数返回某个特定的值,如何做?

A: 使用return命令。如下代码,保存为add.c, 并进入gdb调试状态:

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int main()
{
    int i = 2;
    int sum;
    printf("%d\n", i);
    sum = add(i, 3);
    printf("sum is %d\n", sum);

    return 0;
}
如下调试:

可以看到,add函数,参数为2和3,但是可以强制改变它的返回值。


Q: 有的时候,需要修改某个变量的值来调试查看可能的结果,怎么做?

A: 可以使用set  var命令。使用上面的代码,进入调试状态:

可以看到使用set  var  i=100将i的数值改变了。


Q: 如果需要查看当前执行的函数的内部基本信息,怎么办?

A: 可以使用info  frame命令(缩写为i  f).依然使用上面的add.c代码,进入调试状态:

可以看到,里面包含了语言、参数、局部变量和一些寄存器信息等。


Q: 如果需要输出某个地址的数据,用什么命令?

A: 可以使用print  *地址命令。依然使用add.c代码,进入调试状态:

对于内存地址的查看,也可以使用x命令查看。


Q: 有的时候,想直接跳到某一行执行,怎么做?

A: 使用jump命令。如下代码,为loop.c:

#include <stdio.h>

int main()
{
    int i = 2;
    while(i < 1000)
    {
        ++i;
    }
    printf("end...\n");
    return 0;
}
假设在while循环中有断点,想要直接跳到后面的printf函数:


Q: 如果在调试状态,需要主动调用某个函数,求其返回值,怎么做?

A: 可以使用call命令。使用add.c代码:

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int main()
{
    int i = 2;
    int sum;
    printf("%d\n", i);
    sum = add(i, 3);
    printf("sum is %d\n", sum);

    return 0;
}
进入调试状态:


Q: 如果是多线程,如何给不同线程执行的代码打断点?

A: 可以使用info  threads获取所有线程信息,然后使用b  行号  thread  线程号  来打断点。


xichen

2012-5-22 11:11:34




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值