//
// Created by qwe on 2019/12/19.
//


// 堆栈
struct BacktraceState
{
    void** current;
    void** end;
};
_Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg)
{
    BacktraceState* state = reinterpret_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;
}
int captureBacktrace(void** buffer, int max)
{
    BacktraceState state = {buffer, buffer + max};
    _Unwind_Backtrace(unwindCallback, &state);
    return state.current - buffer;
}
void dumpBacktrace(void** buffer, int count)
{
    for(int idx = 0; idx < count; ++idx)
    {
        const void* addr = buffer[idx];
        const char* symbol = "";
        const char* fileName = "";
        Dl_info info;
        if(dladdr(addr, &info))
        {
            if(info.dli_sname)
            {
                symbol = info.dli_sname;
            }
            if(info.dli_fname)
            {
                fileName = info.dli_fname;
            }
        }
        LOG_ERROR << " #" << std::setw(2) << idx << ": " << addr << "  " << fileName << "  " << symbol << LOG_ENDL;
    }
}
