GDBTUI调试C程序

GDB,The GNU Project Debugger的简称,是GNU环境调试器,可以调试多种程序。

而GDB还有一个叫做gdbtui的工具,可以以“可视化”的界面调试源代码。在此以一个简单Hello程序为例,做一个小笔记。

GCC编译之调试信息

CSDN有一篇博客,里面总结了一些生成调试信息的参数,总结下来如下:

-g -ggdb
-g1
级别1(-g1)不包含局部变量和与行号有关的调试信息,因此只能够用于回溯
跟踪和堆栈转储之用
-g2
这是默认的级别,此时产生的调试信息包括扩展的符号表、行号、局部
或外部变量信息。
-g3
包含级别2中的所有调试信息,以及源代码中定义的宏
-g系列以“原生格式(native format)”生成调试信息。GDB 可以直接利用这个信息,其它调试器也可以使用这个调试信息,而-ggdb系列只能被GDB利用

GDBTUI

关于gdbtui是什么,简而言之就是一个可视化的gdb,让你在调试程序时看得见源代码(大多数时候指编译型程序源代码),gdbgui的详细介绍die网站有:https://linux.die.net/man/1/gdbtui

示例

hello.c

// test gdbtui

#include <stdio.h>

int main(int argc, char const *argv[]) {
  printf("%sn", "Hello, world!");
  return 0;
}

不带调试信息的编译指令:

$ gcc -Wall -o hello hello.c

以不带调试信息编译程序,在使用gdbtui时,将无法看到源代码。使用objdump查看段头信息:

hello:     文件格式 elf64-x86-64

节:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     0000001c  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000060  00000000004002b8  00000000004002b8  000002b8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       0000003d  0000000000400318  0000000000400318  00000318  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000008  0000000000400356  0000000000400356  00000356  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  0000000000400360  0000000000400360  00000360  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     00000030  0000000000400380  0000000000400380  00000380  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000018  00000000004003b0  00000000004003b0  000003b0  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000017  00000000004003c8  00000000004003c8  000003c8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000020  00000000004003e0  00000000004003e0  000003e0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         00000172  0000000000400400  0000000000400400  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .fini         00000009  0000000000400574  0000000000400574  00000574  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata       0000001e  0000000000400580  0000000000400580  00000580  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame_hdr 00000034  00000000004005a0  00000000004005a0  000005a0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame     000000f4  00000000004005d8  00000000004005d8  000005d8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .init_array   00000008  0000000000600e10  0000000000600e10  00000e10  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 18 .fini_array   00000008  0000000000600e18  0000000000600e18  00000e18  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 19 .dynamic      000001d0  0000000000600e20  0000000000600e20  00000e20  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 20 .got          00000010  0000000000600ff0  0000000000600ff0  00000ff0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .got.plt      00000020  0000000000601000  0000000000601000  00001000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .data         00000004  0000000000601020  0000000000601020  00001020  2**0
                  CONTENTS, ALLOC, LOAD, DATA
 23 .bss          00000004  0000000000601024  0000000000601024  00001024  2**0
                  ALLOC
 24 .comment      0000002c  0000000000000000  0000000000000000  00001024  2**0
                  CONTENTS, READONLY

关于段头表,它是保存elf可链接或可执行程序运行所必须的数据,具体可以去wiki或者参考Oracle的链接库指南。不过这里显然没有.debug段头。

如果我们采用默认的调试信息产生级别编译程序,即使用如下编译指令:

$ gcc -g -Wall -o hello hello.c

再次使用objdump查看段头,此时就多了如下段头:

 25 .debug_aranges 00000030  0000000000000000  0000000000000000  00001050  2**0
                  CONTENTS, READONLY, DEBUGGING
 26 .debug_info   00000341  0000000000000000  0000000000000000  00001080  2**0
                  CONTENTS, READONLY, DEBUGGING
 27 .debug_abbrev 000000f3  0000000000000000  0000000000000000  000013c1  2**0
                  CONTENTS, READONLY, DEBUGGING
 28 .debug_line   000000c4  0000000000000000  0000000000000000  000014b4  2**0
                  CONTENTS, READONLY, DEBUGGING
 29 .debug_str    000002ac  0000000000000000  0000000000000000  00001578  2**0
                  CONTENTS, READONLY, DEBUGGING

此时使用gdbtui(可以在gdb中使用快捷键Ctrl+x+a打开),设置断点在第6行。因为有调试信息,就可以得到如下结果:

gdbtui-hello
gdbtui,hello程序简单测试

如果我们使用objdump反汇编,就会发现有调试信息的目标程序具有很多.debug段的汇编代码,而没有调试信息的目标程序则没有这部分汇编代码。

这里只是对gdb的简单笔记,希望对有幸阅读到的人有帮助。

作者: V

Web Dev

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s