gdb调试出错程序

  • Post author:
  • Post category:其他


今天写了一个hook函数,执行出错,不得其解,错误信息无法定位原因,使用gdb很快解决。

Ubuntu 16.04.6 LTS



一、背景

写了一个hook函数,放在LD_PRELOAD下,用来监控malloc和free行为,代码如下:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <syslog.h>
#include <unistd.h>

#define gettid() syscall(__NR_gettid)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define TRY_LOAD_HOOK_FUNC(name) if (unlikely(!g_sys_##name)) {g_sys_##name = (sys_##name##_t)dlsym(RTLD_NEXT,#name);}


typedef void* (*sys_malloc_t)(size_t size);
static sys_malloc_t g_sys_malloc = NULL;
void* malloc(size_t size)
{
    printf("start");
    TRY_LOAD_HOOK_FUNC(malloc);
    void *p = g_sys_malloc(size);
    printf ("%lu malloc (%u) == 0x%08x\n", gettid(), (unsigned int) size, p);
    return p;
}

编译文件命令如下:

gcc -o myhook.so -fPIC -shared  myhook.c -ldl

测试程序的内容如下malloc.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
    printf("enter\n");
    void *p = malloc(1);
    free(p);
    printf("left,%p\n", p);
}

编译这个文件:

gcc -o malloc ./malloc.c

现在使用前面的自定义hook函数输出错误原因:

bingsanlang@ubuntu:~$ LD_PRELOAD=./myhook.so ./malloc
Segmentation fault (core dumped)

从Segmentation fault (core dumped)这个错误信息 根本不知道哪儿出问题了,这时候可以借助下gdb查看下具体错误原因和调用栈。



二、gdb调试问题代码

输入如下命令,对malloc执行文件进行调试:

gdb ./mallco

进入后设置环境变量并r运行:

(gdb) set environment LD_PRELOAD=./hook.so
(gdb) r
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff785819e in _IO_vfprintf_internal (s=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    format=0x7ffff7bd57dd "my malloc: %zu\n", ap=ap@entry=0x7fffff7ff428)
    at vfprintf.c:1267
1267	vfprintf.c: No such file or directory.

输入bt能看到详细信息:

(gdb) bt
#0  0x00007ffff785819e in _IO_vfprintf_internal (s=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    format=0x7ffff7bd57dd "my malloc: %zu\n", ap=ap@entry=0x7fffff7ff428)
    at vfprintf.c:1267
#1  0x00007ffff78608a9 in __printf (format=<optimized out>) at printf.c:33
#2  0x00007ffff7bd5754 in malloc () from ./hook.so
#3  0x00007ffff78781e5 in __GI__IO_file_doallocate (
    fp=0x7ffff7bd0620 <_IO_2_1_stdout_>) at filedoalloc.c:127
#4  0x00007ffff78865a4 in __GI__IO_doallocbuf (
    fp=fp@entry=0x7ffff7bd0620 <_IO_2_1_stdout_>) at genops.c:398
#5  0x00007ffff7885908 in _IO_new_file_overflow (f=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    ch=-1) at fileops.c:820
#6  0x00007ffff788429d in _IO_new_file_xsputn (f=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    data=0x7ffff7bd57dd, n=11) at fileops.c:1331
#7  0x00007ffff7858251 in _IO_vfprintf_internal (s=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    format=0x7ffff7bd57dd "my malloc: %zu\n", ap=ap@entry=0x7fffff7ffbd8)
    at vfprintf.c:1320
#8  0x00007ffff78608a9 in __printf (format=<optimized out>) at printf.c:33
#9  0x00007ffff7bd5754 in malloc () from ./hook.so
#10 0x00007ffff78781e5 in __GI__IO_file_doallocate (
    fp=0x7ffff7bd0620 <_IO_2_1_stdout_>) at filedoalloc.c:127
#11 0x00007ffff78865a4 in __GI__IO_doallocbuf (
    fp=fp@entry=0x7ffff7bd0620 <_IO_2_1_stdout_>) at genops.c:398
#12 0x00007ffff7885908 in _IO_new_file_overflow (f=0x7ffff7bd0620 <_IO_2_1_stdout_>, 
    ch=-1) at fileops.c:820

堆栈 挺多,有经验的人大概能立马看出来是printf调用 malloc递归调用的问题。

如果没有相关经验 的人,可以根据r运行 的错误 信息 :

1267 vfprintf.c: No such file or directory.

再加上一些关键字:printf malloc等搜索,可以从stackoverflow等 网站上查到问题原因。



三、解决办法

从2可以得到问题的原因是malloc调用printf,printf初始的情况下会调用malloc申请内存,形成递归调用,从而堆栈溢出,程序终止,解决办法就是使用write方法代替printf方法。

问题解决的链接 如下:


https://stackoverflow.com/questions/22196097/ld-preload-causing-segmentation-fault-for-linux-commands


https://docs.oracle.com/cd/E19253-01/819-7050/chapter3-24/

解决之后的代码如

Linux的hook机制:自定义动态链接库hook

文章中所示。



版权声明:本文为whbing1471原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。