I'm developing the native application that works with Android via the NDK.
I need to call the backtrace()
function when there is a crash. The problem is that there is no <execinfo.h>
for the NDK.
Is there any other way to get that back trace?
Android have no backtrace()
, but unwind.h
is here to serve. Symbolization is possible via dladdr()
.
The following code is my simple implementation of backtrace (with no demangling):
#include <iostream>
#include <iomanip>
#include <unwind.h>
#include <dlfcn.h>
namespace {
struct BacktraceState
{
void** current;
void** end;
};
static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)
{
BacktraceState* state = static_cast<BacktraceState*>(arg);
uintptr_t pc = _Unwind_GetIP(context);
if (pc) {
if (state->current == state->end) {
return _URC_END_OF_STACK;
} else {
*state->current++ = reinterpret_cast<void*>(pc);
}
}
return _URC_NO_REASON;
}
}
size_t captureBacktrace(void** buffer, size_t max)
{
BacktraceState state = {buffer, buffer + max};
_Unwind_Backtrace(unwindCallback, &state);
return state.current - buffer;
}
void dumpBacktrace(std::ostream& os, void** buffer, size_t count)
{
for (size_t idx = 0; idx < count; ++idx) {
const void* addr = buffer[idx];
const char* symbol = "";
Dl_info info;
if (dladdr(addr, &info) && info.dli_sname) {
symbol = info.dli_sname;
}
os << " #" << std::setw(2) << idx << ": " << addr << " " << symbol << "\n";
}
}
It may be used for backtracing into LogCat like
#include <sstream>
#include <android/log.h>
void backtraceToLogcat()
{
const size_t max = 30;
void* buffer[max];
std::ostringstream oss;
dumpBacktrace(oss, buffer, captureBacktrace(buffer, max));
__android_log_print(ANDROID_LOG_INFO, "app_name", "%s", oss.str().c_str());
}