linux下gdb调试本地程序

    xiaoxiao2025-03-16  51

    1. 首先保证编译的程序包含了symbols符号表,否则会有如下提示:

    Reading symbols from demo...(no debugging symbols found)...done. 这样表明编译的可执行程序没有包含符号表,需要在CMakeLists.txt添加下面一条语句

    add_definitions("-Wall -g")

     

    2. 启动进入调试:

       输入gdb  application

       提示

    “Type "apropos word" to search for commands related to "word"... Reading symbols from demo...done.”

    表示加载成功;

     

    3. 调试界面输入:

    r (run) 开始运行

    b  设置断电

    p /a +地址:展开地址的内容

    ......

     

    例子:

    命令格式:x/nfu <addr>

    如:

    (gdb)x/1xb 0x7fffffffd708

     

     x : examine 的缩写

     

    n : 表示要显示的内存单元个数f : 表示显示方式, 可取如下值 x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六进制格式显示变量。 i 指令地址格式 c 按字符格式显示变量。 f 按浮点数格式显示变量。u表示一个地址单元的长度,与n一起表示显示的地址长度 b表示单字节, h表示双字节, w表示四字节, g表示八字节

    示例程序:(测试htonl()函数)

     

     

    int main()

    {

    int a = 0x401326;

    int b = htonl(a);

     

    return 0;

    }

    编译调试;

    $gcc -o a.out main.c -g

    $gdb a.out

    运行到return 0; (gdb)p/x a

    0x401326

    (gdb)p &a

    (int *) 0x7fffffffd708

    (gdb)x/1xb  0x7fffffffd708      显示0x7fffffffd708(address)处1个(n)1字节(u)的内容,以十六进制(x)表示;

    0x7fffffffd708: 0x26

    (gdb)x/1xb   0x7fffffffd709     a以小端模式存放于内存;

    0x7fffffffd709: 0x13

    (gdb)p/x b         a->b,主机字节序 -> 网络字节序, 小端 -> 大端

    0x26134000

    (gdb)p &b

    (int *) 0x7fffffffd70c

    (gdb)x/1xb   0x7fffffffd70c

    0x7fffffffd70c: 0x00

    (gdb)x/1xb   0x7fffffffd70d

    0x7fffffffd70d: 0x40

     

    gdb查看虚函数表、函数地址

    1. 查看函数地址

        看函数在代码的哪一行,使用info line就可以看到类似下面这中输出

    点击(此处)折叠或打开

    (gdb) info line a.cpp:10Line 10 of "a.cpp" starts at address 0x80487d4 <_ZN1B5test2Ev> and ends at 0x80487d7 <_ZN1B5test2Ev+3>.(gdb) p _ZN1B5test2Ev$1 = {void (B * const)} 0x80487d4(gdb)

        可以直接根据函数地址去打断点,当然如果知道文件和行号其实没必要拐个弯来打这种费解的断点,应用场合更多是想使用汇编调试的时候。

    点击(此处)折叠或打开

    16 public:17 virtual void test2(){18 cout << "If I'm lying, I'm crying!" << endl;19 }20(gdb) info line 17Line 17 of "a.cpp" starts at address 0x8048808 <_ZN1D5test2Ev> and ends at 0x804880e <_ZN1D5test2Ev+6>.(gdb) b *0x804880eNote: breakpoint 2 also set at pc 0x804880e.Breakpoint 3 at 0x804880e: file a.cpp, line 18.

     

     

    2. 查看虚函数表

        如果仅仅是想知道当前对象的真实类别,那使用这句就可以看到了(示例里面的b实际上是D类对象,而非B类)。

    点击(此处)折叠或打开

    (gdb) set print object on(gdb) p b$3 = (D &) @0xbfe3116c: { = {_vptr.B = 0x8048948}, }

        查看对象里面的虚指针,也很简单,把虚指针指向的内容显示一下就可以了。

    点击(此处)折叠或打开

    (gdb) p b$6 = (D &) @0xbfe3116c: { = {_vptr.B = 0x8048948}, }(gdb) p /a *(void**)0x8048948@2$7 = {0x8048834 <_ZN1D4testEv>, 0x8048808 <_ZN1D5test2Ev>}

        查看虚表的前面,会发现g++实现的时候将RTTI信息放到虚函数表的前面一点点了。反汇编查看代码其实也可以发现的,typeid会根据虚表指针偏移一下去找RTTI信息。

    点击(此处)折叠或打开

    (gdb) p /a *((void**)0x8048948-1)$18 = 0x8048950 <_ZTI1D>

    点击(此处)折叠或打开

    sles10sp1:~/test # c++filt _ZTI
    最新回复(0)