1

In android NDK, I didn't find the traceback function, so I need implement one myself.

The mytraceback will be called in two call stack, one is f<10>() and the other is in the global override new operator().

But seams only the first one works when I run the code in android. (On linux, seams both works).

So what's the difference to make the mytraceback work in f<10>() but not new operator()?

Code:

#include <iostream>
#include <vector>
#include <algorithm>
#include <unwind.h>

#ifdef LINUX
#include <execinfo.h>
#include <cxxabi.h>
#endif

#include <dlfcn.h>
#include <stdint.h>
#include <new>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

typedef struct {
    size_t count;
    void** addrs;
} stack_crawl_state_t;

static _Unwind_Reason_Code trace_function(_Unwind_Context *context, void *arg)
{
    stack_crawl_state_t* state = (stack_crawl_state_t*)arg;
    if (state->count) {
        void* ip = (void*)_Unwind_GetIP(context);
        printf("Get the ip:%x\n", ip);
        if (ip) {
            state->addrs[0] = ip;
            state->addrs++;
            state->count--;
            return _URC_NO_REASON;
        }
    }

    return _URC_END_OF_STACK;
}


// implement android version backtrace function.
static int mybacktrace(void** addrs, size_t size)
{
    printf("============begin unwind================\n");
    stack_crawl_state_t state;
    state.count = size;
    state.addrs = addrs;
    _Unwind_Backtrace(trace_function, (void*)&state);
    return size - state.count;
}

void *operator new(size_t size) throw (std::bad_alloc)
{
    void *callstack[16];
    int i = mybacktrace(callstack, 16);
    return malloc(size);
}

void operator delete(void *ptr) throw()
{
}

class X
{
};

template <int I> void f()
{
    f<I-1>();
}

template <> void f<0>()
{
    void *callstack[16];
    int i = mybacktrace(callstack, 16);
}

int createObj2()
{
    X * p = new X();
}

int createObj1()
{
    createObj2();
}


int main()
{
    createObj1();
    f<10>();
}

result:

============begin unwind================
Get the ip:8898
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
Get the ip:88f0
============begin unwind================
Get the ip:8898
Get the ip:8960
Get the ip:8a6c
Get the ip:8a5c
Get the ip:8a4c
Get the ip:8a3c
Get the ip:8a2c
Get the ip:8a1c
Get the ip:8a0c
Get the ip:89fc
Get the ip:89ec
Get the ip:89dc
Get the ip:89c4
Get the ip:400823d8

Build command line:

export NDK_PATH=/home/zijingwu/Downloads/android-ndk-r9d
$NDK_PATH/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++   -O0  -I$NDK_PATH/sources/cxx-stl/stlport/stlport -I.   -DBSD=1  -DENABLE_ERROR_CATCH -DSOCKLEN_T=socklen_t -DHAVE_SOCKADDR_LEN=1 -DTIME_BASE=int --sysroot=$NDK_PATH/platforms/android-18/arch-arm/ -DANDROID -march=armv7-a -mfpu=neon -mfloat-abi=softfp -flax-vector-conversions -DPOSIX -Wno-unused-local-typedefs -g -gdwarf-2 -Wall  -o test.o -c test.cpp

$NDK_PATH/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -o -L.  -nostdlib --sysroot=$NDK_PATH/platforms/android-18/arch-arm/ -Wl,--eh-frame-hdr,-m,armelf_linux_eabi,-z,noexecstack,-z,relro,-z,now -fPIC -Xlinker -start-group  -Wl,--export-dynamic test.o  $NDK_PATH/platforms/android-18/arch-arm/usr/lib/crtbegin_dynamic.o $NDK_PATH/platforms/android-18/arch-arm/usr/lib/crtend_android.o $NDK_PATH/platforms/android-18/arch-arm/usr/lib/liblog.so -L$NDK_PATH/sources/cxx-stl/stlport/libs/armeabi -Wl,-z,defs -Wl,--no-whole-archive -lstlport_shared -lstdc++ -lc -ldl -lm -lgcc -llog -Wl,--whole-archive -Xlinker --end-group -o test
ZijingWu
  • 3,350
  • 3
  • 25
  • 40
  • It doesn't look like your operator's getting used at all - there's no "adsfadfadsf" in your output. I've read that the Android C++ compiler seems to always call the noexcept / potentially nullptr-returning version of `operator new` even if not asked to, so you might want to try overloading that.... – Tony Delroy Jul 09 '14 at 04:16
  • @TonyD, Sorry, my fault. I just missed to copy the first line in the result. Sorry for confuse, actually i have verified the `operator new` has been called. – ZijingWu Jul 09 '14 at 05:04
  • You could start investigating by printing the return value from `_Unwind_Backtrace` - could be e.g. `_URC_NO_REASON _URC_FOREIGN_EXCEPTION_CAUGHT _URC_FATAL_PHASE2_ERROR _URC_FATAL_PHASE1_ERROR _URC_NORMAL_STOP _URC_END_OF_STACK _URC_HANDLER_FOUND _URC_INSTALL_CONTEXT _URC_CONTINUE_UNWIND` which might give a bit of a hint of what's going wrong... something more to Google. – Tony Delroy Jul 09 '14 at 05:27
  • @TonyD, I have print out the `_Unwind_Backtrace`, it is 9, which means `_URC_FAILURE = 9`, but I cannot figure out why it failed. So any suggestion? – ZijingWu Jul 09 '14 at 06:00
  • only an echo of my earlier suggestion to keep googling, reading Android implementation notes or `_Unwind_Backtrace` source code... I don't know anything about Android really and don't have such a system to work on. Maybe someone else will be able to help more. – Tony Delroy Jul 09 '14 at 06:11

0 Answers0