2013年12月28日 星期六

BackTace caller name in C/C++

1. down binutils and build
~~~binutils 2.25.1 x86_64 & aarch64 both build pass other version may be not~~~
download: https://ftp.gnu.org/gnu/binutils
x86_64
./configure --host=x86_64-linux-gnu --target=x86_64-linux-gnu --prefix=$HOME/binutils-2.25.1/build
make && make install
or
aarch64
./configure --host=x86_64-linux-gnu --target=aarch64-linux-gnu --prefix=$HOME/binutils-2.25.1/build
make && make install

cp -f ~/binutils-2.25.1/build/bin/addr2line [your project path]

2. using backtrace and popen funtion
static void backtraceLast(const char* abspath)
{
    int     addrlen;
    int     max_frames      = 64;
    char    symline[256]    = {0};
    char    straddr[256]    = {0};
    char    cmdline[256]    = {0};
    char    result[256]     = {0};
    FILE*   fp;
    char*   strStar;
    char*   strEnd;
    void*   addrlist[max_frames];
    char**  symlist;

    addrlen   = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
    if( addrlen >= 3 )
    {
        //hand made parser
        /*symlist   = backtrace_symbols (addrlist, addrlen);
        if (symlist != NULL)
        {
            snprintf(symline, sizeof(symline), "%s", symlist[2]);
            strStar = strchr(symline,'[') + 1;
            strEnd  = strchr(strStar,']');
            *strEnd = 0x00;
            snprintf(straddr, sizeof(straddr), "%s", strStar);
        }
        free(symlist);*/

        if( strlen(straddr) > 0 )
        {
            snprintf(cmdline, sizeof(cmdline), "./addr2line -e %s -f %p", abspath, addrlist[2]);
            fp = popen(cmdline, "r");
            if (fp)
            {
                while (fgets(result, sizeof(result), fp))
                {
                    printf("%s", result);
                }
            }
            pclose(fp);
        }
    }
}

3. build code flags
CFLAGS = -O0 -g
CXXFLAGS = -O0 -g
or
CFLAGS = -O1 -g -fno-inline-functions-called-once -fno-omit-frame-pointer
CXXFLAGS = -O1 -g -fno-inline-functions-called-once -fno-omit-frame-pointer

4. if you want to use binutils-2.39.tar.xz for aarch64 compiler (option)
#######Way A: modify config.guess#######
gedit ~/binutils-2.39/config.guess
~find
x86_64:Linux:*:*)
set_cc_for_build
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_X32 >/dev/null
    then
LIBCABI=${LIBC}x32
    fi
fi
GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
~change to
x86_64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
~then
./configure --host=x86_64-linux-gnu --target=aarch64-linux-gnu --prefix=$HOME/binutils-2.25.1/build --program-prefix=""
make && make install

#######Way B: add --build=x86_64-unknown-linux-gnu#######
~~~add [--build=x86_64-unknown-linux-gnu] means enable cross compiler
./configure --build=build=x86_64-unknown-linux-gnu --host=x86_64-linux-gnu --target=aarch64-linux-gnu --prefix=$HOME/binutils-2.39/build --program-prefix=""

make && make install

note:
~~~the config.guess will effect ~/binutils-2.39/configure
test "x$ac_build_alias" = x &&
  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
~~~and create Makefile correctly
AR_FOR_BUILD = ar
AS_FOR_BUILD = as
CC_FOR_BUILD = gcc
CXX_FOR_BUILD = g++
LD_FOR_BUILD = ld
RANLIB_FOR_BUILD = ranlib

download:
1. patched full source
https://www.mediafire.com/file/3tyys8hsjwc8bkj/binutils-2.39.tar.gz
2. build scripts on patched source also normal source
https://www.mediafire.com/file/joe4pxsl902o4fa/build_x64_addr2line.sh
https://www.mediafire.com/file/axmfbegv6p6el0t/build_aarch64_addr2line.sh
3. caller example
https://www.mediafire.com/file/6zxp2hked67qez9/callername.tar.gz
demo:
https://www.mediafire.com/view/k1vhndmvm08m596/callername.png

沒有留言:

張貼留言