0
int do_backtrace()
{
  unw_cursor_t cursor;
  unw_context_t context;

  unw_getcontext(&context);
  unw_init_local(&cursor, &context);
  char buf[2048+1];
  int len = 0;
  memset(buf, 0, sizeof(buf));

  int n=0;
  while ( unw_step(&cursor) ) {
    unw_word_t ip, sp, off;

    unw_get_reg(&cursor, UNW_REG_IP, &ip);
    unw_get_reg(&cursor, UNW_REG_SP, &sp);

    char symbol[256] = {0};
    unw_get_proc_name(&cursor, symbol, sizeof(symbol), &off);
    strcat(buf, symbol);
    strcat(buf, "\n");

    // printf("#%-2d 0x%016" PRIxPTR " sp=0x%016" PRIxPTR " %s + 0x%" PRIxPTR "\n",
    //     ++n, ip, sp, symbol, off);

  }
  u_int32_t fd;
  fd = open("/tmp/unwind.txt", O_CREAT|O_RDWR);
  if(fd != -1)
  {
    write(fd, buf, 2048);
  }
  close(fd);

  return len;
}



int fac()
{
    char *pStr= NULL;
    memcpy(pStr, "Hello", strlen("Hello"));
    return 1;

}

int test()
{
  fac();
  return 1;
}

void exception_default_handler(int signo, siginfo_t *info, void *context)
{
  do_backtrace();
  exit(1);
}

#define SETSIG(sa, sig, func) \
    {    memset( &sa, 0, sizeof( struct sigaction ) ); \
         sa.sa_sigaction = func; \
         sa.sa_flags = SA_RESTART | SA_SIGINFO; \
        sigaction(sig, &sa, 0L); \
    }

int main()
{
    struct sigaction sa;
    SETSIG(sa, SIGINT,  exception_default_handler);
    SETSIG(sa, SIGSEGV, exception_default_handler);
    SETSIG(sa, SIGILL,  exception_default_handler);
    SETSIG(sa, SIGBUS,  exception_default_handler);
    SETSIG(sa, SIGQUIT, exception_default_handler);
    SETSIG(sa, SIGFPE,  exception_default_handler);
    test();

  return 0;
}


cat /tmp/unwind.txt
_Z25exception_default_handleriP9siginfo_tPv
sigwaitinfo
_Z4testv
main
libc_start_main_stage2

Above is my code. When I execute the program, the output is as below, why the backtrace is stopped at the function 'test'?

in my view, it should be stopped at the function 'fac' at leat. it is highly expected at 'memcpy'.

I searched many webpage through google and still have no idea. Could you please help to give some suggestions? Thank you very much!

I have tried to modify the code and add more depth function call levels.

I found the output backtrace will always stopped at depth-1 level function.

for example

function A() call function B()

function B() call function C()

function C() call function D()

fragment fail in function D() on purpose.

then the output backtrace will stop at function C()

In my view, it should stop at function D() at least.

jackion
  • 1
  • 2
  • Per [footnote 188 of the C11 standard](https://port70.net/~nsz/c/c11/n1570.html#note188): "Thus, a signal handler cannot, in general, call standard library functions." You can not call functions like `printf()` from a signal handler. **EVERY** example of code that does that is **wrong**. [POSIX allows the calling of async-signal-safe functions](https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03) from a signal handler, but that's all. And `printf()` isn't one of them. – Andrew Henle Mar 28 '22 at 13:14
  • @AndrewHenle Thank you very much for you quick feedback. I have updated my code as above, the same result – jackion Mar 28 '22 at 13:44
  • what version of libunwind are you using? There was a recent PR related to unwinding through SIGSEGV: https://github.com/libunwind/libunwind/pull/449/files – Tanner Firl Apr 07 '23 at 05:06

0 Answers0