backward-cpp icon indicating copy to clipboard operation
backward-cpp copied to clipboard

Slightly incorrect stack trace in release (with debug info) mode

Open xirius opened this issue 7 years ago • 4 comments

Here is the sample code that reproduces the issue: #define BACKWARD_HAS_DW 1

//... includes above
#define BACKWARD_HAS_DW 1
using namespace backward;

void print(ResolvedTrace& trace)
{
    for (auto& loc : trace.inliners)
        std::cout
            << " " << loc.filename
            << " " << loc.function
            << ": "
            << loc.line
            << std::endl;
}

void Backtrace()
{
    StackTrace st;
    st.load_here(32);

    TraceResolver tr;
    tr.load_stacktrace(st);

    for (size_t i = 0; i < st.size(); ++i)
    {
        ResolvedTrace trace = tr.resolve(st[i]);

        print(trace);

        std::cout
            << " " << trace.object_filename
            << " " << trace.object_function
            << " [" << trace.addr << "]: "
            << trace.source.line
            << std::endl;
    }
}

namespace ns
{
    template <typename T, typename U>
    inline void foo(T t, U u)
    {
        Backtrace();
    }
}

template <typename T>
struct Klass
{
    T t;

    inline void bar()
    {
        ns::foo(t, true);
        auto x = 0;
    }
};

inline void c()
{
    Klass<int> k;
    k.bar();
}

void b()
{
    c();
}

void a()
{
    b();
}

int main(int argc, char* argv[])
{
    a();
}

screenshot

The stack trace it produces (removed not interesting info) is:

sample Backtrace() [0x559733a2e67a]: 41 sample/src/test.cpp foo<int, bool>: 77 sample/src/test.cpp bar: 85 sample/src/test.cpp c: 90 sample/src/test.cpp b: 95 sample/src/test.cpp a: 100 sample main [0x559733a2e258]: 66

line 41 is inside Backtrace - ok line 77 is inside bar() - reported foo<int, bool> line 85 is inside c() - reported bar() line 90 is inside b() - reported c() etc ...

It looks like it is shifted (inlined functions). Works perfectly in debug. Not sure if interpret it correctely though.

xirius avatar Nov 28 '18 20:11 xirius

are you using unwind for walking the stack?

what platform, os, compiler are you using

On Wed, Nov 28, 2018, 12:23 Alexandre Anoutchine <[email protected] wrote:

Here is the sample code that reproduces the issue: #define BACKWARD_HAS_DW 1

//... includes above #define BACKWARD_HAS_DW 1using namespace backward; void print(ResolvedTrace& trace) { for (auto& loc : trace.inliners) std::cout << " " << loc.filename << " " << loc.function << ": " << loc.line << std::endl; } void Backtrace() { StackTrace st; st.load_here(32);

TraceResolver tr;
tr.load_stacktrace(st);

for (size_t i = 0; i < st.size(); ++i)
{
    ResolvedTrace trace = tr.resolve(st[i]);

    print(trace);

    std::cout
        << " " << trace.object_filename
        << " " << trace.object_function
        << " [" << trace.addr << "]: "
        << trace.source.line
        << std::endl;
}

} namespace ns { template <typename T, typename U> inline void foo(T t, U u) { Backtrace(); } } template <typename T>struct Klass { T t;

inline void bar()
{
    ns::foo(t, true);
    auto x = 0;
}

}; inline void c() { Klass k; k.bar(); } void b() { c(); } void a() { b(); } int main(int argc, char* argv[]) { a(); }

[image: screenshot] https://user-images.githubusercontent.com/417876/49179983-d4a1aa80-f353-11e8-822d-9a054d4549d0.png

The stack trace it produces (removed not interesting info) is:

sample Backtrace() [0x559733a2e67a]: 41 sample/src/test.cpp foo<int, bool>: 77 sample/src/test.cpp bar: 85 sample/src/test.cpp c: 90 sample/src/test.cpp b: 95 sample/src/test.cpp a: 100 sample main [0x559733a2e258]: 66

line 41 is inside Backtrace - ok line 77 is inside bar() - reported foo<int, bool> line 85 is inside c() - reported bar() line 90 is inside b() - reported c() etc ...

It looks like it is shifted (inlined functions). Works perfectly in debug. Not sure if interpret it correctely though.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/bombela/backward-cpp/issues/130, or mute the thread https://github.com/notifications/unsubscribe-auth/AANMjNT2pdV0UMx970u5_z3wyXEOTUOKks5uzvDcgaJpZM4Y4X3m .

bombela avatar Nov 28 '18 21:11 bombela

Yes, unwind (dw, elf) Ubuntu 18.04.1 x86_64 gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

xirius avatar Nov 28 '18 21:11 xirius

It seems that for inlined functions the line number doesn't correspond to the function name.

struct inliners_search_cb {
...
 case DW_TAG_inlined_subroutine:
	ResolvedTrace::SourceLoc sloc;
	Dwarf_Attribute attr_mem;

	if ((name = dwarf_diename(die))) {
		sloc.function = name;
	}
	if ((name = die_call_file(die))) {
		sloc.filename = name;
	}

	Dwarf_Word line = 0, col = 0;
	dwarf_formudata(dwarf_attr(die, DW_AT_call_line, &attr_mem), &line);

So the function name it reports doesn't correspond to the line number. It is like it is shifted for the function names but the line numbers are correct. Any idea what might be wrong ?

By the way, is it possible to have demangled names for the inline functions ? (I'm using elfutils)

xirius avatar Apr 18 '19 20:04 xirius

As far as I can tell the code relies on the information from the die. Could it be in your case the https://github.com/bombela/backward-cpp/blob/master/backward.hpp#L2759 branch is taken and behaves wrong?

Dwarf function names are not mangled. Only object information (used as fallback) are mangled though, and we demangle them as best as we can.

bombela avatar Apr 18 '19 21:04 bombela