libunwind doesn't work - unw_step() repeatedly returns the same symbol

85 views
Skip to first unread message

George Xian

unread,
Oct 31, 2019, 1:14:13 AM10/31/19
to android-ndk
I am working on a software project that is a Qt for Android project. The source code is mainly C/C++. The NDK version being used is r20 (Clang compiler) and the Qt version is 5.13. I have the libraries built in Visual Studio using the Android C++ development toolkit. The fronted Qt application is built in QtCreator 4.9.2.

We need to write the stack trace to a file at certain points of the application. The typical way to do this is using libunwind. I have tested libunwind with a sample application and it works as expected. However, in the production application, it keeps returning the same symbol upon each unw_step() call.

Note that for this topic, libunwind is not being used inside a signal handler. Notice the lack of copying of the context into unw_cursor registers. 

Below is the helper function I have written to generate the stack trace. It writes the addresses of each stack frame to the "trace" array passed in as the first argument. It also gives the ability to skip the first few frames:

    int StackTrace::Generate(intptr_t trace[], int size, int skipFrames)
    {
        int stackcount = 0;
        unw_context_t unw_context;
        if (unw_getcontext(&unw_context) < 0)
        {
            return -1;
        }

        unw_cursor_t unw_cursor;
        if (unw_init_local(&unw_cursor, &unw_context) < 0)
        {
            return -1;
        }

        int index = 0;
        while (unw_step(&unw_cursor) > 0 && stackcount < size)
        {
            if (index >= skipFrames)
            {
                unw_word_t ip;
                unw_get_reg(&unw_cursor, UNW_REG_IP, &ip);

                *trace = ip;
                trace++;
                stackcount++;
            }

            index++;
        }

        return stackcount;
    }

The calls to unw_step() always returns "1" and the subsequent call to "unw_get_reg(&unw_cursor, UNW_REG_IP, &ip)" always returns the same value for "ip". Resulting in an infinite loop if the "stackcount < size" condition isn't also checked. I decoded the symbol for "ip" and it is correct - one level up from this helper function. I have also noticed that the register UNW_ARM_R14 (which is the link register) is always the same is the value for "ip" (hence the infinite loop?), but I have no idea why this is happening.

Does anyone know what is going on here? Which compilation options should I check ("-funwind-tables" doesn't seem to change anything)? Why would the same code work under the test app but not the production app? What else should I verify?

georg...@trimble.com

unread,
Jul 9, 2021, 12:47:26 AMJul 9
to android-ndk
I did manage to libunwind working on my application. Removing excess this excess clause in some of Java classes fixed the issue:

    static
    {
        System.loadLibrary("SCJNI");
    }

Reply all
Reply to author
Forward
0 new messages