Loading

C语言RELEASE版本程序堆栈调试信息分离和还原

C程序DEMO 文件 main.c

#define _GNU_SOURCE
#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdint.h>
#include <ucontext.h>
#include <unistd.h>
#include <sys/wait.h>
#include <setjmp.h>

static void *buffer[100] = {0}; // 用于存储地址列表
static int nptrs = 0;
static sigjmp_buf jmpbuf;

void print_stack_trace()
{
    printf("Relative addresses:\n");
    for (int i = 0; i < nptrs; i++)
    {
        Dl_info info;
        if (dladdr(buffer[i], &info) != 0)
        {
            uintptr_t base = (uintptr_t)info.dli_fbase;
            printf("Frame base %p\n", info.dli_fbase);
            uintptr_t addr = (uintptr_t)buffer[i];
            printf("Frame %d: relative offset = 0x%lx\n", i, (unsigned long)(addr - base));
        }
        else
        {
            printf("Frame %d: no information available\n", i);
        }
    }
}

void segv_handler(int sig)
{
    // 捕获调用栈
    nptrs = backtrace(buffer, 100);
    backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO);

    siglongjmp(jmpbuf, 1);
}



void crash_function()
{
    int *p = NULL;
    *p = 42; // 故意制造一个段错误
}

int main()
{
    int jmpid = 0;
    pid_t pid = fork();
    
    if (pid < 0) {
        perror("fork failed");
        exit(1);
    }
    
    if (pid == 0) {
        // 子进程
        pid_t cpid = getpid();
        printf("Child: %d \n", cpid);
        jmpid = setjmp(jmpbuf);
        if (jmpid == 0)
        {
            signal(SIGSEGV, segv_handler);
        }
        else
        {
            printf("Child tag: %d \n", cpid);
            // print_stack_trace();
            signal(SIGSEGV, SIG_DFL);
		    kill(pid, SIGSEGV);
        }
    
    } else {
        // 父进程
        printf("Parent: %d \n", getpid());
        // 等待子进程结束
        waitpid(pid, NULL, 0);
        
        printf("Parent end: %d \n", getpid());
        exit(0);
    }

    crash_function();

    return 0;
}

编译 -O2 优化

mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ gcc -o2 main.c -o main 
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ ./main 
Parent: 26425 
Child: 26426 
./main(+0x130b)[0x55c0f8c7930b]
/lib/x86_64-linux-gnu/libc.so.6(+0x3c050)[0x7fbcc0f09050]
./main(+0x1351)[0x55c0f8c79351]
./main(+0x1483)[0x55c0f8c79483]
/lib/x86_64-linux-gnu/libc.so.6(+0x2724a)[0x7fbcc0ef424a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7fbcc0ef4305]
./main(+0x1141)[0x55c0f8c79141]
Child tag: 26426 
Segmentation fault (core dumped)
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main 0x1483
??:?
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ 

-O2 优化后生成的程序 main 不能通过堆栈的相对地址查询到堆栈信息

编译 -g -O2 附加调试信息和优化

mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ gcc -g -o2 main.c -o main 
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ ./main 
Parent: 27118 
Child: 27119 
./main(+0x130b)[0x5569150ce30b]
/lib/x86_64-linux-gnu/libc.so.6(+0x3c050)[0x7fa78e6d4050]
./main(+0x1351)[0x5569150ce351]
./main(+0x1483)[0x5569150ce483]
/lib/x86_64-linux-gnu/libc.so.6(+0x2724a)[0x7fa78e6bf24a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7fa78e6bf305]
./main(+0x1141)[0x5569150ce141]
Child tag: 27119 
Segmentation fault (core dumped)
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main 0x1483
/home/mestc/repos/cpp/main.c:93

剔除调试信息

mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ objcopy --only-keep-debug main main.debug
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main 0x1483
/home/mestc/repos/cpp/main.c:93
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main.debug 0x1483
/home/mestc/repos/cpp/main.c:93
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ ./main
Parent: 27844 
Child: 27845 
./main(+0x130b)[0x5556cb0a430b]
/lib/x86_64-linux-gnu/libc.so.6(+0x3c050)[0x7f1e086d2050]
./main(+0x1351)[0x5556cb0a4351]
./main(+0x1483)[0x5556cb0a4483]
/lib/x86_64-linux-gnu/libc.so.6(+0x2724a)[0x7f1e086bd24a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f1e086bd305]
./main(+0x1141)[0x5556cb0a4141]
Child tag: 27845 
Segmentation fault (core dumped)
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ ./main.debug 
bash: ./main.debug: cannot execute binary file: Exec format error
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ strip --strip-debug main
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main 0x1483
??:?
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ ./main
Parent: 28082 
Child: 28083 
./main(+0x130b)[0x55b2ac28d30b]
/lib/x86_64-linux-gnu/libc.so.6(+0x3c050)[0x7f9f691f2050]
./main(+0x1351)[0x55b2ac28d351]
./main(+0x1483)[0x55b2ac28d483]
/lib/x86_64-linux-gnu/libc.so.6(+0x2724a)[0x7f9f691dd24a]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85)[0x7f9f691dd305]
./main(+0x1141)[0x55b2ac28d141]
Child tag: 28083 
Segmentation fault (core dumped)
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main.debug 0x1483
/home/mestc/repos/cpp/main.c:93
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ 

还原 main 的调试信息

mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ objcopy --add-gnu-debuglink=main.debug main
mestc@DESKTOP-4OJQ0ID:~/repos/cpp$ addr2line -e main 0x1483
/home/mestc/repos/cpp/main.c:93
posted @ 2025-03-13 10:42  microestc  阅读(28)  评论(0)    收藏  举报