0

I am currently facing issue with the glibc v2.22 where I am not able to get the proper unwind information. When there is SIGABRT application, it is calling abort function from glibc. It should be using unwind information which is enabled in the build. However, it is scanning the stack (as indicated by the red line below the address in the screenshot) and providing the misleading information as shown in the screenshot attached (using sentry for analyzing the dump).

Here, do_crash is called which does assert(0) which then aborts the main application. While analyzing the dump, the do_crash function calls the _fini which is never in the main application's stack.

I have enabled unwind for the glibc by using CFLAGS += "-funwind-tables". I also tried with the flags such as -rdynamic and -fno-omit-frame-pointer but it was also of no use.

Am I missing something here? How can I get the complete backtrace of the signals, particularly SIGABRT?

Thanks in advanceenter image description here

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Aliasgar
  • 33
  • 3
  • `Here, do_crash is called which does assert(0) which then aborts the main application` There is no `do_crash` in glibc source code. So is your application receiving SIGABRT __or__ is __your__ code doing `assert(0)`? – KamilCuk Aug 04 '22 at 08:58

1 Answers1

0

When there is SIGABRT application, it is calling abort function from glibc

That is not true, this is not happening, unless you explicitly registered it.

I have enabled unwind for the glibc by using CFLAGS += "-funwind-tables"

It tells the compiler to add the information, it doesn't "enable unwind". What exactly happens when compiling with -funwind-tables?

Here, do_crash is called which does assert(0) which then aborts the main application.

This is not related to receiving SIGABRT signal.

Am I missing something here?

I believe you are making wrong assumptions - that something is called on SIGABRT, that SIGABRT is sent on assert, that abort() is called on SIGABRT. Nothing is called on SIGABRT and the program is terminated when receiving SIGABRT by default (see man 7 signal), assert just terminates the program and doesn't raise SIGABRT, and abort() raises the SIGABRT signal, not receives it.

How can I get the complete backtrace of the signals, particularly SIGABRT?

Register a handler that will do that. See How to automatically generate a stacktrace when my program crashes .

#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);
}

If you want to print stacktrace on assert() that's completely different and you would overwrite the glibc handler for assert to do that:

#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);
}
KamilCuk
  • 120,984
  • 8
  • 59
  • 111