title: How to unwind the stack to get backtrace for the specified stack pointer (SP)?
body: <p>I'm writing this for Android (ARM only), but I believe the principle is the same for generic Linux as well.</p>
  
  <p>I'm trying to capture the stack trace from within the signal handler, so that I can log it when my app crashes. This is what I've come up with using <code>&lt;unwind.h&gt;</code>.<br>
  Initialization:</p>
  
  <pre><code>struct sigaction signalhandlerDescriptor;
  memset(&amp;signalhandlerDescriptor, 0, sizeof(signalhandlerDescriptor));
  signalhandlerDescriptor.sa_flags = SA_SIGINFO;
  signalhandlerDescriptor._u._sa_sigaction = signalHandler;
  sigaction(SIGSEGV, &amp;signalhandlerDescriptor, 0);
  </code></pre>
  
  <p>The code itself:</p>
  
  <pre><code>struct BacktraceState
  {
      void** current;
      void** end;
      void* pc;
  };
  
  inline _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)
  {
      BacktraceState* state = static_cast&lt;BacktraceState*&gt;(arg);
      state-&gt;pc = (void*)_Unwind_GetIP(context);
      if (state-&gt;pc)
      {
          if (state-&gt;current == state-&gt;end)
              return _URC_END_OF_STACK;
          else
              *state-&gt;current++ = reinterpret_cast&lt;void*&gt;(state-&gt;pc);
      }
      return _URC_NO_REASON;
  }
  
  inline size_t captureBacktrace(void** addrs, size_t max, unsigned long pc)
  {
      BacktraceState state = {addrs, addrs + max, (void*)pc};
      _Unwind_Backtrace(unwindCallback, &amp;state);
      personality_routine();
  
      return state.current - addrs;
  }
  
  inline void dumpBacktrace(std::ostream&amp; os, void** addrs, size_t count)
  {
      for (size_t idx = 0; idx &lt; count; ++idx) {
          const void* addr = addrs[idx];
          const char* symbol = "";
  
          Dl_info info;
          if (dladdr(addr, &amp;info) &amp;&amp; info.dli_sname) {
              symbol = info.dli_sname;
          }
  
          int status = -3;
          char * demangledName = abi::__cxa_demangle(symbol, 0, 0, &amp;status);
          os &lt;&lt; "#" &lt;&lt; idx &lt;&lt; ": " &lt;&lt; addr &lt;&lt; "  " &lt;&lt; (status == 0 ? demangledName : symbol) &lt;&lt; "\n";
          free(demangledName);
      }
  }
  
  void signalHandler(int sig, siginfo_t *siginfo, void *uctx)
  {
      ucontext * context = (ucontext*)uctx;
      unsigned long PC = context-&gt;uc_mcontext.arm_pc;
      unsigned long SP = context-&gt;uc_mcontext.arm_sp;
  
      Logger() &lt;&lt; __PRETTY_FUNCTION__ &lt;&lt; "Fatal signal:" &lt;&lt; sig;
      const size_t maxNumAddresses = 50;
      void* addresses[maxNumAddresses];
      std::ostringstream oss;
  
      const size_t actualNumAddresses = captureBacktrace(addresses, maxNumAddresses, PC);
      dumpBacktrace(oss, addresses, actualNumAddresses);
      Logger() &lt;&lt; oss.str();
      exit(EXIT_FAILURE);
  }
  </code></pre>
  
  <p>Problem: if I get the PC register by calling <code>_Unwind_GetIP(context)</code> in <code>unwindCallback</code>, I get the complete trace <em>for the signal handler stack</em>. Which is a separate stack, and that's obviously not what I want. So I tried supplying the PC taken from the <code>ucontext</code> in signal handler, and got a weird result: I get one stack entry, it is the correct entry - the function which caused the signal in the first place. But it's logged twice (even the address is the same, so it's not a symbolic name look up bug). Obviously, that's not good enough - I need the whole stack. And I wonder if this result is merely accidental (i. e. it shouldn't work in general.</p>
  
  <p>Now, I read I need to also supply the stack pointer, which I apparently can get from <code>ucontext</code>, same as PC. But I don't know what to do with it. Do I have to unwind manually instead of using <code>_Unwind_Backtrace</code>? If so, can you give me sample code? I've been searching for the better part of a day, and still couldn't find anything I could copy and paste into my project.</p>
  
  <p>For what it's worth, here's the <a href="http://www.nongnu.org/libunwind/download.html">libunwind</a> source which contains <code>_Unwind_Backtrace</code> definition. Thought I could figure something out if I see its source, but it's way more complicated than I expected.</p>