异常信息转储预研笔记-捕获指定进程的异常信号

信号中断中存储堆栈信息

目的

捕获指定进程的信号,当信号为core中止信号时,则对指定进程的异常堆栈信息转储至指定文件。

demo

demo代码如下:由于环境隔离,以下代码为手敲且未编译,谨慎使用,领会思路即可。

cpp 复制代码
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <libunwind-ptrace.h>

static pid_t pid;

static void unwind_pid()
{
    unw_addr_space_r as = unw_create_addr_space(&_UPT_accessors, 0);
    
    long errnum = ptrace(PTRACE_ATTACH, pid, 0 ,0);
    if (errnum != 0)
    {
        printf("error: xxx \n");
    }
    void *context = _UPT_create(pid);
    unw_cursor_t cursor;
    if (unw_init_remote(&cursor, as, context) != 0)
    {
        printf("error: cannot initialize cursor for remote unwinding\n");
    }
    FILE *fp;
    fp = fopen("ap.core", "w");
    if (fp == null)
    {
        printf("error: open file failed!\n");
        return;
    }

    do {
        unw_word_t offset, pc;
        char sym[10240];
        if (unw_get_reg(&cursor, UNW_REG_IP, &pc))
            printf("error: xxx\n");

        fprintf(fp, "0x%lx: ", pc);

        if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0)
        {
            fprintf(fp, "(%s+0x%lx)\n", sym, offset);
        }else
        {    
            printf("no symbol name found.\n");
        }

    } while (unw_step(&cursor) > 0);

    _UPT_destroy(conteext);
    (void)ptrace(PTRACE_DETACH, pid, 0, 0);

    fclose(fp);
}

static void signal_cb(int32_t signo)
{
    unwind_pid();
    signal(signo, SIG_DFL);
}

int main(int argc, char** argv)
{
    if (argc != 2)
    {
        printf("USAGE: unwind-pid <pid>\n");
    }
    pid = atoi(argv[1]);
    signal(SIGINT, signal_cb);
    while(1)
    {
        sleep(1);
    }
    return 0;
}

大致思路是注册一个信号处理回调,demo中是对SIGINT信号做出事件处理 ,可根据需求替换或增加(这里有个小坑,下面讲),具体信号说明依然查看这篇文章《异常信息转储预研笔记》,里面有具体说明。当内核发送信号给指定进程,demo进程就会捕获到并进入信号回调处理函数,后面就是通过libunwind开源库将指定进程收到信号前一刻的堆栈信息输出至指定文件

小坑

在测试demo中,一开始使用的是SIGKILL信号,这个信号是最了解最方便模拟的,我想当然的使用kill -9 来结束指定进程,内核当然就会发送SIGKILL信号给指定进程。

但是多次测试发现,demo进程无法捕获到任何信号,不知道哪里有问题,只能来回研究代码。

反复测试无果,只能求助谷歌,终于明白!原来!SIGKILL和SIGSTOP这两个信号!既不能被忽略!也不能被捕捉!:)

换了SIGINT信号,终于行了!SIGINT信号通过键盘键入ctrl c即可模拟。

最后

目前使用的方式都非常粗糙,仅仅输出最基本的堆栈信息,边学习边记录,有不对的地方欢迎提出来共同进步。

后续

下一步计划:输出更丰富可读性更强的异常转储core文件,可能通过dladdr转换地址为函数名称和行号。

相关推荐
搞机小能手9 分钟前
六个能够白嫖学习资料的网站
笔记·学习·分类
nongcunqq44 分钟前
爬虫练习 js 逆向
笔记·爬虫
汐汐咯1 小时前
终端运行java出现???
笔记
无敌小茶3 小时前
Linux学习笔记之环境变量
linux·笔记
帅云毅3 小时前
Web3.0的认知补充(去中心化)
笔记·学习·web3·去中心化·区块链
豆豆3 小时前
day32 学习笔记
图像处理·笔记·opencv·学习·计算机视觉
nenchoumi31194 小时前
VLA 论文精读(十六)FP3: A 3D Foundation Policy for Robotic Manipulation
论文阅读·人工智能·笔记·学习·vln
凉、介4 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci
鬼面瓷5 小时前
CAPL编程_03
前端·数据库·笔记
帅云毅5 小时前
Web漏洞--XSS之订单系统和Shell箱子
前端·笔记·web安全·php·xss