简体   繁体   English

c++中如何直接使用addr2line

[英]How to use addr2line directly in c++

update: this question cannot fix my need, addr2line source is not only 400 lines source, it's relative with other binutils source, I wanna a light solution to do the "get backtrace line number"更新: 这个问题不能解决我的需要,addr2line 源不仅是 400 行源,它与其他 binutils 源相关,我想要一个简单的解决方案来执行“获取回溯行号”

I use following that can get backtrace line number:我使用以下可以获得回溯行号:

addr2line -e /home/roroco/Dropbox/c/ro-c/cmake-build-debug/ex/test_backtrace_with_line_number  0x400d0b

but if I wanna get backtrace all line numbers, I must invoke addr2line cli line by line, it's slow, is there way to get backtrace line number without cli but use pure c++?但是如果我想回溯所有行号,我必须逐行调用 addr2line cli,它很慢,有没有办法在没有 cli 的情况下获取回溯行号但使用纯 C++? or other alternative lib can get line number或其他替代库可以获得行号

I know if I see addr2line, I can do this, if has more convenient c++ lib, please tell me我知道如果我看到addr2line,我可以这样做,如果有更方便的c++ lib,请告诉我

here is my code to get line number with addr2line, I hope pure c++ solution to instead addr2line cli这是我使用 addr2line 获取行号的代码,我希望使用纯 C++ 解决方案来代替 addr2line cli

#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <zconf.h>
#include "regex"

std::string getexepath() {
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
}

std::string sh(std::string cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
            result += buffer.data();
        }
    }
    return result;
}


void print_backtrace(void) {
    void *bt[1024];
    int bt_size;
    char **bt_syms;
    int i;

    bt_size = backtrace(bt, 1024);
    bt_syms = backtrace_symbols(bt, bt_size);
    std::regex re("\\[(.+)\\]");
    auto exec_path = getexepath();
    for (i = 1; i < bt_size; i++) {
        std::string sym = bt_syms[i];
        std::smatch ms;
        if (std::regex_search(sym, ms, re)) {
            std::string addr = ms[1];
            std::string cmd = "addr2line -e " + exec_path + " -f -C " + addr;
            auto r = sh(cmd);
            std::regex re2("\\n$");
            auto r2 = std::regex_replace(r, re2, "");
            std::cout << r2 << std::endl;
        }
    }
    free(bt_syms);
}

void test_m() {
    print_backtrace();
}

int main() {
    test_m();
    return 0;
}

change addr2line source is so hard and I give up this way, I receive @500 - Internal Server Error suggestion, addr2line cli can receive multi addrs, so I change my code like following, only run addr2line once更改 addr2line 源是如此困难,我放弃了这种方式,我收到@500 - 内部服务器错误建议,addr2line cli 可以接收多个地址,所以我更改了我的代码,如下所示,只运行一次 addr2line

#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <zconf.h>
#include "regex"
#include "vector"

std::string getexepath() {
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
}

std::string sh(std::string cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
            result += buffer.data();
        }
    }
    return result;
}


void print_backtrace(void) {
    void *bt[1024];
    int bt_size;
    char **bt_syms;
    int i;

    bt_size = backtrace(bt, 1024);
    bt_syms = backtrace_symbols(bt, bt_size);
    std::regex re("\\[(.+)\\]");
    auto exec_path = getexepath();
    std::string addrs = "";
    for (i = 1; i < bt_size; i++) {
        std::string sym = bt_syms[i];
        std::smatch ms;
        if (std::regex_search(sym, ms, re)) {
            std::string m = ms[1];
            addrs += " " + m;
        }
    }
    auto r = sh("addr2line -e " + exec_path + " -f -C " + addrs);
    std::cout << r << std::endl;
    free(bt_syms);
}

void test_m() {
    print_backtrace();
}

int main() {
    test_m();
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM