gdb带源码调试libc

在使用gcc编译时,如果采用带-g选项编译,即可在二进制文件中附加调试信息以便gdb进行源码级别的调试。如果二进制中存在调试信息并且源码文件存在,则可以使用gdb的list命令来查看源码。通过在ubuntu中安装带调试信息的libc,并下载libc源码,即可配置gdb跟入libc的库函数后进行源码级别的调试

推荐阅读:

源码调试示例

这里我们先自己尝试调试任意的一个带源码的程序:

# include <stdio.h>
int main(){
  puts("hello");
  puts("world");
  return 0;
}

-g选项进行编译:

➜  gcc -g test.c -o test

gdb启动:

➜  gdb -q ./test 
GEF for linux ready, type 'gef' to start, 'gef config' to configure
77 commands loaded for GDB 7.11.1 using Python engine 3.5
[*] 3 commands could not be loaded, run 'gef missing' to know why.
Reading symbols from ./test...done.
gef➤  b main
Breakpoint 1 at 0x40052a: file test.c, line 4.
gef➤  r

便可以在gef中看到源码一栏:

───────────────────────────────────────────────────────────────────────────────────────────────────────────── source:test.c+4 ────
      1	 # include <stdio.h>
      2	 int main(){
      3	   puts("hello");
 →    4	   puts("world");
      5	   return 0;
      6	 }
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
gef➤  

不过如果我们gdb在当前目录找不到test.c文件,则无法进行源码调试。如果源码在其他目录可以在gdb中用directory命令指定,或者在启动gdb时用-d参数指定,一样可以看到源码。比如我们将test.c移动到其父目录后:

mv test.c  ../
➜  gdb -q ./test -d ../

源码调试libc

所以显然我们要准备两个东西:

  • 带调试的libc.so
  • 对应版本的glibc源码

所以首先安装带调试版本的libc:

sudo apt install libc6-dbg  
➜  sudo apt install libc6-dbg:i386

然后下载当前版本的libc源码:

  1. 首先修改/etc/apt/sources.list,将deb-src配置开启
  2. 更新sudo apt update
  3. 使用apt source下载源码apt source libc6-dev

然后在调试时用directory把目录指向对应子文件夹就可以了,比如我要调试malloc:

➜  gdb -q ./applestore -d ../../glibc_source/glibc-2.23/malloc

然后在当GOT表已经初始化完成之后进入到malloc函数之后便可以跟到malloc源码中进行调试:

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:malloc.c+2902 ────
   2897	 
   2898	 /*------------------------ Public wrappers. --------------------------------*/
   2899	 
   2900	 void *
   2901	 __libc_malloc (size_t bytes)
  2902	 {
   2903	   mstate ar_ptr;
   2904	   void *victim;
   2905	 
   2906	   void *(*hook) (size_t, const void *)
   2907	     = atomic_forced_read (__malloc_hook);
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────

参考