跳至主要内容

libunwind查看其他进程的堆栈

 g++ -g3 -o main main.cpp -std=c++11 -lunwind -lunwind-x86_64 -lunwind-ptrace

 

#include <iostream>
#include <libunwind.h>
#include <libunwind-ptrace.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <cxxabi.h>
#include <cstdio>

int wait4stop(pid_t pid) {
    int status = 99;
    do {
        if (waitpid(pid, &status, 0) == -1 || WIFEXITED(status) || WIFSIGNALED(status))
            return 0;
    } while(!WIFSTOPPED(status));
    return 1;
}

void get_backtrace(pid_t pid) {
    unw_cursor_t cursor, resume_cursor;
    unw_context_t context;
    unw_word_t ip, sp, off;

    unw_addr_space_t addr_space = unw_create_addr_space(&_UPT_accessors, __BYTE_ORDER__);
    if (!addr_space) 
        std::cerr << "Failed to create address space" << std::endl;

    unw_getcontext(&context);

    if (-1 == ptrace(PTRACE_ATTACH, pid, nullptr, nullptr))
        std::cerr << "Failed to ptrace" << std::endl;

    if (!wait4stop(pid))
        std::cerr << "wait SIGSTOP of ptrace failed" << std::endl;

    void *rctx = _UPT_create(pid);

    if (rctx == nullptr) 
        std::cerr << "Failed to _UPT_create" << std::endl;

    if (unw_init_remote(&cursor, addr_space, rctx))
        std::cerr << "unw_init_remote failed" << std::endl;

    resume_cursor = cursor;

    const size_t bufflen = 256;
    char *buff = new char[bufflen];

    do {
        char *name = "23333";
        unw_get_reg(&cursor, UNW_REG_IP, &ip);
        unw_get_reg(&cursor, UNW_REG_SP, &sp);

        // 获取函数名字
        if (0 == unw_get_proc_name(&cursor, buff, bufflen, &off)) {
            int status = 99;
            printf("%s---", buff);
            // 如果符号表中没有找到buff的函数名
            if ((name = abi::__cxa_demangle(buff, nullptr, nullptr, &status)) == 0)
                name = buff;
        }
        printf("%s.\n", name);
    } while (unw_step(&cursor) > 0);

    delete[] buff;
    _UPT_resume(addr_space, &resume_cursor, rctx);
    _UPT_destroy(rctx);

    // 然后是将进程结束中断
    ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
}

int main(int argc, char **argv) {
    if (argc < 2) 
        std::cerr << "please input pid" << std::endl;

    pid_t pid = std::atoi(argv[1]);
    get_backtrace(pid);
    return 0;
} 
 
 
 

评论

此博客中的热门博文

ubuntu 添加root登录

Login to your server as root. As the root user, edit the sshd_config file found in  /etc/ssh/sshd_config : vim /etc/ssh/sshd_config ( For details on working with Vim check out our article here !) Add the following line to the file, you can add it anywhere but it’s good practice to find the block about authentication and add it there. PermitRootLogin yes Save and exit the file. Restart the SSH server: systemctl restart sshd or service sshd restart