std::string getStackTrace()

in prod/native/libcommon/code/os/StackTraceCapture.cpp [34:84]


std::string getStackTrace(size_t numberOfFramesToSkip) {
    unw_cursor_t unwindCursor;
    unw_context_t unwindContext;
    constexpr size_t funcNameBufferSize = 100;
    char funcNameBuffer[funcNameBufferSize];
    unw_word_t offsetInsideFunc;

    if (unw_getcontext(&unwindContext) < 0) {
        return {};
    }
    if (unw_init_local(&unwindCursor, &unwindContext) < 0) {
        return {};
    }

    std::string output;
    for (size_t frameIndex = 0;; ++frameIndex) {
        // +1 is for this function frame
        if (frameIndex >= numberOfFramesToSkip + 1) {
            unw_proc_info_t pi;
            if (unw_get_proc_info(&unwindCursor, &pi) == 0) {
                *funcNameBuffer = 0;
                offsetInsideFunc = 0;
                int getProcNameRetVal = unw_get_proc_name(&unwindCursor, funcNameBuffer, funcNameBufferSize, &offsetInsideFunc);
                if (getProcNameRetVal != UNW_ESUCCESS && getProcNameRetVal != -UNW_ENOMEM) {
                    strcpy(funcNameBuffer, "???");
                    unw_word_t pc;
                    unw_get_reg(&unwindCursor, UNW_REG_IP, &pc);
                    offsetInsideFunc = pc - pi.start_ip;
                }

                Dl_info dlInfo;
                if (dladdr((const void *)pi.gp, &dlInfo)) {
                    output.append(elasticapm::utils::stringPrintf("%s(%s+0x%lx) ModuleBase: %p FuncStart: 0x%lx FuncEnd: 0x%lx FuncStartRelative: 0x%lx FuncOffsetRelative: 0x%lx\n\t'addr2line -afCp -e \"%s\" %lx'\n", dlInfo.dli_fname ? dlInfo.dli_fname : "???", dlInfo.dli_sname ? dlInfo.dli_sname : funcNameBuffer, offsetInsideFunc, dlInfo.dli_fbase, pi.start_ip, pi.end_ip, pi.start_ip - reinterpret_cast<unw_word_t>(dlInfo.dli_fbase), pi.start_ip - reinterpret_cast<unw_word_t>(dlInfo.dli_fbase) + offsetInsideFunc, dlInfo.dli_fname ? dlInfo.dli_fname : "???", pi.start_ip - reinterpret_cast<unw_word_t>(dlInfo.dli_fbase) + offsetInsideFunc));
                } else {
                    output.append(elasticapm::utils::stringPrintf("dladdr failed on frame %zu\n", frameIndex));
                }
            } else {
                output.append(elasticapm::utils::stringPrintf("unw_get_proc_info failed on frame %zu", frameIndex));
            }
        }

        int unwindStepRetVal = 0;
        unwindStepRetVal = unw_step(&unwindCursor);
        if (unwindStepRetVal < 0) {
            return output;
        } else if (unwindStepRetVal == 0) {
            break;
        }
    }
    return output;
}