GDB调试Release版ELF文件

对外发布版本都是release版本的ELF文件,如果出现问题就很难调查问题的真正原因。如果产生
core文件也就是只能知道个堆栈,内存。很难弄清楚原因。所以,就使用gdb步步跟进asm吧。

如果直接gdb release文件会提示:
(no debugging symbols found)

因为是release版的可执行文件,肯定是没有debug段的,没有debug段就没有debug符号表。

可以使用nm -a 可执行文件名 | grep debug,如果有debug信息就会打印如下内容:

[root@localhost ~]# nm -a a.debug.out | grep debug
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_frame
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_loc
0000000000000000 N .debug_pubnames
0000000000000000 N .debug_str

我写了个简单的程序用来演示怎样调试Release的ELF文件。源代码如下:

#include <stdio.h>

int show();

int main(int argc)
{
    printf("hello \n");

    if (argc >= 2)
        show("77");

    return 0;
}

int show(int a)
{
    int i = 0;
    unsigned int a1 = 0;
    unsigned int a2 = 1;

    printf("%d %d ", 0, 1);

    for(i = 0; i < 20; i++)
    {
        a = a2;
        a2 += a1;
        printf("%u ", a2);
        a1 = a;
    }

    printf("\n");
    return 0;
}

代码虽然有些不合规矩,只是便于调试而已。使用gcc进行编译

gcc test.c

 

编译完成后会在当前目录下生成一个a.out文件

[root@localhost ~]# file a.out
a.out: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

 

看到file的结果为not stripped,这里千万别strip。如果strip了所有的符号段都没了,就不要调试了,调试起来也很难。

接着运行gdb:

进入layou asm模式(《Debugging with gdb》的解释为:Display the assembly window only.):

在使用GDB调试Release文件时可能会用到的命令:
nexti
nexti arg
ni Execute one machine instruction, but if it is a function call, proceed until the
function returns.
An argument is a repeat count, as in next.

stepi
stepi arg
si Execute one machine instruction, then stop and return to the debugger.
It is often useful to do ‘display/i $pc’ when stepping by machine instructions.
This makes gdb automatically display the next instruction to be executed, each
time your program stops. See Section 10.7 [Automatic Display], page 111.
An argument is a repeat count, as in step.

info registers
Print the names and values of all registers except floating-point and vector
registers (in the selected stack frame).

info all-registers
Print the names and values of all registers, including floating-point and vector
registers (in the selected stack frame).

info registers regname ...
Print the relativized value of each specified register regname. As discussed in
detail below, register values are normally relative to the selected stack frame.
regname may be any register name valid on the machine you are using, with or
without the initial ‘$’.

x addr
x Use the x command to examine memory.

set var
Evaluate expression EXP and assign result to variable VAR, using assignment
syntax appropriate for the current language (VAR = EXP or VAR := EXP for
example).  VAR may be a debugger "convenience" variable (names starting
with $), a register (a few standard names starting with $), or an actual
variable in the program being debugged.  EXP is any valid expression.
This may usually be abbreviated to simply "set".参见(17.1 Assignment to Variables)

要想真正的调试,还必须了解AT&T汇编。AT&T汇编与英特尔汇编最大的区别就是操作数的顺序。(如果有人有AT&T汇编的电子书麻烦请传我一份)
需要按照逻辑关系将汇编代码与C代码相对应之后再去调试。可以试着将上面的C代码与汇编代码对应一下试试调试。

另:提供一种简单的方法来调试Release文件,这种方法的缺点在于你必须有ELF文件的源代码。
1、objcopy --only-keep-debug projectD projectsymbol.dbg #生成符号表;
2、gdb -q --symbol=projectsymbol.dbg -exec=projectR #加载符号表;
3、跟平常调试带debug段的elf一样了。

posted @ 2013-01-24 19:43  wales.guo  阅读(4716)  评论(0编辑  收藏  举报