jeremy-rifkin / cpptrace

Simple, portable, and self-contained stacktrace library for C++11 and newer
MIT License
621 stars 64 forks source link

Empty frame symbol and line #101

Closed AlirezaMUAI closed 6 months ago

AlirezaMUAI commented 6 months ago

I started using cpptrace in my project, and noticed the printed trace lines were mostly without info about function name or line in the code (90% of the printed trace lines looked similar to the last line in the picture below taken from cpptrace documentation, which only has frame address in blue followed only by "at" and file name). image However, when I tried a simple function using backtrace I had written before, I noticed it had more info (like the function names) for the same printed trace lines. This is the function I wrote:

    const int stack_trace_size = STK_TRC_SIZE;
    void* callstack[stack_trace_size];
    int frames = backtrace(callstack, stack_trace_size);
    char** symbols = backtrace_symbols(callstack, frames);
    if (symbols == nullptr) {
        fprintf(stderr, "Error obtaining stack trace\n");
    }
    else{
        fprintf(stderr, "Stack Trace: \n")
        for (int i = 1; i < frames; ++i) {
              fprintf(stderr, "%s \n", symbols[i]);
         }
    }

I initially thought cpptrace is doing some clipping when printing trace lines (as the trace lines for my code could get long), but after investigating the source code (at src/cpprace.cpp) I noticed it is actually due to the trace line (frame) missing symbol and line information. This is the corresponding code taken form src/cpprace.cpp):

            if(!frame.symbol.empty()) {
                stream
                    << " in "
                    << yellow
                    << frame.symbol
                    << reset;
            }
            if(!frame.filename.empty()) {
                stream
                    << " at "
                    << green
                    << frame.filename
                    << reset;
                if(frame.line.has_value()) {
                    stream
                        << ":"
                        << blue
                        << frame.line.value()
                        << reset;
                    if(frame.column.has_value()) {
                        stream << ':'
                            << blue
                            << std::to_string(frame.column.value())
                            << reset;
                    }
                }
            }

After further investigation, I noticed the presence of such info depended on whether I was using the rdynamic compiler linking flag in my CMakeLists.txt file (target_link_options($TARGET PUBLIC "-rdynamic"). Without the flag, I got a trace kinda similar to cpptrace (missing information like function name), but when using the flag I got more trace info. So my guess is having something similar might fix the issue and cause more lines printed by cpptrace have function name and line number?

It is worth mentioning I was using debug Cmake build.

jeremy-rifkin commented 6 months ago

Hi, By default cpptrace will be looking for dwarf debug symbols as opposed to -rdynamic export information like backtrace_symbols relies on. Can you make sure you’re compiling with -g? (though that should be part of DEBUG it would be helpful to double check)

AlirezaMUAI commented 6 months ago

I am compiling with -g in debug. Below are screenshots of my program's stack traces before and after using -g and debug (sorry for covering the line text, I cannot share info about my code or the file names).
Without -g and debug: before_debug

With -g and debug: after_debug

Compiling using -g and in debug does add some info to the printed trace, but there is still a lot of lines hat don't show much information.

jeremy-rifkin commented 6 months ago

Thanks for the additional info. The green paths in the middle that don’t have symbol name or line info, do those correspond to libraries?

If a library is compiled without debug symbols, or if some .cpp files are compiled without debug symbol, cpptrace won’t be able to get debug info for instruction pointers in that code.

AlirezaMUAI commented 6 months ago

Yes, they correspond to libraries. So I guess I have to find a way to compile the library with debug symbols.

Thank you for the help and info!