glibc:无法获取某些部分的展开信息

glibc: unable to get unwind information for certain sections

提问人:Aliasgar 提问时间:10/18/2021 最后编辑:Peter CordesAliasgar 更新时间:8/4/2022 访问量:386

问:

我目前面临 glibc v2.22 的问题,我无法获得正确的放松信息。 当有 SIGABRT 应用程序时,它从 glibc 调用中止函数。它应该使用在构建中启用的展开信息。但是,它正在扫描堆栈(如屏幕截图中地址下方的红线所示)并提供误导性信息,如所附的屏幕截图所示(使用哨兵分析转储)。

这里,称为 which does which 然后中止主应用程序。在分析转储时,do_crash 函数调用 which 从未在主应用程序的堆栈中。do_crashassert(0)_fini

我已经通过使用 为 glibc 启用了 unwind。我也尝试过使用诸如 and 之类的标志,但它也没有用。CFLAGS += "-funwind-tables"-rdynamic-fno-omit-frame-pointer

我在这里遗漏了什么吗?如何获得信号的完整回溯,尤其是 SIGABRT?

提前致谢enter image description here

C glibc Sentry Backtrace 堆栈放卷

评论

0赞 KamilCuk 8/4/2022
Here, do_crash is called which does assert(0) which then aborts the main applicationglibc 源代码中没有。那么您的应用程序是否正在接收 SIGABRT,或者您的代码正在执行?do_crashassert(0)

答:

0赞 KamilCuk 8/4/2022 #1

当有 SIGABRT 应用程序时,它正在从 glibc 调用中止函数

这不是真的,除非您明确注册它,否则不会发生这种情况。

我已经使用 CFLAGS += “-funwind-tables” 为 glibc 启用了 unwind

它告诉编译器添加信息,它不会“启用展开”。使用 -funwind-tables 编译时究竟会发生什么?

在这里,调用了 do_crash assert(0),然后中止了主应用程序。

这与接收 SIGABRT 信号无关。

我在这里遗漏了什么吗?

我相信你做出了错误的假设——某些东西被调用了 SIGABRT,SIGABRT 被发送到断言,即被调用.默认情况下,SIGABRT 上不会调用任何内容,并且程序在接收 SIGABRT 时终止(请参阅 ),只是终止程序而不引发 SIGABRT,并引发信号,而不是接收信号。abort()SIGABRTman 7 signalassertabort()SIGABRT

如何获得信号的完整回溯,尤其是 SIGABRT?

注册一个将执行此操作的处理程序。请参 阅如何在程序崩溃时自动生成堆栈跟踪

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

void handler(int sig) {
    void *array[10];
    size_t size;
    size = backtrace(array, 10);
    backtrace_symbols_fd(array, size, STDERR_FILENO);
    _Exit(1);
}

int main(int argc, char **argv) {
    signal(SIGABRT, handler); // install our handler
    raise(SIGABRT);
}

如果你想打印堆栈跟踪,那就完全不同了,你会覆盖 glibc 处理程序 for assert 来做到这一点:assert()

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

void print_trace(void) {
    void *array[10];
    size_t size;
    size = backtrace(array, 10);
    backtrace_symbols_fd(array, size, STDERR_FILENO);
}

// based on https://code.woboq.org/userspace/glibc/assert/assert.c.html
void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) {
    extern const char *__progname;
    fprintf(stderr, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
            __progname, __progname[0] ? ": " : "",
            file, line,
            function ? function : "", function ? ": " : "",
            assertion);
    print_trace();
    abort();
}

int main() {
    assert(0);
}